Commit 53699287 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] cmap annotations

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: default avatarAl Viro <viro@parcelfarce.linux.org.uk>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent cfd3aaa3
...@@ -2419,7 +2419,7 @@ static int aty128_pci_resume(struct pci_dev *pdev) ...@@ -2419,7 +2419,7 @@ static int aty128_pci_resume(struct pci_dev *pdev)
wait_for_idle(par); wait_for_idle(par);
aty128fb_set_par(info); aty128fb_set_par(info);
fb_pan_display(info, &info->var); fb_pan_display(info, &info->var);
fb_set_cmap(&info->cmap, 1, info); fb_set_cmap(&info->cmap, info);
/* Refresh */ /* Refresh */
fb_set_suspend(info, 0); fb_set_suspend(info, 0);
......
...@@ -922,7 +922,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev) ...@@ -922,7 +922,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
/* Restore display & engine */ /* Restore display & engine */
radeonfb_set_par(info); radeonfb_set_par(info);
fb_pan_display(info, &info->var); fb_pan_display(info, &info->var);
fb_set_cmap(&info->cmap, 1, info); fb_set_cmap(&info->cmap, info);
/* Refresh */ /* Refresh */
fb_set_suspend(info, 0); fb_set_suspend(info, 0);
......
...@@ -2310,7 +2310,7 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table) ...@@ -2310,7 +2310,7 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
else else
palette_cmap.len = 16; palette_cmap.len = 16;
palette_cmap.start = 0; 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) static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
......
...@@ -111,7 +111,7 @@ int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp) ...@@ -111,7 +111,7 @@ int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
} }
cmap->start = 0; cmap->start = 0;
cmap->len = len; cmap->len = len;
fb_copy_cmap(fb_default_cmap(len), cmap, 0); fb_copy_cmap(fb_default_cmap(len), cmap);
return 0; return 0;
fail: fail:
...@@ -143,53 +143,50 @@ void fb_dealloc_cmap(struct fb_cmap *cmap) ...@@ -143,53 +143,50 @@ void fb_dealloc_cmap(struct fb_cmap *cmap)
* fb_copy_cmap - copy a colormap * fb_copy_cmap - copy a colormap
* @from: frame buffer colormap structure * @from: frame buffer colormap structure
* @to: frame buffer colormap structure * @to: frame buffer colormap structure
* @fsfromto: determine copy method
* *
* Copy contents of colormap from @from to @to. * 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 tooff = 0, fromoff = 0;
int size; int size;
if (to->start > from->start) if (to->start > from->start)
fromoff = to->start-from->start; fromoff = to->start - from->start;
else else
tooff = from->start-to->start; tooff = from->start - to->start;
size = to->len-tooff; size = to->len - tooff;
if (size > (int) (from->len - fromoff)) if (size > (int) (from->len - fromoff))
size = from->len-fromoff; size = from->len - fromoff;
if (size <= 0) if (size <= 0)
return -EINVAL; return -EINVAL;
size *= sizeof(u16); size *= sizeof(u16);
switch (fsfromto) {
case 0:
memcpy(to->red+tooff, from->red+fromoff, size); memcpy(to->red+tooff, from->red+fromoff, size);
memcpy(to->green+tooff, from->green+fromoff, size); memcpy(to->green+tooff, from->green+fromoff, size);
memcpy(to->blue+tooff, from->blue+fromoff, size); memcpy(to->blue+tooff, from->blue+fromoff, size);
if (from->transp && to->transp) if (from->transp && to->transp)
memcpy(to->transp+tooff, from->transp+fromoff, size); memcpy(to->transp+tooff, from->transp+fromoff, size);
break; return 0;
case 1: }
if (copy_from_user(to->red+tooff, from->red+fromoff, size))
return -EFAULT; int fb_cmap_to_user(struct fb_cmap *from, struct fb_cmap_user *to)
if (copy_from_user(to->green+tooff, from->green+fromoff, size)) {
return -EFAULT; int tooff = 0, fromoff = 0;
if (copy_from_user(to->blue+tooff, from->blue+fromoff, size)) int size;
return -EFAULT;
if (from->transp && to->transp) if (to->start > from->start)
if (copy_from_user(to->transp+tooff, from->transp+fromoff, size)) fromoff = to->start - from->start;
return -EFAULT; else
break; tooff = from->start - to->start;
case 2: 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)) if (copy_to_user(to->red+tooff, from->red+fromoff, size))
return -EFAULT; return -EFAULT;
if (copy_to_user(to->green+tooff, from->green+fromoff, size)) if (copy_to_user(to->green+tooff, from->green+fromoff, size))
...@@ -199,15 +196,12 @@ int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto) ...@@ -199,15 +196,12 @@ int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
if (from->transp && to->transp) if (from->transp && to->transp)
if (copy_to_user(to->transp+tooff, from->transp+fromoff, size)) if (copy_to_user(to->transp+tooff, from->transp+fromoff, size))
return -EFAULT; return -EFAULT;
break;
}
return 0; return 0;
} }
/** /**
* fb_set_cmap - set the colormap * fb_set_cmap - set the colormap
* @cmap: frame buffer colormap structure * @cmap: frame buffer colormap structure
* @kspc: boolean, 1 copy local, 0 get_user() function
* @info: frame buffer info structure * @info: frame buffer info structure
* *
* Sets the colormap @cmap for a screen of device @info. * Sets the colormap @cmap for a screen of device @info.
...@@ -216,11 +210,11 @@ int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto) ...@@ -216,11 +210,11 @@ int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
* *
*/ */
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; int i, start;
u16 *red, *green, *blue, *transp; u16 *red, *green, *blue, *transp;
u_int hred, hgreen, hblue, htransp; u_int hred, hgreen, hblue, htransp = 0xffff;
red = cmap->red; red = cmap->red;
green = cmap->green; green = cmap->green;
...@@ -231,32 +225,49 @@ int fb_set_cmap(struct fb_cmap *cmap, int kspc, struct fb_info *info) ...@@ -231,32 +225,49 @@ int fb_set_cmap(struct fb_cmap *cmap, int kspc, struct fb_info *info)
if (start < 0 || !info->fbops->fb_setcolreg) if (start < 0 || !info->fbops->fb_setcolreg)
return -EINVAL; return -EINVAL;
for (i = 0; i < cmap->len; i++) { for (i = 0; i < cmap->len; i++) {
if (kspc) { hred = *red++;
hred = *red; hgreen = *green++;
hgreen = *green; hblue = *blue++;
hblue = *blue;
htransp = transp ? *transp : 0xffff;
} else {
get_user(hred, red);
get_user(hgreen, green);
get_user(hblue, blue);
if (transp) if (transp)
get_user(htransp, transp); htransp = *transp++;
else if (info->fbops->fb_setcolreg(start++,
htransp = 0xffff; hred, hgreen, hblue, htransp,
info))
break;
} }
red++; return 0;
green++; }
blue++;
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) if (transp)
transp++; transp++;
if (info->fbops->fb_setcolreg(start++, hred, hgreen, hblue, htransp, info))
return 0;
} }
return 0; return 0;
} }
/** /**
* fb_default_cmap - get default colormap * fb_default_cmap - get default colormap
* @len: size of palette for a depth * @len: size of palette for a depth
......
...@@ -593,7 +593,7 @@ static void fb_set_logocmap(struct fb_info *info, ...@@ -593,7 +593,7 @@ static void fb_set_logocmap(struct fb_info *info,
palette_cmap.blue[j] = clut[2] << 8 | clut[2]; palette_cmap.blue[j] = clut[2] << 8 | clut[2];
clut += 3; clut += 3;
} }
fb_set_cmap(&palette_cmap, 1, info); fb_set_cmap(&palette_cmap, info);
} }
} }
...@@ -938,9 +938,9 @@ fb_load_cursor_image(struct fb_info *info) ...@@ -938,9 +938,9 @@ fb_load_cursor_image(struct fb_info *info)
} }
int 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; struct fb_cursor cursor;
char *data = NULL, *mask = NULL; char *data = NULL, *mask = NULL;
u16 *red = NULL, *green = NULL, *blue = NULL, *transp = NULL; u16 *red = NULL, *green = NULL, *blue = NULL, *transp = NULL;
...@@ -1073,7 +1073,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) ...@@ -1073,7 +1073,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
fb_pan_display(info, &info->var); 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) { if (info->flags & FBINFO_MISC_MODECHANGEUSER) {
info->flags &= ~FBINFO_MISC_MODECHANGEUSER; info->flags &= ~FBINFO_MISC_MODECHANGEUSER;
...@@ -1102,7 +1102,7 @@ fb_blank(struct fb_info *info, int blank) ...@@ -1102,7 +1102,7 @@ fb_blank(struct fb_info *info, int blank)
cmap.len = info->cmap.len; cmap.len = info->cmap.len;
} else } else
cmap = info->cmap; cmap = info->cmap;
return fb_set_cmap(&cmap, 1, info); return fb_set_cmap(&cmap, info);
} }
static int static int
...@@ -1117,7 +1117,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -1117,7 +1117,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
#ifdef CONFIG_FRAMEBUFFER_CONSOLE #ifdef CONFIG_FRAMEBUFFER_CONSOLE
struct fb_con2fbmap con2fb; struct fb_con2fbmap con2fb;
#endif #endif
struct fb_cmap cmap; struct fb_cmap_user cmap;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int i; int i;
...@@ -1145,11 +1145,11 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -1145,11 +1145,11 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case FBIOPUTCMAP: case FBIOPUTCMAP:
if (copy_from_user(&cmap, argp, sizeof(cmap))) if (copy_from_user(&cmap, argp, sizeof(cmap)))
return -EFAULT; return -EFAULT;
return (fb_set_cmap(&cmap, 0, info)); return (fb_set_user_cmap(&cmap, info));
case FBIOGETCMAP: case FBIOGETCMAP:
if (copy_from_user(&cmap, argp, sizeof(cmap))) if (copy_from_user(&cmap, argp, sizeof(cmap)))
return -EFAULT; return -EFAULT;
return (fb_copy_cmap(&info->cmap, &cmap, 2)); return fb_cmap_to_user(&info->cmap, &cmap);
case FBIOPAN_DISPLAY: case FBIOPAN_DISPLAY:
if (copy_from_user(&var, argp, sizeof(var))) if (copy_from_user(&var, argp, sizeof(var)))
return -EFAULT; return -EFAULT;
......
...@@ -235,7 +235,7 @@ static int offb_blank(int blank, struct fb_info *info) ...@@ -235,7 +235,7 @@ static int offb_blank(int blank, struct fb_info *info)
break; break;
} }
} else } else
fb_set_cmap(&info->cmap, 1, info); fb_set_cmap(&info->cmap, info);
return 0; return 0;
} }
......
...@@ -386,7 +386,7 @@ static int pxafb_blank(int blank, struct fb_info *info) ...@@ -386,7 +386,7 @@ static int pxafb_blank(int blank, struct fb_info *info)
//TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); //TODO if (pxafb_blank_helper) pxafb_blank_helper(blank);
if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR || if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
fbi->fb.fix.visual == FB_VISUAL_STATIC_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); pxafb_schedule_work(fbi, C_ENABLE);
} }
return 0; return 0;
......
...@@ -1074,7 +1074,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info) ...@@ -1074,7 +1074,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
case VESA_NO_BLANKING: case VESA_NO_BLANKING:
if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR || if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
fbi->fb.fix.visual == FB_VISUAL_STATIC_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); sa1100fb_schedule_work(fbi, C_ENABLE);
} }
return 0; return 0;
......
...@@ -132,7 +132,7 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, ...@@ -132,7 +132,7 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
return -EFAULT; return -EFAULT;
cmap.start = index + i; cmap.start = index + i;
err = fb_set_cmap(&cmap, 0, info); err = fb_set_cmap(&cmap, info);
if (err) if (err)
return err; return err;
} }
......
...@@ -1566,10 +1566,10 @@ sisfb_do_install_cmap(int con, struct fb_info *info) ...@@ -1566,10 +1566,10 @@ sisfb_do_install_cmap(int con, struct fb_info *info)
if(con != ivideo->currcon) return; if(con != ivideo->currcon) return;
if(fb_display[con].cmap.len) { 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 { } else {
int size = sisfb_get_cmap_len(&fb_display[con].var); 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);
} }
} }
......
...@@ -43,7 +43,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) ...@@ -43,7 +43,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
info->cursor.image.fg_color = cursor->image.fg_color; info->cursor.image.fg_color = cursor->image.fg_color;
} else { } else {
if (cursor->image.cmap.len) 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; info->cursor.image.depth = cursor->image.depth;
} }
......
...@@ -1050,7 +1050,7 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) ...@@ -1050,7 +1050,7 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
bg_color = ((cmap.red[cmap.start+1] << 16) | bg_color = ((cmap.red[cmap.start+1] << 16) |
(cmap.green[cmap.start+1] << 8) | (cmap.green[cmap.start+1] << 8) |
(cmap.blue[cmap.start+1])); (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); spin_lock_irqsave(&par->DAClock, flags);
banshee_make_room(par, 2); banshee_make_room(par, 2);
tdfx_outl(par, HWCURC0, bg_color); tdfx_outl(par, HWCURC0, bg_color);
......
...@@ -851,7 +851,7 @@ struct fb_cmap32 { ...@@ -851,7 +851,7 @@ struct fb_cmap32 {
static int fb_getput_cmap(unsigned int fd, unsigned int cmd, unsigned long arg) 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; struct fb_cmap32 __user *cmap32;
__u32 data; __u32 data;
int err; int err;
......
...@@ -16,7 +16,11 @@ ...@@ -16,7 +16,11 @@
#define FBIOGETCMAP 0x4604 #define FBIOGETCMAP 0x4604
#define FBIOPUTCMAP 0x4605 #define FBIOPUTCMAP 0x4605
#define FBIOPAN_DISPLAY 0x4606 #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) #define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor)
#endif
/* 0x4607-0x460B are defined below */ /* 0x4607-0x460B are defined below */
/* #define FBIOGET_MONITORSPEC 0x460C */ /* #define FBIOGET_MONITORSPEC 0x460C */
/* #define FBIOPUT_MONITORSPEC 0x460D */ /* #define FBIOPUT_MONITORSPEC 0x460D */
...@@ -397,6 +401,36 @@ struct fb_info; ...@@ -397,6 +401,36 @@ struct fb_info;
struct device; struct device;
struct file; 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 * Register/unregister for framebuffer events
*/ */
...@@ -696,8 +730,10 @@ extern const struct fb_videomode vesa_modes[]; ...@@ -696,8 +730,10 @@ extern const struct fb_videomode vesa_modes[];
/* drivers/video/fbcmap.c */ /* drivers/video/fbcmap.c */
extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp); extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
extern void fb_dealloc_cmap(struct fb_cmap *cmap); 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_copy_cmap(struct fb_cmap *from, struct fb_cmap *to);
extern int fb_set_cmap(struct fb_cmap *cmap, int kspc, struct fb_info *fb_info); 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 struct fb_cmap *fb_default_cmap(int len);
extern void fb_invert_cmaps(void); extern void fb_invert_cmaps(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment