⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imsttfb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
#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), &reg[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), &reg[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 + -