root/drivers/char/fbmem.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. PROC_CONSOLE
  2. fb_read
  3. fb_write
  4. fb_ioctl
  5. fb_mmap
  6. fb_open
  7. fb_release
  8. register_framebuffer
  9. unregister_framebuffer
  10. fbmem_init

   1 /*
   2  *  linux/drivers/char/fbmem.c
   3  *
   4  *  Copyright (C) 1994 Martin Schaller
   5  *
   6  * This file is subject to the terms and conditions of the GNU General Public
   7  * License.  See the file README.legal in the main directory of this archive
   8  * for more details.
   9  */
  10 
  11 #include <linux/types.h>
  12 #include <linux/errno.h>
  13 #include <linux/sched.h>
  14 #include <linux/kernel.h>
  15 #include <linux/major.h>
  16 #include <linux/malloc.h>
  17 #include <linux/mman.h>
  18 #include <linux/tty.h>
  19 
  20 #include <asm/segment.h>
  21 #include <asm/bootinfo.h>
  22 #include <asm/page.h>
  23 #include <asm/pgtable.h>
  24 
  25 #include <linux/fb.h>
  26 
  27 #define FB_MAJOR        29
  28 
  29 #define FB_MODES_SHIFT    5     /* 32 modes per framebuffer */
  30 #define FB_NUM_MINORS   256     /* 256 Minors               */
  31 #define FB_MAX          (FB_NUM_MINORS / (1 << FB_MODES_SHIFT))
  32 
  33 #define GET_INODE(i) MKDEV(FB_MAJOR, (i) << FB_MODES_SHIFT)
  34 #define GET_FB_IDX(node) (MINOR(node) >> FB_MODES_SHIFT)
  35 #define GET_FB_VAR_IDX(node) (MINOR(node) & ((1 << FB_MODES_SHIFT)-1)) 
  36 
  37 struct fb_ops *registered_fb[FB_MAX];
  38 struct fb_var_screeninfo *registered_fb_var[FB_MAX];
  39 int registered_fb_var_num[FB_MAX];
  40 int fb_curr_open[FB_MAX];
  41 int fb_open_count[FB_MAX];
  42 
  43 static inline int PROC_CONSOLE(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  44 {
  45         if (!current->tty)
  46                 return fg_console;
  47 
  48         if (MINOR(current->tty->device) < 1)
  49                 return fg_console;
  50 
  51         return MINOR(current->tty->device) - 1;
  52 }
  53 
  54 static int 
  55 fb_read(struct inode *inode, struct file *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  56 {
  57         unsigned long p = file->f_pos;
  58         struct fb_ops *fb = registered_fb[GET_FB_IDX(inode->i_rdev)];
  59         struct fb_fix_screeninfo fix;
  60         char *base_addr;
  61         int copy_size;
  62 
  63         if (! fb)
  64                 return -ENODEV;
  65         if (count < 0)
  66                 return -EINVAL;
  67 
  68         fb->fb_get_fix(&fix,PROC_CONSOLE());
  69         base_addr=(char *) fix.smem_start;
  70         copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
  71         memcpy_tofs(buf, base_addr+p, copy_size);
  72         file->f_pos += copy_size;
  73         return copy_size;
  74 }
  75 
  76 static int 
  77 fb_write(struct inode *inode, struct file *file, const char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  78 {
  79         unsigned long p = file->f_pos;
  80         struct fb_ops *fb = registered_fb[GET_FB_IDX(inode->i_rdev)];
  81         struct fb_fix_screeninfo fix;
  82         char *base_addr;
  83         int copy_size;
  84 
  85         if (! fb)
  86                 return -ENODEV;
  87         if (count < 0)
  88                 return -EINVAL;
  89         fb->fb_get_fix(&fix, PROC_CONSOLE());
  90         base_addr=(char *) fix.smem_start;
  91         copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
  92         memcpy_fromfs(base_addr+p, buf, copy_size); 
  93         file->f_pos += copy_size;
  94         return copy_size;
  95 }
  96 
  97 
  98 static int 
  99 fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
     /* [previous][next][first][last][top][bottom][index][help] */
 100          unsigned long arg)
 101 {
 102         struct fb_ops *fb = registered_fb[GET_FB_IDX(inode->i_rdev)];
 103         struct fb_cmap cmap;
 104         struct fb_var_screeninfo var;
 105         struct fb_fix_screeninfo fix;
 106 
 107         int i,fbidx,vidx;
 108         
 109         if (! fb)
 110                 return -ENODEV;
 111         switch (cmd) {
 112         case FBIOGET_VSCREENINFO:
 113                 i = verify_area(VERIFY_WRITE, (void *) arg, 
 114                                 sizeof(struct fb_var_screeninfo));
 115                 if (i) return i;
 116                 fbidx=GET_FB_IDX(inode->i_rdev);
 117                 vidx=GET_FB_VAR_IDX(inode->i_rdev);
 118                 if (! vidx) /* ask device driver for current */
 119                         i=fb->fb_get_var(&var, PROC_CONSOLE());
 120                 else
 121                         var=registered_fb_var[fbidx][vidx-1];
 122                 memcpy_tofs((void *) arg, &var, sizeof(var));
 123                 return i;
 124         case FBIOPUT_VSCREENINFO:
 125                 i = verify_area(VERIFY_WRITE, (void *) arg, 
 126                                 sizeof(struct fb_var_screeninfo));
 127                 if (i) return i;
 128                 memcpy_fromfs(&var, (void *) arg, sizeof(var));
 129                 i=fb->fb_set_var(&var, PROC_CONSOLE());
 130                 memcpy_tofs((void *) arg, &var, sizeof(var));
 131                 fbidx=GET_FB_IDX(inode->i_rdev);
 132                 vidx=GET_FB_VAR_IDX(inode->i_rdev);
 133                 if (! i && vidx)
 134                         registered_fb_var[fbidx][vidx-1]=var;
 135                 return i;
 136         case FBIOGET_FSCREENINFO:
 137                 i = verify_area(VERIFY_WRITE, (void *) arg, 
 138                                 sizeof(struct fb_fix_screeninfo));
 139                 if (i)  return i;
 140                 i=fb->fb_get_fix(&fix, PROC_CONSOLE());
 141                 memcpy_tofs((void *) arg, &fix, sizeof(fix));
 142                 return i;
 143         case FBIOPUTCMAP:
 144                 i = verify_area(VERIFY_READ, (void *) arg,
 145                                 sizeof(struct fb_cmap));
 146                 if (i) return i;
 147                 memcpy_fromfs(&cmap, (void *) arg, sizeof(cmap));
 148                 i = verify_area(VERIFY_READ, (void *) cmap.red, 
 149                                 cmap.len * sizeof(unsigned short));
 150                 if (i) return i;
 151                 i = verify_area(VERIFY_READ, (void *) cmap.green, 
 152                                 cmap.len * sizeof(unsigned short));
 153                 if (i) return i;
 154                 i = verify_area(VERIFY_READ, (void *) cmap.blue, 
 155                                 cmap.len * sizeof(unsigned short));
 156                 if (i) return i;
 157                 if (cmap.transp) {
 158                         i = verify_area(VERIFY_READ, (void *) cmap.transp, 
 159                                         cmap.len * sizeof(unsigned short));
 160                         if (i) return i;
 161                 }
 162                 return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE()));
 163         case FBIOGETCMAP:
 164                 i = verify_area(VERIFY_READ, (void *) arg,
 165                                 sizeof(struct fb_cmap));
 166                 if (i)  return i;
 167                 memcpy_fromfs(&cmap, (void *) arg, sizeof(cmap));
 168                 i = verify_area(VERIFY_WRITE, (void *) cmap.red, 
 169                                 cmap.len * sizeof(unsigned short));
 170                 if (i) return i;
 171                 i = verify_area(VERIFY_WRITE, (void *) cmap.green, 
 172                                 cmap.len * sizeof(unsigned short));
 173                 if (i) return i;
 174                 i = verify_area(VERIFY_WRITE, (void *) cmap.blue, 
 175                                 cmap.len * sizeof(unsigned short));
 176                 if (i) return i;
 177                 if (cmap.transp) {
 178                         i = verify_area(VERIFY_WRITE, (void *) cmap.transp, 
 179                                         cmap.len * sizeof(unsigned short));
 180                         if (i) return i;
 181                 }
 182                 return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE()));
 183         default:
 184                 return (fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE()));
 185         }
 186 }
 187 
 188 static int 
 189 fb_mmap(struct inode *inode, struct file *file, struct vm_area_struct * vma)
     /* [previous][next][first][last][top][bottom][index][help] */
 190 {
 191         struct fb_ops *fb = registered_fb[GET_FB_IDX(inode->i_rdev)];
 192         struct fb_fix_screeninfo fix;
 193 
 194         if (! fb)
 195                 return -ENODEV;
 196         fb->fb_get_fix(&fix, PROC_CONSOLE());
 197         if ((vma->vm_end - vma->vm_start + vma->vm_offset) > fix.smem_len)
 198                 return -EINVAL;
 199         vma->vm_offset += fix.smem_start;
 200         if (vma->vm_offset & ~PAGE_MASK)
 201                 return -ENXIO;
 202         if (boot_info.cputype & CPU_68040)
 203                 pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
 204         if (remap_page_range(vma->vm_start, vma->vm_offset,
 205                              vma->vm_end - vma->vm_start, vma->vm_page_prot))
 206                 return -EAGAIN;
 207         vma->vm_inode = inode;
 208         inode->i_count++;
 209         return 0;
 210 }
 211 
 212 static int
 213 fb_open(struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 214 {
 215         int fbidx=GET_FB_IDX(inode->i_rdev);
 216         int vidx=GET_FB_VAR_IDX(inode->i_rdev);
 217         struct fb_ops *fb = registered_fb[fbidx];
 218         int err;
 219         
 220         if (! vidx)             /* fb?current always succeeds */ 
 221                 return 0;
 222         if (vidx > registered_fb_var_num[fbidx])
 223                 return -EINVAL;
 224         if (fb_curr_open[fbidx] && fb_curr_open[fbidx] != vidx)
 225                 return -EBUSY;
 226         if (file->f_mode & 2) /* only set parameters if opened writeable */
 227                 if ((err=fb->fb_set_var(registered_fb_var[fbidx] + vidx-1, PROC_CONSOLE())))
 228                         return err;
 229         fb_curr_open[fbidx] = vidx;
 230         fb_open_count[fbidx]++;
 231         return 0;
 232 }
 233 
 234 static void 
 235 fb_release(struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 236 {
 237         int fbidx=GET_FB_IDX(inode->i_rdev);
 238         int vidx=GET_FB_VAR_IDX(inode->i_rdev);
 239         if (! vidx)
 240                 return;
 241         if (! (--fb_open_count[fbidx]))
 242                 fb_curr_open[fbidx]=0;
 243 }
 244 
 245 static struct file_operations fb_fops = {
 246         NULL,           /* lseek        */
 247         fb_read,        /* read         */
 248         fb_write,       /* write        */
 249         NULL,           /* readdir      */
 250         NULL,           /* select       */
 251         fb_ioctl,       /* ioctl        */
 252         fb_mmap,        /* mmap         */
 253         fb_open,        /* open         */
 254         fb_release,     /* release      */
 255         NULL            /* fsync        */
 256 };
 257 
 258 int
 259 register_framebuffer(char *id, int *node, struct fb_ops *fbops, int fbvar_num, 
     /* [previous][next][first][last][top][bottom][index][help] */
 260                      struct fb_var_screeninfo *fbvar)
 261 {
 262         int i;
 263         for (i = 0 ; i < FB_MAX; i++)
 264                 if (! registered_fb[i])
 265                         break;
 266         if (i == FB_MAX)
 267                 return -ENXIO;
 268         registered_fb[i]=fbops;
 269         registered_fb_var[i]=fbvar;
 270         registered_fb_var_num[i]=fbvar_num;
 271         *node=GET_INODE(i);
 272         return 0;
 273 }
 274 
 275 int
 276 unregister_framebuffer(int node)
     /* [previous][next][first][last][top][bottom][index][help] */
 277 {
 278         int i=GET_FB_IDX(node);
 279         if (! registered_fb[i])
 280                 return -EINVAL; 
 281         registered_fb[i]=NULL;
 282         registered_fb_var[i]=NULL;
 283         return 0;
 284 }
 285 
 286 void
 287 fbmem_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 288 {
 289         if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
 290                 printk("unable to get major %d for fb devs\n", FB_MAJOR);
 291 }
 292 

/* [previous][next][first][last][top][bottom][index][help] */