📄 sis.c
字号:
write_xr(6,temp); return 0; }; if (op==LINEAR_DISABLE){ int temp; sis_is_linear=0; read_xr(6,temp); temp &=0x7f; write_xr(0x20,0) ; write_xr(0x21,0) ; write_xr(6,temp); return 0; }; if (op==LINEAR_QUERY_BASE) return sis_linear_base; if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */ else return -1; /* Unknown function. */}static int sis_match_programmable_clock(int clock){return clock ;}static int sis_map_clock(int bpp, int clock){return clock ;}static int sis_map_horizontal_crtc(int bpp, int pixelclock, int htiming){return htiming;}/* Function table (exported) */DriverSpecs __svgalib_sis_driverspecs ={ sis_saveregs, sis_setregs, sis_unlock, sis_lock, sis_test, sis_init, sis_setpage, NULL, NULL, sis_setmode, sis_modeavailable, sis_setdisplaystart, sis_setlogicalwidth, sis_getmodeinfo, 0, /* old blit funcs */ 0, 0, 0, 0, 0, /* ext_set */ 0, /* accel */ sis_linear, 0, /* accelspecs, filled in during init. */ NULL, /* Emulation */};/* Initialize chipset (called after detection) */static int sis_init(int force, int par1, int par2){ unsigned long buf[64]; int found=0; int _ioperm=0; sis_unlock(); if (force) { sis_memory = par1; sis_chiptype = par2; } else { }; 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); sis_linear_base=0; sis_chiptype=0; if (!found){ sis_linear_base=buf[4]&0xffffff00; switch((buf[0]>>16)&0xffff) { case PCI_CHIP_SG86C201: sis_chiptype=SIS_86C201; break; case PCI_CHIP_SG86C202: sis_chiptype=SIS_86C202; break; case PCI_CHIP_SG86C205: sis_chiptype=SIS_86C205; break; case PCI_CHIP_SG86C215: sis_chiptype=SIS_86C215; break; case PCI_CHIP_SG86C225: sis_chiptype=SIS_86C225; break; case PCI_CHIP_SIS5597: sis_chiptype=SIS_5597; break; case PCI_CHIP_SIS300: case PCI_CHIP_SIS540: case PCI_CHIP_SIS630: case PCI_CHIP_SIS530: sis_chiptype=SIS_530; break;/* case PCI_CHIP_SIS5598: sis_chiptype=SIS_5598; break;*/ case PCI_CHIP_SIS6326: sis_chiptype=SIS_6326; break; }; }; if(sis_memory==0){ if ((sis_chiptype == SIS_6326)||(sis_chiptype==SIS_530)){ int temp; read_xr(0x0C,temp); temp >>= 1; sis_memory=1024<<(temp&0x03); }; if ( sis_chiptype == SIS_5597) { int temp,bsiz; /* Because 5597 shares main memory, I test for BIOS CONFIGURED memory.*/ read_xr(0x0C,temp); bsiz = (temp >> 1) & 3; read_xr(0x2F,temp); temp &= 7; temp++; if (bsiz > 0) temp = temp << 1; sis_memory = 256 * temp; }; if(sis_chiptype<SIS_5597) { int temp; read_xr(0x0F,temp); sis_memory=1024<<(temp&0x03); }; }; if (__svgalib_driver_report) { printf("Using SIS driver, %iKB. Chiptype=%i\n",sis_memory,sis_chiptype); }; cardspecs = malloc(sizeof(CardSpecs)); cardspecs->videoMemory = sis_memory; cardspecs->maxPixelClock4bpp = 75000; cardspecs->maxPixelClock8bpp = 135000; cardspecs->maxPixelClock16bpp = 135000; cardspecs->maxPixelClock24bpp = 135000; cardspecs->maxPixelClock32bpp = 0; cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; cardspecs->maxHorizontalCrtc = 2040; cardspecs->maxPixelClock4bpp = 0; cardspecs->nClocks =0; cardspecs->mapClock = sis_map_clock; cardspecs->mapHorizontalCrtc = sis_map_horizontal_crtc; cardspecs->matchProgrammableClock=sis_match_programmable_clock; __svgalib_driverspecs = &__svgalib_sis_driverspecs; __svgalib_banked_mem_base=0xa0000; __svgalib_banked_mem_size=0x10000; __svgalib_linear_mem_base=sis_linear_base; __svgalib_linear_mem_size=sis_memory*0x400; return 0;}static voidsisCalcClock(int Clock, int max_VLD, unsigned int *vclk){ int M, N, P, PSN, VLD, PSNx; int bestM=0, bestN=0, bestP=0, bestPSN=0, bestVLD=0; double bestError, abest = 42.0, bestFout; double target; double Fvco, Fout; double error, aerror; /* * fd = fref*(Numerator/Denumerator)*(Divider/PostScaler) * * M = Numerator [1:128] * N = DeNumerator [1:32] * VLD = Divider (Vco Loop Divider) : divide by 1, 2 * P = Post Scaler : divide by 1, 2, 3, 4 * PSN = Pre Scaler (Reference Divisor Select) * * result in vclk[] */#define Midx 0#define Nidx 1#define VLDidx 2#define Pidx 3#define PSNidx 4#define Fref 14318180/* stability constraints for internal VCO -- MAX_VCO also determines * the maximum Video pixel clock */#define MIN_VCO Fref#define MAX_VCO 135000000#define MAX_VCO_5597 353000000#define MAX_PSN 0 /* no pre scaler for this chip */#define TOLERANCE 0.01 /* search smallest M and N in this tolerance */ int M_min = 2; int M_max = 128; /* abest=10000.0; */ target = Clock * 1000; if ((sis_chiptype == SIS_5597) || (sis_chiptype == SIS_6326)){ int low_N = 2; int high_N = 5; int PSN = 1; P = 1; if (target < MAX_VCO_5597 / 2) P = 2; if (target < MAX_VCO_5597 / 3) P = 3; if (target < MAX_VCO_5597 / 4) P = 4; if (target < MAX_VCO_5597 / 6) P = 6; if (target < MAX_VCO_5597 / 8) P = 8; Fvco = P * target; for (N = low_N; N <= high_N; N++){ double M_desired = Fvco / Fref * N; if (M_desired > M_max * max_VLD) continue; if ( M_desired > M_max ) { M = M_desired / 2 + 0.5; VLD = 2; } else { M = Fvco / Fref * N + 0.5; VLD = 1; }; Fout = (double)Fref * (M * VLD)/(N * P); error = (target - Fout) / target; aerror = (error < 0) ? -error : error;/* if (aerror < abest && abest > TOLERANCE) {*/ if (aerror < abest) { abest = aerror; bestError = error; bestM = M; bestN = N; bestP = P; bestPSN = PSN; bestVLD = VLD; bestFout = Fout; } } } else { for (PSNx = 0; PSNx <= MAX_PSN ; PSNx++) { int low_N, high_N; double FrefVLDPSN; PSN = !PSNx ? 1 : 4; low_N = 2; high_N = 32; for ( VLD = 1 ; VLD <= max_VLD ; VLD++ ) { FrefVLDPSN = (double)Fref * VLD / PSN; for (N = low_N; N <= high_N; N++) { double tmp = FrefVLDPSN / N; for (P = 1; P <= 4; P++) { double Fvco_desired = target * ( P ); double M_desired = Fvco_desired / tmp; /* Which way will M_desired be rounded? * Do all three just to be safe. */ int M_low = M_desired - 1; int M_hi = M_desired + 1; if (M_hi < M_min || M_low > M_max) continue; if (M_low < M_min) M_low = M_min; if (M_hi > M_max) M_hi = M_max; for (M = M_low; M <= M_hi; M++) { Fvco = tmp * M; if (Fvco <= MIN_VCO) continue; if (Fvco > MAX_VCO) break; Fout = Fvco / ( P ); error = (target - Fout) / target; aerror = (error < 0) ? -error : error; if (aerror < abest) { abest = aerror; bestError = error; bestM = M; bestN = N; bestP = P; bestPSN = PSN; bestVLD = VLD; bestFout = Fout; } } } } } } } vclk[Midx] = bestM; vclk[Nidx] = bestN; vclk[VLDidx] = bestVLD; vclk[Pidx] = bestP; vclk[PSNidx] = bestPSN;};static void sisClockLoad(int Clock, unsigned char *regs) { unsigned int vclk[5]; unsigned char temp, xr2a, xr2b; sisCalcClock(Clock, 2, vclk); xr2a = (vclk[Midx] - 1) & 0x7f ; xr2a |= ((vclk[VLDidx] == 2 ) ? 1 : 0 ) << 7 ; xr2b = (vclk[Nidx] -1) & 0x1f ; /* bits [4:0] contain denumerator -MC */ if (vclk[Pidx] <= 4){ xr2b |= (vclk[Pidx] -1 ) << 5 ; /* postscale 1,2,3,4 */ temp=regs[XR(0x13)]; temp &= 0xBF; regs[XR(0x13)]=temp; } else { xr2b |= ((vclk[Pidx] / 2) -1 ) << 5 ; /* postscale 6,8 */ temp=regs[XR(0x13)]; temp |= 0x40; regs[XR(0x13)]=temp; }; xr2b |= 0x80 ; /* gain for high frequency */ regs[XR(0x2a)]=xr2a; regs[XR(0x2b)]=xr2b; if (sis_chiptype == SIS_5597 || sis_chiptype == SIS_6326) { temp=regs[XR(0x23)]; if (sis_edo_vram) temp |= 0x40; regs[XR(0x23)]=temp; } if (sis_chiptype == SIS_5597 || sis_chiptype == SIS_6326 || sis_chiptype == SIS_530) { /*write_xr(0x3B, 0x08 );*/ if (sis_chiptype == SIS_5597) { temp=regs[XR(0x34)]; if (sis_host_bus) temp |= 0x18; else temp &= ~0x18; regs[XR(0x34)]=temp; temp=regs[XR(0x3D)]; if (sis_host_bus) temp &= 0x0F; regs[XR(0x3D)]=temp; } /* One-Cycle VRAM */ temp=regs[XR(0x34)]; if (sis_fast_vram) regs[XR(0x34)]=temp; /* pci burst */ temp=regs[XR(0x35)]; if (sis_pci_burst_on) temp |= 0x10; else if (sis_pci_burst_off) temp &= ~0x10; regs[XR(0x35)]=temp; /* pci burst,also */ if (sis_chiptype != SIS_530) { temp=regs[XR(0x26)]; if (sis_pci_burst_on) temp |= 0x20; else if (sis_pci_burst_off) temp &= ~0x20; regs[XR(0x26)]=temp; }/* Merge FIFOs */ temp=regs[XR(0x07)]; temp |= 0x80; regs[XR(0x07)]=temp; };}static int sisMClk(void){ int mclk; unsigned char xr28, xr29, xr13, xr10; if (sis_chiptype == SIS_530) { /* The MCLK in SiS530/620 is set by BIOS in SR10 */ read_xr(0x10, xr10); switch(xr10 & 0x0f) { case 1: mclk = 75000; /* 75 Mhz */ break; case 2: mclk = 83000; /* 83 Mhz */ break; case 3: mclk = 100000;/* 100 Mhz */ break; case 0: default: mclk = 66000; /* 66 Mhz */ } return(mclk); } /* Numerator */ read_xr(0x28,xr28); mclk=14318*((xr28 & 0x7f)+1); /* Denumerator */ read_xr(0x29,xr29); mclk=mclk/((xr29 & 0x1f)+1); /* Divider. Does not seem to work for mclk for older cards */ if ( (sis_chiptype==SIS_6326) && ((xr28 & 0x80)!=0 ) ) { mclk = mclk*2; } /* Post-scaler. Values depends on SR13 bit 7 */ read_xr(0x13,xr13); if ( (xr13 & 0x80)==0 ) { mclk = mclk / (((xr29 & 0x60) >> 5)+1); } else { /* Values 00 and 01 are reserved */ if ((xr29 & 0x60) == 0x40) mclk=mclk/6; if ((xr29 & 0x60) == 0x60) mclk=mclk/8; } return(mclk);}static voidsis_CPUthreshold(int dotClock,int bpp,int *thresholdLow,int *thresholdHigh){ unsigned char temp; int mclk; int safetymargin, gap; float z, z1, z2; /* Yeou */ int factor; mclk=sisMClk(); if (sis_chiptype == SIS_530) /* Yeou for 530 thresholod */ { /* z = f *((dotClock * bpp)/(buswidth*mclk); thresholdLow = (z+1)/2 + 4; thresholdHigh = 0x1F; where f = 0x60 when UMA (SR0D D[0] = 1) 0x30 LFB (SR0D D[0] = 0) */ read_xr (0x0d, temp); if (temp & 0x01) factor = 0x60; else factor = 0x30; z1 = (float)(dotClock * bpp); z2 = (float)(64.0 * mclk); z = ((float) factor * (z1 / z2)); *thresholdLow = ((int)z + 1) / 2 + 4 ; *thresholdHigh = 0x1F; } else { /* For sis other product */ /* Adjust thresholds. Safetymargin is to be adjusted by fifo_XXX options. Try to mantain a fifo margin of gap. At high Vclk*bpp this isn't possible, so limit the thresholds. The values I guess are : FIFO_CONSERVATIVE : safetymargin = 5 ; FIFO_MODERATE : safetymargin = 3 ; Default : safetymargin = 1 ; (good enough in many cases) FIFO_AGGRESSIVE : safetymargin = 0 ; gap=4 seems to be the best value in either case... */ safetymargin=3; gap = 4; *thresholdLow = ((bpp*dotClock) / mclk)+safetymargin; *thresholdHigh = ((bpp*dotClock) / mclk)+gap+safetymargin; /* 24 bpp seems to need lower FIFO limits. At 16bpp is possible to put a thresholdHigh of 0 (0x10) with good results on my system(good performance, and virtually no noise) */ if ( *thresholdLow > (bpp < 24 ? 0xe:0x0d) ) { *thresholdLow = (bpp < 24 ? 0xe:0x0d); } if ( *thresholdHigh > (bpp < 24 ? 0x10:0x0f) ) { *thresholdHigh = (bpp < 24 ? 0x10:0x0f); } }; /* sis530 */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -