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

📄 sis_main.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 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 * * Partly based on the VBE 2.0 compliant graphic boards framebuffer driver, * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> * * Authors:   	SiS (www.sis.com.tw) *		(Various others) *		Thomas Winischhofer <thomas@winischhofer.net>: *			- many fixes and enhancements for all chipset series, *			- extended bridge handling, TV output for Chrontel 7005 *                      - 650/LVDS support (for LCD panels up to 1400x1050) *                      - 650/Chrontel 7019 support *                      - 301B/301LV(x)/302B/302LV(x) LCD and TV support *			- memory queue handling enhancements, *                      - 2D acceleration and y-panning, *                      - portation to 2.5 API (yet incomplete) *			- everything marked with "TW" and more *			(see http://www.winischhofer.net/ *			for more information and updates) */#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>#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,33)#include <linux/spinlock.h>#endif#include "osdef.h"#include <linux/types.h>#include <linux/sisfb.h>#include <asm/io.h>#include <asm/mtrr.h>#include <video/fbcon.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>#include <video/fbcon-cfb24.h>#include <video/fbcon-cfb32.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)#include "../fbcon-accel.h"#endif#include "vgatypes.h"#include "sis_main.h"#include "sis.h"//#ifdef LINUXBIOS//#include "bios.h"//#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,33)#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#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)/* TEMP */void my_cfb_imageblit(struct fb_info *info, struct fb_image *image);#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 to BIOS 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;		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;}/* -------------------- Exported functions ----------------------------- */static void sis_get_glyph(struct fb_info *info, SIS_GLYINFO *gly){#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)#define currcon info->currcon#endif	struct display *p = &fb_display[currcon];	u16 c;	u8 *cdat;	int widthb;	u8 *gbuf = gly->gmask;	int size;	TWDEBUG("Inside get_glyph");	gly->fontheight = fontheight(p);	gly->fontwidth = fontwidth(p);	widthb = (fontwidth(p) + 7) / 8;	c = gly->ch & p->charmask;	if (fontwidth(p) <= 8)		cdat = p->fontdata + c * fontheight(p);	else		cdat = p->fontdata + (c * fontheight(p) << 1);	size = fontheight(p) * widthb;	memcpy(gbuf, cdat, size);	gly->ngmask = size;	TWDEBUG("End of get_glyph");#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)#undef currcon #endif}void sis_dispinfo(struct ap_data *rec){        TWDEBUG("Inside dispinfo");	rec->minfo.bpp    = ivideo.video_bpp;	rec->minfo.xres   = ivideo.video_width;	rec->minfo.yres   = ivideo.video_height;	rec->minfo.v_xres = ivideo.video_vwidth;	rec->minfo.v_yres = ivideo.video_vheight;	rec->minfo.org_x  = ivideo.org_x;	rec->minfo.org_y  = ivideo.org_y;	rec->minfo.vrate  = ivideo.refresh_rate;	rec->iobase       = ivideo.vga_base - 0x30;	rec->mem_size     = ivideo.video_size;	rec->disp_state   = ivideo.disp_state; 	rec->version      = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL; 	rec->hasVB        = ivideo.hasVB; 	rec->TV_type      = ivideo.TV_type; 	rec->TV_plug      = ivideo.TV_plug; 	rec->chip         = ivideo.chip;	TWDEBUG("End of dispinfo");}/* ------------------ Internal Routines ------------------------------ */static void sisfb_search_mode(const char *name){	int i = 0, j = 0;	if(name == NULL)		return;	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_INFO "sisfb: Invalid mode '%s'\n", name);}static void sisfb_search_vesamode(unsigned int vesamode){	int i = 0, j = 0;	if(vesamode == 0) {		sisfb_mode_idx = MODE_INDEX_NONE;		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_INFO "sisfb: Invalid VESA mode 0x%x'\n", vesamode);}static int sisfb_validate_mode(int myindex){   u16 xres, yres;#ifdef CONFIG_FB_SIS_300   if(sisvga_engine == SIS_300_VGA) {       if(!(sisbios_mode[sisfb_mode_idx].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 (ivideo.disp_state & DISPTYPE_DISP2) {     case DISPTYPE_LCD:	switch (sishw_ext.ulCRT2LCDType) {	case LCD_1024x768:	 	xres = 1024; yres =  768;  break;	case LCD_1280x1024:		xres = 1280; yres = 1024;  break;	case LCD_1280x960:	        xres = 1280; yres =  960;  break;	case LCD_2048x1536:		xres = 2048; yres = 1536;  break;	case LCD_1920x1440:		xres = 1920; yres = 1440;  break;	case LCD_1600x1200:		xres = 1600; yres = 1200;  break;	case LCD_800x600:		xres =  800; yres =  600;  break;	case LCD_640x480:		xres =  640; yres =  480;  break;	case LCD_320x480:				/* TW: FSTN */		xres =  320; yres =  480;  break;        case LCD_1024x600:		xres = 1024; yres =  600;  break;	case LCD_1152x864:		xres = 1152; yres =  864;  break;	case LCD_1152x768:		xres = 1152; yres =  768;  break;	case LCD_1280x768:		xres = 1280; yres =  768;  break;	case LCD_1400x1050:		xres = 1400; yres = 1050;  break;	default:	        xres =    0; yres =    0;  break;	}	if(sisbios_mode[myindex].xres > xres) {	        return(-1);	}        if(sisbios_mode[myindex].yres > yres) {	        return(-1);	}	if (sisbios_mode[myindex].xres == 720) {		return(-1);	}	break;     case DISPTYPE_TV:	switch (sisbios_mode[myindex].xres) {	case 512:	case 640:	case 800:		break;	case 720:		if (ivideo.TV_type == TVMODE_NTSC) {			if (sisbios_mode[myindex].yres != 480) {				return(-1);			}		} else if (ivideo.TV_type == TVMODE_PAL) {			if (sisbios_mode[myindex].yres != 576) {				return(-1);			}		}		/* TW: LVDS/CHRONTEL does not support 720 */		if (ivideo.hasVB == HASVB_LVDS_CHRONTEL ||					ivideo.hasVB == HASVB_CHRONTEL) {				return(-1);		}		break;	case 1024:		if (ivideo.TV_type == TVMODE_NTSC) {			if(sisbios_mode[myindex].bpp == 32) {			       return(-1);			}		}		/* TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)*/		if (ivideo.hasVB == HASVB_LVDS_CHRONTEL ||					ivideo.hasVB == HASVB_CHRONTEL) {		    if(ivideo.chip < SIS_315H) {				return(-1);		    }		}		break;	default:		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_INFO "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_INFO "sisfb: Invalid queuemode type: %s\n", name);}static u8 sisfb_search_refresh_rate(unsigned int rate){	u16 xres, yres;	int i = 0;	xres = sisbios_mode[sisfb_mode_idx].xres;	yres = sisbios_mode[sisfb_mode_idx].yres;	sisfb_rate_idx = 0;	while ((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {		if ((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {			if (sisfb_vrate[i].refresh == rate) {				sisfb_rate_idx = sisfb_vrate[i].idx;				break;			} else if (sisfb_vrate[i].refresh > rate) {				if ((sisfb_vrate[i].refresh - rate) <= 2) {					DPRINTK("sisfb: Adjusting rate from %d up to %d\n",						rate, sisfb_vrate[i].refresh);					sisfb_rate_idx = sisfb_vrate[i].idx;					ivideo.refresh_rate = sisfb_vrate[i].refresh;				} else if (((rate - sisfb_vrate[i-1].refresh) <= 2)						&& (sisfb_vrate[i].idx != 1)) {					DPRINTK("sisfb: Adjusting rate from %d down to %d\n",						rate, sisfb_vrate[i-1].refresh);					sisfb_rate_idx = sisfb_vrate[i-1].idx;					ivideo.refresh_rate = sisfb_vrate[i-1].refresh;				}				break;			}		}		i++;	}	if (sisfb_rate_idx > 0) {		return sisfb_rate_idx;	} else {		printk(KERN_INFO			"sisfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);		return 0;	}}#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,			 unsigned *transp, struct fb_info *fb_info){	if (regno >= ivideo.video_cmap_len)		return 1;	*red = sis_palette[regno].red;	*green = sis_palette[regno].green;	*blue = sis_palette[regno].blue;	*transp = 0;	return 0;}#endifstatic int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,

⌨️ 快捷键说明

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