📄 imsttfb.c
字号:
#if 0static intimsttfb_load_cursor_image(struct imstt_par *par, int width, int height, __u8 fgc){ u_int x, y; if (width > 32 || height > 32) return -EINVAL; if (par->ramdac == IBM) { par->cmap_regs[PIDXHI] = 1; eieio(); for (x = 0; x < 0x100; x++) { par->cmap_regs[PIDXLO] = x; eieio(); par->cmap_regs[PIDXDATA] = 0x00; eieio(); } par->cmap_regs[PIDXHI] = 1; eieio(); for (y = 0; y < height; y++) for (x = 0; x < width >> 2; x++) { par->cmap_regs[PIDXLO] = x + y * 8; eieio(); par->cmap_regs[PIDXDATA] = 0xff; eieio(); } par->cmap_regs[PIDXHI] = 0; eieio(); par->cmap_regs[PIDXLO] = CURS1R; eieio(); par->cmap_regs[PIDXDATA] = fgc; eieio(); par->cmap_regs[PIDXLO] = CURS1G; eieio(); par->cmap_regs[PIDXDATA] = fgc; eieio(); par->cmap_regs[PIDXLO] = CURS1B; eieio(); par->cmap_regs[PIDXDATA] = fgc; eieio(); par->cmap_regs[PIDXLO] = CURS2R; eieio(); par->cmap_regs[PIDXDATA] = fgc; eieio(); par->cmap_regs[PIDXLO] = CURS2G; eieio(); par->cmap_regs[PIDXDATA] = fgc; eieio(); par->cmap_regs[PIDXLO] = CURS2B; eieio(); par->cmap_regs[PIDXDATA] = fgc; eieio(); par->cmap_regs[PIDXLO] = CURS3R; eieio(); par->cmap_regs[PIDXDATA] = fgc; eieio(); par->cmap_regs[PIDXLO] = CURS3G; eieio(); par->cmap_regs[PIDXDATA] = fgc; eieio(); par->cmap_regs[PIDXLO] = CURS3B; eieio(); par->cmap_regs[PIDXDATA] = fgc; eieio(); } else { par->cmap_regs[TVPADDRW] = TVPIRICC; eieio(); par->cmap_regs[TVPIDATA] &= 0x03; eieio(); par->cmap_regs[TVPADDRW] = 0; eieio(); for (x = 0; x < 0x200; x++) { par->cmap_regs[TVPCRDAT] = 0x00; eieio(); } for (x = 0; x < 0x200; x++) { par->cmap_regs[TVPCRDAT] = 0xff; eieio(); } par->cmap_regs[TVPADDRW] = TVPIRICC; eieio(); par->cmap_regs[TVPIDATA] &= 0x03; eieio(); for (y = 0; y < height; y++) for (x = 0; x < width >> 3; x++) { par->cmap_regs[TVPADDRW] = x + y * 8; eieio(); par->cmap_regs[TVPCRDAT] = 0xff; eieio(); } par->cmap_regs[TVPADDRW] = TVPIRICC; eieio(); par->cmap_regs[TVPIDATA] |= 0x08; eieio(); for (y = 0; y < height; y++) for (x = 0; x < width >> 3; x++) { par->cmap_regs[TVPADDRW] = x + y * 8; eieio(); par->cmap_regs[TVPCRDAT] = 0xff; eieio(); } par->cmap_regs[TVPCADRW] = 0x00; eieio(); for (x = 0; x < 12; x++) { par->cmap_regs[TVPCDATA] = fgc; eieio(); } } return 1;}static voidimstt_set_cursor(struct imstt_par *par, struct fb_image *d, int on){ if (par->ramdac == IBM) { par->cmap_regs[PIDXHI] = 0; eieio(); if (!on) { par->cmap_regs[PIDXLO] = CURSCTL; eieio(); par->cmap_regs[PIDXDATA] = 0x00; eieio(); } else { par->cmap_regs[PIDXLO] = CURSXHI; eieio(); par->cmap_regs[PIDXDATA] = d->dx >> 8; eieio(); par->cmap_regs[PIDXLO] = CURSXLO; eieio(); par->cmap_regs[PIDXDATA] = d->dx & 0xff;eieio(); par->cmap_regs[PIDXLO] = CURSYHI; eieio(); par->cmap_regs[PIDXDATA] = d->dy >> 8; eieio(); par->cmap_regs[PIDXLO] = CURSYLO; eieio(); par->cmap_regs[PIDXDATA] = d->dy & 0xff;eieio(); par->cmap_regs[PIDXLO] = CURSCTL; eieio(); par->cmap_regs[PIDXDATA] = 0x02; eieio(); } } else { if (!on) { par->cmap_regs[TVPADDRW] = TVPIRICC; eieio(); par->cmap_regs[TVPIDATA] = 0x00; eieio(); } else { __u16 x = d->dx + 0x40, y = d->dy + 0x40; par->cmap_regs[TVPCXPOH] = x >> 8; eieio(); par->cmap_regs[TVPCXPOL] = x & 0xff; eieio(); par->cmap_regs[TVPCYPOH] = y >> 8; eieio(); par->cmap_regs[TVPCYPOL] = y & 0xff; eieio(); par->cmap_regs[TVPADDRW] = TVPIRICC; eieio(); par->cmap_regs[TVPIDATA] = 0x02; eieio(); } }}static int imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor){ struct imstt_par *par = info->par; u32 flags = cursor->set, fg, bg, xx, yy; if (cursor->dest == NULL && cursor->rop == ROP_XOR) return 1; imstt_set_cursor(info, cursor, 0); if (flags & FB_CUR_SETPOS) { xx = cursor->image.dx - info->var.xoffset; yy = cursor->image.dy - info->var.yoffset; } if (flags & FB_CUR_SETSIZE) { } if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP)) { int fg_idx = cursor->image.fg_color; int width = (cursor->image.width+7)/8; u8 *dat = (u8 *) cursor->image.data; u8 *dst = (u8 *) cursor->dest; u8 *msk = (u8 *) cursor->mask; switch (cursor->rop) { case ROP_XOR: for (i = 0; i < cursor->image.height; i++) { for (j = 0; j < width; j++) { d_idx = i * MAX_CURS/8 + j; data[d_idx] = byte_rev[dat[s_idx] ^ dst[s_idx]]; mask[d_idx] = byte_rev[msk[s_idx]]; s_idx++; } } break; case ROP_COPY: default: for (i = 0; i < cursor->image.height; i++) { for (j = 0; j < width; j++) { d_idx = i * MAX_CURS/8 + j; data[d_idx] = byte_rev[dat[s_idx]]; mask[d_idx] = byte_rev[msk[s_idx]]; s_idx++; } } break; } fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) | ((info->cmap.green[fg_idx] & 0xf8) << 2) | ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15; imsttfb_load_cursor_image(par, xx, yy, fgc); } if (cursor->enable) imstt_set_cursor(info, cursor, 1); return 0;}#endif#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 fb_info *info, u_int cmd, u_long arg){ struct imstt_par *par = info->par; void __user *argp = (void __user *)arg; __u32 reg[2]; __u8 idx[2]; switch (cmd) { case FBIMSTT_SETREG: if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) return -EFAULT; write_reg_le32(par->dc_regs, reg[0], reg[1]); return 0; case FBIMSTT_GETREG: if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) return -EFAULT; reg[1] = read_reg_le32(par->dc_regs, reg[0]); if (copy_to_user((void __user *)(arg + 4), ®[1], 4)) return -EFAULT; return 0; case FBIMSTT_SETCMAPREG: if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) return -EFAULT; write_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0], reg[1]); return 0; case FBIMSTT_GETCMAPREG: if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0])) return -EFAULT; reg[1] = read_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0]); if (copy_to_user((void __user *)(arg + 4), ®[1], 4)) return -EFAULT; return 0; case FBIMSTT_SETIDXREG: if (copy_from_user(idx, argp, 2)) return -EFAULT; par->cmap_regs[PIDXHI] = 0; eieio(); par->cmap_regs[PIDXLO] = idx[0]; eieio(); par->cmap_regs[PIDXDATA] = idx[1]; eieio(); return 0; case FBIMSTT_GETIDXREG: if (copy_from_user(idx, argp, 1)) return -EFAULT; par->cmap_regs[PIDXHI] = 0; eieio(); par->cmap_regs[PIDXLO] = idx[0]; eieio(); idx[1] = par->cmap_regs[PIDXDATA]; if (copy_to_user((void __user *)(arg + 1), &idx[1], 1)) return -EFAULT; return 0; default: return -ENOIOCTLCMD; }}static struct pci_device_id imsttfb_pci_tbl[] = { { 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_check_var = imsttfb_check_var, .fb_set_par = imsttfb_set_par, .fb_setcolreg = imsttfb_setcolreg, .fb_pan_display = imsttfb_pan_display, .fb_blank = imsttfb_blank, .fb_fillrect = imsttfb_fillrect, .fb_copyarea = imsttfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_ioctl = imsttfb_ioctl,};static void __devinitinit_imstt(struct fb_info *info){ struct imstt_par *par = info->par; __u32 i, tmp, *ip, *end; tmp = read_reg_le32(par->dc_regs, PRC); if (par->ramdac == IBM) info->fix.smem_len = (tmp & 0x0004) ? 0x400000 : 0x200000; else info->fix.smem_len = 0x800000; ip = (__u32 *)info->screen_base; end = (__u32 *)(info->screen_base + info->fix.smem_len); while (ip < end) *ip++ = 0; /* initialize the card */ tmp = read_reg_le32(par->dc_regs, STGCTL); write_reg_le32(par->dc_regs, STGCTL, tmp & ~0x1); write_reg_le32(par->dc_regs, SSR, 0); /* set default values for DAC registers */ if (par->ramdac == IBM) { par->cmap_regs[PPMASK] = 0xff; eieio(); par->cmap_regs[PIDXHI] = 0; eieio(); for (i = 0; i < ARRAY_SIZE(ibm_initregs); i++) { par->cmap_regs[PIDXLO] = ibm_initregs[i].addr; eieio(); par->cmap_regs[PIDXDATA] = ibm_initregs[i].value; eieio(); } } else { for (i = 0; i < ARRAY_SIZE(tvp_initregs); i++) { par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr; eieio(); par->cmap_regs[TVPIDATA] = tvp_initregs[i].value; eieio(); } }#if USE_NV_MODES && defined(CONFIG_PPC32) { int vmode = init_vmode, cmode = init_cmode; if (vmode == -1) { vmode = nvram_read_byte(NV_VMODE); if (vmode <= 0 || vmode > VMODE_MAX) vmode = VMODE_640_480_67; } if (cmode == -1) { cmode = nvram_read_byte(NV_CMODE); if (cmode < CMODE_8 || cmode > CMODE_32) cmode = CMODE_8; } if (mac_vmode_to_var(vmode, cmode, &info->var)) { info->var.xres = info->var.xres_virtual = INIT_XRES; info->var.yres = info->var.yres_virtual = INIT_YRES; info->var.bits_per_pixel = INIT_BPP; } }#else info->var.xres = info->var.xres_virtual = INIT_XRES; info->var.yres = info->var.yres_virtual = INIT_YRES; info->var.bits_per_pixel = INIT_BPP;#endif if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >> 3) > info->fix.smem_len || !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) { printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel); framebuffer_release(info); return; } sprintf(info->fix.id, "IMS TT (%s)", par->ramdac == IBM ? "IBM" : "TVP"); info->fix.mmio_len = 0x1000; info->fix.accel = FB_ACCEL_IMS_TWINTURBO; info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = info->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; info->fix.line_length = info->var.xres * (info->var.bits_per_pixel >> 3); info->fix.xpanstep = 8; info->fix.ypanstep = 1; info->fix.ywrapstep = 0; info->var.accel_flags = FB_ACCELF_TEXT;// if (par->ramdac == IBM)// imstt_cursor_init(info); if (info->var.green.length == 6) set_565(par); else set_555(par); set_imstt_regvals(info, info->var.bits_per_pixel); info->var.pixclock = 1000000 / getclkMHz(par); info->fbops = &imsttfb_ops; info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_YPAN; fb_alloc_cmap(&info->cmap, 0, 0); if (register_framebuffer(info) < 0) { framebuffer_release(info); return; } tmp = (read_reg_le32(par->dc_regs, SSTATUS) & 0x0f00) >> 8; printk("fb%u: %s frame buffer; %uMB vram; chip version %u\n", info->node, info->fix.id, info->fix.smem_len >> 20, tmp);}static int __devinitimsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent){ unsigned long addr, size; struct imstt_par *par; struct fb_info *info;#ifdef CONFIG_PPC_OF struct device_node *dp; dp = pci_device_to_OF_node(pdev); if(dp) printk(KERN_INFO "%s: OF name %s\n",__func__, dp->name); else printk(KERN_ERR "imsttfb: no OF node for pci device\n");#endif /* CONFIG_PPC_OF */ info = framebuffer_alloc(sizeof(struct imstt_par), &pdev->dev); if (!info) { printk(KERN_ERR "imsttfb: Can't allocate memory\n"); return -ENOMEM; } par = info->par; addr = pci_resource_start (pdev, 0); size = pci_resource_len (pdev, 0); if (!request_mem_region(addr, size, "imsttfb")) { printk(KERN_ERR "imsttfb: Can't reserve memory region\n"); framebuffer_release(info); return -ENODEV; } switch (pdev->device) { case PCI_DEVICE_ID_IMS_TT128: /* IMS,tt128mbA */ par->ramdac = IBM;#ifdef CONFIG_PPC_OF if (dp && ((strcmp(dp->name, "IMS,tt128mb8") == 0) || (strcmp(dp->name, "IMS,tt128mb8A") == 0))) par->ramdac = TVP;#endif /* CONFIG_PPC_OF */ break; case PCI_DEVICE_ID_IMS_TT3D: /* IMS,tt3d */ par->ramdac = TVP; break; default: printk(KERN_INFO "imsttfb: Device 0x%x unknown, " "contact maintainer.\n", pdev->device); release_mem_region(addr, size); framebuffer_release(info); return -ENODEV; } info->fix.smem_start = addr; info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ? 0x400000 : 0x800000); info->fix.mmio_start = addr + 0x800000; par->dc_regs = ioremap(addr + 0x800000, 0x1000); par->cmap_regs_phys = addr + 0x840000; par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000); info->pseudo_palette = par->palette; init_imstt(info); pci_set_drvdata(pdev, info); return 0;}static void __devexitimsttfb_remove(struct pci_dev *pdev){ struct fb_info *info = pci_get_drvdata(pdev); struct imstt_par *par = info->par; int size = pci_resource_len(pdev, 0); unregister_framebuffer(info); iounmap(par->cmap_regs); iounmap(par->dc_regs); iounmap(info->screen_base); release_mem_region(info->fix.smem_start, size); framebuffer_release(info);}#ifndef MODULEstatic int __initimsttfb_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, "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 */static int __init imsttfb_init(void){#ifndef MODULE char *option = NULL; if (fb_get_options("imsttfb", &option)) return -ENODEV; imsttfb_setup(option);#endif return pci_register_driver(&imsttfb_pci_driver);} static void __exit imsttfb_exit(void){ pci_unregister_driver(&imsttfb_pci_driver);}MODULE_LICENSE("GPL");module_init(imsttfb_init);module_exit(imsttfb_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -