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

📄 sis_main.c

📁 linux嵌入式课程实践中的一个关于声卡驱动程序 。
💻 C
📖 第 1 页 / 共 5 页
字号:
	return 1;}static void sisfb_blank (int blank, struct fb_info *info){	u8 reg;	vgawb (CRTC_ADR, 0x17);	reg = vgarb (CRTC_DATA);	if (blank > 0)		reg &= 0x7f;	else		reg |= 0x80;	vgawb (CRTC_ADR, 0x17);	vgawb (CRTC_DATA, reg);}int sisfb_setup (char *options){	char *this_opt;	fb_info.fontname[0] = '\0';	ivideo.refresh_rate = 0;	if (!options || !*options)		return 0;	for (this_opt = strtok (options, ","); this_opt;	     this_opt = strtok (NULL, ",")) {		if (!*this_opt)			continue;		if (!strcmp (this_opt, "inverse")) {			sisfb_inverse = 1;			fb_invert_cmaps ();		} else if (!strncmp (this_opt, "font:", 5)) {			strcpy (fb_info.fontname, this_opt + 5);		} else if (!strncmp (this_opt, "mode:", 5)) {			sisfb_search_mode (this_opt + 5);		} else if (!strncmp (this_opt, "vrate:", 6)) {			ivideo.refresh_rate =			    simple_strtoul (this_opt + 6, NULL, 0);		} else if (!strncmp (this_opt, "off", 3)) {			sisfb_off = 1;		} else if (!strncmp (this_opt, "crt1off", 7)) {			sisfb_crt1off = 1;		} else if (!strncmp (this_opt, "filter:", 7)) {			filter = (int) simple_strtoul (this_opt + 7, NULL, 0);		}		/*karl */		else if (!strncmp (this_opt, "tvmode:", 7)) {			if (!strncmp (this_opt + 7, "pal", 3))				sisfb_tvmode = 1;			if (!strncmp (this_opt + 7, "ntsc", 4))				sisfb_tvmode = 2;		}		/*karl:10/01/2001 */		else if (!strncmp (this_opt, "mem:", 4)) {			sisfb_mem = simple_strtoul (this_opt + 4, NULL, 0);		} else			DPRINTK ("invalid parameter %s\n", this_opt);	}	return 0;}int __init sisfb_init (void){	struct pci_dev *pdev = NULL;	struct board *b;	int pdev_valid = 0;	//unsigned long rom_vbase;	u32 reg32;	u16 reg16;	u8 reg;	int nRes;	outb (0x77, 0x80);	if (sisfb_off)		return -ENXIO;	pci_for_each_dev (pdev)	{		for (b = sisdev_list; b->vendor; b++) {			if ((b->vendor == pdev->vendor)			    && (b->device == pdev->device)) {				pdev_valid = 1;				strcpy (fb_info.modename, b->name);				ivideo.chip_id = pdev->device;				pci_read_config_byte (pdev, PCI_REVISION_ID,						      &ivideo.revision_id);				pci_read_config_word (pdev, PCI_COMMAND, &reg16);				// Eden Chen				//sishw_ext.uRevisionID = ivideo.revision_id;				sishw_ext.jChipRevision = ivideo.revision_id;				// ~Eden Chen				sisvga_enabled = reg16 & 0x1;				break;			}		}			if (pdev_valid)			break;	}		if (!pdev_valid)		return -1;		// Eden Chen	switch (ivideo.chip_id) {	case PCI_DEVICE_ID_SI_300:		ivideo.chip = SIS_300;		sisvga_engine = SIS_300_VGA;		break;	case PCI_DEVICE_ID_SI_630_VGA:	{		sisfb_set_reg4 (0xCF8, 0x80000000);		reg32 = sisfb_get_reg3 (0xCFC);		if (reg32 == 0x07301039) {			ivideo.chip = SIS_730;			strcpy (fb_info.modename, "SIS 730");		} else			ivideo.chip = SIS_630;		sisvga_engine = SIS_300_VGA;		break;	}	case PCI_DEVICE_ID_SI_540_VGA:		ivideo.chip = SIS_540;		sisvga_engine = SIS_300_VGA;		break;	case PCI_DEVICE_ID_SI_315H:		ivideo.chip = SIS_315H;		sisvga_engine = SIS_315_VGA;		break;	case PCI_DEVICE_ID_SI_315:		ivideo.chip = SIS_315;		sisvga_engine = SIS_315_VGA;		break;	case PCI_DEVICE_ID_SI_315PRO:		ivideo.chip = SIS_315PRO;		sisvga_engine = SIS_315_VGA;		break;	case PCI_DEVICE_ID_SI_550_VGA:		ivideo.chip = SIS_550;		sisvga_engine = SIS_315_VGA;		break;	}	// Eden Chen	//sishw_ext.jChipID = ivideo.chip;	sishw_ext.jChipType = ivideo.chip;	// for Debug	if ((sishw_ext.jChipType == SIS_315PRO)	    || (sishw_ext.jChipType == SIS_315))		sishw_ext.jChipType = SIS_315H;		// ~Eden Chen	DPRINTK ("%s is used as %s device(VGA Engine %d).\n",		 fb_info.modename, sisvga_enabled ? "primary" : "secondary",		 sisvga_engine);		ivideo.video_base = pci_resource_start (pdev, 0);	ivideo.mmio_base = pci_resource_start (pdev, 1);	// Eden Chen	//sishw_ext.IOAddress = (unsigned short) ivideo.vga_base 	//      = pci_resource_start(pdev, 2) + 0x30;	sishw_ext.ulIOAddress = (unsigned short) ivideo.vga_base = pci_resource_start (pdev, 2) + 0x30;	// ~Eden Chen	sisfb_mmio_size = pci_resource_len (pdev, 1);	if (!sisvga_enabled)		if (pci_enable_device (pdev))			return -EIO;		vgawb (SEQ_ADR, IND_SIS_PASSWORD);	vgawb (SEQ_DATA, SIS_PASSWORD);#ifdef LINUXBIOS#ifdef CONFIG_FB_SIS_300	if (sisvga_engine == SIS_300_VGA)	{		vgawb (SEQ_ADR, 0x28);		vgawb (SEQ_DATA, 0x37);		vgawb (SEQ_ADR, 0x29);		vgawb (SEQ_DATA, 0x61);		vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_1A);		reg = vgarb (SEQ_DATA);		reg |= SIS_SCRATCH_REG_1A_MASK;		vgawb (SEQ_DATA, reg);	}#endif#ifdef CONFIG_FB_SIS_315	if (ivideo.chip == SIS_550) {		vgawb (SEQ_ADR, 0x28);		vgawb (SEQ_DATA, 0x5A);			vgawb (SEQ_ADR, 0x29);		vgawb (SEQ_DATA, 0x64);		vgawb (CRTC_ADR, 0x3A);		vgawb (CRTC_DATA, 0x00);	}#endif#endif	if (sisvga_engine == SIS_315_VGA) {		switch (ivideo.chip) {		case SIS_315H:		case SIS_315:			sishw_ext.bIntegratedMMEnabled = TRUE;			break;		case SIS_550:			// Eden Chen			//vgawb(SEQ_ADR, IND_SIS_SCRATCH_REG_1A);			//reg = vgarb(SEQ_DATA);			//if (reg & SIS_SCRATCH_REG_1A_MASK)			//      sishw_ext.bIntegratedMMEnabled = TRUE;			//else			//      sishw_ext.bIntegratedMMEnabled = FALSE;			//for Debug			sishw_ext.bIntegratedMMEnabled = TRUE;			// ~Eden Chen			break;		default:			break;		}	} else if (sisvga_engine == SIS_300_VGA) {		if (ivideo.chip == SIS_300) {			sishw_ext.bIntegratedMMEnabled = TRUE;		} else {			vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_1A);			reg = vgarb (SEQ_DATA);			if (reg & SIS_SCRATCH_REG_1A_MASK)				sishw_ext.bIntegratedMMEnabled = TRUE;			else				sishw_ext.bIntegratedMMEnabled = FALSE;		}	}	// Eden Chen	sishw_ext.pDevice = NULL;	sishw_ext.pjVirtualRomBase = NULL;	sishw_ext.pjCustomizedROMImage = NULL;	sishw_ext.bSkipDramSizing = 0;	sishw_ext.pQueryVGAConfigSpace = &sisfb_query_VGA_config_space;	sishw_ext.pQueryNorthBridgeSpace = &sisfb_query_north_bridge_space;	strcpy (sishw_ext.szVBIOSVer, "0.84");	sishw_ext.pSR = vmalloc (sizeof (SIS_DSReg) * SR_BUFFER_SIZE);	if (sishw_ext.pSR == NULL)		printk (KERN_DEBUG "Allocated SRReg space fail.\n");	sishw_ext.pSR[0].jIdx = sishw_ext.pSR[0].jVal = 0xFF;	sishw_ext.pCR = vmalloc (sizeof (SIS_DSReg) * CR_BUFFER_SIZE);	if (sishw_ext.pCR == NULL)		printk (KERN_DEBUG "Allocated CRReg space fail.\n");	sishw_ext.pCR[0].jIdx = sishw_ext.pCR[0].jVal = 0xFF;	// ~Eden Chen	#ifdef CONFIG_FB_SIS_300	if (sisvga_engine == SIS_300_VGA) {		if (!sisvga_enabled) {			// Eden Chen			sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x2000000);			//SiSInit300(&sishw_ext);			SiSInit (&sishw_ext);			vgawb (SEQ_ADR, IND_SIS_PASSWORD);			vgawb (SEQ_DATA, SIS_PASSWORD);			// ~Eden Chen		}#ifdef LINUXBIOS		else {			// Eden Chen			sishw_ext.pjVideoMemoryAddress			    = ioremap (ivideo.video_base, 0x2000000);			//SiSInit300(&sishw_ext);			SiSInit (&sishw_ext);			vgawb (SEQ_ADR, IND_SIS_PASSWORD);			vgawb (SEQ_DATA, SIS_PASSWORD);			// ~Eden Chen		}		vgawb (SEQ_ADR, 0x7);		reg = vgarb (SEQ_DATA);		reg |= 0x10;		vgawb (SEQ_DATA, reg);#endif		sisfb_get_dram_size_300 ();	}#endif	#ifdef CONFIG_FB_SIS_315	if (sisvga_engine == SIS_315_VGA) {		if (!sisvga_enabled) {			/* Mapping Max FB Size for 315 Init */			// Eden Chen			//sishw_ext.VirtualVideoMemoryAddress 			sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x8000000);			//SiSInit310(&sishw_ext);			SiSInit (&sishw_ext);				vgawb (SEQ_ADR, IND_SIS_PASSWORD);			vgawb (SEQ_DATA, SIS_PASSWORD);				sishw_ext.bSkipDramSizing = TRUE;			vgawb (SEQ_ADR, 0x13);			sishw_ext.pSR[0].jIdx = 0x13;			sishw_ext.pSR[0].jVal = vgarb (SEQ_DATA);			vgawb (SEQ_ADR, 0x14);			sishw_ext.pSR[1].jIdx = 0x14;			sishw_ext.pSR[1].jVal = vgarb (SEQ_DATA);			sishw_ext.pSR[2].jIdx = 0xFF;			sishw_ext.pSR[2].jVal = 0xFF;			// Eden Chen		}#ifdef LINUXBIOS		else {			sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x8000000);			SiSInit (&sishw_ext);			vgawb (SEQ_ADR, IND_SIS_PASSWORD);			vgawb (SEQ_DATA, SIS_PASSWORD);				sishw_ext.bSkipDramSizing = TRUE;			vgawb (SEQ_ADR, 0x13);			sishw_ext.pSR[0].jIdx = 0x13;			sishw_ext.pSR[0].jVal = vgarb (SEQ_DATA);			vgawb (SEQ_ADR, 0x14);			sishw_ext.pSR[1].jIdx = 0x14;			sishw_ext.pSR[1].jVal = vgarb (SEQ_DATA);			sishw_ext.pSR[2].jIdx = 0xFF;			sishw_ext.pSR[2].jVal = 0xFF;		}#endif		sisfb_get_dram_size_315 ();	}#endif	//Eden Chen 	vgawb (SEQ_ADR, IND_SIS_PCI_ADDRESS_SET);	reg = vgarb (SEQ_DATA);	reg |= SIS_PCI_ADDR_ENABLE;	reg |= SIS_MEM_MAP_IO_ENABLE;	vgawb (SEQ_DATA, reg);	vgawb (SEQ_ADR, IND_SIS_MODULE_ENABLE);	reg = vgarb (SEQ_DATA);	reg |= SIS_ENABLE_2D;	vgawb (SEQ_DATA, reg);	//~Eden Chen	// Eden Chen	sishw_ext.ulVideoMemorySize = ivideo.video_size;	// ~Eden Chen	if (!request_mem_region (ivideo.video_base, ivideo.video_size, "sisfb FB")) {		printk (KERN_ERR "sisfb: cannot reserve frame buffer memory\n");		return -ENODEV;	}	if (!request_mem_region (ivideo.mmio_base, sisfb_mmio_size, "sisfb MMIO")) {		printk (KERN_ERR "sisfb: cannot reserve MMIO region\n");		release_mem_region (ivideo.video_base, ivideo.video_size);		return -ENODEV;	}	// Eden Chen	//sishw_ext.VirtualVideoMemoryAddress = ivideo.video_vbase 	sishw_ext.pjVideoMemoryAddress = ivideo.video_vbase = ioremap (ivideo.video_base, ivideo.video_size);	// Eden Chen	ivideo.mmio_vbase = ioremap (ivideo.mmio_base, sisfb_mmio_size);	printk (KERN_INFO		"sisfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",		ivideo.video_base, ivideo.video_vbase, ivideo.video_size / 1024);	printk (KERN_INFO		"sisfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",		ivideo.mmio_base, ivideo.mmio_vbase, sisfb_mmio_size / 1024);	#ifdef CONFIG_FB_SIS_300	if (sisvga_engine == SIS_300_VGA) {		sisfb_get_VB_type_300 ();		if (ivideo.hasVB != HASVB_NONE) {			sisfb_detect_VB_connect_300 ();		}	}#endif#ifdef CONFIG_FB_SIS_315	if (sisvga_engine == SIS_315_VGA) {		sisfb_get_VB_type_315 ();		if (ivideo.hasVB != HASVB_NONE) {			sisfb_detect_VB_connect_315 ();		}	}#endif	// Eden Chensishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;sishw_ext.usExternalChip = 0;	switch (ivideo.hasVB) {	case HASVB_301:		/*karl */		vgawb (VB_PART4_ADR, 0x01);		reg = vgarb (VB_PART4_DATA);		if ((reg != 0xB1) && (reg != 0xB0))			sishw_ext.ujVBChipID = VB_CHIP_301;		else			sishw_ext.ujVBChipID = VB_CHIP_301B;		break;	case HASVB_302:		sishw_ext.ujVBChipID = VB_CHIP_302;		break;	case HASVB_303:		sishw_ext.ujVBChipID = VB_CHIP_303;		break;	case HASVB_LVDS:		sishw_ext.usExternalChip = 0x1;		break;	case HASVB_TRUMPION:		sishw_ext.usExternalChip = 0x2;		break;	case HASVB_CHRONTEL:		sishw_ext.usExternalChip = 0x4;		break;	case HASVB_LVDS_CHRONTEL:		sishw_ext.usExternalChip = 0x5;		break;	default:		break;	}	// ~Eden Chen	if (ivideo.disp_state & DISPTYPE_DISP2) {		if (sisfb_crt1off)			ivideo.disp_state |= DISPMODE_SINGLE;		else			ivideo.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);	} else		ivideo.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;	if (ivideo.disp_state & DISPTYPE_LCD) {		vgawb (CRTC_ADR, IND_SIS_LCD_PANEL);		reg = vgarb (CRTC_DATA);		// Eden Chen		switch (reg) {		case SIS_LCD_PANEL_800X600:			sishw_ext.ulCRT2LCDType = LCD_800x600;			break;		case SIS_LCD_PANEL_1024X768:			sishw_ext.ulCRT2LCDType = LCD_1024x768;			break;		case SIS_LCD_PANEL_1280X1024:			sishw_ext.ulCRT2LCDType = LCD_1280x1024;			break;		case SIS_LCD_PANEL_640X480:			sishw_ext.ulCRT2LCDType = LCD_640x480;			break;		case SIS_LCD_PANEL_1280X960:			sishw_ext.ulCRT2LCDType = LCD_1280x960;			break;		default:			sishw_ext.ulCRT2LCDType = LCD_1024x768;			break;		}	// ~Eden Chen	}	if (sisfb_mode_idx >= 0)		sisfb_validate_mode ();		if (sisfb_mode_idx < 0) {		switch (ivideo.disp_state & DISPTYPE_DISP2) {		case DISPTYPE_LCD:			sisfb_mode_idx = DEFAULT_LCDMODE;			break;		case DISPTYPE_TV:			sisfb_mode_idx = DEFAULT_TVMODE;			break;		default:			sisfb_mode_idx = DEFAULT_MODE;			break;		}	}		sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;		if (ivideo.refresh_rate != 0)		sisfb_search_refresh_rate (ivideo.refresh_rate);	if (sisfb_rate_idx == 0) {		sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;		ivideo.refresh_rate = 60;	}	ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;	ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;	ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;	ivideo.org_x = ivideo.org_y = 0;	video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);	printk (KERN_INFO "sisfb: mode is %dx%dx%d, linelength=%d\n",		ivideo.video_width, ivideo.video_height, ivideo.video_bpp,		video_linelength);	// Eden Chen	// Check interface correction  For Debug	DPRINTK ("VM Adr=0x%p\n", sishw_ext.pjVideoMemoryAddress);	DPRINTK ("VM Size=%ldK\n", sishw_ext.ulVideoMemorySize / 1024);	DPRINTK ("IO Adr=0x%lx\n", sishw_ext.ulIOAddress);	DPRINTK ("Chip=%d\n", sishw_ext.jChipType);	DPRINTK ("ChipRevision=%d\n", sishw_ext.jChipRevision);	DPRINTK ("VBChip=%d\n", sishw_ext.ujVBChipID);	DPRINTK ("ExtVB=%d\n", sishw_ext.usExternalChip);	DPRINTK ("LCD=%ld\n", sishw_ext.ulCRT2LCDType);	DPRINTK ("bIntegratedMMEnabled=%d\n", sishw_ext.bIntegratedMMEnabled);	// ~Eden Chen	sisfb_pre_setmode ();	if (SiSSetMode (&sishw_ext, sisfb_mode_no) == 0) {		DPRINTK ("set mode[0x%x]: failed\n", sisfb_mode_no);		return -1;	}	vgawb (SEQ_ADR, IND_SIS_PASSWORD);	vgawb (SEQ_DATA, SIS_PASSWORD);	// Eden Chen	sisfb_post_setmode ();	sisfb_crtc_to_var (&default_var);	fb_info.changevar = NULL;	fb_info.node = -1;	fb_info.fbops = &sisfb_ops;	fb_info.disp = &disp;	fb_info.switch_con = &sisfb_switch;	fb_info.updatevar = &sisfb_update_var;	fb_info.blank = &sisfb_blank;	fb_info.flags = FBINFO_FLAG_DEFAULT;	sisfb_set_disp (-1, &default_var);	if (sisfb_heap_init ()) {		DPRINTK ("sisfb: Failed to enable offscreen heap\n");	}		/*H.C. */	nRes = 	mtrr_add ((unsigned int) ivideo.video_base, (unsigned int) ivideo.video_size,  MTRR_TYPE_WRCOMB, 1);	v

⌨️ 快捷键说明

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