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

📄 sis_main.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * SiS 300/630/730/540/315/550/650/740 frame buffer device * for Linux kernels 2.4.x and 2.5.x * * Authors:   	SiS (www.sis.com.tw) *		Thomas Winischhofer <thomas@winischhofer.net>: *			- SiS Xabre (330) support *			- many fixes and enhancements for all chipset series, *			- extended bridge handling, TV output for Chrontel 7005 *                      - 650/740/LVDS support (for LCD panels up to 1600x1200) *                      - 650/740/Chrontel 7019 support (LCD and TV) *                      - 30xB/30xLV LCD, TV and VGA2 support *			- memory queue handling enhancements, *                      - 2D acceleration and y-panning, *                      - rewritten for 2.5 API (>= 2.5.63) *			- etc. *			(see http://www.winischhofer.net/ *			for more information and updates) * * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver, * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> * */#include <linux/config.h>#include <linux/version.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/fb.h>#include <linux/console.h>#include <linux/selection.h>#include <linux/ioport.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/vt_kern.h>#include <linux/capability.h>#include <linux/fs.h>#include <linux/agp_backend.h>#include <linux/types.h>#include <asm/uaccess.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)#include <linux/spinlock.h>#endif#include "osdef.h"#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)#include <video/sisfb.h>#else#include <linux/sisfb.h>#endif#include <asm/io.h>#ifdef CONFIG_MTRR#include <asm/mtrr.h>#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)#include <video/fbcon.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>#include <video/fbcon-cfb24.h>#include <video/fbcon-cfb32.h>#endif#include "vgatypes.h"#include "sis_main.h"#include "sis.h"#if 0#ifdef LINUXBIOS#include "bios.h"#endif#endif/* -------------------- Macro definitions ---------------------------- */#undef SISFBDEBUG 	/* TW: no debugging */#ifdef SISFBDEBUG#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)#else#define DPRINTK(fmt, args...)#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)#ifdef SISFBACCEL#ifdef FBCON_HAS_CFB8extern struct display_switch fbcon_sis8;#endif#ifdef FBCON_HAS_CFB16extern struct display_switch fbcon_sis16;#endif#ifdef FBCON_HAS_CFB32extern struct display_switch fbcon_sis32;#endif#endif#endif/* --------------- Hardware Access Routines -------------------------- */void sisfb_set_reg4(u16 port, unsigned long data){	outl((u32) (data & 0xffffffff), port);}u32 sisfb_get_reg3(u16 port){	u32 data;	data = inl(port);	return (data);}/* ------------ Interface for init & mode switching code ------------- */BOOLEANsisfb_query_VGA_config_space(PSIS_HW_DEVICE_INFO psishw_ext,	unsigned long offset, unsigned long set, unsigned long *value){	static struct pci_dev *pdev = NULL;	static unsigned char init = 0, valid_pdev = 0;	if (!set)		DPRINTK("sisfb: Get VGA offset 0x%lx\n", offset);	else		DPRINTK("sisfb: Set offset 0x%lx to 0x%lx\n", offset, *value);	if (!init) {		init = TRUE;		pci_for_each_dev(pdev) {			DPRINTK("sisfb: Current: 0x%x, target: 0x%x\n",			         pdev->device, ivideo.chip_id);			if ((pdev->vendor == PCI_VENDOR_ID_SI)			           && (pdev->device == ivideo.chip_id)) {				valid_pdev = TRUE;				break;			}		}	}	if (!valid_pdev) {		printk(KERN_DEBUG "sisfb: Can't find SiS %d VGA device.\n",				ivideo.chip_id);		return FALSE;	}	if (set == 0)		pci_read_config_dword(pdev, offset, (u32 *)value);	else		pci_write_config_dword(pdev, offset, (u32)(*value));	return TRUE;}BOOLEAN sisfb_query_north_bridge_space(PSIS_HW_DEVICE_INFO psishw_ext,	unsigned long offset, unsigned long set, unsigned long *value){	static struct pci_dev *pdev = NULL;	static unsigned char init = 0, valid_pdev = 0;	u16 nbridge_id = 0;	if (!init) {		init = TRUE;		switch (ivideo.chip) {		case SIS_540:			nbridge_id = PCI_DEVICE_ID_SI_540;			break;		case SIS_630:			nbridge_id = PCI_DEVICE_ID_SI_630;			break;		case SIS_730:			nbridge_id = PCI_DEVICE_ID_SI_730;			break;		case SIS_550:			nbridge_id = PCI_DEVICE_ID_SI_550;			break;		case SIS_650:			nbridge_id = PCI_DEVICE_ID_SI_650;			break;		case SIS_740:						nbridge_id = PCI_DEVICE_ID_SI_740;			break;		default:			nbridge_id = 0;			break;		}		pci_for_each_dev(pdev) {			DPRINTK("Current: 0x%x, target: 0x%x\n",					pdev->device, ivideo.chip_id);			if ((pdev->vendor == PCI_VENDOR_ID_SI)					&& (pdev->device == nbridge_id)) {				valid_pdev = TRUE;				break;			}		}	}	if (!valid_pdev) {		printk(KERN_DEBUG "sisfb: Can't find SiS %d North Bridge device.\n",				nbridge_id);		return FALSE;	}	if (set == 0)		pci_read_config_dword(pdev, offset, (u32 *)value);	else		pci_write_config_dword(pdev, offset, (u32)(*value));	return TRUE;}/* ------------------ Internal helper routines ----------------- */static void sisfb_search_mode(const char *name){	int i = 0, j = 0;	if(name == NULL) {	   printk(KERN_ERR "sisfb: Internal error, using default mode.\n");	   sisfb_mode_idx = DEFAULT_MODE;	   return;	}		#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)		        if (!strcmp(name, sisbios_mode[MODE_INDEX_NONE].name)) {	   printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");	   sisfb_mode_idx = DEFAULT_MODE;	   return;	}#endif			while(sisbios_mode[i].mode_no != 0) {		if (!strcmp(name, sisbios_mode[i].name)) {			sisfb_mode_idx = i;			j = 1;			break;		}		i++;	}	if(!j) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", name);}static void sisfb_search_vesamode(unsigned int vesamode){	int i = 0, j = 0;	if(vesamode == 0) {#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)			sisfb_mode_idx = MODE_INDEX_NONE;#else		printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");		sisfb_mode_idx = DEFAULT_MODE;#endif				return;	}	vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */	while(sisbios_mode[i].mode_no != 0) {		if( (sisbios_mode[i].vesa_mode_no_1 == vesamode) ||		    (sisbios_mode[i].vesa_mode_no_2 == vesamode) ) {			sisfb_mode_idx = i;			j = 1;			break;		}		i++;	}	if(!j) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);}static int sisfb_validate_mode(int myindex, unsigned long vbflags){   u16 xres, yres;#ifdef CONFIG_FB_SIS_300   if(sisvga_engine == SIS_300_VGA) {       if(!(sisbios_mode[myindex].chipset & MD_SIS300)) {           return(-1);       }   }#endif#ifdef CONFIG_FB_SIS_315   if(sisvga_engine == SIS_315_VGA) {       if(!(sisbios_mode[myindex].chipset & MD_SIS315)) {	   return(-1);       }   }#endif   switch (vbflags & VB_DISPTYPE_DISP2) {     case CRT2_LCD:	switch (sishw_ext.ulCRT2LCDType) {	case LCD_640x480:		xres =  640; yres =  480;  break;	case LCD_800x600:		xres =  800; yres =  600;  break;        case LCD_1024x600:		xres = 1024; yres =  600;  break;			case LCD_1024x768:	 	xres = 1024; yres =  768;  break;	case LCD_1152x768:		xres = 1152; yres =  768;  break;			case LCD_1280x960:	        xres = 1280; yres =  960;  break;			case LCD_1280x768:		xres = 1280; yres =  768;  break;	case LCD_1280x1024:		xres = 1280; yres = 1024;  break;	case LCD_1400x1050:		xres = 1400; yres = 1050;  break;			case LCD_1600x1200:		xres = 1600; yres = 1200;  break;	case LCD_320x480:				/* TW: FSTN */		xres =  320; yres =  480;  break;	default:	        xres =    0; yres =    0;  break;	}	if(sisbios_mode[myindex].xres > xres) {	        return(-1);	}        if(sisbios_mode[myindex].yres > yres) {	        return(-1);	}	if(vbflags & (VB_LVDS | VB_30xBDH)) {	   switch (sisbios_mode[myindex].xres) {	   	case 320:			if((sisbios_mode[myindex].yres != 200) &&	           	   (sisbios_mode[myindex].yres != 240) &&			   (sisbios_mode[myindex].yres != 480))		          	return -1;			if(sisbios_mode[myindex].yres == 480) {			   	if(!enable_dstn) return -1;			}			break;		case 400:	       		if(sisbios_mode[myindex].yres != 300) return -1;	       		break;	   	case 512:	       		if(sisbios_mode[myindex].yres != 384) return -1;			if(sishw_ext.ulCRT2LCDType == LCD_1024x600) return -1;	       		break;	   	case 640:		       	if((sisbios_mode[myindex].yres != 400) &&	           	   (sisbios_mode[myindex].yres != 480))		          	return -1;	       		break;	   	case 800:		       	if(sisbios_mode[myindex].yres != 600) return -1;	       		break;	   	case 1024:		       	if((sisbios_mode[myindex].yres != 600) &&	           	   (sisbios_mode[myindex].yres != 768))		          	return -1;			if((sisbios_mode[myindex].yres == 600) &&			   (sishw_ext.ulCRT2LCDType != LCD_1024x600))			   	return -1;			break;		case 1152:			if((sisbios_mode[myindex].yres) != 768) return -1;			if(sishw_ext.ulCRT2LCDType != LCD_1152x768) return -1;			break;	   	case 1280:		   	if((sisbios_mode[myindex].yres != 768) &&	           	   (sisbios_mode[myindex].yres != 1024))		          	return -1;			if((sisbios_mode[myindex].yres == 768) &&			   (sishw_ext.ulCRT2LCDType != LCD_1280x768))			   	return -1;							break;	   	case 1400:		   	if(sisbios_mode[myindex].yres != 1050) return -1;			break;	   	case 1600:		   	if(sisbios_mode[myindex].yres != 1200) return -1;			break;	   	default:		        return -1;			   }	} else {	   switch (sisbios_mode[myindex].xres) {	   	case 320:			if((sisbios_mode[myindex].yres != 200) &&	           	   (sisbios_mode[myindex].yres != 240))		          	return -1;			break;		case 400:	       		if(sisbios_mode[myindex].yres != 300) return -1;	       		break;	   	case 512:	       		if(sisbios_mode[myindex].yres != 384) return -1;	       		break;	   	case 640:		       	if((sisbios_mode[myindex].yres != 400) &&	           	   (sisbios_mode[myindex].yres != 480))		          	return -1;	       		break;	   	case 800:		       	if(sisbios_mode[myindex].yres != 600) return -1;	       		break;	   	case 1024:		       	if(sisbios_mode[myindex].yres != 768) return -1;			break;	   	case 1280:		   	if((sisbios_mode[myindex].yres != 960) &&	           	   (sisbios_mode[myindex].yres != 1024))		          	return -1;			if(sisbios_mode[myindex].yres == 960) {			    if(sishw_ext.ulCRT2LCDType == LCD_1400x1050) 			   	return -1;			}			break;	   	case 1400:		   	if(sisbios_mode[myindex].yres != 1050) return -1;			break;	   	case 1600:		   	if(sisbios_mode[myindex].yres != 1200) return -1;			break;	   	default:		        return -1;			   }	}	break;     case CRT2_TV:	switch (sisbios_mode[myindex].xres) {	case 512:		if(vbflags & VB_CHRONTEL) return -1;		/* fall through */	case 640:	case 800:		break;	case 720:		if (vbflags & VB_CHRONTEL) return -1;		if (vbflags & TV_NTSC) {			if (sisbios_mode[myindex].yres != 480) {				return -1;			}		} else if (vbflags & TV_PAL) {			if (sisbios_mode[myindex].yres != 576) {				return -1;			}		}		break;	case 1024:		if (vbflags & VB_301) return -1;		if (vbflags & VB_CHRONTEL) {		    if(ivideo.chip < SIS_315H) {				return(-1);		    }		}		if (vbflags & TV_NTSC) {			if(sisbios_mode[myindex].bpp == 32) {			       return(-1);			}		}		break;	default:		return -1;	}	break;     case CRT2_VGA:	        if(sisbios_mode[myindex].xres > 1280) return -1;	break;	     }     return(myindex);}static void sisfb_search_crt2type(const char *name){	int i = 0;	if(name == NULL)		return;	while(sis_crt2type[i].type_no != -1) {		if (!strcmp(name, sis_crt2type[i].name)) {			sisfb_crt2type = sis_crt2type[i].type_no;			sisfb_tvplug = sis_crt2type[i].tvplug_no;			break;		}		i++;	}	if(sisfb_crt2type < 0)		printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);}static void sisfb_search_queuemode(const char *name){	int i = 0;	if(name == NULL)		return;	while (sis_queuemode[i].type_no != -1) {		if (!strcmp(name, sis_queuemode[i].name)) {			sisfb_queuemode = sis_queuemode[i].type_no;			break;		}		i++;	}	if (sisfb_queuemode < 0)		printk(KERN_ERR "sisfb: Invalid queuemode type: %s\n", name);

⌨️ 快捷键说明

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