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

📄 s3fb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	return 0;}/* ------------------------------------------------------------------------- *//* Frame buffer operations */static struct fb_ops s3fb_ops = {	.owner		= THIS_MODULE,	.fb_open	= s3fb_open,	.fb_release	= s3fb_release,	.fb_check_var	= s3fb_check_var,	.fb_set_par	= s3fb_set_par,	.fb_setcolreg	= s3fb_setcolreg,	.fb_blank	= s3fb_blank,	.fb_pan_display	= s3fb_pan_display,	.fb_fillrect	= s3fb_fillrect,	.fb_copyarea	= cfb_copyarea,	.fb_imageblit	= s3fb_imageblit,	.fb_get_caps    = svga_get_caps,};/* ------------------------------------------------------------------------- */static int __devinit s3_identification(int chip){	if (chip == CHIP_XXX_TRIO) {		u8 cr30 = vga_rcrt(NULL, 0x30);		u8 cr2e = vga_rcrt(NULL, 0x2e);		u8 cr2f = vga_rcrt(NULL, 0x2f);		if ((cr30 == 0xE0) || (cr30 == 0xE1)) {			if (cr2e == 0x10)				return CHIP_732_TRIO32;			if (cr2e == 0x11) {				if (! (cr2f & 0x40))					return CHIP_764_TRIO64;				else					return CHIP_765_TRIO64VP;			}		}	}	if (chip == CHIP_XXX_TRIO64V2_DXGX) {		u8 cr6f = vga_rcrt(NULL, 0x6f);		if (! (cr6f & 0x01))			return CHIP_775_TRIO64V2_DX;		else			return CHIP_785_TRIO64V2_GX;	}	if (chip == CHIP_XXX_VIRGE_DXGX) {		u8 cr6f = vga_rcrt(NULL, 0x6f);		if (! (cr6f & 0x01))			return CHIP_375_VIRGE_DX;		else			return CHIP_385_VIRGE_GX;	}	return CHIP_UNKNOWN;}/* PCI probe */static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id){	struct fb_info *info;	struct s3fb_info *par;	int rc;	u8 regval, cr38, cr39;	/* Ignore secondary VGA device because there is no VGA arbitration */	if (! svga_primary_device(dev)) {		dev_info(&(dev->dev), "ignoring secondary device\n");		return -ENODEV;	}	/* Allocate and fill driver data structure */	info = framebuffer_alloc(sizeof(struct s3fb_info), &(dev->dev));	if (!info) {		dev_err(&(dev->dev), "cannot allocate memory\n");		return -ENOMEM;	}	par = info->par;	mutex_init(&par->open_lock);	info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;	info->fbops = &s3fb_ops;	/* Prepare PCI device */	rc = pci_enable_device(dev);	if (rc < 0) {		dev_err(info->device, "cannot enable PCI device\n");		goto err_enable_device;	}	rc = pci_request_regions(dev, "s3fb");	if (rc < 0) {		dev_err(info->device, "cannot reserve framebuffer region\n");		goto err_request_regions;	}	info->fix.smem_start = pci_resource_start(dev, 0);	info->fix.smem_len = pci_resource_len(dev, 0);	/* Map physical IO memory address into kernel space */	info->screen_base = pci_iomap(dev, 0, 0);	if (! info->screen_base) {		rc = -ENOMEM;		dev_err(info->device, "iomap for framebuffer failed\n");		goto err_iomap;	}	/* Unlock regs */	cr38 = vga_rcrt(NULL, 0x38);	cr39 = vga_rcrt(NULL, 0x39);	vga_wseq(NULL, 0x08, 0x06);	vga_wcrt(NULL, 0x38, 0x48);	vga_wcrt(NULL, 0x39, 0xA5);	/* Find how many physical memory there is on card */	/* 0x36 register is accessible even if other registers are locked */	regval = vga_rcrt(NULL, 0x36);	info->screen_size = s3_memsizes[regval >> 5] << 10;	info->fix.smem_len = info->screen_size;	par->chip = id->driver_data & CHIP_MASK;	par->rev = vga_rcrt(NULL, 0x2f);	if (par->chip & CHIP_UNDECIDED_FLAG)		par->chip = s3_identification(par->chip);	/* Find MCLK frequency */	regval = vga_rseq(NULL, 0x10);	par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F)  + 2);	par->mclk_freq = par->mclk_freq >> (regval >> 5);	/* Restore locks */	vga_wcrt(NULL, 0x38, cr38);	vga_wcrt(NULL, 0x39, cr39);	strcpy(info->fix.id, s3_names [par->chip]);	info->fix.mmio_start = 0;	info->fix.mmio_len = 0;	info->fix.type = FB_TYPE_PACKED_PIXELS;	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;	info->fix.ypanstep = 0;	info->fix.accel = FB_ACCEL_NONE;	info->pseudo_palette = (void*) (par->pseudo_palette);	/* Prepare startup mode */	rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);	if (! ((rc == 1) || (rc == 2))) {		rc = -EINVAL;		dev_err(info->device, "mode %s not found\n", mode_option);		goto err_find_mode;	}	rc = fb_alloc_cmap(&info->cmap, 256, 0);	if (rc < 0) {		dev_err(info->device, "cannot allocate colormap\n");		goto err_alloc_cmap;	}	rc = register_framebuffer(info);	if (rc < 0) {		dev_err(info->device, "cannot register framebuffer\n");		goto err_reg_fb;	}	printk(KERN_INFO "fb%d: %s on %s, %d MB RAM, %d MHz MCLK\n", info->node, info->fix.id,		 pci_name(dev), info->fix.smem_len >> 20, (par->mclk_freq + 500) / 1000);	if (par->chip == CHIP_UNKNOWN)		printk(KERN_INFO "fb%d: unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n",			info->node, vga_rcrt(NULL, 0x2d), vga_rcrt(NULL, 0x2e),			vga_rcrt(NULL, 0x2f), vga_rcrt(NULL, 0x30));	/* Record a reference to the driver data */	pci_set_drvdata(dev, info);#ifdef CONFIG_MTRR	if (mtrr) {		par->mtrr_reg = -1;		par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);	}#endif	return 0;	/* Error handling */err_reg_fb:	fb_dealloc_cmap(&info->cmap);err_alloc_cmap:err_find_mode:	pci_iounmap(dev, info->screen_base);err_iomap:	pci_release_regions(dev);err_request_regions:/*	pci_disable_device(dev); */err_enable_device:	framebuffer_release(info);	return rc;}/* PCI remove */static void __devexit s3_pci_remove(struct pci_dev *dev){	struct fb_info *info = pci_get_drvdata(dev);	if (info) {#ifdef CONFIG_MTRR		struct s3fb_info *par = info->par;		if (par->mtrr_reg >= 0) {			mtrr_del(par->mtrr_reg, 0, 0);			par->mtrr_reg = -1;		}#endif		unregister_framebuffer(info);		fb_dealloc_cmap(&info->cmap);		pci_iounmap(dev, info->screen_base);		pci_release_regions(dev);/*		pci_disable_device(dev); */		pci_set_drvdata(dev, NULL);		framebuffer_release(info);	}}/* PCI suspend */static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state){	struct fb_info *info = pci_get_drvdata(dev);	struct s3fb_info *par = info->par;	dev_info(info->device, "suspend\n");	acquire_console_sem();	mutex_lock(&(par->open_lock));	if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {		mutex_unlock(&(par->open_lock));		release_console_sem();		return 0;	}	fb_set_suspend(info, 1);	pci_save_state(dev);	pci_disable_device(dev);	pci_set_power_state(dev, pci_choose_state(dev, state));	mutex_unlock(&(par->open_lock));	release_console_sem();	return 0;}/* PCI resume */static int s3_pci_resume(struct pci_dev* dev){	struct fb_info *info = pci_get_drvdata(dev);	struct s3fb_info *par = info->par;	int err;	dev_info(info->device, "resume\n");	acquire_console_sem();	mutex_lock(&(par->open_lock));	if (par->ref_count == 0) {		mutex_unlock(&(par->open_lock));		release_console_sem();		return 0;	}	pci_set_power_state(dev, PCI_D0);	pci_restore_state(dev);	err = pci_enable_device(dev);	if (err) {		mutex_unlock(&(par->open_lock));		release_console_sem();		dev_err(info->device, "error %d enabling device for resume\n", err);		return err;	}	pci_set_master(dev);	s3fb_set_par(info);	fb_set_suspend(info, 0);	mutex_unlock(&(par->open_lock));	release_console_sem();	return 0;}/* List of boards that we are trying to support */static struct pci_device_id s3_devices[] __devinitdata = {	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8810), .driver_data = CHIP_XXX_TRIO},	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8811), .driver_data = CHIP_XXX_TRIO},	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8812), .driver_data = CHIP_M65_AURORA64VP},	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8814), .driver_data = CHIP_767_TRIO64UVP},	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8901), .driver_data = CHIP_XXX_TRIO64V2_DXGX},	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8902), .driver_data = CHIP_551_PLATO_PX},	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE},	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX},	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX},	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2},	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P},	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P},	{0, 0, 0, 0, 0, 0, 0}};MODULE_DEVICE_TABLE(pci, s3_devices);static struct pci_driver s3fb_pci_driver = {	.name		= "s3fb",	.id_table	= s3_devices,	.probe		= s3_pci_probe,	.remove		= __devexit_p(s3_pci_remove),	.suspend	= s3_pci_suspend,	.resume		= s3_pci_resume,};/* Parse user speficied options */#ifndef MODULEstatic int  __init s3fb_setup(char *options){	char *opt;	if (!options || !*options)		return 0;	while ((opt = strsep(&options, ",")) != NULL) {		if (!*opt)			continue;#ifdef CONFIG_MTRR		else if (!strncmp(opt, "mtrr:", 5))			mtrr = simple_strtoul(opt + 5, NULL, 0);#endif		else if (!strncmp(opt, "fasttext:", 9))			fasttext = simple_strtoul(opt + 9, NULL, 0);		else			mode_option = opt;	}	return 0;}#endif/* Cleanup */static void __exit s3fb_cleanup(void){	pr_debug("s3fb: cleaning up\n");	pci_unregister_driver(&s3fb_pci_driver);}/* Driver Initialisation */static int __init s3fb_init(void){#ifndef MODULE	char *option = NULL;	if (fb_get_options("s3fb", &option))		return -ENODEV;	s3fb_setup(option);#endif	pr_debug("s3fb: initializing\n");	return pci_register_driver(&s3fb_pci_driver);}/* ------------------------------------------------------------------------- *//* Modularization */module_init(s3fb_init);module_exit(s3fb_cleanup);

⌨️ 快捷键说明

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