sis_main.c

来自「讲述linux的初始化过程」· C语言 代码 · 共 2,375 行 · 第 1/4 页

C
2,375
字号
	do_set_var(&fb_display[con].var, 1, info);	sisfb_set_disp(con, &fb_display[con].var);	/* Install new colormap */	do_install_cmap(con, info);	cols = sisbios_mode[mode_idx].cols;	rows = sisbios_mode[mode_idx].rows;	vc_resize_con(rows, cols, fb_display[con].conp->vc_num);	sisfb_update_var(con, info);	return 1;}/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */static void sisfb_blank(int blank, struct fb_info *info){	u8 CRData;	vgawb(CRTC_ADR, 0x17);	CRData = vgarb(CRTC_DATA);	if (blank > 0)		/* turn off CRT1 */		CRData &= 0x7f;	else			/* turn on CRT1 */		CRData |= 0x80;	vgawb(CRTC_ADR, 0x17);	vgawb(CRTC_DATA, CRData);}int has_VB(void){	u8 uSR38, uSR39, uVBChipID;	vgawb(SEQ_ADR, 0x38);	uSR38 = vgarb(SEQ_DATA);	vgawb(SEQ_ADR, 0x39);	uSR39 = vgarb(SEQ_DATA);	vgawb(IND_SIS_CRT2_PORT_14, 0x0);	uVBChipID = vgarb(IND_SIS_CRT2_PORT_14+1);	if (		( (HwExt.jChipID == SIS_Glamour) && (uSR38 & 0x20) ) /* 300 */		||		( (HwExt.jChipID >= SIS_Trojan ) && (uSR38 & 0x20) && (!(uSR39 & 0x80)) ) /* 630/540 */		||		( (HwExt.jChipID == SIS_Trojan ) && ((HwExt.revision_id & 0xf0) == 0x30) && (uVBChipID == 1) ) /* 630s */		||		( (HwExt.jChipID == SIS_730) && (uVBChipID == 1) ) /* 730 */	   )	{		ivideo.hasVB = HASVB_301;		return TRUE;	}	else	{		ivideo.hasVB = HASVB_NONE;		return FALSE;	}}void sis_get301info(void){	u8 uCRData;	unsigned long disp_state=0;	if (HwExt.jChipID >= SIS_Trojan)	{		if (!has_VB())		{			vgawb(CRTC_ADR, 0x37);			uCRData = vgarb(CRTC_DATA);			switch((uCRData >> 1) & 0x07)			{			case 2:				ivideo.hasVB = HASVB_LVDS;				break;			case 4:				ivideo.hasVB = HASVB_LVDS_CHRONTEL;				break;			case 3:				ivideo.hasVB = HASVB_TRUMPION;				break;			default:				break;			}		}	}	else	{		has_VB();	}	vgawb(CRTC_ADR, 0x32);	uCRData = vgarb(CRTC_DATA); 	switch(uDispType)	{	case MASK_DISPTYPE_CRT2: 		disp_state = DISPTYPE_CRT2;		break;	case MASK_DISPTYPE_LCD:		disp_state = DISPTYPE_LCD;		break;	case MASK_DISPTYPE_TV:		disp_state = DISPTYPE_TV;		break;	}	if(disp_state & 0x7)	{		if(crt1off)			disp_state |= DISPMODE_SINGLE;		else			disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);	}	else		disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;	ivideo.disp_state = disp_state;}int __init sisfb_init(void){	struct pci_dev *pdev = NULL;	struct board *b;	int pdev_valid = 0;	unsigned char jTemp;	u8 uSRData, uCRData;	outb(0x77, 0x80);	if (sisfb_off)		return -ENXIO;	pci_for_each_dev(pdev) {		for (b = dev_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, &HwExt.revision_id);				break;			}		}		if (pdev_valid)			break;	}	if (!pdev_valid)		return -1;	switch(ivideo.chip_id)	{	case PCI_DEVICE_ID_SI_300:		HwExt.jChipID = SIS_Glamour;		break;	case PCI_DEVICE_ID_SI_630_VGA:		HwExt.jChipID = SIS_Trojan;		break;	case PCI_DEVICE_ID_SI_540_VGA:		HwExt.jChipID = SIS_Spartan;		break;	case PCI_DEVICE_ID_SI_730_VGA:		HwExt.jChipID = SIS_730;		break;	}	ivideo.video_base = pci_resource_start(pdev, 0);	ivideo.mmio_base = pci_resource_start(pdev, 1);	ivideo.vga_base = pci_resource_start(pdev, 2) + 0x30;	HwExt.IOAddress = (unsigned short)ivideo.vga_base; 	rom_base = 0x000C0000;	MMIO_SIZE =  pci_resource_len(pdev, 1);#ifdef NOBIOS	if (pci_enable_device(pdev))		return -EIO;	/* Image file instead of VGA-bios */	HwExt.VirtualRomBase = rom_vbase = (unsigned long) RomData;#else#ifdef CONFIG_FB_SIS_LINUXBIOS	if (pci_enable_device(pdev))		return -EIO;	HwExt.VirtualRomBase = rom_vbase = 0;#else	request_region(rom_base, 32, "sisfb");	HwExt.VirtualRomBase = rom_vbase 		= (unsigned long) ioremap(rom_base, MAX_ROM_SCAN);#endif#endif	/* set passwd */	vgawb(SEQ_ADR, IND_SIS_PASSWORD);	vgawb(SEQ_DATA, SIS_PASSWORD);	/* Enable MMIO & PCI linear address */	vgawb(SEQ_ADR, IND_SIS_PCI_ADDRESS_SET);	jTemp = vgarb(SEQ_DATA);	jTemp |= SIS_PCI_ADDR_ENABLE;	jTemp |= SIS_MEM_MAP_IO_ENABLE;	vgawb(SEQ_DATA, jTemp);#ifdef CONFIG_FB_SIS_LINUXBIOS	pdev_valid = 0;	pci_for_each_dev(pdev) {		u8 uPCIData=0;		if ((pdev->vendor == PCI_VENDOR_ID_SI) && (pdev->device==0x630)) 		{			pci_read_config_byte(pdev, 0x63, &uPCIData);			uPCIData = (uPCIData & 0x70) >> 4;			ivideo.video_size = (unsigned int)(1 << (uPCIData+21));			pdev_valid = 1;			break;		}	}	if (!pdev_valid)		return -1;#else	vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE);	ivideo.video_size = ((unsigned int) ((vgarb(SEQ_DATA) & 0x3f) + 1) << 20);#endif	/* get CRT2 connection state */	vgawb(SEQ_ADR, 0x17);	uSRData = vgarb(SEQ_DATA);	vgawb(CRTC_ADR, 0x32);	uCRData = vgarb(CRTC_DATA);	ivideo.TV_plug = ivideo.TV_type = 0;	if((uSRData&0x0F) && (HwExt.jChipID>=SIS_Trojan))	{		/* CRT1 connect detection */		if((uSRData & 0x01) && !crt1off)			crt1off = 0;		else		{			if(uSRData&0x0E)     /* DISP2 connected */				crt1off = 1;			else				crt1off = 0;		}		/* detection priority : CRT2 > LCD > TV */		if(uSRData & 0x08 )			uDispType = MASK_DISPTYPE_CRT2;		else if(uSRData & 0x02)			uDispType = MASK_DISPTYPE_LCD;		else if(uSRData & 0x04)		{			if(uSRData & 0x80)			{				ivideo.TV_type = TVMODE_HIVISION;				ivideo.TV_plug = TVPLUG_SVIDEO;			}			else if(uSRData & 0x20)				ivideo.TV_plug = TVPLUG_SVIDEO;			else if(uSRData & 0x10)				ivideo.TV_plug = TVPLUG_COMPOSITE;			else if(uSRData & 0x40)				ivideo.TV_plug = TVPLUG_SCART;			if(ivideo.TV_type == 0)			{				u8 uSR16;				vgawb(SEQ_ADR, 0x16);				uSR16 = vgarb(SEQ_DATA);				if(uSR16 & 0x20)					ivideo.TV_type = TVMODE_PAL;				else					ivideo.TV_type = TVMODE_NTSC;			}			uDispType = MASK_DISPTYPE_TV;		}	} 	else	{		if((uCRData & 0x20) && !crt1off)			crt1off = 0;		else		{			if(uCRData&0x5F)   /* DISP2 connected */				crt1off = 1;			else				crt1off = 0;		}		if(uCRData & 0x10)			uDispType = MASK_DISPTYPE_CRT2;		else if(uCRData & 0x08)			uDispType = MASK_DISPTYPE_LCD;		else if(uCRData & 0x47)		{			uDispType = MASK_DISPTYPE_TV;			if(uCRData & 0x40)			{				ivideo.TV_type = TVMODE_HIVISION;				ivideo.TV_plug = TVPLUG_SVIDEO;			}			else if(uCRData & 0x02)				ivideo.TV_plug = TVPLUG_SVIDEO;			else if(uCRData & 0x01)				ivideo.TV_plug = TVPLUG_COMPOSITE;			else if(uCRData & 0x04)				ivideo.TV_plug = TVPLUG_SCART;			if(ivideo.TV_type == 0)			{				u8 uTemp;				uTemp = *((u8 *)(HwExt.VirtualRomBase+0x52));				if(uTemp&0x40)				{					uTemp=*((u8 *)(HwExt.VirtualRomBase+0x53));				}				else				{					vgawb(SEQ_ADR, 0x38);					uTemp = vgarb(SEQ_DATA);				}				if(uTemp & 0x01)					ivideo.TV_type = TVMODE_PAL;				else					ivideo.TV_type = TVMODE_NTSC;			}		}	}	if(uDispType == MASK_DISPTYPE_LCD)   // LCD conntected	{		// TODO: set LCDType by EDID		HwExt.usLCDType = LCD1024;	}	if (HwExt.jChipID >= SIS_Trojan)	{		vgawb(SEQ_ADR, 0x1A);		uSRData = vgarb(SEQ_DATA);		if (uSRData & 0x10)			HwExt.bIntegratedMMEnabled = TRUE;		else			HwExt.bIntegratedMMEnabled = FALSE;	}	if(mode_idx >= 0)	/* mode found */	{		/* Filtering mode for VB */		switch(uDispType & MASK_DISPTYPE_DISP2)		{		case MASK_DISPTYPE_LCD:			switch(HwExt.usLCDType)			{	    	case LCD1024:				if(sisbios_mode[mode_idx].xres > 1024)					mode_idx = -1;				break;	    	case LCD1280:				if(sisbios_mode[mode_idx].xres > 1280)					mode_idx = -1;				break;	    	case LCD2048:				if(sisbios_mode[mode_idx].xres > 2048)					mode_idx = -1;				break;	    	case LCD1920:				if(sisbios_mode[mode_idx].xres > 1920)					mode_idx = -1;				break;	    	case LCD1600:				if(sisbios_mode[mode_idx].xres > 1600)					mode_idx = -1;				break;	    	case LCD800:				if(sisbios_mode[mode_idx].xres > 800)					mode_idx = -1;				break;	    	case LCD640:				if(sisbios_mode[mode_idx].xres > 640)					mode_idx = -1;				break;			default:				mode_idx = -1;			}			if(sisbios_mode[mode_idx].xres == 720)  /* only for TV */				mode_idx = -1;			break;		case MASK_DISPTYPE_TV:			switch(sisbios_mode[mode_idx].xres)			{			case 800:			case 640:				break;			case 720:				if(ivideo.TV_type == TVMODE_NTSC)				{					if(sisbios_mode[mode_idx].yres != 480)						mode_idx = -1;				}				else if(ivideo.TV_type == TVMODE_PAL)				{					if(sisbios_mode[mode_idx].yres != 576)						mode_idx = -1;				}				break;			default:				/* illegal mode */				mode_idx = -1;			}			break;		}	}			if (mode_idx < 0)	{		switch(uDispType & MASK_DISPTYPE_DISP2)		{		case MASK_DISPTYPE_LCD:			mode_idx = DEFAULT_LCDMODE;			break;		case MASK_DISPTYPE_TV:			mode_idx = DEFAULT_TVMODE;			break;		default:			mode_idx = DEFAULT_MODE;		}	}#ifdef CONFIG_FB_SIS_LINUXBIOS	mode_idx = DEFAULT_MODE;	rate_idx = sisbios_mode[mode_idx].rate_idx;	/* set to default refresh rate 60MHz */	ivideo.refresh_rate = 60;#endif	mode_no = sisbios_mode[mode_idx].mode_no;	if (ivideo.refresh_rate != 0)		search_refresh_rate(ivideo.refresh_rate);	if (rate_idx == 0) {		rate_idx = sisbios_mode[mode_idx].rate_idx;			/* set to default refresh rate 60MHz */		ivideo.refresh_rate = 60;	}	ivideo.video_bpp = sisbios_mode[mode_idx].bpp;	ivideo.video_vwidth = ivideo.video_width = sisbios_mode[mode_idx].xres;	ivideo.video_vheight = ivideo.video_height = sisbios_mode[mode_idx].yres;	ivideo.org_x = ivideo.org_y = 0;	video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);	printk(KERN_DEBUG "FB base: 0x%lx, size: 0x%dK\n", 		ivideo.video_base, (unsigned int)ivideo.video_size/1024);	printk(KERN_DEBUG "MMIO base: 0x%lx, size: 0x%dK\n", 		ivideo.mmio_base, (unsigned int)MMIO_SIZE/1024);	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, MMIO_SIZE, "sisfb MMIO")) 	{		printk(KERN_ERR "sisfb: cannot reserve MMIO region\n");		release_mem_region(ivideo.video_base, ivideo.video_size);		return -ENODEV;	}	HwExt.VirtualVideoMemoryAddress = ivideo.video_vbase 		= ioremap(ivideo.video_base, ivideo.video_size);	ivideo.mmio_vbase = ioremap(ivideo.mmio_base, MMIO_SIZE);#ifdef NOBIOS	SiSInit300(&HwExt);#else#ifdef CONFIG_FB_SIS_LINUXBIOS	SiSInit300(&HwExt);#endif#endif	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: mode is %dx%dx%d, linelength=%d\n",	       ivideo.video_width, ivideo.video_height, ivideo.video_bpp,	       video_linelength);	/* enable 2D engine */	vgawb(SEQ_ADR, IND_SIS_MODULE_ENABLE);	jTemp = vgarb(SEQ_DATA);	jTemp |= SIS_2D_ENABLE;	vgawb(SEQ_DATA, jTemp);	pre_setmode();	if (SiSSetMode(&HwExt, mode_no)) {		DPRINTK("sisfb: set mode[0x%x]: failed\n", mode_no);		return -1;	}	post_setmode();	/* Get VB functions */	sis_get301info();	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");	}	/* to avoid the inversed bgcolor bug of the initial state */	vc_resize_con(1, 1, 0);	if (register_framebuffer(&fb_info) < 0)		return -EINVAL;	printk(KERN_INFO "fb%d: %s frame buffer device\n",	       GET_FB_IDX(fb_info.node), fb_info.modename);	return 0;}#ifdef MODULEstatic char *mode = NULL;static unsigned int rate = 0;static unsigned int crt1 = 1;MODULE_PARM(mode, "s");MODULE_PARM(rate, "i");MODULE_PARM(crt1, "i");	/* default: CRT1 enable */int init_module(void){	if (mode)		search_mode(mode);	ivideo.refresh_rate = rate;	if(crt1 == 0)		crt1off = 1;	else		crt1off = 0;		sisfb_init();	return 0;}void cleanup_module(void){	unregister_framebuffer(&fb_info);}#endif				/* MODULE */EXPORT_SYMBOL(sis_malloc);EXPORT_SYMBOL(sis_free);EXPORT_SYMBOL(ivideo);

⌨️ 快捷键说明

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