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

📄 tdfxfb.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	struct tdfx_par *par = info->par;	int size = image->height * ((image->width * image->depth + 7) >> 3);	int fifo_free;	int i, stride = info->fix.line_length;	u32 bpp = info->var.bits_per_pixel;	u32 dstfmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);	u8 *chardata = (u8 *) image->data;	u32 srcfmt;	u32 dx = image->dx;	u32 dy = image->dy;	u32 dstbase = 0;	if (image->depth != 1) {#ifdef BROKEN_CODE		banshee_make_room(par, 6 + ((size + 3) >> 2));		srcfmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13) |			0x400000;#else		cfb_imageblit(info, image);#endif		return;	}	banshee_make_room(par, 9);	switch (info->fix.visual) {	case FB_VISUAL_PSEUDOCOLOR:		tdfx_outl(par, COLORFORE, image->fg_color);		tdfx_outl(par, COLORBACK, image->bg_color);		break;	case FB_VISUAL_TRUECOLOR:	default:		tdfx_outl(par, COLORFORE,			  par->palette[image->fg_color]);		tdfx_outl(par, COLORBACK,			  par->palette[image->bg_color]);	}#ifdef __BIG_ENDIAN	srcfmt = 0x400000 | BIT(20);#else	srcfmt = 0x400000;#endif	/* asume always image->height < 4096 */	if (dy + image->height > 4095) {		dstbase = stride * dy;		dy = 0;	}	/* asume always image->width < 4096 */	if (dx + image->width > 4095) {		dstbase += dx * bpp >> 3;		dx = 0;	}	tdfx_outl(par, DSTBASE, dstbase);	tdfx_outl(par, SRCXY, 0);	tdfx_outl(par, DSTXY, dx | (dy << 16));	tdfx_outl(par, COMMAND_2D,		  COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24));	tdfx_outl(par, SRCFORMAT, srcfmt);	tdfx_outl(par, DSTFORMAT, dstfmt);	tdfx_outl(par, DSTSIZE, image->width | (image->height << 16));	/* A count of how many free FIFO entries we've requested.	 * When this goes negative, we need to request more. */	fifo_free = 0;	/* Send four bytes at a time of data */	for (i = (size >> 2); i > 0; i--) {		if (--fifo_free < 0) {			fifo_free = 31;			banshee_make_room(par, fifo_free);		}		tdfx_outl(par, LAUNCH_2D, *(u32 *)chardata);		chardata += 4;	}	/* Send the leftovers now */	banshee_make_room(par, 3);	switch (size % 4) {	case 0:		break;	case 1:		tdfx_outl(par, LAUNCH_2D, *chardata);		break;	case 2:		tdfx_outl(par, LAUNCH_2D, *(u16 *)chardata);		break;	case 3:		tdfx_outl(par, LAUNCH_2D,			*(u16 *)chardata | (chardata[3] << 24));		break;	}}#endif /* CONFIG_FB_3DFX_ACCEL */static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor){	struct tdfx_par *par = info->par;	u32 vidcfg;	if (!hwcursor)		return -EINVAL;	/* just to force soft_cursor() call */	/* Too large of a cursor or wrong bpp :-( */	if (cursor->image.width > 64 ||	    cursor->image.height > 64 ||	    cursor->image.depth > 1)		return -EINVAL;	vidcfg = tdfx_inl(par, VIDPROCCFG);	if (cursor->enable)		tdfx_outl(par, VIDPROCCFG, vidcfg | VIDCFG_HWCURSOR_ENABLE);	else		tdfx_outl(par, VIDPROCCFG, vidcfg & ~VIDCFG_HWCURSOR_ENABLE);	/*	 * If the cursor is not be changed this means either we want the	 * current cursor state (if enable is set) or we want to query what	 * we can do with the cursor (if enable is not set)	 */	if (!cursor->set)		return 0;	/* fix cursor color - XFree86 forgets to restore it properly */	if (cursor->set & FB_CUR_SETCMAP) {		struct fb_cmap cmap = info->cmap;		u32 bg_idx = cursor->image.bg_color;		u32 fg_idx = cursor->image.fg_color;		unsigned long bg_color, fg_color;		fg_color = (((u32)cmap.red[fg_idx]   & 0xff00) << 8) |			   (((u32)cmap.green[fg_idx] & 0xff00) << 0) |			   (((u32)cmap.blue[fg_idx]  & 0xff00) >> 8);		bg_color = (((u32)cmap.red[bg_idx]   & 0xff00) << 8) |			   (((u32)cmap.green[bg_idx] & 0xff00) << 0) |			   (((u32)cmap.blue[bg_idx]  & 0xff00) >> 8);		banshee_make_room(par, 2);		tdfx_outl(par, HWCURC0, bg_color);		tdfx_outl(par, HWCURC1, fg_color);	}	if (cursor->set & FB_CUR_SETPOS) {		int x = cursor->image.dx;		int y = cursor->image.dy - info->var.yoffset;		x += 63;		y += 63;		banshee_make_room(par, 1);		tdfx_outl(par, HWCURLOC, (y << 16) + x);	}	if (cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE)) {		/*		 * Voodoo 3 and above cards use 2 monochrome cursor patterns.		 *    The reason is so the card can fetch 8 words at a time		 * and are stored on chip for use for the next 8 scanlines.		 * This reduces the number of times for access to draw the		 * cursor for each screen refresh.		 *    Each pattern is a bitmap of 64 bit wide and 64 bit high		 * (total of 8192 bits or 1024 bytes). The two patterns are		 * stored in such a way that pattern 0 always resides in the		 * lower half (least significant 64 bits) of a 128 bit word		 * and pattern 1 the upper half. If you examine the data of		 * the cursor image the graphics card uses then from the		 * begining you see line one of pattern 0, line one of		 * pattern 1, line two of pattern 0, line two of pattern 1,		 * etc etc. The linear stride for the cursor is always 16 bytes		 * (128 bits) which is the maximum cursor width times two for		 * the two monochrome patterns.		 */		u8 __iomem *cursorbase = info->screen_base + info->fix.smem_len;		u8 *bitmap = (u8 *)cursor->image.data;		u8 *mask = (u8 *)cursor->mask;		int i;		fb_memset(cursorbase, 0, 1024);		for (i = 0; i < cursor->image.height; i++) {			int h = 0;			int j = (cursor->image.width + 7) >> 3;			for (; j > 0; j--) {				u8 data = *mask ^ *bitmap;				if (cursor->rop == ROP_COPY)					data = *mask & *bitmap;				/* Pattern 0. Copy the cursor mask to it */				fb_writeb(*mask, cursorbase + h);				mask++;				/* Pattern 1. Copy the cursor bitmap to it */				fb_writeb(data, cursorbase + h + 8);				bitmap++;				h++;			}			cursorbase += 16;		}	}	return 0;}static struct fb_ops tdfxfb_ops = {	.owner		= THIS_MODULE,	.fb_check_var	= tdfxfb_check_var,	.fb_set_par	= tdfxfb_set_par,	.fb_setcolreg	= tdfxfb_setcolreg,	.fb_blank	= tdfxfb_blank,	.fb_pan_display	= tdfxfb_pan_display,	.fb_sync	= banshee_wait_idle,	.fb_cursor	= tdfxfb_cursor,#ifdef CONFIG_FB_3DFX_ACCEL	.fb_fillrect	= tdfxfb_fillrect,	.fb_copyarea	= tdfxfb_copyarea,	.fb_imageblit	= tdfxfb_imageblit,#else	.fb_fillrect	= cfb_fillrect,	.fb_copyarea	= cfb_copyarea,	.fb_imageblit	= cfb_imageblit,#endif};/** *      tdfxfb_probe - Device Initializiation * *      @pdev:  PCI Device to initialize *      @id:    PCI Device ID * *      Initializes and allocates resources for PCI device @pdev. * */static int __devinit tdfxfb_probe(struct pci_dev *pdev,				  const struct pci_device_id *id){	struct tdfx_par *default_par;	struct fb_info *info;	int err, lpitch;	err = pci_enable_device(pdev);	if (err) {		printk(KERN_ERR "tdfxfb: Can't enable pdev: %d\n", err);		return err;	}	info = framebuffer_alloc(sizeof(struct tdfx_par), &pdev->dev);	if (!info)		return -ENOMEM;	default_par = info->par;	/* Configure the default fb_fix_screeninfo first */	switch (pdev->device) {	case PCI_DEVICE_ID_3DFX_BANSHEE:		strcat(tdfx_fix.id, " Banshee");		default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK;		break;	case PCI_DEVICE_ID_3DFX_VOODOO3:		strcat(tdfx_fix.id, " Voodoo3");		default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK;		break;	case PCI_DEVICE_ID_3DFX_VOODOO5:		strcat(tdfx_fix.id, " Voodoo5");		default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK;		break;	}	tdfx_fix.mmio_start = pci_resource_start(pdev, 0);	tdfx_fix.mmio_len = pci_resource_len(pdev, 0);	if (!request_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len,				"tdfx regbase")) {		printk(KERN_ERR "tdfxfb: Can't reserve regbase\n");		goto out_err;	}	default_par->regbase_virt =		ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len);	if (!default_par->regbase_virt) {		printk(KERN_ERR "fb: Can't remap %s register area.\n",				tdfx_fix.id);		goto out_err_regbase;	}	tdfx_fix.smem_start = pci_resource_start(pdev, 1);	tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device);	if (!tdfx_fix.smem_len) {		printk(KERN_ERR "fb: Can't count %s memory.\n", tdfx_fix.id);		goto out_err_regbase;	}	if (!request_mem_region(tdfx_fix.smem_start,				pci_resource_len(pdev, 1), "tdfx smem")) {		printk(KERN_ERR "tdfxfb: Can't reserve smem\n");		goto out_err_regbase;	}	info->screen_base = ioremap_nocache(tdfx_fix.smem_start,					    tdfx_fix.smem_len);	if (!info->screen_base) {		printk(KERN_ERR "fb: Can't remap %s framebuffer.\n",				tdfx_fix.id);		goto out_err_screenbase;	}	default_par->iobase = pci_resource_start(pdev, 2);	if (!request_region(pci_resource_start(pdev, 2),			    pci_resource_len(pdev, 2), "tdfx iobase")) {		printk(KERN_ERR "tdfxfb: Can't reserve iobase\n");		goto out_err_screenbase;	}	printk(KERN_INFO "fb: %s memory = %dK\n", tdfx_fix.id,			tdfx_fix.smem_len >> 10);	default_par->mtrr_handle = -1;	if (!nomtrr)		default_par->mtrr_handle =			mtrr_add(tdfx_fix.smem_start, tdfx_fix.smem_len,				 MTRR_TYPE_WRCOMB, 1);	tdfx_fix.ypanstep	= nopan ? 0 : 1;	tdfx_fix.ywrapstep	= nowrap ? 0 : 1;	info->fbops		= &tdfxfb_ops;	info->fix		= tdfx_fix;	info->pseudo_palette	= default_par->palette;	info->flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;#ifdef CONFIG_FB_3DFX_ACCEL	info->flags		|= FBINFO_HWACCEL_FILLRECT |				   FBINFO_HWACCEL_COPYAREA |				   FBINFO_HWACCEL_IMAGEBLIT |				   FBINFO_READS_FAST;#endif	/* reserve 8192 bits for cursor */	/* the 2.4 driver says PAGE_MASK boundary is not enough for Voodoo4 */	if (hwcursor)		info->fix.smem_len = (info->fix.smem_len - 1024) &					(PAGE_MASK << 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 = tdfx_var;	/* maximize virtual vertical length */	lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3);	info->var.yres_virtual = info->fix.smem_len / lpitch;	if (info->var.yres_virtual < info->var.yres)		goto out_err_iobase;	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {		printk(KERN_ERR "tdfxfb: Can't allocate color map\n");		goto out_err_iobase;	}	if (register_framebuffer(info) < 0) {		printk(KERN_ERR "tdfxfb: can't register framebuffer\n");		fb_dealloc_cmap(&info->cmap);		goto out_err_iobase;	}	/*	 * Our driver data	 */	pci_set_drvdata(pdev, info);	return 0;out_err_iobase:	if (default_par->mtrr_handle >= 0)		mtrr_del(default_par->mtrr_handle, info->fix.smem_start,			 info->fix.smem_len);	release_mem_region(pci_resource_start(pdev, 2),			   pci_resource_len(pdev, 2));out_err_screenbase:	if (info->screen_base)		iounmap(info->screen_base);	release_mem_region(tdfx_fix.smem_start, pci_resource_len(pdev, 1));out_err_regbase:	/*	 * Cleanup after anything that was remapped/allocated.	 */	if (default_par->regbase_virt)		iounmap(default_par->regbase_virt);	release_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len);out_err:	framebuffer_release(info);	return -ENXIO;}#ifndef MODULEstatic void tdfxfb_setup(char *options){	char *this_opt;	if (!options || !*options)		return;	while ((this_opt = strsep(&options, ",")) != NULL) {		if (!*this_opt)			continue;		if (!strcmp(this_opt, "nopan")) {			nopan = 1;		} else if (!strcmp(this_opt, "nowrap")) {			nowrap = 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 {			mode_option = this_opt;		}	}}#endif/** *      tdfxfb_remove - Device removal * *      @pdev:  PCI Device to cleanup * *      Releases all resources allocated during the course of the driver's *      lifetime for the PCI device @pdev. * */static void __devexit tdfxfb_remove(struct pci_dev *pdev){	struct fb_info *info = pci_get_drvdata(pdev);	struct tdfx_par *par = info->par;	unregister_framebuffer(info);	if (par->mtrr_handle >= 0)		mtrr_del(par->mtrr_handle, info->fix.smem_start,			 info->fix.smem_len);	iounmap(par->regbase_virt);	iounmap(info->screen_base);	/* Clean up after reserved regions */	release_region(pci_resource_start(pdev, 2),		       pci_resource_len(pdev, 2));	release_mem_region(pci_resource_start(pdev, 1),			   pci_resource_len(pdev, 1));	release_mem_region(pci_resource_start(pdev, 0),			   pci_resource_len(pdev, 0));	pci_set_drvdata(pdev, NULL);	framebuffer_release(info);}static int __init tdfxfb_init(void){#ifndef MODULE	char *option = NULL;	if (fb_get_options("tdfxfb", &option))		return -ENODEV;	tdfxfb_setup(option);#endif	return pci_register_driver(&tdfxfb_driver);}static void __exit tdfxfb_exit(void){	pci_unregister_driver(&tdfxfb_driver);}MODULE_AUTHOR("Hannu Mallat <hmallat@cc.hut.fi>");MODULE_DESCRIPTION("3Dfx framebuffer device driver");MODULE_LICENSE("GPL");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 (default: enabled)");#endifmodule_init(tdfxfb_init);module_exit(tdfxfb_exit);

⌨️ 快捷键说明

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