Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 
 17 void 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 
 28 EXPORT_SYMBOL(sbusfb_fill_var);
 29 
 30 static 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 
 37 int 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_page_range(vma,
 78                                         vma->vm_start + page,
 79                                         map_offset, map_size,
 80                                         vma->vm_page_prot, iospace);
 81                 if (r)
 82                         return -EAGAIN;
 83                 page += map_size;
 84         }
 85 
 86         return 0;
 87 }
 88 EXPORT_SYMBOL(sbusfb_mmap_helper);
 89 
 90 int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
 91                         struct fb_info *info,
 92                         int type, int fb_depth, unsigned long fb_size)
 93 {
 94         switch(cmd) {
 95         case FBIOGTYPE: {
 96                 struct fbtype __user *f = (struct fbtype __user *) arg;
 97 
 98                 if (put_user(type, &f->fb_type) ||
 99                     __put_user(info->var.yres, &f->fb_height) ||
100                     __put_user(info->var.xres, &f->fb_width) ||
101                     __put_user(fb_depth, &f->fb_depth) ||
102                     __put_user(0, &f->fb_cmsize) ||
103                     __put_user(fb_size, &f->fb_cmsize))
104                         return -EFAULT;
105                 return 0;
106         }
107         case FBIOPUTCMAP_SPARC: {
108                 struct fbcmap __user *c = (struct fbcmap __user *) arg;
109                 struct fb_cmap cmap;
110                 u16 red, green, blue;
111                 u8 red8, green8, blue8;
112                 unsigned char __user *ured;
113                 unsigned char __user *ugreen;
114                 unsigned char __user *ublue;
115                 int index, count, i;
116 
117                 if (get_user(index, &c->index) ||
118                     __get_user(count, &c->count) ||
119                     __get_user(ured, &c->red) ||
120                     __get_user(ugreen, &c->green) ||
121                     __get_user(ublue, &c->blue))
122                         return -EFAULT;
123 
124                 cmap.len = 1;
125                 cmap.red = &red;
126                 cmap.green = &green;
127                 cmap.blue = &blue;
128                 cmap.transp = NULL;
129                 for (i = 0; i < count; i++) {
130                         int err;
131 
132                         if (get_user(red8, &ured[i]) ||
133                             get_user(green8, &ugreen[i]) ||
134                             get_user(blue8, &ublue[i]))
135                                 return -EFAULT;
136 
137                         red = red8 << 8;
138                         green = green8 << 8;
139                         blue = blue8 << 8;
140 
141                         cmap.start = index + i;
142                         err = fb_set_cmap(&cmap, info);
143                         if (err)
144                                 return err;
145                 }
146                 return 0;
147         }
148         case FBIOGETCMAP_SPARC: {
149                 struct fbcmap __user *c = (struct fbcmap __user *) arg;
150                 unsigned char __user *ured;
151                 unsigned char __user *ugreen;
152                 unsigned char __user *ublue;
153                 struct fb_cmap *cmap = &info->cmap;
154                 int index, count, i;
155                 u8 red, green, blue;
156 
157                 if (get_user(index, &c->index) ||
158                     __get_user(count, &c->count) ||
159                     __get_user(ured, &c->red) ||
160                     __get_user(ugreen, &c->green) ||
161                     __get_user(ublue, &c->blue))
162                         return -EFAULT;
163 
164                 if (index + count > cmap->len)
165                         return -EINVAL;
166 
167                 for (i = 0; i < count; i++) {
168                         red = cmap->red[index + i] >> 8;
169                         green = cmap->green[index + i] >> 8;
170                         blue = cmap->blue[index + i] >> 8;
171                         if (put_user(red, &ured[i]) ||
172                             put_user(green, &ugreen[i]) ||
173                             put_user(blue, &ublue[i]))
174                                 return -EFAULT;
175                 }
176                 return 0;
177         }
178         default:
179                 return -EINVAL;
180         };
181 }
182 EXPORT_SYMBOL(sbusfb_ioctl_helper);
183 
  This page was automatically generated by the LXR engine.