fb_set_cmap() and fb_copy_cmap() split into kernel and userland versions.
fb_cmap, fb_image and fb_cursor split and annotated.
fixed bug in sbuslib.c that used to call "userland" version of fb_set_cmap()
when kernel one was need (RGB data was already copied into kernel space).
Signed-off-by: Al Viro <viro@parcelfarce.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
wait_for_idle(par);
aty128fb_set_par(info);
fb_pan_display(info, &info->var);
- fb_set_cmap(&info->cmap, 1, info);
+ fb_set_cmap(&info->cmap, info);
/* Refresh */
fb_set_suspend(info, 0);
/* Restore display & engine */
radeonfb_set_par(info);
fb_pan_display(info, &info->var);
- fb_set_cmap(&info->cmap, 1, info);
+ fb_set_cmap(&info->cmap, info);
/* Refresh */
fb_set_suspend(info, 0);
else
palette_cmap.len = 16;
palette_cmap.start = 0;
- return fb_set_cmap(&palette_cmap, 1, info);
+ return fb_set_cmap(&palette_cmap, info);
}
static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
}
cmap->start = 0;
cmap->len = len;
- fb_copy_cmap(fb_default_cmap(len), cmap, 0);
+ fb_copy_cmap(fb_default_cmap(len), cmap);
return 0;
fail:
* fb_copy_cmap - copy a colormap
* @from: frame buffer colormap structure
* @to: frame buffer colormap structure
- * @fsfromto: determine copy method
*
* Copy contents of colormap from @from to @to.
- *
- * @fsfromto accepts the following integer parameters:
- * 0: memcpy function
- * 1: copy_from_user() function to copy from userspace
- * 2: copy_to_user() function to copy to userspace
- *
*/
-int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
+int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to)
{
- int tooff = 0, fromoff = 0;
- int size;
-
- if (to->start > from->start)
- fromoff = to->start-from->start;
- else
- tooff = from->start-to->start;
- size = to->len-tooff;
- if (size > (int) (from->len - fromoff))
- size = from->len-fromoff;
- if (size <= 0)
- return -EINVAL;
- size *= sizeof(u16);
-
- switch (fsfromto) {
- case 0:
+ int tooff = 0, fromoff = 0;
+ int size;
+
+ if (to->start > from->start)
+ fromoff = to->start - from->start;
+ else
+ tooff = from->start - to->start;
+ size = to->len - tooff;
+ if (size > (int) (from->len - fromoff))
+ size = from->len - fromoff;
+ if (size <= 0)
+ return -EINVAL;
+ size *= sizeof(u16);
+
memcpy(to->red+tooff, from->red+fromoff, size);
memcpy(to->green+tooff, from->green+fromoff, size);
memcpy(to->blue+tooff, from->blue+fromoff, size);
if (from->transp && to->transp)
- memcpy(to->transp+tooff, from->transp+fromoff, size);
- break;
- case 1:
- if (copy_from_user(to->red+tooff, from->red+fromoff, size))
- return -EFAULT;
- if (copy_from_user(to->green+tooff, from->green+fromoff, size))
- return -EFAULT;
- if (copy_from_user(to->blue+tooff, from->blue+fromoff, size))
- return -EFAULT;
- if (from->transp && to->transp)
- if (copy_from_user(to->transp+tooff, from->transp+fromoff, size))
- return -EFAULT;
- break;
- case 2:
+ memcpy(to->transp+tooff, from->transp+fromoff, size);
+ return 0;
+}
+
+int fb_cmap_to_user(struct fb_cmap *from, struct fb_cmap_user *to)
+{
+ int tooff = 0, fromoff = 0;
+ int size;
+
+ if (to->start > from->start)
+ fromoff = to->start - from->start;
+ else
+ tooff = from->start - to->start;
+ size = to->len - tooff;
+ if (size > (int) (from->len - fromoff))
+ size = from->len - fromoff;
+ if (size <= 0)
+ return -EINVAL;
+ size *= sizeof(u16);
+
if (copy_to_user(to->red+tooff, from->red+fromoff, size))
return -EFAULT;
if (copy_to_user(to->green+tooff, from->green+fromoff, size))
if (from->transp && to->transp)
if (copy_to_user(to->transp+tooff, from->transp+fromoff, size))
return -EFAULT;
- break;
- }
- return 0;
+ return 0;
}
/**
* fb_set_cmap - set the colormap
* @cmap: frame buffer colormap structure
- * @kspc: boolean, 1 copy local, 0 get_user() function
* @info: frame buffer info structure
*
* Sets the colormap @cmap for a screen of device @info.
*
*/
-int fb_set_cmap(struct fb_cmap *cmap, int kspc, struct fb_info *info)
+int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info)
{
- int i, start;
- u16 *red, *green, *blue, *transp;
- u_int hred, hgreen, hblue, htransp;
-
- red = cmap->red;
- green = cmap->green;
- blue = cmap->blue;
- transp = cmap->transp;
- start = cmap->start;
-
- if (start < 0 || !info->fbops->fb_setcolreg)
- return -EINVAL;
- for (i = 0; i < cmap->len; i++) {
- if (kspc) {
- hred = *red;
- hgreen = *green;
- hblue = *blue;
- htransp = transp ? *transp : 0xffff;
- } else {
- get_user(hred, red);
- get_user(hgreen, green);
- get_user(hblue, blue);
- if (transp)
- get_user(htransp, transp);
- else
- htransp = 0xffff;
+ int i, start;
+ u16 *red, *green, *blue, *transp;
+ u_int hred, hgreen, hblue, htransp = 0xffff;
+
+ red = cmap->red;
+ green = cmap->green;
+ blue = cmap->blue;
+ transp = cmap->transp;
+ start = cmap->start;
+
+ if (start < 0 || !info->fbops->fb_setcolreg)
+ return -EINVAL;
+ for (i = 0; i < cmap->len; i++) {
+ hred = *red++;
+ hgreen = *green++;
+ hblue = *blue++;
+ if (transp)
+ htransp = *transp++;
+ if (info->fbops->fb_setcolreg(start++,
+ hred, hgreen, hblue, htransp,
+ info))
+ break;
}
- red++;
- green++;
- blue++;
- if (transp)
- transp++;
- if (info->fbops->fb_setcolreg(start++, hred, hgreen, hblue, htransp, info))
- return 0;
- }
- return 0;
+ return 0;
}
+int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
+{
+ int i, start;
+ u16 __user *red, *green, *blue, *transp;
+ u_int hred, hgreen, hblue, htransp = 0xffff;
+
+ red = cmap->red;
+ green = cmap->green;
+ blue = cmap->blue;
+ transp = cmap->transp;
+ start = cmap->start;
+
+ if (start < 0 || !info->fbops->fb_setcolreg)
+ return -EINVAL;
+ for (i = 0; i < cmap->len; i++, red++, blue++, green++) {
+ if (get_user(hred, red) ||
+ get_user(hgreen, green) ||
+ get_user(hblue, blue) ||
+ (transp && get_user(htransp, transp)))
+ return -EFAULT;
+ if (info->fbops->fb_setcolreg(start++,
+ hred, hgreen, hblue, htransp,
+ info))
+ return 0;
+ if (transp)
+ transp++;
+ }
+ return 0;
+}
/**
* fb_default_cmap - get default colormap
palette_cmap.blue[j] = clut[2] << 8 | clut[2];
clut += 3;
}
- fb_set_cmap(&palette_cmap, 1, info);
+ fb_set_cmap(&palette_cmap, info);
}
}
}
int
-fb_cursor(struct fb_info *info, struct fb_cursor __user *sprite)
+fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite)
{
- struct fb_cursor cursor_user;
+ struct fb_cursor_user cursor_user;
struct fb_cursor cursor;
char *data = NULL, *mask = NULL;
u16 *red = NULL, *green = NULL, *blue = NULL, *transp = NULL;
fb_pan_display(info, &info->var);
- fb_set_cmap(&info->cmap, 1, info);
+ fb_set_cmap(&info->cmap, info);
if (info->flags & FBINFO_MISC_MODECHANGEUSER) {
info->flags &= ~FBINFO_MISC_MODECHANGEUSER;
cmap.len = info->cmap.len;
} else
cmap = info->cmap;
- return fb_set_cmap(&cmap, 1, info);
+ return fb_set_cmap(&cmap, info);
}
static int
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
struct fb_con2fbmap con2fb;
#endif
- struct fb_cmap cmap;
+ struct fb_cmap_user cmap;
void __user *argp = (void __user *)arg;
int i;
case FBIOPUTCMAP:
if (copy_from_user(&cmap, argp, sizeof(cmap)))
return -EFAULT;
- return (fb_set_cmap(&cmap, 0, info));
+ return (fb_set_user_cmap(&cmap, info));
case FBIOGETCMAP:
if (copy_from_user(&cmap, argp, sizeof(cmap)))
return -EFAULT;
- return (fb_copy_cmap(&info->cmap, &cmap, 2));
+ return fb_cmap_to_user(&info->cmap, &cmap);
case FBIOPAN_DISPLAY:
if (copy_from_user(&var, argp, sizeof(var)))
return -EFAULT;
break;
}
} else
- fb_set_cmap(&info->cmap, 1, info);
+ fb_set_cmap(&info->cmap, info);
return 0;
}
//TODO if (pxafb_blank_helper) pxafb_blank_helper(blank);
if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
- fb_set_cmap(&fbi->fb.cmap, 1, info);
+ fb_set_cmap(&fbi->fb.cmap, info);
pxafb_schedule_work(fbi, C_ENABLE);
}
return 0;
case VESA_NO_BLANKING:
if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
- fb_set_cmap(&fbi->fb.cmap, 1, info);
+ fb_set_cmap(&fbi->fb.cmap, info);
sa1100fb_schedule_work(fbi, C_ENABLE);
}
return 0;
return -EFAULT;
cmap.start = index + i;
- err = fb_set_cmap(&cmap, 0, info);
+ err = fb_set_cmap(&cmap, info);
if (err)
return err;
}
if(con != ivideo->currcon) return;
if(fb_display[con].cmap.len) {
- fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info);
+ fb_set_cmap(&fb_display[con].cmap, sisfb_setcolreg, info);
} else {
int size = sisfb_get_cmap_len(&fb_display[con].var);
- fb_set_cmap(fb_default_cmap(size), 1, sisfb_setcolreg, info);
+ fb_set_cmap(fb_default_cmap(size), sisfb_setcolreg, info);
}
}
info->cursor.image.fg_color = cursor->image.fg_color;
} else {
if (cursor->image.cmap.len)
- fb_copy_cmap(&cursor->image.cmap, &info->cursor.image.cmap, 0);
+ fb_copy_cmap(&cursor->image.cmap, &info->cursor.image.cmap);
}
info->cursor.image.depth = cursor->image.depth;
}
bg_color = ((cmap.red[cmap.start+1] << 16) |
(cmap.green[cmap.start+1] << 8) |
(cmap.blue[cmap.start+1]));
- fb_copy_cmap(&cmap, &info->cursor.image.cmap, 0);
+ fb_copy_cmap(&cmap, &info->cursor.image.cmap);
spin_lock_irqsave(&par->DAClock, flags);
banshee_make_room(par, 2);
tdfx_outl(par, HWCURC0, bg_color);
static int fb_getput_cmap(unsigned int fd, unsigned int cmd, unsigned long arg)
{
- struct fb_cmap __user *cmap;
+ struct fb_cmap_user __user *cmap;
struct fb_cmap32 __user *cmap32;
__u32 data;
int err;
#define FBIOGETCMAP 0x4604
#define FBIOPUTCMAP 0x4605
#define FBIOPAN_DISPLAY 0x4606
+#ifdef __KERNEL__
+#define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor_user)
+#else
#define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor)
+#endif
/* 0x4607-0x460B are defined below */
/* #define FBIOGET_MONITORSPEC 0x460C */
/* #define FBIOPUT_MONITORSPEC 0x460D */
struct device;
struct file;
+struct fb_cmap_user {
+ __u32 start; /* First entry */
+ __u32 len; /* Number of entries */
+ __u16 __user *red; /* Red values */
+ __u16 __user *green;
+ __u16 __user *blue;
+ __u16 __user *transp; /* transparency, can be NULL */
+};
+
+struct fb_image_user {
+ __u32 dx; /* Where to place image */
+ __u32 dy;
+ __u32 width; /* Size of image */
+ __u32 height;
+ __u32 fg_color; /* Only used when a mono bitmap */
+ __u32 bg_color;
+ __u8 depth; /* Depth of the image */
+ const char __user *data; /* Pointer to image data */
+ struct fb_cmap_user cmap; /* color map info */
+};
+
+struct fb_cursor_user {
+ __u16 set; /* what to set */
+ __u16 enable; /* cursor on/off */
+ __u16 rop; /* bitop operation */
+ const char __user *mask; /* cursor mask bits */
+ struct fbcurpos hot; /* cursor hot spot */
+ struct fb_image_user image; /* Cursor image */
+};
+
/*
* Register/unregister for framebuffer events
*/
/* drivers/video/fbcmap.c */
extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
extern void fb_dealloc_cmap(struct fb_cmap *cmap);
-extern int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);
-extern int fb_set_cmap(struct fb_cmap *cmap, int kspc, struct fb_info *fb_info);
+extern int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to);
+extern int fb_cmap_to_user(struct fb_cmap *from, struct fb_cmap_user *to);
+extern int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *fb_info);
+extern int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *fb_info);
extern struct fb_cmap *fb_default_cmap(int len);
extern void fb_invert_cmaps(void);