📄 sbusfb.c
字号:
if (copy_from_user (&f, cursor, sizeof(struct fbcursor))) return -EFAULT; op = f.set; if (op & FB_CUR_SETSHAPE){ if ((u32) f.size.fbx > fb->cursor.hwsize.fbx) return -EINVAL; if ((u32) f.size.fby > fb->cursor.hwsize.fby) return -EINVAL; if (f.size.fbx > 32) bytes = f.size.fby << 3; else bytes = f.size.fby << 2; } if (op & FB_CUR_SETCMAP){ if (f.cmap.index || f.cmap.count != 2) return -EINVAL; if (copy_from_user (red, f.cmap.red, 2) || copy_from_user (green, f.cmap.green, 2) || copy_from_user (blue, f.cmap.blue, 2)) return -EFAULT; } if (op & FB_CUR_SETCMAP) (*fb->setcursormap) (fb, red, green, blue); if (op & FB_CUR_SETSHAPE){ u32 u; fb->cursor.size = f.size; memset ((void *)&fb->cursor.bits, 0, sizeof (fb->cursor.bits)); if (copy_from_user (fb->cursor.bits [0], f.mask, bytes) || copy_from_user (fb->cursor.bits [1], f.image, bytes)) return -EFAULT; if (f.size.fbx <= 32) { u = 0xffffffff << (32 - f.size.fbx); for (i = fb->cursor.size.fby - 1; i >= 0; i--) { fb->cursor.bits [0][i] &= u; fb->cursor.bits [1][i] &= fb->cursor.bits [0][i]; } } else { u = 0xffffffff << (64 - f.size.fbx); for (i = fb->cursor.size.fby - 1; i >= 0; i--) { fb->cursor.bits [0][2*i+1] &= u; fb->cursor.bits [1][2*i] &= fb->cursor.bits [0][2*i]; fb->cursor.bits [1][2*i+1] &= fb->cursor.bits [0][2*i+1]; } } (*fb->setcurshape) (fb); } if (op & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)){ if (op & FB_CUR_SETCUR) fb->cursor.enable = f.enable; if (op & FB_CUR_SETPOS) fb->cursor.cpos = f.pos; if (op & FB_CUR_SETHOT) fb->cursor.chot = f.hot; (*fb->setcursor) (fb); } return 0;}static unsigned char hw_cursor_cmap[2] = { 0, 0xff };static voidsbusfb_cursor_timer_handler(unsigned long dev_addr){ struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)dev_addr; if (!fb->setcursor) return; if (fb->cursor.mode & CURSOR_BLINK) { fb->cursor.enable ^= 1; fb->setcursor(fb); } fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate; add_timer(&fb->cursor.timer);}static void sbusfb_cursor(struct display *p, int mode, int x, int y){ struct fb_info_sbusfb *fb = sbusfbinfod(p); switch (mode) { case CM_ERASE: fb->cursor.mode &= ~CURSOR_BLINK; fb->cursor.enable = 0; (*fb->setcursor)(fb); break; case CM_MOVE: case CM_DRAW: if (fb->cursor.mode & CURSOR_SHAPE) { fb->cursor.size.fbx = fontwidth(p); fb->cursor.size.fby = fontheight(p); fb->cursor.chot.fbx = 0; fb->cursor.chot.fby = 0; fb->cursor.enable = 1; memset (fb->cursor.bits, 0, sizeof (fb->cursor.bits)); fb->cursor.bits[0][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p))); fb->cursor.bits[1][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p))); fb->cursor.bits[0][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p))); fb->cursor.bits[1][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p))); (*fb->setcursormap) (fb, hw_cursor_cmap, hw_cursor_cmap, hw_cursor_cmap); (*fb->setcurshape) (fb); } fb->cursor.mode = CURSOR_BLINK; if (fontwidthlog(p)) fb->cursor.cpos.fbx = (x << fontwidthlog(p)) + fb->x_margin; else fb->cursor.cpos.fbx = (x * fontwidth(p)) + fb->x_margin; if (fontheightlog(p)) fb->cursor.cpos.fby = (y << fontheightlog(p)) + fb->y_margin; else fb->cursor.cpos.fby = (y * fontheight(p)) + fb->y_margin; (*fb->setcursor)(fb); break; }} /* * Get the Colormap */static int sbusfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */ return fb_get_cmap(cmap, kspc, sbusfb_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2); return 0;} /* * Set the Colormap */static int sbusfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err; struct display *disp; if (con >= 0) disp = &fb_display[con]; else disp = info->disp; if (!disp->cmap.len) { /* no colormap allocated? */ if ((err = fb_alloc_cmap(&disp->cmap, 1<<disp->var.bits_per_pixel, 0))) return err; } if (con == currcon) { /* current console? */ err = fb_set_cmap(cmap, kspc, sbusfb_setcolreg, info); if (!err) { struct fb_info_sbusfb *fb = sbusfbinfo(info); if (fb->loadcmap) (*fb->loadcmap)(fb, &fb_display[con], cmap->start, cmap->len); } return err; } else fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); return 0;}static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, int con, struct fb_info *info){ struct fb_info_sbusfb *fb = sbusfbinfo(info); int i; int lastconsole; switch (cmd){ case FBIOGTYPE: /* return frame buffer type */ if (copy_to_user((struct fbtype *)arg, &fb->type, sizeof(struct fbtype))) return -EFAULT; break; case FBIOGATTR: { struct fbgattr *fba = (struct fbgattr *) arg; i = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct fbgattr)); if (i) return i; if (__put_user(fb->emulations[0], &fba->real_type) || __put_user(0, &fba->owner) || __copy_to_user(&fba->fbtype, &fb->type, sizeof(struct fbtype)) || __put_user(0, &fba->sattr.flags) || __put_user(fb->type.fb_type, &fba->sattr.emu_type) || __put_user(-1, &fba->sattr.dev_specific[0])) return -EFAULT; for (i = 0; i < 4; i++) { if (put_user(fb->emulations[i], &fba->emu_types[i])) return -EFAULT; } break; } case FBIOSATTR: i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbsattr)); if (i) return i; return -EINVAL; case FBIOSVIDEO: if (fb->consolecnt) { lastconsole = info->display_fg->vc_num; if (vt_cons[lastconsole]->vc_mode == KD_TEXT) break; } if (get_user(i, (int *)arg)) return -EFAULT; if (i){ if (!fb->blanked || !fb->unblank) break; if (fb->consolecnt || (fb->open && fb->mmaped)) (*fb->unblank)(fb); fb->blanked = 0; } else { if (fb->blanked || !fb->blank) break; (*fb->blank)(fb); fb->blanked = 1; } break; case FBIOGVIDEO: if (put_user(fb->blanked, (int *) arg)) return -EFAULT; break; case FBIOGETCMAP_SPARC: { char *rp, *gp, *bp; int end, count, index; struct fbcmap *cmap; if (!fb->loadcmap) return -EINVAL; i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbcmap)); if (i) return i; cmap = (struct fbcmap *) arg; if (__get_user(count, &cmap->count) || __get_user(index, &cmap->index)) return -EFAULT; if ((index < 0) || (index > 255)) return -EINVAL; if (index + count > 256) count = 256 - index; if (__get_user(rp, &cmap->red) || __get_user(gp, &cmap->green) || __get_user(bp, &cmap->blue)) return -EFAULT; if (verify_area (VERIFY_WRITE, rp, count)) return -EFAULT; if (verify_area (VERIFY_WRITE, gp, count)) return -EFAULT; if (verify_area (VERIFY_WRITE, bp, count)) return -EFAULT; end = index + count; for (i = index; i < end; i++){ if (__put_user(fb->color_map CM(i,0), rp) || __put_user(fb->color_map CM(i,1), gp) || __put_user(fb->color_map CM(i,2), bp)) return -EFAULT; rp++; gp++; bp++; } (*fb->loadcmap)(fb, NULL, index, count); break; } case FBIOPUTCMAP_SPARC: { /* load color map entries */ char *rp, *gp, *bp; int end, count, index; struct fbcmap *cmap; if (!fb->loadcmap) return -EINVAL; i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbcmap)); if (i) return i; cmap = (struct fbcmap *) arg; if (__get_user(count, &cmap->count) || __get_user(index, &cmap->index)) return -EFAULT; if ((index < 0) || (index > 255)) return -EINVAL; if (index + count > 256) count = 256 - index; if (__get_user(rp, &cmap->red) || __get_user(gp, &cmap->green) || __get_user(bp, &cmap->blue)) return -EFAULT; if (verify_area (VERIFY_READ, rp, count)) return -EFAULT; if (verify_area (VERIFY_READ, gp, count)) return -EFAULT; if (verify_area (VERIFY_READ, bp, count)) return -EFAULT; end = index + count; for (i = index; i < end; i++){ if (__get_user(fb->color_map CM(i,0), rp)) return -EFAULT; if (__get_user(fb->color_map CM(i,1), gp)) return -EFAULT; if (__get_user(fb->color_map CM(i,2), bp)) return -EFAULT; rp++; gp++; bp++; } (*fb->loadcmap)(fb, NULL, index, count); break; } case FBIOGCURMAX: { struct fbcurpos *p = (struct fbcurpos *) arg; if (!fb->setcursor) return -EINVAL; if(verify_area (VERIFY_WRITE, p, sizeof (struct fbcurpos))) return -EFAULT; if (__put_user(fb->cursor.hwsize.fbx, &p->fbx) || __put_user(fb->cursor.hwsize.fby, &p->fby)) return -EFAULT; break; } case FBIOSCURSOR: if (!fb->setcursor) return -EINVAL; if (fb->consolecnt) { lastconsole = info->display_fg->vc_num; if (vt_cons[lastconsole]->vc_mode == KD_TEXT) return -EINVAL; /* Don't let graphics programs hide our nice text cursor */ fb->cursor.mode = CURSOR_SHAPE; /* Forget state of our text cursor */ } return sbus_hw_scursor ((struct fbcursor *) arg, fb); case FBIOSCURPOS: if (!fb->setcursor) return -EINVAL; /* Don't let graphics programs move our nice text cursor */ if (fb->consolecnt) { lastconsole = info->display_fg->vc_num; if (vt_cons[lastconsole]->vc_mode == KD_TEXT) return -EINVAL; /* Don't let graphics programs move our nice text cursor */ } if (copy_from_user(&fb->cursor.cpos, (void *)arg, sizeof(struct fbcurpos))) return -EFAULT; (*fb->setcursor) (fb); break; default: if (fb->ioctl) return fb->ioctl(fb, cmd, arg); return -EINVAL; } return 0;} /* * Setup: parse used options */int __init sbusfb_setup(char *options){ char *p; for (p = options;;) { if (!strncmp(p, "nomargins", 9)) { defx_margin = 0; defy_margin = 0; } else if (!strncmp(p, "margins=", 8)) { int i, j; char *q; i = simple_strtoul(p+8,&q,10); if (i >= 0 && *q == 'x') { j = simple_strtoul(q+1,&q,10); if (j >= 0 && (*q == ' ' || !*q)) { defx_margin = i; defy_margin = j; } } } else if (!strncmp(p, "font=", 5)) { int i; for (i = 0; i < sizeof(fontname) - 1; i++) if (p[i+5] == ' ' || !p[i+5]) break; memcpy(fontname, p+5, i); fontname[i] = 0; } else if (!strncmp(p, "noblink", 7)) curblink = 0; while (*p && *p != ' ' && *p != ',') p++; if (*p != ',') break; p++; } return 0;}static int sbusfbcon_switch(int con, struct fb_info *info){ int x_margin, y_margin; struct fb_info_sbusfb *fb = sbusfbinfo(info); int lastconsole; /* Do we have to save the colormap? */ if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, 1, sbusfb_getcolreg, info); if (info->display_fg) { lastconsole = info->display_fg->vc_num; if (lastconsole != con && (fontwidth(&fb_display[lastconsole]) != fontwidth(&fb_display[con]) || fontheight(&fb_display[lastconsole]) != fontheight(&fb_display[con]))) fb->cursor.mode |= CURSOR_SHAPE; } x_margin = (fb_display[con].var.xres_virtual - fb_display[con].var.xres) / 2; y_margin = (fb_display[con].var.yres_virtual - fb_display[con].var.yres) / 2; if (fb->margins) fb->margins(fb, &fb_display[con], x_margin, y_margin); if (fb->graphmode || fb->x_margin != x_margin || fb->y_margin != y_margin) { fb->x_margin = x_margin; fb->y_margin = y_margin; sbusfb_clear_margin(&fb_display[con], 0); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -