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

📄 pm2fb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		WAIT_FIFO(par, 4);		pm2_WR(par, PM2R_RD_CURSOR_X_LSB, x & 0xff);		pm2_WR(par, PM2R_RD_CURSOR_X_MSB, (x >> 8) & 0x7);		pm2_WR(par, PM2R_RD_CURSOR_Y_LSB, y & 0xff);		pm2_WR(par, PM2R_RD_CURSOR_Y_MSB, (y >> 8) & 0x7);	}	if (cursor->set & FB_CUR_SETCMAP) {		u32 fg_idx = cursor->image.fg_color;		u32 bg_idx = cursor->image.bg_color;		WAIT_FIFO(par, 7);		pm2_WR(par, PM2R_RD_CURSOR_COLOR_ADDRESS, 1);		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,			info->cmap.red[bg_idx] >> 8);		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,			info->cmap.green[bg_idx] >> 8);		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,			info->cmap.blue[bg_idx] >> 8);		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,			info->cmap.red[fg_idx] >> 8);		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,			info->cmap.green[fg_idx] >> 8);		pm2_WR(par, PM2R_RD_CURSOR_COLOR_DATA,			info->cmap.blue[fg_idx] >> 8);	}	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {		u8 *bitmap = (u8 *)cursor->image.data;		u8 *mask = (u8 *)cursor->mask;		int i;		WAIT_FIFO(par, 1);		pm2_WR(par, PM2R_RD_PALETTE_WRITE_ADDRESS, 0);		for (i = 0; i < cursor->image.height; i++) {			int j = (cursor->image.width + 7) >> 3;			int k = 8 - j;			WAIT_FIFO(par, 8);			for (; j > 0; j--) {				u8 data = *bitmap ^ *mask;				if (cursor->rop == ROP_COPY)					data = *mask & *bitmap;				/* bitmap data */				pm2_WR(par, PM2R_RD_CURSOR_DATA, data);				bitmap++;				mask++;			}			for (; k > 0; k--)				pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);		}		for (; i < 64; i++) {			int j = 8;			WAIT_FIFO(par, 8);			while (j-- > 0)				pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);		}		mask = (u8 *)cursor->mask;		for (i = 0; i < cursor->image.height; i++) {			int j = (cursor->image.width + 7) >> 3;			int k = 8 - j;			WAIT_FIFO(par, 8);			for (; j > 0; j--) {				/* mask */				pm2_WR(par, PM2R_RD_CURSOR_DATA, *mask);				mask++;			}			for (; k > 0; k--)				pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);		}		for (; i < 64; i++) {			int j = 8;			WAIT_FIFO(par, 8);			while (j-- > 0)				pm2_WR(par, PM2R_RD_CURSOR_DATA, 0);		}	}	return 0;}/* ------------ Hardware Independent Functions ------------ *//* *  Frame buffer operations */static struct fb_ops pm2fb_ops = {	.owner		= THIS_MODULE,	.fb_check_var	= pm2fb_check_var,	.fb_set_par	= pm2fb_set_par,	.fb_setcolreg	= pm2fb_setcolreg,	.fb_blank	= pm2fb_blank,	.fb_pan_display	= pm2fb_pan_display,	.fb_fillrect	= pm2fb_fillrect,	.fb_copyarea	= pm2fb_copyarea,	.fb_imageblit	= pm2fb_imageblit,	.fb_sync	= pm2fb_sync,	.fb_cursor	= pm2fb_cursor,};/* * PCI stuff *//** * Device initialisation * * Initialise and allocate resource for PCI device. * * @param	pdev	PCI device. * @param	id	PCI device ID. */static int __devinit pm2fb_probe(struct pci_dev *pdev,				 const struct pci_device_id *id){	struct pm2fb_par *default_par;	struct fb_info *info;	int err;	int retval = -ENXIO;	err = pci_enable_device(pdev);	if (err) {		printk(KERN_WARNING "pm2fb: Can't enable pdev: %d\n", err);		return err;	}	info = framebuffer_alloc(sizeof(struct pm2fb_par), &pdev->dev);	if (!info)		return -ENOMEM;	default_par = info->par;	switch (pdev->device) {	case  PCI_DEVICE_ID_TI_TVP4020:		strcpy(pm2fb_fix.id, "TVP4020");		default_par->type = PM2_TYPE_PERMEDIA2;		break;	case  PCI_DEVICE_ID_3DLABS_PERMEDIA2:		strcpy(pm2fb_fix.id, "Permedia2");		default_par->type = PM2_TYPE_PERMEDIA2;		break;	case  PCI_DEVICE_ID_3DLABS_PERMEDIA2V:		strcpy(pm2fb_fix.id, "Permedia2v");		default_par->type = PM2_TYPE_PERMEDIA2V;		break;	}	pm2fb_fix.mmio_start = pci_resource_start(pdev, 0);	pm2fb_fix.mmio_len = PM2_REGS_SIZE;#if defined(__BIG_ENDIAN)	/*	 * PM2 has a 64k register file, mapped twice in 128k. Lower	 * map is little-endian, upper map is big-endian.	 */	pm2fb_fix.mmio_start += PM2_REGS_SIZE;	DPRINTK("Adjusting register base for big-endian.\n");#endif	DPRINTK("Register base at 0x%lx\n", pm2fb_fix.mmio_start);	/* Registers - request region and map it. */	if (!request_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len,				"pm2fb regbase")) {		printk(KERN_WARNING "pm2fb: Can't reserve regbase.\n");		goto err_exit_neither;	}	default_par->v_regs =		ioremap_nocache(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);	if (!default_par->v_regs) {		printk(KERN_WARNING "pm2fb: Can't remap %s register area.\n",		       pm2fb_fix.id);		release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len);		goto err_exit_neither;	}	/* Stash away memory register info for use when we reset the board */	default_par->mem_control = pm2_RD(default_par, PM2R_MEM_CONTROL);	default_par->boot_address = pm2_RD(default_par, PM2R_BOOT_ADDRESS);	default_par->mem_config = pm2_RD(default_par, PM2R_MEM_CONFIG);	DPRINTK("MemControl 0x%x BootAddress 0x%x MemConfig 0x%x\n",		default_par->mem_control, default_par->boot_address,		default_par->mem_config);	if (default_par->mem_control == 0 &&		default_par->boot_address == 0x31 &&		default_par->mem_config == 0x259fffff) {		default_par->memclock = CVPPC_MEMCLOCK;		default_par->mem_control = 0;		default_par->boot_address = 0x20;		default_par->mem_config = 0xe6002021;		if (pdev->subsystem_vendor == 0x1048 &&			pdev->subsystem_device == 0x0a31) {			DPRINTK("subsystem_vendor: %04x, "				"subsystem_device: %04x\n",				pdev->subsystem_vendor, pdev->subsystem_device);			DPRINTK("We have not been initialized by VGA BIOS and "				"are running on an Elsa Winner 2000 Office\n");			DPRINTK("Initializing card timings manually...\n");			default_par->memclock = 100000;		}		if (pdev->subsystem_vendor == 0x3d3d &&			pdev->subsystem_device == 0x0100) {			DPRINTK("subsystem_vendor: %04x, "				"subsystem_device: %04x\n",				pdev->subsystem_vendor, pdev->subsystem_device);			DPRINTK("We have not been initialized by VGA BIOS and "				"are running on an 3dlabs reference board\n");			DPRINTK("Initializing card timings manually...\n");			default_par->memclock = 74894;		}	}	/* Now work out how big lfb is going to be. */	switch (default_par->mem_config & PM2F_MEM_CONFIG_RAM_MASK) {	case PM2F_MEM_BANKS_1:		pm2fb_fix.smem_len = 0x200000;		break;	case PM2F_MEM_BANKS_2:		pm2fb_fix.smem_len = 0x400000;		break;	case PM2F_MEM_BANKS_3:		pm2fb_fix.smem_len = 0x600000;		break;	case PM2F_MEM_BANKS_4:		pm2fb_fix.smem_len = 0x800000;		break;	}	pm2fb_fix.smem_start = pci_resource_start(pdev, 1);	/* Linear frame buffer - request region and map it. */	if (!request_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len,				"pm2fb smem")) {		printk(KERN_WARNING "pm2fb: Can't reserve smem.\n");		goto err_exit_mmio;	}	info->screen_base =		ioremap_nocache(pm2fb_fix.smem_start, pm2fb_fix.smem_len);	if (!info->screen_base) {		printk(KERN_WARNING "pm2fb: Can't ioremap smem area.\n");		release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len);		goto err_exit_mmio;	}#ifdef CONFIG_MTRR	default_par->mtrr_handle = -1;	if (!nomtrr)		default_par->mtrr_handle =			mtrr_add(pm2fb_fix.smem_start,				 pm2fb_fix.smem_len,				 MTRR_TYPE_WRCOMB, 1);#endif	info->fbops		= &pm2fb_ops;	info->fix		= pm2fb_fix;	info->pseudo_palette	= default_par->palette;	info->flags		= FBINFO_DEFAULT |				  FBINFO_HWACCEL_YPAN |				  FBINFO_HWACCEL_COPYAREA |				  FBINFO_HWACCEL_IMAGEBLIT |				  FBINFO_HWACCEL_FILLRECT;	info->pixmap.addr = kmalloc(PM2_PIXMAP_SIZE, GFP_KERNEL);	if (!info->pixmap.addr) {		retval = -ENOMEM;		goto err_exit_pixmap;	}	info->pixmap.size = PM2_PIXMAP_SIZE;	info->pixmap.buf_align = 4;	info->pixmap.scan_align = 4;	info->pixmap.access_align = 32;	info->pixmap.flags = FB_PIXMAP_SYSTEM;	if (noaccel) {		printk(KERN_DEBUG "disabling acceleration\n");		info->flags |= FBINFO_HWACCEL_DISABLED;		info->pixmap.scan_align = 1;	}	if (!mode_option)		mode_option = "640x480@60";	err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);	if (!err || err == 4)		info->var = pm2fb_var;	retval = fb_alloc_cmap(&info->cmap, 256, 0);	if (retval < 0)		goto err_exit_both;	retval = register_framebuffer(info);	if (retval < 0)		goto err_exit_all;	printk(KERN_INFO "fb%d: %s frame buffer device, memory = %dK.\n",	       info->node, info->fix.id, pm2fb_fix.smem_len / 1024);	/*	 * Our driver data	 */	pci_set_drvdata(pdev, info);	return 0; err_exit_all:	fb_dealloc_cmap(&info->cmap); err_exit_both:	kfree(info->pixmap.addr); err_exit_pixmap:	iounmap(info->screen_base);	release_mem_region(pm2fb_fix.smem_start, pm2fb_fix.smem_len); err_exit_mmio:	iounmap(default_par->v_regs);	release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len); err_exit_neither:	framebuffer_release(info);	return retval;}/** * Device removal. * * Release all device resources. * * @param	pdev	PCI device to clean up. */static void __devexit pm2fb_remove(struct pci_dev *pdev){	struct fb_info *info = pci_get_drvdata(pdev);	struct fb_fix_screeninfo *fix = &info->fix;	struct pm2fb_par *par = info->par;	unregister_framebuffer(info);#ifdef CONFIG_MTRR	if (par->mtrr_handle >= 0)		mtrr_del(par->mtrr_handle, info->fix.smem_start,			 info->fix.smem_len);#endif /* CONFIG_MTRR */	iounmap(info->screen_base);	release_mem_region(fix->smem_start, fix->smem_len);	iounmap(par->v_regs);	release_mem_region(fix->mmio_start, fix->mmio_len);	pci_set_drvdata(pdev, NULL);	fb_dealloc_cmap(&info->cmap);	kfree(info->pixmap.addr);	kfree(info);}static struct pci_device_id pm2fb_id_table[] = {	{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TVP4020,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ 0, }};static struct pci_driver pm2fb_driver = {	.name		= "pm2fb",	.id_table	= pm2fb_id_table,	.probe		= pm2fb_probe,	.remove		= __devexit_p(pm2fb_remove),};MODULE_DEVICE_TABLE(pci, pm2fb_id_table);#ifndef MODULE/** * Parse user speficied options. * * This is, comma-separated options following `video=pm2fb:'. */static int __init pm2fb_setup(char *options){	char *this_opt;	if (!options || !*options)		return 0;	while ((this_opt = strsep(&options, ",")) != NULL) {		if (!*this_opt)			continue;		if (!strcmp(this_opt, "lowhsync"))			lowhsync = 1;		else if (!strcmp(this_opt, "lowvsync"))			lowvsync = 1;		else if (!strncmp(this_opt, "hwcursor=", 9))			hwcursor = simple_strtoul(this_opt + 9, NULL, 0);#ifdef CONFIG_MTRR		else if (!strncmp(this_opt, "nomtrr", 6))			nomtrr = 1;#endif		else if (!strncmp(this_opt, "noaccel", 7))			noaccel = 1;		else			mode_option = this_opt;	}	return 0;}#endifstatic int __init pm2fb_init(void){#ifndef MODULE	char *option = NULL;	if (fb_get_options("pm2fb", &option))		return -ENODEV;	pm2fb_setup(option);#endif	return pci_register_driver(&pm2fb_driver);}module_init(pm2fb_init);#ifdef MODULE/* *  Cleanup */static void __exit pm2fb_exit(void){	pci_unregister_driver(&pm2fb_driver);}#endif#ifdef MODULEmodule_exit(pm2fb_exit);module_param(mode_option, charp, 0);MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");module_param_named(mode, mode_option, charp, 0);MODULE_PARM_DESC(mode, "Initial video mode e.g. '648x480-8@60' (deprecated)");module_param(lowhsync, bool, 0);MODULE_PARM_DESC(lowhsync, "Force horizontal sync low regardless of mode");module_param(lowvsync, bool, 0);MODULE_PARM_DESC(lowvsync, "Force vertical sync low regardless of mode");module_param(noaccel, bool, 0);MODULE_PARM_DESC(noaccel, "Disable acceleration");module_param(hwcursor, int, 0644);MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "			"(1=enable, 0=disable, default=1)");#ifdef CONFIG_MTRRmodule_param(nomtrr, bool, 0);MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");#endifMODULE_AUTHOR("Jim Hague <jim.hague@acm.org>");MODULE_DESCRIPTION("Permedia2 framebuffer device driver");MODULE_LICENSE("GPL");#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -