root/drivers/video/fbdev/sbuslib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sbusfb_fill_var
  2. sbusfb_mmapsize
  3. sbusfb_mmap_helper
  4. sbusfb_ioctl_helper
  5. fbiogetputcmap
  6. fbiogscursor
  7. sbusfb_compat_ioctl

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* sbuslib.c: Helper library for SBUS framebuffer drivers.
   3  *
   4  * Copyright (C) 2003 David S. Miller (davem@redhat.com)
   5  */
   6 
   7 #include <linux/compat.h>
   8 #include <linux/kernel.h>
   9 #include <linux/module.h>
  10 #include <linux/string.h>
  11 #include <linux/fb.h>
  12 #include <linux/mm.h>
  13 #include <linux/uaccess.h>
  14 #include <linux/of_device.h>
  15 
  16 #include <asm/fbio.h>
  17 
  18 #include "sbuslib.h"
  19 
  20 void sbusfb_fill_var(struct fb_var_screeninfo *var, struct device_node *dp,
  21                      int bpp)
  22 {
  23         memset(var, 0, sizeof(*var));
  24 
  25         var->xres = of_getintprop_default(dp, "width", 1152);
  26         var->yres = of_getintprop_default(dp, "height", 900);
  27         var->xres_virtual = var->xres;
  28         var->yres_virtual = var->yres;
  29         var->bits_per_pixel = bpp;
  30 }
  31 
  32 EXPORT_SYMBOL(sbusfb_fill_var);
  33 
  34 static unsigned long sbusfb_mmapsize(long size, unsigned long fbsize)
  35 {
  36         if (size == SBUS_MMAP_EMPTY) return 0;
  37         if (size >= 0) return size;
  38         return fbsize * (-size);
  39 }
  40 
  41 int sbusfb_mmap_helper(struct sbus_mmap_map *map,
  42                        unsigned long physbase,
  43                        unsigned long fbsize,
  44                        unsigned long iospace,
  45                        struct vm_area_struct *vma)
  46 {
  47         unsigned int size, page, r, map_size;
  48         unsigned long map_offset = 0;
  49         unsigned long off;
  50         int i;
  51                                         
  52         if (!(vma->vm_flags & (VM_SHARED | VM_MAYSHARE)))
  53                 return -EINVAL;
  54 
  55         size = vma->vm_end - vma->vm_start;
  56         if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
  57                 return -EINVAL;
  58 
  59         off = vma->vm_pgoff << PAGE_SHIFT;
  60 
  61         /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
  62 
  63         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
  64 
  65         /* Each page, see which map applies */
  66         for (page = 0; page < size; ){
  67                 map_size = 0;
  68                 for (i = 0; map[i].size; i++)
  69                         if (map[i].voff == off+page) {
  70                                 map_size = sbusfb_mmapsize(map[i].size, fbsize);
  71 #ifdef __sparc_v9__
  72 #define POFF_MASK       (PAGE_MASK|0x1UL)
  73 #else
  74 #define POFF_MASK       (PAGE_MASK)
  75 #endif                          
  76                                 map_offset = (physbase + map[i].poff) & POFF_MASK;
  77                                 break;
  78                         }
  79                 if (!map_size) {
  80                         page += PAGE_SIZE;
  81                         continue;
  82                 }
  83                 if (page + map_size > size)
  84                         map_size = size - page;
  85                 r = io_remap_pfn_range(vma,
  86                                         vma->vm_start + page,
  87                                         MK_IOSPACE_PFN(iospace,
  88                                                 map_offset >> PAGE_SHIFT),
  89                                         map_size,
  90                                         vma->vm_page_prot);
  91                 if (r)
  92                         return -EAGAIN;
  93                 page += map_size;
  94         }
  95 
  96         return 0;
  97 }
  98 EXPORT_SYMBOL(sbusfb_mmap_helper);
  99 
 100 int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
 101                         struct fb_info *info,
 102                         int type, int fb_depth, unsigned long fb_size)
 103 {
 104         switch(cmd) {
 105         case FBIOGTYPE: {
 106                 struct fbtype __user *f = (struct fbtype __user *) arg;
 107 
 108                 if (put_user(type, &f->fb_type) ||
 109                     put_user(info->var.yres, &f->fb_height) ||
 110                     put_user(info->var.xres, &f->fb_width) ||
 111                     put_user(fb_depth, &f->fb_depth) ||
 112                     put_user(0, &f->fb_cmsize) ||
 113                     put_user(fb_size, &f->fb_cmsize))
 114                         return -EFAULT;
 115                 return 0;
 116         }
 117         case FBIOPUTCMAP_SPARC: {
 118                 struct fbcmap __user *c = (struct fbcmap __user *) arg;
 119                 struct fb_cmap cmap;
 120                 u16 red, green, blue;
 121                 u8 red8, green8, blue8;
 122                 unsigned char __user *ured;
 123                 unsigned char __user *ugreen;
 124                 unsigned char __user *ublue;
 125                 unsigned int index, count, i;
 126 
 127                 if (get_user(index, &c->index) ||
 128                     get_user(count, &c->count) ||
 129                     get_user(ured, &c->red) ||
 130                     get_user(ugreen, &c->green) ||
 131                     get_user(ublue, &c->blue))
 132                         return -EFAULT;
 133 
 134                 cmap.len = 1;
 135                 cmap.red = &red;
 136                 cmap.green = &green;
 137                 cmap.blue = &blue;
 138                 cmap.transp = NULL;
 139                 for (i = 0; i < count; i++) {
 140                         int err;
 141 
 142                         if (get_user(red8, &ured[i]) ||
 143                             get_user(green8, &ugreen[i]) ||
 144                             get_user(blue8, &ublue[i]))
 145                                 return -EFAULT;
 146 
 147                         red = red8 << 8;
 148                         green = green8 << 8;
 149                         blue = blue8 << 8;
 150 
 151                         cmap.start = index + i;
 152                         err = fb_set_cmap(&cmap, info);
 153                         if (err)
 154                                 return err;
 155                 }
 156                 return 0;
 157         }
 158         case FBIOGETCMAP_SPARC: {
 159                 struct fbcmap __user *c = (struct fbcmap __user *) arg;
 160                 unsigned char __user *ured;
 161                 unsigned char __user *ugreen;
 162                 unsigned char __user *ublue;
 163                 struct fb_cmap *cmap = &info->cmap;
 164                 unsigned int index, count, i;
 165                 u8 red, green, blue;
 166 
 167                 if (get_user(index, &c->index) ||
 168                     get_user(count, &c->count) ||
 169                     get_user(ured, &c->red) ||
 170                     get_user(ugreen, &c->green) ||
 171                     get_user(ublue, &c->blue))
 172                         return -EFAULT;
 173 
 174                 if (index > cmap->len || count > cmap->len - index)
 175                         return -EINVAL;
 176 
 177                 for (i = 0; i < count; i++) {
 178                         red = cmap->red[index + i] >> 8;
 179                         green = cmap->green[index + i] >> 8;
 180                         blue = cmap->blue[index + i] >> 8;
 181                         if (put_user(red, &ured[i]) ||
 182                             put_user(green, &ugreen[i]) ||
 183                             put_user(blue, &ublue[i]))
 184                                 return -EFAULT;
 185                 }
 186                 return 0;
 187         }
 188         default:
 189                 return -EINVAL;
 190         }
 191 }
 192 EXPORT_SYMBOL(sbusfb_ioctl_helper);
 193 
 194 #ifdef CONFIG_COMPAT
 195 static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long arg)
 196 {
 197         struct fbcmap32 __user *argp = (void __user *)arg;
 198         struct fbcmap __user *p = compat_alloc_user_space(sizeof(*p));
 199         u32 addr;
 200         int ret;
 201 
 202         ret = copy_in_user(p, argp, 2 * sizeof(int));
 203         ret |= get_user(addr, &argp->red);
 204         ret |= put_user(compat_ptr(addr), &p->red);
 205         ret |= get_user(addr, &argp->green);
 206         ret |= put_user(compat_ptr(addr), &p->green);
 207         ret |= get_user(addr, &argp->blue);
 208         ret |= put_user(compat_ptr(addr), &p->blue);
 209         if (ret)
 210                 return -EFAULT;
 211         return info->fbops->fb_ioctl(info,
 212                         (cmd == FBIOPUTCMAP32) ?
 213                         FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC,
 214                         (unsigned long)p);
 215 }
 216 
 217 static int fbiogscursor(struct fb_info *info, unsigned long arg)
 218 {
 219         struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p));
 220         struct fbcursor32 __user *argp =  (void __user *)arg;
 221         compat_uptr_t addr;
 222         int ret;
 223 
 224         ret = copy_in_user(p, argp,
 225                               2 * sizeof (short) + 2 * sizeof(struct fbcurpos));
 226         ret |= copy_in_user(&p->size, &argp->size, sizeof(struct fbcurpos));
 227         ret |= copy_in_user(&p->cmap, &argp->cmap, 2 * sizeof(int));
 228         ret |= get_user(addr, &argp->cmap.red);
 229         ret |= put_user(compat_ptr(addr), &p->cmap.red);
 230         ret |= get_user(addr, &argp->cmap.green);
 231         ret |= put_user(compat_ptr(addr), &p->cmap.green);
 232         ret |= get_user(addr, &argp->cmap.blue);
 233         ret |= put_user(compat_ptr(addr), &p->cmap.blue);
 234         ret |= get_user(addr, &argp->mask);
 235         ret |= put_user(compat_ptr(addr), &p->mask);
 236         ret |= get_user(addr, &argp->image);
 237         ret |= put_user(compat_ptr(addr), &p->image);
 238         if (ret)
 239                 return -EFAULT;
 240         return info->fbops->fb_ioctl(info, FBIOSCURSOR, (unsigned long)p);
 241 }
 242 
 243 int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 244 {
 245         switch (cmd) {
 246         case FBIOGTYPE:
 247         case FBIOSATTR:
 248         case FBIOGATTR:
 249         case FBIOSVIDEO:
 250         case FBIOGVIDEO:
 251         case FBIOGCURSOR32:     /* This is not implemented yet.
 252                                    Later it should be converted... */
 253         case FBIOSCURPOS:
 254         case FBIOGCURPOS:
 255         case FBIOGCURMAX:
 256                 return info->fbops->fb_ioctl(info, cmd, arg);
 257         case FBIOPUTCMAP32:
 258                 return fbiogetputcmap(info, cmd, arg);
 259         case FBIOGETCMAP32:
 260                 return fbiogetputcmap(info, cmd, arg);
 261         case FBIOSCURSOR32:
 262                 return fbiogscursor(info, arg);
 263         default:
 264                 return -ENOIOCTLCMD;
 265         }
 266 }
 267 EXPORT_SYMBOL(sbusfb_compat_ioctl);
 268 #endif

/* [<][>][^][v][top][bottom][index][help] */