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

📄 neofb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		printk(KERN_INFO "neofb: mapped io at %p\n",		       par->mmio_vbase);	return 0;}static void neo_unmap_mmio(struct fb_info *info){	struct neofb_par *par = info->par;	DBG("neo_unmap_mmio");	iounmap(par->mmio_vbase);	par->mmio_vbase = NULL;	release_mem_region(info->fix.mmio_start,			   info->fix.mmio_len);}static int __devinit neo_map_video(struct fb_info *info,				   struct pci_dev *dev, int video_len){	//unsigned long addr;	DBG("neo_map_video");	info->fix.smem_start = pci_resource_start(dev, 0);	info->fix.smem_len = video_len;	if (!request_mem_region(info->fix.smem_start, info->fix.smem_len,				"frame buffer")) {		printk("neofb: frame buffer in use\n");		return -EBUSY;	}	info->screen_base =	    ioremap(info->fix.smem_start, info->fix.smem_len);	if (!info->screen_base) {		printk("neofb: unable to map screen memory\n");		release_mem_region(info->fix.smem_start,				   info->fix.smem_len);		return -ENOMEM;	} else		printk(KERN_INFO "neofb: mapped framebuffer at %p\n",		       info->screen_base);#ifdef CONFIG_MTRR	((struct neofb_par *)(info->par))->mtrr =		mtrr_add(info->fix.smem_start, pci_resource_len(dev, 0),				MTRR_TYPE_WRCOMB, 1);#endif	/* Clear framebuffer, it's all white in memory after boot */	memset_io(info->screen_base, 0, info->fix.smem_len);	/* Allocate Cursor drawing pad.	info->fix.smem_len -= PAGE_SIZE;	addr = info->fix.smem_start + info->fix.smem_len;	write_le32(NEOREG_CURSMEMPOS, ((0x000f & (addr >> 10)) << 8) |					((0x0ff0 & (addr >> 10)) >> 4), par);	addr = (unsigned long) info->screen_base + info->fix.smem_len;	info->sprite.addr = (u8 *) addr; */	return 0;}static void neo_unmap_video(struct fb_info *info){	DBG("neo_unmap_video");#ifdef CONFIG_MTRR	{		struct neofb_par *par = info->par;		mtrr_del(par->mtrr, info->fix.smem_start,			 info->fix.smem_len);	}#endif	iounmap(info->screen_base);	info->screen_base = NULL;	release_mem_region(info->fix.smem_start,			   info->fix.smem_len);}static int __devinit neo_scan_monitor(struct fb_info *info){	struct neofb_par *par = info->par;	unsigned char type, display;	int w;	// Eventually we will have i2c support.	info->monspecs.modedb = kmalloc(sizeof(struct fb_videomode), GFP_KERNEL);	if (!info->monspecs.modedb)		return -ENOMEM;	info->monspecs.modedb_len = 1;	/* Determine the panel type */	vga_wgfx(NULL, 0x09, 0x26);	type = vga_rgfx(NULL, 0x21);	display = vga_rgfx(NULL, 0x20);	if (!par->internal_display && !par->external_display) {		par->internal_display = display & 2 || !(display & 3) ? 1 : 0;		par->external_display = display & 1;		printk (KERN_INFO "Autodetected %s display\n",			par->internal_display && par->external_display ? "simultaneous" :			par->internal_display ? "internal" : "external");	}	/* Determine panel width -- used in NeoValidMode. */	w = vga_rgfx(NULL, 0x20);	vga_wgfx(NULL, 0x09, 0x00);	switch ((w & 0x18) >> 3) {	case 0x00:		// 640x480@60		par->NeoPanelWidth = 640;		par->NeoPanelHeight = 480;		memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));		break;	case 0x01:		par->NeoPanelWidth = 800;		if (par->libretto) {			par->NeoPanelHeight = 480;			memcpy(info->monspecs.modedb, &mode800x480, sizeof(struct fb_videomode));		} else {			// 800x600@60			par->NeoPanelHeight = 600;			memcpy(info->monspecs.modedb, &vesa_modes[8], sizeof(struct fb_videomode));		}		break;	case 0x02:		// 1024x768@60		par->NeoPanelWidth = 1024;		par->NeoPanelHeight = 768;		memcpy(info->monspecs.modedb, &vesa_modes[13], sizeof(struct fb_videomode));		break;	case 0x03:		/* 1280x1024@60 panel support needs to be added */#ifdef NOT_DONE		par->NeoPanelWidth = 1280;		par->NeoPanelHeight = 1024;		memcpy(info->monspecs.modedb, &vesa_modes[20], sizeof(struct fb_videomode));		break;#else		printk(KERN_ERR		       "neofb: Only 640x480, 800x600/480 and 1024x768 panels are currently supported\n");		return -1;#endif	default:		// 640x480@60		par->NeoPanelWidth = 640;		par->NeoPanelHeight = 480;		memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));		break;	}	printk(KERN_INFO "Panel is a %dx%d %s %s display\n",	       par->NeoPanelWidth,	       par->NeoPanelHeight,	       (type & 0x02) ? "color" : "monochrome",	       (type & 0x10) ? "TFT" : "dual scan");	return 0;}static int __devinit neo_init_hw(struct fb_info *info){	struct neofb_par *par = info->par;	int videoRam = 896;	int maxClock = 65000;	int CursorMem = 1024;	int CursorOff = 0x100;	DBG("neo_init_hw");	neoUnlock();#if 0	printk(KERN_DEBUG "--- Neo extended register dump ---\n");	for (int w = 0; w < 0x85; w++)		printk(KERN_DEBUG "CR %p: %p\n", (void *) w,		       (void *) vga_rcrt(NULL, w));	for (int w = 0; w < 0xC7; w++)		printk(KERN_DEBUG "GR %p: %p\n", (void *) w,		       (void *) vga_rgfx(NULL, w));#endif	switch (info->fix.accel) {	case FB_ACCEL_NEOMAGIC_NM2070:		videoRam = 896;		maxClock = 65000;		break;	case FB_ACCEL_NEOMAGIC_NM2090:	case FB_ACCEL_NEOMAGIC_NM2093:	case FB_ACCEL_NEOMAGIC_NM2097:		videoRam = 1152;		maxClock = 80000;		break;	case FB_ACCEL_NEOMAGIC_NM2160:		videoRam = 2048;		maxClock = 90000;		break;	case FB_ACCEL_NEOMAGIC_NM2200:		videoRam = 2560;		maxClock = 110000;		break;	case FB_ACCEL_NEOMAGIC_NM2230:		videoRam = 3008;		maxClock = 110000;		break;	case FB_ACCEL_NEOMAGIC_NM2360:		videoRam = 4096;		maxClock = 110000;		break;	case FB_ACCEL_NEOMAGIC_NM2380:		videoRam = 6144;		maxClock = 110000;		break;	}	switch (info->fix.accel) {	case FB_ACCEL_NEOMAGIC_NM2070:	case FB_ACCEL_NEOMAGIC_NM2090:	case FB_ACCEL_NEOMAGIC_NM2093:		CursorMem = 2048;		CursorOff = 0x100;		break;	case FB_ACCEL_NEOMAGIC_NM2097:	case FB_ACCEL_NEOMAGIC_NM2160:		CursorMem = 1024;		CursorOff = 0x100;		break;	case FB_ACCEL_NEOMAGIC_NM2200:	case FB_ACCEL_NEOMAGIC_NM2230:	case FB_ACCEL_NEOMAGIC_NM2360:	case FB_ACCEL_NEOMAGIC_NM2380:		CursorMem = 1024;		CursorOff = 0x1000;		par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;		break;	}/*	info->sprite.size = CursorMem;	info->sprite.scan_align = 1;	info->sprite.buf_align = 1;	info->sprite.flags = FB_PIXMAP_IO;	info->sprite.outbuf = neofb_draw_cursor;*/	par->maxClock = maxClock;	par->cursorOff = CursorOff;	return videoRam * 1024;}static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const struct						   pci_device_id *id){	struct fb_info *info;	struct neofb_par *par;	info = framebuffer_alloc(sizeof(struct neofb_par), &dev->dev);	if (!info)		return NULL;	par = info->par;	info->fix.accel = id->driver_data;	par->pci_burst = !nopciburst;	par->lcd_stretch = !nostretch;	par->libretto = libretto;	par->internal_display = internal;	par->external_display = external;	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;	switch (info->fix.accel) {	case FB_ACCEL_NEOMAGIC_NM2070:		snprintf(info->fix.id, sizeof(info->fix.id),				"MagicGraph 128");		break;	case FB_ACCEL_NEOMAGIC_NM2090:		snprintf(info->fix.id, sizeof(info->fix.id),				"MagicGraph 128V");		break;	case FB_ACCEL_NEOMAGIC_NM2093:		snprintf(info->fix.id, sizeof(info->fix.id),				"MagicGraph 128ZV");		break;	case FB_ACCEL_NEOMAGIC_NM2097:		snprintf(info->fix.id, sizeof(info->fix.id),				"MagicGraph 128ZV+");		break;	case FB_ACCEL_NEOMAGIC_NM2160:		snprintf(info->fix.id, sizeof(info->fix.id),				"MagicGraph 128XD");		break;	case FB_ACCEL_NEOMAGIC_NM2200:		snprintf(info->fix.id, sizeof(info->fix.id),				"MagicGraph 256AV");		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |		               FBINFO_HWACCEL_COPYAREA |                	       FBINFO_HWACCEL_FILLRECT;		break;	case FB_ACCEL_NEOMAGIC_NM2230:		snprintf(info->fix.id, sizeof(info->fix.id),				"MagicGraph 256AV+");		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |		               FBINFO_HWACCEL_COPYAREA |                	       FBINFO_HWACCEL_FILLRECT;		break;	case FB_ACCEL_NEOMAGIC_NM2360:		snprintf(info->fix.id, sizeof(info->fix.id),				"MagicGraph 256ZX");		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |		               FBINFO_HWACCEL_COPYAREA |                	       FBINFO_HWACCEL_FILLRECT;		break;	case FB_ACCEL_NEOMAGIC_NM2380:		snprintf(info->fix.id, sizeof(info->fix.id),				"MagicGraph 256XL+");		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |		               FBINFO_HWACCEL_COPYAREA |                	       FBINFO_HWACCEL_FILLRECT;		break;	}	info->fix.type = FB_TYPE_PACKED_PIXELS;	info->fix.type_aux = 0;	info->fix.xpanstep = 0;	info->fix.ypanstep = 4;	info->fix.ywrapstep = 0;	info->fix.accel = id->driver_data;	info->fbops = &neofb_ops;	info->pseudo_palette = par->palette;	return info;}static void neo_free_fb_info(struct fb_info *info){	if (info) {		/*		 * Free the colourmap		 */		fb_dealloc_cmap(&info->cmap);		framebuffer_release(info);	}}/* --------------------------------------------------------------------- */static int __devinit neofb_probe(struct pci_dev *dev,				 const struct pci_device_id *id){	struct fb_info *info;	u_int h_sync, v_sync;	int video_len, err;	DBG("neofb_probe");	err = pci_enable_device(dev);	if (err)		return err;	err = -ENOMEM;	info = neo_alloc_fb_info(dev, id);	if (!info)		return err;	err = neo_map_mmio(info, dev);	if (err)		goto err_map_mmio;	err = neo_scan_monitor(info);	if (err)		goto err_scan_monitor;	video_len = neo_init_hw(info);	if (video_len < 0) {		err = video_len;		goto err_init_hw;	}	err = neo_map_video(info, dev, video_len);	if (err)		goto err_init_hw;	if (!fb_find_mode(&info->var, info, mode_option, NULL, 0,			info->monspecs.modedb, 16)) {		printk(KERN_ERR "neofb: Unable to find usable video mode.\n");		goto err_map_video;	}	/*	 * Calculate the hsync and vsync frequencies.  Note that	 * we split the 1e12 constant up so that we can preserve	 * the precision and fit the results into 32-bit registers.	 *  (1953125000 * 512 = 1e12)	 */	h_sync = 1953125000 / info->var.pixclock;	h_sync =	    h_sync * 512 / (info->var.xres + info->var.left_margin +			    info->var.right_margin + info->var.hsync_len);	v_sync =	    h_sync / (info->var.yres + info->var.upper_margin +		      info->var.lower_margin + info->var.vsync_len);	printk(KERN_INFO "neofb v" NEOFB_VERSION	       ": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",	       info->fix.smem_len >> 10, info->var.xres,	       info->var.yres, h_sync / 1000, h_sync % 1000, v_sync);	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)		goto err_map_video;	err = register_framebuffer(info);	if (err < 0)		goto err_reg_fb;	printk(KERN_INFO "fb%d: %s frame buffer device\n",	       info->node, info->fix.id);	/*	 * Our driver data	 */	pci_set_drvdata(dev, info);	return 0;err_reg_fb:	fb_dealloc_cmap(&info->cmap);err_map_video:	neo_unmap_video(info);err_init_hw:	fb_destroy_modedb(info->monspecs.modedb);err_scan_monitor:	neo_unmap_mmio(info);err_map_mmio:	neo_free_fb_info(info);	return err;}static void __devexit neofb_remove(struct pci_dev *dev){	struct fb_info *info = pci_get_drvdata(dev);	DBG("neofb_remove");	if (info) {		/*		 * If unregister_framebuffer fails, then		 * we will be leaving hooks that could cause		 * oopsen laying around.		 */		if (unregister_framebuffer(info))			printk(KERN_WARNING			       "neofb: danger danger!  Oopsen imminent!\n");		neo_unmap_video(info);		fb_destroy_modedb(info->monspecs.modedb);		neo_unmap_mmio(info);		neo_free_fb_info(info);		/*		 * Ensure that the driver data is no longer		 * valid.		 */		pci_set_drvdata(dev, NULL);	}}static struct pci_device_id neofb_devices[] = {	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2070,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2070},	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2090,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2090},	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2093,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2093},	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2097,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2097},	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2160,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2160},	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2200,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2200},	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2230,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2230},	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2360,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2360},	{PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2380,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2380},	{0, 0, 0, 0, 0, 0, 0}};MODULE_DEVICE_TABLE(pci, neofb_devices);static struct pci_driver neofb_driver = {	.name =		"neofb",	.id_table =	neofb_devices,	.probe =	neofb_probe,	.remove =	__devexit_p(neofb_remove)};/* ************************* init in-kernel code ************************** */#ifndef MODULEstatic int __init neofb_setup(char *options){	char *this_opt;	DBG("neofb_setup");	if (!options || !*options)		return 0;	while ((this_opt = strsep(&options, ",")) != NULL) {		if (!*this_opt)			continue;		if (!strncmp(this_opt, "internal", 8))			internal = 1;		else if (!strncmp(this_opt, "external", 8))			external = 1;		else if (!strncmp(this_opt, "nostretch", 9))			nostretch = 1;		else if (!strncmp(this_opt, "nopciburst", 10))			nopciburst = 1;		else if (!strncmp(this_opt, "libretto", 8))			libretto = 1;		else			mode_option = this_opt;	}	return 0;}#endif  /*  MODULE  */static int __init neofb_init(void){#ifndef MODULE	char *option = NULL;	if (fb_get_options("neofb", &option))		return -ENODEV;	neofb_setup(option);#endif	return pci_register_driver(&neofb_driver);}module_init(neofb_init);#ifdef MODULEstatic void __exit neofb_exit(void){	pci_unregister_driver(&neofb_driver);}module_exit(neofb_exit);#endif				/* MODULE */

⌨️ 快捷键说明

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