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)
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);
......
......@@ -922,7 +922,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
/* 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);
......
......@@ -2310,7 +2310,7 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
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)
......
......@@ -111,7 +111,7 @@ int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
}
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:
......@@ -143,53 +143,50 @@ void fb_dealloc_cmap(struct fb_cmap *cmap)
* 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;
fromoff = to->start - from->start;
else
tooff = from->start-to->start;
size = to->len-tooff;
tooff = from->start - to->start;
size = to->len - tooff;
if (size > (int) (from->len - fromoff))
size = from->len-fromoff;
size = from->len - fromoff;
if (size <= 0)
return -EINVAL;
size *= sizeof(u16);
switch (fsfromto) {
case 0:
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:
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))
......@@ -199,15 +196,12 @@ int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
if (from->transp && to->transp)
if (copy_to_user(to->transp+tooff, from->transp+fromoff, size))
return -EFAULT;
break;
}
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.
......@@ -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;
u16 *red, *green, *blue, *transp;
u_int hred, hgreen, hblue, htransp;
u_int hred, hgreen, hblue, htransp = 0xffff;
red = cmap->red;
green = cmap->green;
......@@ -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)
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);
hred = *red++;
hgreen = *green++;
hblue = *blue++;
if (transp)
get_user(htransp, transp);
else
htransp = 0xffff;
htransp = *transp++;
if (info->fbops->fb_setcolreg(start++,
hred, hgreen, hblue, htransp,
info))
break;
}
red++;
green++;
blue++;
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++;
if (info->fbops->fb_setcolreg(start++, hred, hgreen, hblue, htransp, info))
return 0;
}
return 0;
}
/**
* fb_default_cmap - get default colormap
* @len: size of palette for a depth
......
......@@ -593,7 +593,7 @@ static void fb_set_logocmap(struct fb_info *info,
palette_cmap.blue[j] = clut[2] << 8 | clut[2];
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)
}
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;
......@@ -1073,7 +1073,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *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) {
info->flags &= ~FBINFO_MISC_MODECHANGEUSER;
......@@ -1102,7 +1102,7 @@ fb_blank(struct fb_info *info, int blank)
cmap.len = info->cmap.len;
} else
cmap = info->cmap;
return fb_set_cmap(&cmap, 1, info);
return fb_set_cmap(&cmap, info);
}
static int
......@@ -1117,7 +1117,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
#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;
......@@ -1145,11 +1145,11 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
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;
......
......@@ -235,7 +235,7 @@ static int offb_blank(int blank, struct fb_info *info)
break;
}
} else
fb_set_cmap(&info->cmap, 1, info);
fb_set_cmap(&info->cmap, info);
return 0;
}
......
......@@ -386,7 +386,7 @@ static int pxafb_blank(int blank, struct fb_info *info)
//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;
......
......@@ -1074,7 +1074,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
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;
......
......@@ -132,7 +132,7 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
return -EFAULT;
cmap.start = index + i;
err = fb_set_cmap(&cmap, 0, info);
err = fb_set_cmap(&cmap, info);
if (err)
return err;
}
......
......@@ -1566,10 +1566,10 @@ sisfb_do_install_cmap(int con, struct fb_info *info)
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);
}
}
......
......@@ -43,7 +43,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
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;
}
......
......@@ -1050,7 +1050,7 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
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);
......
......@@ -851,7 +851,7 @@ struct fb_cmap32 {
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;
......
......@@ -16,7 +16,11 @@
#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 */
......@@ -397,6 +401,36 @@ struct fb_info;
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
*/
......@@ -696,8 +730,10 @@ extern const struct fb_videomode vesa_modes[];
/* 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);
......
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