Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 77b2555b52a894a2e39a42e43d993df875c46a6a 184 lines 4.5 kB view raw
1/* sbuslib.c: Helper library for SBUS framebuffer drivers. 2 * 3 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 4 */ 5 6#include <linux/kernel.h> 7#include <linux/module.h> 8#include <linux/string.h> 9#include <linux/fb.h> 10#include <linux/mm.h> 11 12#include <asm/oplib.h> 13#include <asm/fbio.h> 14 15#include "sbuslib.h" 16 17void sbusfb_fill_var(struct fb_var_screeninfo *var, int prom_node, int bpp) 18{ 19 memset(var, 0, sizeof(*var)); 20 21 var->xres = prom_getintdefault(prom_node, "width", 1152); 22 var->yres = prom_getintdefault(prom_node, "height", 900); 23 var->xres_virtual = var->xres; 24 var->yres_virtual = var->yres; 25 var->bits_per_pixel = bpp; 26} 27 28EXPORT_SYMBOL(sbusfb_fill_var); 29 30static unsigned long sbusfb_mmapsize(long size, unsigned long fbsize) 31{ 32 if (size == SBUS_MMAP_EMPTY) return 0; 33 if (size >= 0) return size; 34 return fbsize * (-size); 35} 36 37int sbusfb_mmap_helper(struct sbus_mmap_map *map, 38 unsigned long physbase, 39 unsigned long fbsize, 40 unsigned long iospace, 41 struct vm_area_struct *vma) 42{ 43 unsigned int size, page, r, map_size; 44 unsigned long map_offset = 0; 45 unsigned long off; 46 int i; 47 48 size = vma->vm_end - vma->vm_start; 49 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) 50 return -EINVAL; 51 52 off = vma->vm_pgoff << PAGE_SHIFT; 53 54 /* To stop the swapper from even considering these pages */ 55 vma->vm_flags |= (VM_IO | VM_RESERVED); 56 57 /* Each page, see which map applies */ 58 for (page = 0; page < size; ){ 59 map_size = 0; 60 for (i = 0; map[i].size; i++) 61 if (map[i].voff == off+page) { 62 map_size = sbusfb_mmapsize(map[i].size, fbsize); 63#ifdef __sparc_v9__ 64#define POFF_MASK (PAGE_MASK|0x1UL) 65#else 66#define POFF_MASK (PAGE_MASK) 67#endif 68 map_offset = (physbase + map[i].poff) & POFF_MASK; 69 break; 70 } 71 if (!map_size){ 72 page += PAGE_SIZE; 73 continue; 74 } 75 if (page + map_size > size) 76 map_size = size - page; 77 r = io_remap_pfn_range(vma, 78 vma->vm_start + page, 79 MK_IOSPACE_PFN(iospace, 80 map_offset >> PAGE_SHIFT), 81 map_size, 82 vma->vm_page_prot); 83 if (r) 84 return -EAGAIN; 85 page += map_size; 86 } 87 88 return 0; 89} 90EXPORT_SYMBOL(sbusfb_mmap_helper); 91 92int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, 93 struct fb_info *info, 94 int type, int fb_depth, unsigned long fb_size) 95{ 96 switch(cmd) { 97 case FBIOGTYPE: { 98 struct fbtype __user *f = (struct fbtype __user *) arg; 99 100 if (put_user(type, &f->fb_type) || 101 __put_user(info->var.yres, &f->fb_height) || 102 __put_user(info->var.xres, &f->fb_width) || 103 __put_user(fb_depth, &f->fb_depth) || 104 __put_user(0, &f->fb_cmsize) || 105 __put_user(fb_size, &f->fb_cmsize)) 106 return -EFAULT; 107 return 0; 108 } 109 case FBIOPUTCMAP_SPARC: { 110 struct fbcmap __user *c = (struct fbcmap __user *) arg; 111 struct fb_cmap cmap; 112 u16 red, green, blue; 113 u8 red8, green8, blue8; 114 unsigned char __user *ured; 115 unsigned char __user *ugreen; 116 unsigned char __user *ublue; 117 int index, count, i; 118 119 if (get_user(index, &c->index) || 120 __get_user(count, &c->count) || 121 __get_user(ured, &c->red) || 122 __get_user(ugreen, &c->green) || 123 __get_user(ublue, &c->blue)) 124 return -EFAULT; 125 126 cmap.len = 1; 127 cmap.red = &red; 128 cmap.green = &green; 129 cmap.blue = &blue; 130 cmap.transp = NULL; 131 for (i = 0; i < count; i++) { 132 int err; 133 134 if (get_user(red8, &ured[i]) || 135 get_user(green8, &ugreen[i]) || 136 get_user(blue8, &ublue[i])) 137 return -EFAULT; 138 139 red = red8 << 8; 140 green = green8 << 8; 141 blue = blue8 << 8; 142 143 cmap.start = index + i; 144 err = fb_set_cmap(&cmap, info); 145 if (err) 146 return err; 147 } 148 return 0; 149 } 150 case FBIOGETCMAP_SPARC: { 151 struct fbcmap __user *c = (struct fbcmap __user *) arg; 152 unsigned char __user *ured; 153 unsigned char __user *ugreen; 154 unsigned char __user *ublue; 155 struct fb_cmap *cmap = &info->cmap; 156 int index, count, i; 157 u8 red, green, blue; 158 159 if (get_user(index, &c->index) || 160 __get_user(count, &c->count) || 161 __get_user(ured, &c->red) || 162 __get_user(ugreen, &c->green) || 163 __get_user(ublue, &c->blue)) 164 return -EFAULT; 165 166 if (index + count > cmap->len) 167 return -EINVAL; 168 169 for (i = 0; i < count; i++) { 170 red = cmap->red[index + i] >> 8; 171 green = cmap->green[index + i] >> 8; 172 blue = cmap->blue[index + i] >> 8; 173 if (put_user(red, &ured[i]) || 174 put_user(green, &ugreen[i]) || 175 put_user(blue, &ublue[i])) 176 return -EFAULT; 177 } 178 return 0; 179 } 180 default: 181 return -EINVAL; 182 }; 183} 184EXPORT_SYMBOL(sbusfb_ioctl_helper);