sis_main.c
来自「Linux内核源代码 为压缩文件 是<<Linux内核>>」· C语言 代码 · 共 2,375 行 · 第 1/4 页
C
2,375 行
/* * SiS 300/630/540 frame buffer device For Kernal 2.4.x * * This driver is partly based on the VBE 2.0 compliant graphic * boards framebuffer driver, which is * * (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> * */#define EXPORT_SYMTAB#undef SISFBDEBUG#include <linux/config.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/malloc.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/sisfb.h>#include <linux/fs.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>#include "sis.h"#ifdef NOBIOS#include "bios.h"#endif/* ------------------- Constant Definitions ------------------------- *//* capabilities */#define TURBO_QUEUE_CAP 0x80#define HW_CURSOR_CAP 0x40/* VGA register Offsets */#define SEQ_ADR (0x14)#define SEQ_DATA (0x15)#define DAC_ADR (0x18)#define DAC_DATA (0x19)#define CRTC_ADR (0x24)#define CRTC_DATA (0x25)#define DAC2_ADR 0x16 - 0x30#define DAC2_DATA 0x17 - 0x30/* SiS indexed register indexes */#define IND_SIS_PASSWORD (0x05)#define IND_SIS_DRAM_SIZE (0x14)#define IND_SIS_MODULE_ENABLE (0x1E)#define IND_SIS_PCI_ADDRESS_SET (0x20)#define IND_SIS_TURBOQUEUE_ADR (0x26)#define IND_SIS_TURBOQUEUE_SET (0x27)/* Sis register value */#define SIS_PASSWORD (0x86)#define SIS_2D_ENABLE (0x40)#define SIS_MEM_MAP_IO_ENABLE (0x01)#define SIS_PCI_ADDR_ENABLE (0x80)//#define MMIO_SIZE 0x10000 /* 64K MMIO capability */#define MAX_ROM_SCAN 0x10000#define RESERVED_MEM_SIZE_4M 0x400000 /* 4M */#define RESERVED_MEM_SIZE_8M 0x800000 /* 8M *//* Mode set stuff */#define DEFAULT_MODE 0 /* 640x480x8 */#define DEFAULT_LCDMODE 9 /* 800x600x8 */#define DEFAULT_TVMODE 9 /* 800x600x8 *//* heap stuff */#define OH_ALLOC_SIZE 4000#define SENTINEL 0x7fffffff#define TURBO_QUEUE_AREA_SIZE 0x80000 /* 512K */#define HW_CURSOR_AREA_SIZE 0x1000 /* 4K *//* ------------------- Global Variables ----------------------------- */struct video_info ivideo;HW_DEVICE_EXTENSION HwExt={0,0,0,0,0,0};struct GlyInfo { unsigned char ch; int fontwidth; int fontheight; u8 gmask[72]; int ngmask;};/* Supported SiS Chips list */static struct board { u16 vendor, device; const char *name;} dev_list[] = { {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300, "SIS 300"}, {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, "SIS 540"}, {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, "SIS 630"}, {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_730_VGA, "SIS 730"}, {0, 0, NULL}};/* card parameters */unsigned long rom_base;unsigned long rom_vbase;/* mode */static int video_type = FB_TYPE_PACKED_PIXELS;static int video_linelength;static int video_cmap_len;static int sisfb_off = 0;static int crt1off = 0;static struct fb_var_screeninfo default_var = { 0, 0, 0, 0, 0, 0, 0, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, FB_ACTIVATE_NOW, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, FB_VMODE_NONINTERLACED, {0, 0, 0, 0, 0, 0}};static struct display disp;static struct fb_info fb_info;static struct { u16 blue, green, red, pad;} palette[256];static union {#ifdef FBCON_HAS_CFB16 u16 cfb16[16];#endif#ifdef FBCON_HAS_CFB24 u32 cfb24[16];#endif#ifdef FBCON_HAS_CFB32 u32 cfb32[16];#endif} fbcon_cmap;static int inverse = 0;static int currcon = 0;static struct display_switch sisfb_sw;static u8 caps = 0;static unsigned long MMIO_SIZE = 0;/* ModeSet stuff */unsigned char uDispType = 0;int mode_idx = -1;u8 mode_no = 0;u8 rate_idx = 0;static const struct _sisbios_mode { char name[15]; u8 mode_no; u16 xres; u16 yres; u16 bpp; u16 rate_idx; u16 cols; u16 rows;} sisbios_mode[] = { {"640x480x8", 0x2E, 640, 480, 8, 1, 80, 30}, {"640x480x16", 0x44, 640, 480, 16, 1, 80, 30}, {"640x480x32", 0x62, 640, 480, 32, 1, 80, 30}, {"720x480x8", 0x31, 720, 480, 8, 1, 90, 30}, /* NTSC TV */ {"720x480x16", 0x33, 720, 480, 16, 1, 90, 30}, {"720x480x32", 0x35, 720, 480, 32, 1, 90, 30}, {"720x576x8", 0x32, 720, 576, 8, 1, 90, 36}, /* PAL TV */ {"720x576x16", 0x34, 720, 576, 16, 1, 90, 36}, {"720x576x32", 0x36, 720, 576, 32, 1, 90, 36}, {"800x600x8", 0x30, 800, 600, 8, 2, 100, 37}, {"800x600x16", 0x47, 800, 600, 16, 2, 100, 37}, {"800x600x32", 0x63, 800, 600, 32, 2, 100, 37}, {"1024x768x8", 0x38, 1024, 768, 8, 2, 128, 48}, {"1024x768x16", 0x4A, 1024, 768, 16, 2, 128, 48}, {"1024x768x32", 0x64, 1024, 768, 32, 2, 128, 48}, {"1280x1024x8", 0x3A, 1280, 1024, 8, 2, 160, 64}, {"1280x1024x16", 0x4D, 1280, 1024, 16, 2, 160, 64}, {"1280x1024x32", 0x65, 1280, 1024, 32, 2, 160, 64}, {"1600x1200x8", 0x3C, 1600, 1200, 8, 1, 200, 75}, {"1600x1200x16", 0x3D, 1600, 1200, 16, 1, 200, 75}, {"1600x1200x32", 0x66, 1600, 1200, 32, 1, 200, 75}, {"1920x1440x8", 0x68, 1920, 1440, 8, 1, 240, 75}, {"1920x1440x16", 0x69, 1920, 1440, 16, 1, 240, 75}, {"1920x1440x32", 0x6B, 1920, 1440, 32, 1, 240, 75}, {"\0", 0x00, 0, 0, 0, 0, 0, 0}};static struct _vrate { u16 idx; u16 xres; u16 yres; u16 refresh;} vrate[] = { {1, 640, 480, 60}, {2, 640, 480, 72}, {3, 640, 480, 75}, {4, 640, 480, 85}, {5, 640, 480, 100}, {6, 640, 480, 120}, {7, 640, 480, 160}, {8, 640, 480, 200}, {1, 720, 480, 60}, {1, 720, 576, 50}, {1, 800, 600, 56}, {2, 800, 600, 60}, {3, 800, 600, 72}, {4, 800, 600, 75}, {5, 800, 600, 85}, {6, 800, 600, 100}, {7, 800, 600, 120}, {8, 800, 600, 160}, {1, 1024, 768, 43}, {2, 1024, 768, 60}, {3, 1024, 768, 70}, {4, 1024, 768, 75}, {5, 1024, 768, 85}, {6, 1024, 768, 100}, {7, 1024, 768, 120}, {1, 1280, 1024, 43}, {2, 1280, 1024, 60}, {3, 1280, 1024, 75}, {4, 1280, 1024, 85}, {1, 1600, 1200, 60}, {2, 1600, 1200, 65}, {3, 1600, 1200, 70}, {4, 1600, 1200, 75}, {5, 1600, 1200, 85}, {1, 1920, 1440, 60}, {0, 0, 0, 0}};/* HEAP stuff */struct OH { struct OH *pohNext; struct OH *pohPrev; unsigned long ulOffset; unsigned long ulSize;};struct OHALLOC { struct OHALLOC *pohaNext; struct OH aoh[1];};struct HEAP { struct OH ohFree; struct OH ohUsed; struct OH *pohFreeList; struct OHALLOC *pohaChain; unsigned long ulMaxFreeSize;};struct HEAP heap;unsigned long heap_start;unsigned long heap_end;unsigned long heap_size;unsigned int tqueue_pos;unsigned long hwcursor_vbase;/* -------------------- Macro definitions --------------------------- */#ifdef SISFBDEBUG#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)#else#define DPRINTK(fmt, args...)#endif#define vgawb(reg,data) \ (outb(data, ivideo.vga_base+reg))#define vgaww(reg,data) \ (outw(data, ivideo.vga_base+reg))#define vgawl(reg,data) \ (outl(data, ivideo.vga_base+reg))#define vgarb(reg) \ (inb(ivideo.vga_base+reg))/* ---------------------- Routine Prototype ------------------------- *//* Interface used by the world */int sisfb_setup(char *options);static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info);static int sisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);static int sisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);static int sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);static int sisfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int con, struct fb_info *info);/* Interface to the low level console driver */int sisfb_init(void);static int sisfb_update_var(int con, struct fb_info *info);static int sisfb_switch(int con, struct fb_info *info);static void sisfb_blank(int blank, struct fb_info *info);/* Internal routines */static void crtc_to_var(struct fb_var_screeninfo *var);static void sisfb_set_disp(int con, struct fb_var_screeninfo *var);static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *fb_info);static int sis_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fb_info);static void do_install_cmap(int con, struct fb_info *info);static int do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info);/* set-mode routines */void SetReg1(u16 port, u16 index, u16 data);void SetReg3(u16 port, u16 data);void SetReg4(u16 port, unsigned long data);u8 GetReg1(u16 port, u16 index);u8 GetReg2(u16 port);u32 GetReg3(u16 port);extern BOOLEAN SiSSetMode(PHW_DEVICE_EXTENSION HwDeviceExtension, USHORT ModeNo);extern BOOLEAN SiSInit300(PHW_DEVICE_EXTENSION HwDeviceExtension);static void pre_setmode(void);static void post_setmode(void);static void search_mode(const char *name);static u8 search_refresh_rate(unsigned int rate);/* heap routines */static int sisfb_heap_init(void);static struct OH *poh_new_node(void);static struct OH *poh_allocate(unsigned long size);static struct OH *poh_free(unsigned long base);static void delete_node(struct OH *poh);static void insert_node(struct OH *pohList, struct OH *poh);static void free_node(struct OH *poh);/* ---------------------- Internal Routines ------------------------- */inline static u32 RD32(unsigned char *base, s32 off){ return readl(base + off);}inline static void WR32(unsigned char *base, s32 off, u32 v){ writel(v, base + off);}inline static void WR16(unsigned char *base, s32 off, u16 v){ writew(v, base + off);}inline static void WR8(unsigned char *base, s32 off, u8 v){ writeb(v, base + off);}inline static u32 regrl(s32 off){ return RD32(ivideo.mmio_vbase, off);}inline static void regwl(s32 off, u32 v){ WR32(ivideo.mmio_vbase, off, v);}inline static void regww(s32 off, u16 v){ WR16(ivideo.mmio_vbase, off, v);}inline static void regwb(s32 off, u8 v){ WR8(ivideo.mmio_vbase, off, v);}/* * Get CRTC registers to set var */static void crtc_to_var(struct fb_var_screeninfo *var){ u16 VRE, VBE, VRS, VBS, VDE, VT; u16 HRE, HBE, HRS, HBS, HDE, HT; u8 uSRdata, uCRdata, uCRdata2, uCRdata3, uMRdata; int A, B, C, D, E, F, temp; double hrate, drate; vgawb(SEQ_ADR, 0x6); uSRdata = vgarb(SEQ_DATA); if (uSRdata & 0x20) var->vmode = FB_VMODE_INTERLACED; else var->vmode = FB_VMODE_NONINTERLACED; switch ((uSRdata & 0x1c) >> 2) { case 0: var->bits_per_pixel = 8; break; case 2: var->bits_per_pixel = 16; break; case 4: var->bits_per_pixel = 32; break; } switch (var->bits_per_pixel) { case 8: var->red.length = 6; var->green.length = 6; var->blue.length = 6; video_cmap_len = 256; break; case 16: /* RGB 565 */ var->red.offset = 11; var->red.length = 5; var->green.offset = 5; var->green.length = 6; var->blue.offset = 0; var->blue.length = 5; var->transp.offset = 0; var->transp.length = 0; video_cmap_len = 16; break; case 24: /* RGB 888 */ var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 0; var->transp.length = 0; video_cmap_len = 16; break; case 32: var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 24; var->transp.length = 8; video_cmap_len = 16; break; } vgawb(SEQ_ADR, 0xa); uSRdata = vgarb(SEQ_DATA); vgawb(CRTC_ADR, 0x6); uCRdata = vgarb(CRTC_DATA); vgawb(CRTC_ADR, 0x7); uCRdata2 = vgarb(CRTC_DATA); VT = (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x01) << 8) | ((u16) (uCRdata2 & 0x20) << 4) | ((u16) (uSRdata & 0x01) << 10); A = VT + 2; vgawb(CRTC_ADR, 0x12); uCRdata = vgarb(CRTC_DATA); VDE = (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x02) << 7) | ((u16) (uCRdata2 & 0x40) << 3) | ((u16) (uSRdata & 0x02) << 9); E = VDE + 1; vgawb(CRTC_ADR, 0x10); uCRdata = vgarb(CRTC_DATA); VRS = (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x04) << 6) | ((u16) (uCRdata2 & 0x80) << 2) | ((u16) (uSRdata & 0x08) << 7); F = VRS + 1 - E; vgawb(CRTC_ADR, 0x15); uCRdata = vgarb(CRTC_DATA); vgawb(CRTC_ADR, 0x9); uCRdata3 = vgarb(CRTC_DATA); VBS = (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x08) << 5) | ((u16) (uCRdata3 & 0x20) << 4) | ((u16) (uSRdata & 0x04) << 8); vgawb(CRTC_ADR, 0x16); uCRdata = vgarb(CRTC_DATA); VBE = (uCRdata & 0xff) | ((u16) (uSRdata & 0x10) << 4); temp = VBE - ((E - 1) & 511); B = (temp > 0) ? temp : (temp + 512); vgawb(CRTC_ADR, 0x11); uCRdata = vgarb(CRTC_DATA); VRE = (uCRdata & 0x0f) | ((uSRdata & 0x20) >> 1); temp = VRE - ((E + F - 1) & 31); C = (temp > 0) ? temp : (temp + 32); D = B - F - C; var->yres = var->yres_virtual = E; var->upper_margin = D; var->lower_margin = F; var->vsync_len = C; vgawb(SEQ_ADR, 0xb); uSRdata = vgarb(SEQ_DATA); vgawb(CRTC_ADR, 0x0); uCRdata = vgarb(CRTC_DATA); HT = (uCRdata & 0xff) | ((u16) (uSRdata & 0x03) << 8); A = HT + 5; vgawb(CRTC_ADR, 0x1); uCRdata = vgarb(CRTC_DATA); HDE = (uCRdata & 0xff) | ((u16) (uSRdata & 0x0C) << 6); E = HDE + 1; vgawb(CRTC_ADR, 0x4); uCRdata = vgarb(CRTC_DATA); HRS = (uCRdata & 0xff) | ((u16) (uSRdata & 0xC0) << 2); F = HRS - E - 3; vgawb(CRTC_ADR, 0x2); uCRdata = vgarb(CRTC_DATA); HBS = (uCRdata & 0xff) | ((u16) (uSRdata & 0x30) << 4); vgawb(SEQ_ADR, 0xc); uSRdata = vgarb(SEQ_DATA); vgawb(CRTC_ADR, 0x3); uCRdata = vgarb(CRTC_DATA); vgawb(CRTC_ADR, 0x5); uCRdata2 = vgarb(CRTC_DATA); HBE = (uCRdata & 0x1f) | ((u16) (uCRdata2 & 0x80) >> 2) | ((u16) (uSRdata & 0x03) << 6); HRE = (uCRdata2 & 0x1f) | ((uSRdata & 0x04) << 3); temp = HBE - ((E - 1) & 255); B = (temp > 0) ? temp : (temp + 256); temp = HRE - ((E + F + 3) & 63); C = (temp > 0) ? temp : (temp + 64); D = B - F - C; var->xres = var->xres_virtual = E * 8; var->left_margin = D * 8; var->right_margin = F * 8; var->hsync_len = C * 8; var->activate = FB_ACTIVATE_NOW; var->sync = 0; uMRdata = vgarb(0x1C); if (uMRdata & 0x80) var->sync &= ~FB_SYNC_VERT_HIGH_ACT; else var->sync |= FB_SYNC_VERT_HIGH_ACT; if (uMRdata & 0x40) var->sync &= ~FB_SYNC_HOR_HIGH_ACT; else var->sync |= FB_SYNC_HOR_HIGH_ACT; VT += 2; VT <<= 1; HT = (HT + 5) * 8; hrate = (double) ivideo.refresh_rate * (double) VT / 2; drate = hrate * HT; var->pixclock = (u32) (1E12 / drate);}static void sisfb_set_disp(int con, struct fb_var_screeninfo *var){ struct fb_fix_screeninfo fix;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?