📄 sis.c
字号:
/*SIS chipset driver Matan Ziv-Av <matan@svgalib.org>Fixes for 530 and for vesafb by Marcelo de Paula Bezerra <mosca@internetaddress.com>.This driver is based on the XFree86 sis driver, written by Alan Hourihaneand modified by Xavier Ducoin, Mike Chapman, Juanjo Santamarta, Mitani Hiroshi, David Thomas. And on the documentation availbale from sis's web pages (not manychipset companies still do this).*/#include <stdlib.h>#include <stdio.h> #include <string.h>#include <unistd.h>#include "vga.h"#include "libvga.h"#include "driver.h"#include "timing.h"#include "vgaregs.h"#include "interface.h"#include "accel.h"#include "vgapci.h"#define SISREG_SAVE(i) (VGA_TOTAL_REGS+i)#define SIS_TOTAL_REGS (VGA_TOTAL_REGS + 0x48 - 5)#define XR(i) (VGA_TOTAL_REGS+i-5)#define PCI_CHIP_SG86C201 0x0001#define PCI_CHIP_SG86C202 0x0002#define PCI_CHIP_SG86C205 0x0205#define PCI_CHIP_SG86C215 0x0215#define PCI_CHIP_SG86C225 0x0225#define PCI_CHIP_SIS5598 0x0200#define PCI_CHIP_SIS5597 0x0200#define PCI_CHIP_SIS6326 0x6326#define PCI_CHIP_SIS530 0x6306#define PCI_CHIP_SIS300 0x0300#define PCI_CHIP_SIS540 0x5300#define PCI_CHIP_SIS630 0x6300#define ClockReg XR(0x07) #define DualBanks XR(0x0B)#define BankReg XR(0x06)#define CRTCOff XR(0x0A)#define DispCRT XR(0x27)#define Unknown XR(0x08)#define LinearAddr0 XR(0x20)#define LinearAddr1 XR(0x21)enum { SIS_86C201=0, SIS_86C202, SIS_86C205, SIS_86C215, SIS_86C225, SIS_5597, SIS_5598, SIS_6326, SIS_530 };#define write_xr(num,val) {outb(SEQ_I, num);outb(SEQ_D, val);}#define read_xr(num,var) {outb(SEQ_I, num);var=inb(SEQ_D);} static int sis_init(int, int, int);static void sis_unlock(void);static void sis_lock(void);static void sisClockLoad(int, unsigned char *);static void sis_CPUthreshold(int,int,int *,int *);void __svgalib_sisaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels);static int sis_memory;static int sis_is_linear, sis_linear_base;static int sis_chiptype;static int sis_edo_vram = 0, sis_host_bus = 0, sis_fast_vram = 0, sis_pci_burst_on = 0, sis_pci_burst_off = 0;static CardSpecs *cardspecs;static void sis_setpage(int page){ char tmp; read_xr(0x0b,tmp); if (tmp&8) { outb(0x3cb,page); outb(0x3cd,page); } else outb(0x3cd,page|(page<<4));}static int __svgalib_sis_inlinearmode(void){return sis_is_linear;}/* Fill in chipset specific mode information */static void sis_getmodeinfo(int mode, vga_modeinfo *modeinfo){ if(modeinfo->colors==16)return; modeinfo->maxpixels = sis_memory*1024/modeinfo->bytesperpixel; modeinfo->maxlogicalwidth = 4088; modeinfo->startaddressrange = sis_memory * 1024 - 1; modeinfo->haveblit = 0; modeinfo->flags &= ~HAVE_RWPAGE; if (modeinfo->bytesperpixel >= 1) { if(sis_linear_base)modeinfo->flags |= CAPABLE_LINEAR; if (__svgalib_sis_inlinearmode()) modeinfo->flags |= IS_LINEAR; }}/* Read and save chipset-specific registers */static int sis_saveregs(unsigned char regs[]){ int i; sis_unlock(); regs[XR(0x40)] = inb(0x3cb); regs[XR(0x41)] = inb(0x3cd); if(sis_chiptype==SIS_5597) for(i=0x38; i<0x3a;i++)read_xr(i,regs[XR(i)]); if(sis_chiptype==SIS_6326) for(i=0x38; i<0x3d;i++)read_xr(i,regs[XR(i)]); if(sis_chiptype==SIS_530) for(i=0x38; i<0x40 ; i++)read_xr(i,regs[XR(i)]); /* get all the clocks */ if (sis_chiptype==SIS_5597 || sis_chiptype==SIS_6326 || sis_chiptype==SIS_530) { i = regs[XR(0x38)] & 0xfc; write_xr(0x38,i|1); read_xr(0x13,regs[XR(0x42)]); read_xr(0x2a,regs[XR(0x43)]); read_xr(0x2b,regs[XR(0x44)]); write_xr(0x38,i|2); read_xr(0x13,regs[XR(0x45)]); read_xr(0x2a,regs[XR(0x46)]); read_xr(0x2b,regs[XR(0x47)]); write_xr(0x38,i); /* Make sure that the loop gets the internal VCLK registers */ } for(i=5; i<0x38;i++)read_xr(i,regs[XR(i)]); if (sis_chiptype==SIS_5597 || sis_chiptype==SIS_6326 || sis_chiptype==SIS_530) write_xr(0x38,regs[XR(0x38)]); return SIS_TOTAL_REGS - VGA_TOTAL_REGS;}/* Set chipset-specific registers */static void sis_setregs(const unsigned char regs[], int mode){ int i; sis_unlock(); outb(0x3cb,regs[XR(0x40)]); outb(0x3cd,regs[XR(0x41)]); /* set all the clocks */ if (sis_chiptype==SIS_5597 || sis_chiptype==SIS_6326 || sis_chiptype==SIS_530) { i = regs[XR(0x38)] & 0xfc; write_xr(0x38,i|1); write_xr(0x13,regs[XR(0x42)]); write_xr(0x2a,regs[XR(0x43)]); write_xr(0x2b,regs[XR(0x44)]); write_xr(0x38,i|2); write_xr(0x13,regs[XR(0x45)]); write_xr(0x2a,regs[XR(0x46)]); write_xr(0x2b,regs[XR(0x47)]); write_xr(0x38,i); /* Make sure that the loop puts the internal VCLK registers */ } for(i=6; i<0x38;i++)write_xr(i,regs[XR(i)]); if(sis_chiptype==SIS_5597) for(i=0x38; i<0x3a;i++)write_xr(i,regs[XR(i)]); if(sis_chiptype==SIS_6326) for(i=0x38; i<0x3d;i++)write_xr(i,regs[XR(i)]); if(sis_chiptype==SIS_530) for(i=0x38; i<0x40;i++)write_xr(i,regs[XR(i)]);}/* Return nonzero if mode is available */static int sis_modeavailable(int mode){ struct info *info; ModeTiming *modetiming; ModeInfo *modeinfo; if ((mode < G640x480x256 ) || mode == G720x348x2) return __svgalib_vga_driverspecs.modeavailable(mode); info = &__svgalib_infotable[mode]; if (sis_memory * 1024 < info->ydim * info->xbytes) return 0; modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); if(modeinfo->bytesPerPixel==4){ free(modeinfo); return 0; }; modetiming = malloc(sizeof(ModeTiming)); if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { free(modetiming); free(modeinfo); return 0; } free(modetiming); free(modeinfo); return SVGADRV;}/* Local, called by sis_setmode(). */static void sis_initializemode(unsigned char *moderegs, ModeTiming * modetiming, ModeInfo * modeinfo, int mode){ /* long k; */ int offset; __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); sis_saveregs(moderegs); sisClockLoad(modetiming->pixelClock,moderegs); offset = modetiming->CrtcHDisplay >> ((modetiming->flags & INTERLACED) ? 2 : 3); moderegs[ATT+16] = 0x01; moderegs[20] = 0x40; moderegs[23] = 0xA3; moderegs[ATT+0x10] = 0x01; /* mode */ moderegs[ATT+0x11] = 0x00; /* overscan (border) color */ moderegs[ATT+0x12] = 0x0F; /* enable all color planes */ moderegs[ATT+0x13] = 0x00; /* horiz pixel panning 0 */ if ( (modeinfo->bitsPerPixel == 16) || (modeinfo->bitsPerPixel == 24) ) moderegs[GRA+0x05] = 0x00; /* normal read/write mode */ if (modeinfo->bitsPerPixel == 16) { offset <<= 1; /* double the width of the buffer */ } else if (modeinfo->bitsPerPixel == 24) { offset += offset << 1; } moderegs[BankReg] = 0x02; moderegs[DualBanks] = 0x00; if ( sis_is_linear ) { moderegs[BankReg] |= 0x80; /* enable linear mode addressing */ moderegs[LinearAddr0] = (sis_linear_base & 0x07f80000) >> 19 ; moderegs[LinearAddr1] = ((sis_linear_base & 0xf8000000) >> 27) | (0x60) ; /* Enable Linear with max 4 mb*/ } else moderegs[DualBanks] |= 0x08; if (modeinfo->bitsPerPixel == 16) { if (modeinfo->greenWeight == 5) moderegs[BankReg] |= 0x04; /* 16bpp = 5-5-5 */ else moderegs[BankReg] |= 0x08; /* 16bpp = 5-6-5 */ } if (modeinfo->bitsPerPixel == 24) { moderegs[BankReg] |= 0x10; moderegs[DualBanks] |= 0x80; } moderegs[0x13] = offset & 0xFF; moderegs[CRTCOff] = ((offset & 0xF00) >> 4) | (((modetiming->CrtcVTotal-2) & 0x400) >> 10 ) | (((modetiming->CrtcVDisplay-1) & 0x400) >> 9 ) | (((modetiming->CrtcVSyncStart) & 0x400) >> 8 ) | (((modetiming->CrtcVSyncStart) & 0x400) >> 7 ) ; if (modetiming->flags & INTERLACED) moderegs[BankReg] |= 0x20; if ((sis_chiptype == SIS_5597) || (sis_chiptype == SIS_6326) || (sis_chiptype == SIS_530)) { moderegs[XR(0x0C)] |= 0x20; /* readahead cache */ moderegs[XR(0x07)] |= 0x80; /* combine FIFOs */ } if((sis_chiptype == SIS_530) || (sis_chiptype==SIS_5597)) { moderegs[XR(0x0c)] |= 0x80; /* 32 bit memory access */ moderegs[XR(0x26)]&=0xfe; /* zero bit 20 of start address */ }; /* makes SR27 d[3:1]=0; If yes, I believe this is the offset for the scroll, or somthing like that... */ moderegs[XR(0x27)]&=0xf0; { int CRT_ENGthreshold,CRT_CPUthresholdLow, CRT_CPUthresholdHigh; CRT_ENGthreshold = 0x1F; sis_CPUthreshold(modetiming->pixelClock, modeinfo->bitsPerPixel, &CRT_CPUthresholdLow, &CRT_CPUthresholdHigh); moderegs[XR(0x08)] = (CRT_ENGthreshold & 0x0F) | (CRT_CPUthresholdLow & 0x0F)<<4 ; moderegs[XR(0x09)] &= 0xF0; /* Yeou */ moderegs[XR(0x09)] |= (CRT_CPUthresholdHigh & 0x0F); /* Yeou */ if (sis_chiptype == SIS_530) { /* CRT/CPU/Engine Threshold Bit[4] */ moderegs[XR(0x3F)] &= 0xE3; moderegs[XR(0x3F)] |= ((CRT_CPUthresholdHigh & 0x10) | ((CRT_ENGthreshold & 0x10) >> 1) | ((CRT_CPUthresholdLow & 0x10) >> 2)); } } moderegs[59]=0x6f; return ;}static int sis_setmode(int mode, int prv_mode){ unsigned char *moderegs; ModeTiming *modetiming; ModeInfo *modeinfo; int tmp, var; if ((mode < G640x480x256)||(mode==G720x348x2)) { if(sis_chiptype >= SIS_5597) { /* Work Around for vesafb case */ read_xr(0x06,tmp); tmp&=~(0x1E); /* Depth registers */ write_xr(0x06,tmp); /* program the 25 and 28 Mhz clocks */ if (sis_chiptype==SIS_5597 || sis_chiptype==SIS_6326 || sis_chiptype==SIS_530) { read_xr(0x38,tmp); tmp &= 0xfc; write_xr(0x38,tmp|1); read_xr(0x13,var); write_xr(0x13,var|0x40); write_xr(0x2a,0x1b); write_xr(0x2b,0xe1); write_xr(0x38,tmp|2); read_xr(0x13,var); write_xr(0x13,var|0x40); write_xr(0x2a,0x4e); write_xr(0x2b,0xe4); write_xr(0x38,tmp); } } return __svgalib_vga_driverspecs.setmode(mode, prv_mode); } if (!sis_modeavailable(mode)) return 1; modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); modetiming = malloc(sizeof(ModeTiming)); if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { free(modetiming); free(modeinfo); return 1; } moderegs = malloc(SIS_TOTAL_REGS); sis_initializemode(moderegs, modetiming, modeinfo, mode); free(modetiming); __svgalib_setregs(moderegs); /* Set standard regs. */ sis_setregs(moderegs, mode); /* Set extended regs. */ free(moderegs); __svgalib_InitializeAcceleratorInterface(modeinfo); free(modeinfo); return 0;}/* Unlock chipset-specific registers */static void sis_unlock(void){ int vgaIOBase, temp; vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; outb(vgaIOBase + 4, 0x11); temp = inb(vgaIOBase + 5); outb(vgaIOBase + 5, temp & 0x7F); outw(SEQ_I,0x8605); }static void sis_lock(void){ int vgaIOBase, temp; vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; outb(vgaIOBase + 4, 0x11); temp = inb(vgaIOBase + 5); outb(vgaIOBase + 5, temp & 0x7F); outw(SEQ_I,0x0005);}#define VENDOR_ID 0x1039/* Indentify chipset, initialize and return non-zero if detected */static int sis_test(void){ int _ioperm=0, found; long buf[64]; if (getenv("IOPERM") == NULL) { _ioperm=1; if (iopl(3) < 0) { printf("svgalib: cannot get I/O permissions\n"); exit(1); } } found=__svgalib_pci_find_vendor_vga(VENDOR_ID,buf,0); if (_ioperm) iopl(0); if(!found&&( (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C201)|| (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C202)|| (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C205)|| (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C215)|| (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C225)|| (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS5597)|| (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS5598)|| (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS530)|| (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS540)|| (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS630)|| (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS300)|| (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS6326) )){ sis_init(0,0,0); return 1; }; return 0;}/* Set display start address (not for 16 color modes) *//* Cirrus supports any address in video memory (up to 2Mb) */static void sis_setdisplaystart(int address){ int temp; address=address >> 2; outw(CRT_IC, (address & 0x00FF00) | 0x0C); outw(CRT_IC, ((address & 0x00FF) << 8) | 0x0D); read_xr(0x27,temp); temp &= 0xf0; temp |= (address&0xf0000)>>16; write_xr(0x27,temp);}/* Set logical scanline length (usually multiple of 8) *//* Cirrus supports multiples of 8, up to 4088 */static void sis_setlogicalwidth(int width){ int offset = width >> 3; int temp; __svgalib_outCR(0x13,offset&0xff); read_xr(0x0a,temp); temp &= 0xf; temp |= (offset&0xf00)>>4; write_xr(0x0a,temp);}static int sis_linear(int op, int param){ if (op==LINEAR_ENABLE){ int temp; sis_is_linear=1; read_xr(6,temp); temp |=0x80; write_xr(0x20,(sis_linear_base & 0x07f80000) >> 19) ; write_xr(0x21,((sis_linear_base & 0xf8000000) >> 27) | (0x60)) ; /* Enable Linear with max 4 mb*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -