📄 imsttfb.c
字号:
{ if (con == currcon) /* current console? */ return fb_get_cmap(cmap, kspc, imsttfb_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else { u_int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); } return 0;}static intimsttfb_set_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err; if (!fb_display[con].cmap.len) { /* no colormap allocated? */ int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0))) return err; } if (con == currcon) /* current console? */ return fb_set_cmap(cmap, kspc, imsttfb_setcolreg, info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0;}#define FBIMSTT_SETREG 0x545401#define FBIMSTT_GETREG 0x545402#define FBIMSTT_SETCMAPREG 0x545403#define FBIMSTT_GETCMAPREG 0x545404#define FBIMSTT_SETIDXREG 0x545405#define FBIMSTT_GETIDXREG 0x545406static intimsttfb_ioctl (struct inode *inode, struct file *file, u_int cmd, u_long arg, int con, struct fb_info *info){ struct fb_info_imstt *p = (struct fb_info_imstt *)info; __u8 idx[2]; __u32 reg[2]; switch (cmd) { case FBIMSTT_SETREG: if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) return -EFAULT; out_le32(&p->dc_regs[reg[0]], reg[1]); return 0; case FBIMSTT_GETREG: if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) return -EFAULT; reg[1] = in_le32(&p->dc_regs[reg[0]]); if (copy_to_user((void *)(arg + 4), ®[1], 4)) return -EFAULT; return 0; case FBIMSTT_SETCMAPREG: if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) return -EFAULT; out_le32(&((u_int *)p->cmap_regs)[reg[0]], reg[1]); return 0; case FBIMSTT_GETCMAPREG: if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) return -EFAULT; reg[1] = in_le32(&((u_int *)p->cmap_regs)[reg[0]]); if (copy_to_user((void *)(arg + 4), ®[1], 4)) return -EFAULT; return 0; case FBIMSTT_SETIDXREG: if (copy_from_user(idx, (void *)arg, 2)) return -EFAULT; p->cmap_regs[PIDXHI] = 0; eieio(); p->cmap_regs[PIDXLO] = idx[0]; eieio(); p->cmap_regs[PIDXDATA] = idx[1]; eieio(); return 0; case FBIMSTT_GETIDXREG: if (copy_from_user(idx, (void *)arg, 1)) return -EFAULT; p->cmap_regs[PIDXHI] = 0; eieio(); p->cmap_regs[PIDXLO] = idx[0]; eieio(); idx[1] = p->cmap_regs[PIDXDATA]; if (copy_to_user((void *)(arg + 1), &idx[1], 1)) return -EFAULT; return 0; default: return -ENOIOCTLCMD; }}static struct pci_device_id imsttfb_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT128, PCI_ANY_ID, PCI_ANY_ID, 0, 0, IBM }, { PCI_VENDOR_ID_IMS, PCI_DEVICE_ID_IMS_TT3D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TVP }, { 0, }};MODULE_DEVICE_TABLE(pci, imsttfb_pci_tbl);static struct pci_driver imsttfb_pci_driver = { name: "imsttfb", id_table: imsttfb_pci_tbl, probe: imsttfb_probe, remove: __devexit_p(imsttfb_remove),};static struct fb_ops imsttfb_ops = { owner: THIS_MODULE, fb_get_fix: imsttfb_get_fix, fb_get_var: imsttfb_get_var, fb_set_var: imsttfb_set_var, fb_get_cmap: imsttfb_get_cmap, fb_set_cmap: imsttfb_set_cmap, fb_pan_display: imsttfb_pan_display, fb_ioctl: imsttfb_ioctl,};static intimsttfbcon_switch (int con, struct fb_info *info){ struct fb_info_imstt *p = (struct fb_info_imstt *)info; struct display *old = &fb_display[currcon], *new = &fb_display[con]; if (old->cmap.len) fb_get_cmap(&old->cmap, 1, imsttfb_getcolreg, info); if (old->conp && old->conp->vc_sw && old->conp->vc_sw->con_cursor) old->conp->vc_sw->con_cursor(old->conp, CM_ERASE); currcon = con; if (old->var.xres != new->var.xres || old->var.yres != new->var.yres || old->var.bits_per_pixel != new->var.bits_per_pixel || old->var.green.length != new->var.green.length || old->var.accel_flags != new->var.accel_flags) { set_dispsw(new, p); if (!compute_imstt_regvals(p, new->var.xres, new->var.yres)) return -1; if (new->var.bits_per_pixel == 16) { if (new->var.green.length == 6) set_565(p); else set_555(p); } set_imstt_regvals(p, new->var.bits_per_pixel); } set_offset(new, p); imsttfbcon_set_font(new, fontwidth(new), fontheight(new)); do_install_cmap(con, info); return 0;}static intimsttfbcon_updatevar (int con, struct fb_info *info){ struct fb_info_imstt *p = (struct fb_info_imstt *)info; struct display *disp = &fb_display[con]; if (con != currcon) goto out; if (p->ramdac == IBM) imsttfbcon_cursor(disp, CM_ERASE, p->cursor.x, p->cursor.y); set_offset(disp, p);out: return 0;}static voidimsttfbcon_blank (int blank, struct fb_info *info){ struct fb_info_imstt *p = (struct fb_info_imstt *)info; __u32 ctrl; ctrl = in_le32(&p->dc_regs[STGCTL]); if (blank > 0) { switch (blank - 1) { case VESA_NO_BLANKING: case VESA_POWERDOWN: ctrl &= ~0x00000380; if (p->ramdac == IBM) { p->cmap_regs[PIDXHI] = 0; eieio(); p->cmap_regs[PIDXLO] = MISCTL2; eieio(); p->cmap_regs[PIDXDATA] = 0x55; eieio(); p->cmap_regs[PIDXLO] = MISCTL1; eieio(); p->cmap_regs[PIDXDATA] = 0x11; eieio(); p->cmap_regs[PIDXLO] = SYNCCTL; eieio(); p->cmap_regs[PIDXDATA] = 0x0f; eieio(); p->cmap_regs[PIDXLO] = PWRMNGMT;eieio(); p->cmap_regs[PIDXDATA] = 0x1f; eieio(); p->cmap_regs[PIDXLO] = CLKCTL; eieio(); p->cmap_regs[PIDXDATA] = 0xc0; } break; case VESA_VSYNC_SUSPEND: ctrl &= ~0x00000020; break; case VESA_HSYNC_SUSPEND: ctrl &= ~0x00000010; break; } } else { if (p->ramdac == IBM) { ctrl |= 0x000017b0; p->cmap_regs[PIDXHI] = 0; eieio(); p->cmap_regs[PIDXLO] = CLKCTL; eieio(); p->cmap_regs[PIDXDATA] = 0x01; eieio(); p->cmap_regs[PIDXLO] = PWRMNGMT;eieio(); p->cmap_regs[PIDXDATA] = 0x00; eieio(); p->cmap_regs[PIDXLO] = SYNCCTL; eieio(); p->cmap_regs[PIDXDATA] = 0x00; eieio(); p->cmap_regs[PIDXLO] = MISCTL1; eieio(); p->cmap_regs[PIDXDATA] = 0x01; eieio(); p->cmap_regs[PIDXLO] = MISCTL2; eieio(); p->cmap_regs[PIDXDATA] = 0x45; eieio(); } else ctrl |= 0x00001780; } out_le32(&p->dc_regs[STGCTL], ctrl);}static void __init init_imstt(struct fb_info_imstt *p){ __u32 i, tmp; __u32 *ip, *end; tmp = in_le32(&p->dc_regs[PRC]); if (p->ramdac == IBM) p->total_vram = (tmp & 0x0004) ? 0x400000 : 0x200000; else p->total_vram = 0x800000; ip = (__u32 *)p->frame_buffer; end = (__u32 *)(p->frame_buffer + p->total_vram); while (ip < end) *ip++ = 0; /* initialize the card */ tmp = in_le32(&p->dc_regs[STGCTL]); out_le32(&p->dc_regs[STGCTL], tmp & ~0x1); out_le32(&p->dc_regs[SSR], 0); /* set default values for DAC registers */ if (p->ramdac == IBM) { p->cmap_regs[PPMASK] = 0xff; eieio(); p->cmap_regs[PIDXHI] = 0; eieio(); for (i = 0; i < sizeof(ibm_initregs) / sizeof(*ibm_initregs); i++) { p->cmap_regs[PIDXLO] = ibm_initregs[i].addr; eieio(); p->cmap_regs[PIDXDATA] = ibm_initregs[i].value; eieio(); } } else { for (i = 0; i < sizeof(tvp_initregs) / sizeof(*tvp_initregs); i++) { p->cmap_regs[TVPADDRW] = tvp_initregs[i].addr; eieio(); p->cmap_regs[TVPIDATA] = tvp_initregs[i].value; eieio(); } }#ifdef CONFIG_ALL_PPC { int vmode = init_vmode, cmode = init_cmode;#ifdef CONFIG_NVRAM /* Attempt to read vmode/cmode from NVRAM */ if (vmode == VMODE_NVRAM) vmode = nvram_read_byte(NV_VMODE); if (cmode == CMODE_NVRAM) cmode = nvram_read_byte(NV_CMODE);#endif /* If we didn't get something from NVRAM, pick a * sane default. */ if (vmode <= 0 || vmode > VMODE_MAX) vmode = VMODE_640_480_67; if (cmode < CMODE_8 || cmode > CMODE_32) cmode = CMODE_8; if (mac_vmode_to_var(vmode, cmode, &p->disp.var)) { p->disp.var.xres = p->disp.var.xres_virtual = INIT_XRES; p->disp.var.yres = p->disp.var.yres_virtual = INIT_YRES; p->disp.var.bits_per_pixel = INIT_BPP; } }#else p->disp.var.xres = p->disp.var.xres_virtual = INIT_XRES; p->disp.var.yres = p->disp.var.yres_virtual = INIT_YRES; p->disp.var.bits_per_pixel = INIT_BPP;#endif if ((p->disp.var.xres * p->disp.var.yres) * (p->disp.var.bits_per_pixel >> 3) > p->total_vram || !(compute_imstt_regvals(p, p->disp.var.xres, p->disp.var.yres))) { printk("imsttfb: %ux%ux%u not supported\n", p->disp.var.xres, p->disp.var.yres, p->disp.var.bits_per_pixel); kfree(p); return; } sprintf(p->fix.id, "IMS TT (%s)", p->ramdac == IBM ? "IBM" : "TVP"); p->fix.smem_start = p->frame_buffer_phys; p->fix.smem_len = p->total_vram; p->fix.mmio_start = p->dc_regs_phys; p->fix.mmio_len = 0x1000; p->fix.accel = FB_ACCEL_IMS_TWINTURBO; p->fix.type = FB_TYPE_PACKED_PIXELS; p->fix.visual = p->disp.var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; p->fix.line_length = p->disp.var.xres * (p->disp.var.bits_per_pixel >> 3); p->fix.xpanstep = 8; p->fix.ypanstep = 1; p->fix.ywrapstep = 0; p->disp.var.accel_flags = noaccel ? 0 : FB_ACCELF_TEXT; set_disp(&p->disp, p); if (!noaccel && p->ramdac == IBM) imstt_cursor_init(p); if (p->disp.var.green.length == 6) set_565(p); else set_555(p); set_imstt_regvals(p, p->disp.var.bits_per_pixel); p->disp.var.pixclock = 1000000 / getclkMHz(p); strcpy(p->info.modename, p->fix.id); strcpy(p->info.fontname, fontname); p->info.node = -1; p->info.fbops = &imsttfb_ops; p->info.disp = &p->disp; p->info.changevar = 0; p->info.switch_con = &imsttfbcon_switch; p->info.updatevar = &imsttfbcon_updatevar; p->info.blank = &imsttfbcon_blank; p->info.flags = FBINFO_FLAG_DEFAULT; for (i = 0; i < 16; i++) { u_int j = color_table[i]; p->palette[i].red = default_red[j]; p->palette[i].green = default_grn[j]; p->palette[i].blue = default_blu[j]; } if (register_framebuffer(&p->info) < 0) { kfree(p); return; } i = GET_FB_IDX(p->info.node); tmp = (in_le32(&p->dc_regs[SSTATUS]) & 0x0f00) >> 8; printk("fb%u: %s frame buffer; %uMB vram; chip version %u\n", i, p->fix.id, p->total_vram >> 20, tmp);#ifdef CONFIG_FB_COMPAT_XPMAC strncpy(display_info.name, "IMS,tt128mb", sizeof(display_info.name)); display_info.fb_address = p->frame_buffer_phys; display_info.cmap_adr_address = p->cmap_regs_phys + PADDRW; display_info.cmap_data_address = p->cmap_regs_phys + PDATA; display_info.disp_reg_address = p->dc_regs_phys; if (!console_fb_info) console_fb_info = &p->info;#endif /* CONFIG_FB_COMPAT_XPMAC */}static int __devinitimsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent){ struct fb_info_imstt *p; unsigned long addr, size; addr = pci_resource_start (pdev, 0); size = pci_resource_len (pdev, 0); p = kmalloc(sizeof(struct fb_info_imstt), GFP_KERNEL); if (!p) { printk(KERN_ERR "imsttfb: Can't allocate memory\n"); return -ENOMEM; } memset(p, 0, sizeof(struct fb_info_imstt)); if (!request_mem_region(addr, size, "imsttfb")) { printk(KERN_ERR "imsttfb: Can't reserve memory region\n"); kfree(p); return -ENODEV; } switch (pdev->device) { case PCI_DEVICE_ID_IMS_TT128: /* IMS,tt128mbA */ p->ramdac = IBM; break; case PCI_DEVICE_ID_IMS_TT3D: /* IMS,tt3d */ p->ramdac = TVP; break; default: printk(KERN_INFO "imsttfb: Device 0x%lx unknown, " "contact maintainer.\n", pdev->device); return -ENODEV; } p->frame_buffer_phys = addr; p->board_size = size; p->frame_buffer = (__u8 *)ioremap(addr, p->ramdac == IBM ? 0x400000 : 0x800000); p->dc_regs_phys = addr + 0x800000; p->dc_regs = (__u32 *)ioremap(addr + 0x800000, 0x1000); p->cmap_regs_phys = addr + 0x840000; p->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000); init_imstt(p); pci_set_drvdata(pdev, p); return 0;}static void __devexitimsttfb_remove(struct pci_dev *pdev){ struct fb_info_imstt *p = pci_get_drvdata(pdev); unregister_framebuffer(&p->info); iounmap(p->cmap_regs); iounmap(p->dc_regs); iounmap(p->frame_buffer); release_mem_region(p->frame_buffer_phys, p->board_size); kfree(p);}#ifndef MODULEint __init imsttfb_setup(char *options){ char *this_opt; if (!options || !*options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { if (!strncmp(this_opt, "font:", 5)) { char *p; int i; p = this_opt + 5; for (i = 0; i < sizeof(fontname) - 1; i++) if (!*p || *p == ' ' || *p == ',') break; memcpy(fontname, this_opt + 5, i); fontname[i] = 0; } else if (!strncmp(this_opt, "noblink", 7)) { curblink = 0; } else if (!strncmp(this_opt, "noaccel", 7)) { noaccel = 1; } else if (!strncmp(this_opt, "inverse", 7)) { inverse = 1; fb_invert_cmaps(); }#if defined(CONFIG_PPC) else if (!strncmp(this_opt, "vmode:", 6)) { int vmode = simple_strtoul(this_opt+6, NULL, 0); if (vmode > 0 && vmode <= VMODE_MAX) init_vmode = vmode; } else if (!strncmp(this_opt, "cmode:", 6)) { int cmode = simple_strtoul(this_opt+6, NULL, 0); switch (cmode) { case CMODE_8: case 8: init_cmode = CMODE_8; break; case CMODE_16: case 15: case 16: init_cmode = CMODE_16; break; case CMODE_32: case 24: case 32: init_cmode = CMODE_32; break; } }#endif } return 0;}#endif /* MODULE */int __init imsttfb_init(void){ return pci_module_init(&imsttfb_pci_driver);} static void __exit imsttfb_exit(void){ pci_unregister_driver(&imsttfb_pci_driver);}#ifdef MODULEMODULE_LICENSE("GPL");module_init(imsttfb_init);#endifmodule_exit(imsttfb_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -