summaryrefslogtreecommitdiff
path: root/xc/programs/Xserver/hw/xfree86/drivers/sis/init300.c
diff options
context:
space:
mode:
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/drivers/sis/init300.c')
-rw-r--r--xc/programs/Xserver/hw/xfree86/drivers/sis/init300.c1030
1 files changed, 1030 insertions, 0 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/sis/init300.c b/xc/programs/Xserver/hw/xfree86/drivers/sis/init300.c
new file mode 100644
index 000000000..5c4e01e98
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/drivers/sis/init300.c
@@ -0,0 +1,1030 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/init300.c,v 1.2 2000/08/04 03:51:46 tsi Exp $ */
+
+#include "xf86.h"
+#include "xf86PciInfo.h"
+
+#include "sis.h"
+#include "sis_regs.h"
+#include "init300.h"
+
+VOID SetReg1(USHORT, USHORT, USHORT);
+VOID SetReg3(USHORT, USHORT);
+VOID SetReg4(USHORT, ULONG);
+USHORT GetReg1(USHORT, USHORT);
+USHORT GetReg2(USHORT);
+ULONG GetReg3(USHORT);
+Bool SiSSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ SISPtr pSiS = SISPTR(pScrn);
+ ULONG temp;
+ USHORT cr30flag,cr31flag;
+ ULONG ROMAddr = (ULONG) SISPTR(pScrn)->BIOS;
+ USHORT BaseAddr = (USHORT) (SISPTR(pScrn)->RelIO +0x30);
+ USHORT ModeNo=0;
+ USHORT Rate;
+
+ P3c4=BaseAddr+0x14;
+ P3d4=BaseAddr+0x24;
+ P3c0=BaseAddr+0x10;
+ P3ce=BaseAddr+0x1e;
+ P3c2=BaseAddr+0x12;
+ P3ca=BaseAddr+0x1a;
+ P3c6=BaseAddr+0x16;
+ P3c7=BaseAddr+0x17;
+ P3c8=BaseAddr+0x18;
+ P3c9=BaseAddr+0x19;
+ P3da=BaseAddr+0x2A;
+
+ ModeNo = CalcModeIndex(pScrn, mode);
+ Rate = CalcRefreshRate(pScrn, mode);
+ SetReg1(P3d4, 0x33, Rate);
+
+ SetReg1(P3c4, 0x20, 0xa1);
+ SetReg1(P3c4, 0x1E, 0x42);
+
+ PresetScratchregister(P3d4); /* add for CRT2 */
+ /* replace GetSenseStatus,SetTVSystem,SetDisplayInfo */
+
+ SetReg1(P3c4,0x05,0x86); /* 1.Openkey */
+ temp=SearchModeID(ROMAddr,ModeNo); /* 2.Get ModeID Table */
+ if(temp==0) return(0);
+
+ SetTVSystem(); /* add for CRT2 */
+ GetLCDDDCInfo(pScrn); /* add for CRT2 */
+ GetVBInfo(BaseAddr,ROMAddr); /* add for CRT2 */
+ GetLCDResInfo(P3d4); /* add for CRT2 */
+
+ temp=CheckMemorySize(ROMAddr); /* 3.Check memory size */
+ if(temp==0) return(0);
+ cr30flag=(UCHAR)GetReg1(P3d4,0x30);
+ if(((cr30flag&0x01)==1)||((cr30flag&0x02)==0)){
+ /* if cr30 d[0]=1 or d[1]=0 set crt1 */
+ SetReg1(P3d4,0x34,ModeNo);
+ /* set CR34->CRT1 ModeNofor CRT2 FIFO */
+ GetModePtr(ROMAddr,ModeNo); /* 4.GetModePtr */
+ SetSeqRegs(ROMAddr); /* 5.SetSeqRegs */
+ SetMiscRegs(ROMAddr); /* 6.SetMiscRegs */
+ SetCRTCRegs(ROMAddr); /* 7.SetCRTCRegs */
+ SetATTRegs(ROMAddr); /* 8.SetATTRegs */
+ SetGRCRegs(ROMAddr); /* 9.SetGRCRegs */
+ ClearExt1Regs(); /* 10.Clear Ext1Regs */
+ temp=GetRatePtr(ROMAddr,ModeNo); /* 11.GetRatePtr */
+ if(temp) {
+ SetSync(ROMAddr); /* 12.SetSync */
+ SetCRT1CRTC(ROMAddr); /* 13.SetCRT1CRTC */
+ SetCRT1Offset(ROMAddr); /* 14.SetCRT1Offset */
+ SetCRT1VCLK(ROMAddr); /* 15.SetCRT1VCLK */
+ SetVCLKState(ROMAddr, ModeNo);
+ if( (pSiS->Chipset == PCI_CHIP_SIS630) || (pSiS->Chipset == PCI_CHIP_SIS540) )
+ SetCRT1FIFO2(ROMAddr);
+ else
+ SetCRT1FIFO(ROMAddr);
+ }
+ SetCRT1ModeRegs(ROMAddr, ModeNo);
+ if( (pSiS->Chipset == PCI_CHIP_SIS630) || (pSiS->Chipset == PCI_CHIP_SIS540) )
+ SetInterlace(ROMAddr,ModeNo);
+ LoadDAC(ROMAddr);
+ }
+ cr31flag=(UCHAR)GetReg1(P3d4,0x31);
+ if(((cr30flag&0x01)==1)||((cr30flag&0x03)==0x02)||
+ (((cr30flag&0x03)==0x00)&&((cr31flag&0x20)==0x20))) {
+ /* if CR30 d[0]=1 or d[1:0]=10, set CRT2 or cr30 cr31== 0x00 0x20 */
+ SetCRT2Group(BaseAddr,ROMAddr,ModeNo, pScrn); /* add for CRT2 */
+ }
+ SetPitch(pScrn, BaseAddr); /* 16.SetPitch */
+ DisplayOn(); /* 17.DisplayOn */
+ return TRUE;
+}
+
+BOOLEAN SearchModeID(ULONG ROMAddr, USHORT ModeNo)
+{
+ UCHAR ModeID;
+ USHORT usIDLength;
+
+ ModeIDOffset=*((USHORT *)(ROMAddr+0x20A)); /* Get EModeIDTable */
+ ModeID=*((UCHAR *)(ROMAddr+ModeIDOffset)); /* Offset 0x20A */
+ usIDLength = GetModeIDLength(ROMAddr, ModeNo);
+ while(ModeID!=0xff && ModeID!=ModeNo) {
+/* ModeIDOffset=ModeIDOffset+10; */ /*StructSize */
+ ModeIDOffset=ModeIDOffset+usIDLength;
+ ModeID=*((UCHAR *)(ROMAddr+ModeIDOffset));
+ }
+ if(ModeID==0xff) return(FALSE);
+ else return(TRUE);
+}
+
+BOOLEAN CheckMemorySize(ULONG ROMAddr)
+{
+ USHORT memorysize;
+ USHORT modeflag;
+ USHORT temp;
+
+ modeflag=*((USHORT *)(ROMAddr+ModeIDOffset+0x01)); /* si+St_ModeFlag */
+ ModeType=modeflag&ModeInfoFlag; /* Get mode type */
+
+ memorysize=modeflag&MemoryInfoFlag;
+ memorysize=memorysize>MemorySizeShift;
+ memorysize++; /* Get memory size */
+
+ temp=GetReg1(P3c4,0x14); /* Get DRAM Size */
+ temp=temp&0x3F;
+ temp++;
+
+ if(temp<memorysize) return(FALSE);
+ else return(TRUE);
+}
+
+VOID GetModePtr(ULONG ROMAddr, USHORT ModeNo)
+{
+ UCHAR index;
+
+ StandTable=*((USHORT *)(ROMAddr+0x202)); /* Get First 0x202 */
+ /* StandTable Offset */
+ if(ModeNo<=13) {
+ index=*((UCHAR *)(ROMAddr+ModeIDOffset+0x03)); /* si+St_ModeFlag */
+ }
+ else {
+ if(ModeType <= 0x02) index=0x1B; /* 02 -> ModeEGA */
+ else index=0x0F;
+ }
+ StandTable=StandTable+64*index;
+}
+
+VOID SetSeqRegs(ULONG ROMAddr)
+{
+ UCHAR SRdata;
+ USHORT i;
+
+ SetReg1(P3c4,0x00,0x03); /* Set SR0 */
+ StandTable=StandTable+0x05;
+ SRdata=*((UCHAR *)(ROMAddr+StandTable)); /* Get SR01 from file */
+ SRdata=SRdata|0x20;
+ SetReg1(P3c4,0x01,SRdata); /* Set SR1 */
+ for(i=02;i<=04;i++) {
+ StandTable++;
+ SRdata=*((UCHAR *)(ROMAddr+StandTable)); /* Get SR2,3,4 from file */
+ SetReg1(P3c4,i,SRdata); /* Set SR2 3 4 */
+ }
+}
+
+VOID SetMiscRegs(ULONG ROMAddr)
+{
+ UCHAR Miscdata;
+
+ StandTable++;
+ Miscdata=*((UCHAR *)(ROMAddr+StandTable)); /* Get Misc from file */
+ SetReg3(P3c2,Miscdata); /* Set Misc(3c2) */
+}
+
+VOID SetCRTCRegs(ULONG ROMAddr)
+{
+ UCHAR CRTCdata;
+ USHORT i;
+
+ CRTCdata=(UCHAR)GetReg1(P3d4,0x11);
+ CRTCdata=CRTCdata&0x7f;
+ SetReg1(P3d4,0x11,CRTCdata); /* Unlock CRTC */
+
+ for(i=0;i<=0x18;i++) {
+ StandTable++;
+ CRTCdata=*((UCHAR *)(ROMAddr+StandTable)); /* Get CRTC from file */
+ SetReg1(P3d4,i,CRTCdata); /* Set CRTC(3d4) */
+ }
+}
+
+VOID SetATTRegs(ULONG ROMAddr)
+{
+ UCHAR ARdata;
+ USHORT i;
+
+ for(i=0;i<=0x13;i++) {
+ StandTable++;
+ ARdata=*((UCHAR *)(ROMAddr+StandTable)); /* Get AR for file */
+ GetReg2(P3da); /* reset 3da */
+ SetReg3(P3c0,i); /* set index */
+ SetReg3(P3c0,ARdata); /* set data */
+ }
+ GetReg2(P3da); /* reset 3da */
+ SetReg3(P3c0,0x14); /* set index */
+ SetReg3(P3c0,0x00); /* set data */
+ GetReg2(P3da); /* Enable Attribute */
+ SetReg3(P3c0,0x20);
+}
+
+VOID SetGRCRegs(ULONG ROMAddr)
+{
+ UCHAR GRdata;
+ USHORT i;
+
+ for(i=0;i<=0x08;i++) {
+ StandTable++;
+ GRdata=*((UCHAR *)(ROMAddr+StandTable)); /* Get GR from file */
+ SetReg1(P3ce,i,GRdata); /* Set GR(3ce) */
+ }
+ if(ModeType>ModeVGA){
+ GRdata=(UCHAR)GetReg1(P3ce,0x05);
+ GRdata=GRdata&0xBF;
+ SetReg1(P3ce,0x05,GRdata);
+ }
+}
+
+VOID ClearExt1Regs()
+{
+ USHORT i;
+
+ for(i=0x0A;i<=0x0E;i++) SetReg1(P3c4,i,0x00); /* Clear SR0A-SR0E */
+}
+
+
+BOOLEAN GetRatePtr(ULONG ROMAddr, USHORT ModeNo)
+{
+ SHORT index;
+ USHORT temp;
+ USHORT ulRefIndexLength;
+
+ if(ModeNo<0x14) return(FALSE); /* Mode No <= 13h then return */
+
+ index=GetReg1(P3d4,0x33); /* Get 3d4 CRTC33 */
+ index=index&0x0F; /* Frame rate index */
+ if(index!=0) index--;
+ REFIndex=*((USHORT *)(ROMAddr+ModeIDOffset+0x04)); /* si+Ext_point */
+
+ ulRefIndexLength = GetRefindexLength(ROMAddr, ModeNo);
+ do {
+ temp=*((USHORT *)(ROMAddr+REFIndex)); /* di => REFIndex */
+ if(temp==0xFFFF) break;
+ temp=temp&ModeInfoFlag;
+ if(temp<ModeType) break;
+
+ REFIndex=REFIndex+ulRefIndexLength; /* rate size */
+ index--;
+ } while(index>=0);
+
+ REFIndex=REFIndex-ulRefIndexLength; /* rate size */
+ return(TRUE);
+}
+
+VOID SetSync(ULONG ROMAddr)
+{
+ USHORT sync;
+ USHORT temp;
+
+ sync=*((USHORT *)(ROMAddr+REFIndex)); /* di+0x00 */
+ sync=sync&0xC0;
+ temp=0x2F;
+ temp=temp|sync;
+ SetReg3(P3c2,temp); /* Set Misc(3c2) */
+}
+
+VOID SetCRT1CRTC(ULONG ROMAddr)
+{
+ UCHAR index;
+ UCHAR data;
+ USHORT i;
+
+ index=*((UCHAR *)(ROMAddr+REFIndex+0x02)) & 0x3F; /* Get index */
+ CRT1Table=*((USHORT *)(ROMAddr+0x204)); /* Get CRT1Table */
+ CRT1Table=CRT1Table+index*CRT1Len;
+
+ data=(UCHAR)GetReg1(P3d4,0x11);
+ data=data&0x7F;
+ SetReg1(P3d4,0x11,data); /* Unlock CRTC */
+
+ CRT1Table--;
+ for(i=0;i<=0x05;i++) {
+ CRT1Table++;
+ data=*((UCHAR *)(ROMAddr+CRT1Table));
+ SetReg1(P3d4,i,data);
+ }
+ for(i=0x06;i<=0x07;i++) {
+ CRT1Table++;
+ data=*((UCHAR *)(ROMAddr+CRT1Table));
+ SetReg1(P3d4,i,data);
+ }
+ for(i=0x10;i<=0x12;i++) {
+ CRT1Table++;
+ data=*((UCHAR *)(ROMAddr+CRT1Table));
+ SetReg1(P3d4,i,data);
+ }
+ for(i=0x15;i<=0x16;i++) {
+ CRT1Table++;
+ data=*((UCHAR *)(ROMAddr+CRT1Table));
+ SetReg1(P3d4,i,data);
+ }
+ for(i=0x0A;i<=0x0C;i++) {
+ CRT1Table++;
+ data=*((UCHAR *)(ROMAddr+CRT1Table));
+ SetReg1(P3c4,i,data);
+ }
+
+ CRT1Table++;
+ data=*((UCHAR *)(ROMAddr+CRT1Table));
+ data=data&0xE0;
+ SetReg1(P3c4,0x0E,data);
+
+ data=(UCHAR)GetReg1(P3d4,0x09);
+ data=data&0xDF;
+ i=*((UCHAR *)(ROMAddr+CRT1Table));
+ i=i&0x01;
+ i=i<<5;
+ data=data|i;
+ i=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
+ i=i&DoubleScanMode;
+ if(i) data=data|0x80;
+ SetReg1(P3d4,0x09,data);
+
+ if(ModeType>0x03) SetReg1(P3d4,0x14,0x4F);
+}
+
+VOID SetCRT1Offset(ULONG ROMAddr)
+{
+ USHORT temp,ah,al;
+ USHORT temp2,i;
+ USHORT DisplayUnit;
+
+ temp=*((UCHAR *)(ROMAddr+ModeIDOffset+0x03)); /* si+Ext_ModeInfo */
+ temp=temp>>4; /* index */
+ ScreenOffset=*((USHORT *)(ROMAddr+0x206)); /* ScreenOffset */
+ temp=*((UCHAR *)(ROMAddr+ScreenOffset+temp)); /* data */
+
+ temp2=*((USHORT *)(ROMAddr+REFIndex+0x00));
+ temp2=temp2&InterlaceMode;
+ if(temp2) temp=temp<<1;
+ temp2=ModeType-ModeEGA;
+ switch (temp2) {
+ case 0 : temp2=1; break;
+ case 1 : temp2=2; break;
+ case 2 : temp2=4; break;
+ case 3 : temp2=4; break;
+ case 4 : temp2=6; break;
+ case 5 : temp2=8; break;
+ }
+ temp=temp*temp2;
+ DisplayUnit=temp;
+
+ temp2=temp;
+ temp=temp>>8; /* ah */
+ temp=temp&0x0F;
+ i=GetReg1(P3c4,0x0E);
+ i=i&0xF0;
+ i=i|temp;
+ SetReg1(P3c4,0x0E,i);
+
+ temp=(UCHAR)temp2;
+ temp=temp&0xFF; /* al */
+ SetReg1(P3d4,0x13,temp);
+
+ temp2=*((USHORT *)(ROMAddr+REFIndex+0x00));
+ temp2=temp2&InterlaceMode;
+ if(temp2) DisplayUnit>>=1;
+
+ DisplayUnit=DisplayUnit<<5;
+ ah=(DisplayUnit&0xff00)>>8;
+ al=DisplayUnit&0x00ff;
+ if(al==0) ah=ah+1;
+ else ah=ah+2;
+ SetReg1(P3c4,0x10,ah);
+}
+
+VOID SetCRT1VCLK(ULONG ROMAddr)
+{
+ USHORT i;
+ UCHAR index,data;
+
+ index=*((UCHAR *)(ROMAddr+REFIndex+0x03)) & 0x3F;
+ CRT1VCLKLen=GetVCLKLen(ROMAddr);
+ data=index*CRT1VCLKLen;
+ VCLKData=*((USHORT *)(ROMAddr+0x208));
+ VCLKData=VCLKData+data;
+
+ SetReg1(P3c4,0x31,0);
+ for(i=0x2B;i<=0x2C;i++) {
+ data=*((UCHAR *)(ROMAddr+VCLKData));
+ SetReg1(P3c4,i,data);
+ VCLKData++;
+ }
+ SetReg1(P3c4,0x2D,0x80);
+}
+
+
+VOID SetCRT1ModeRegs(ULONG ROMAddr, USHORT ModeNo)
+{
+ USHORT data,data2,data3;
+
+ if(ModeNo>0x13) data=*((USHORT *)(ROMAddr+REFIndex+0x00));
+ else data=0;
+ data2=0;
+ if(ModeNo>0x13)
+ if(ModeType>0x02) {
+ data2=data2|0x02;
+ data3=ModeType-ModeVGA;
+ data3=data3<<2;
+ data2=data2|data3;
+ }
+
+ data=data&InterlaceMode;
+ if(data) data2=data2|0x20;
+ SetReg1(P3c4,0x06,data2);
+
+ data=GetReg1(P3c4,0x01);
+ data=data&0xF7;
+ data2=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
+ data2=data2&HalfDCLK;
+ if(data2) data=data|0x08;
+ SetReg1(P3c4,0x01,data);
+
+ data=GetReg1(P3c4,0x0F);
+ data=data&0xF7;
+ data2=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
+ data2=data2&LineCompareOff;
+ if(data2) data=data|0x08;
+ SetReg1(P3c4,0x0F,data);
+
+ data=GetReg1(P3c4,0x21);
+ data=data&0x1F;
+ if(ModeType==0x00) data=data|0x60; /* Text Mode */
+ else if(ModeType<=0x02) data=data|0x00; /* EGA Mode */
+ else data=data|0xA0; /* VGA Mode */
+ SetReg1(P3c4,0x21,data);
+}
+
+VOID SetVCLKState(ULONG ROMAddr, USHORT ModeNo)
+{
+ USHORT data,data2;
+ USHORT VCLK;
+ UCHAR index;
+
+ index=*((UCHAR *)(ROMAddr+REFIndex+0x03));
+ CRT1VCLKLen=GetVCLKLen(ROMAddr);
+ data=index*CRT1VCLKLen;
+ VCLKData=*((USHORT *)(ROMAddr+0x208));
+ VCLKData=VCLKData+data+(CRT1VCLKLen-2);
+ VCLK=*((USHORT *)(ROMAddr+VCLKData));
+ if(ModeNo<=0x13) VCLK=0;
+
+ data=GetReg1(P3c4,0x07);
+ data=data&0x7B;
+ if(VCLK>=150) data=data|0x80; /* VCLK > 150 */
+ SetReg1(P3c4,0x07,data);
+
+ data=GetReg1(P3c4,0x32);
+ data=data&0xD7;
+ if(VCLK>=150) data=data|0x08; /* VCLK > 150 */
+ SetReg1(P3c4,0x32,data);
+
+ data2=0x03;
+ if(VCLK>135) data2=0x02;
+ if(VCLK>160) data2=0x01;
+ if(VCLK>260) data2=0x00;
+ data=GetReg1(P3c4,0x07);
+ data=data&0xFC;
+ data=data|data2;
+ SetReg1(P3c4,0x07,data);
+}
+
+VOID LoadDAC(ULONG ROMAddr)
+{
+ USHORT data,data2;
+ USHORT time,i,j,k;
+ USHORT m,n,o;
+ USHORT si,di,bx,dl;
+ USHORT al,ah,dh;
+ USHORT *table=0;
+
+ data=*((USHORT *)(ROMAddr+ModeIDOffset+0x01));
+ data=data&DACInfoFlag;
+ time=64;
+ if(data==0x00) table=MDA_DAC;
+ if(data==0x08) table=CGA_DAC;
+ if(data==0x10) table=EGA_DAC;
+ if(data==0x18) {
+ time=256;
+ table=VGA_DAC;
+ }
+ if(time==256) j=16;
+ else j=time;
+
+ SetReg3(P3c6,0xFF);
+ SetReg3(P3c8,0x00);
+
+ for(i=0;i<j;i++) {
+ data=table[i];
+ for(k=0;k<3;k++) {
+ data2=0;
+ if(data&0x01) data2=0x2A;
+ if(data&0x02) data2=data2+0x15;
+ SetReg3(P3c9,data2);
+ data=data>>2;
+ }
+ }
+
+ if(time==256) {
+ for(i=16;i<32;i++) {
+ data=table[i];
+ for(k=0;k<3;k++) SetReg3(P3c9,data);
+ }
+ si=32;
+ for(m=0;m<9;m++) {
+ di=si;
+ bx=si+0x04;
+ dl=0;
+ for(n=0;n<3;n++) {
+ for(o=0;o<5;o++) {
+ dh=table[si];
+ ah=table[di];
+ al=table[bx];
+ si++;
+ WriteDAC(dl,ah,al,dh);
+ } /* for 5 */
+ si=si-2;
+ for(o=0;o<3;o++) {
+ dh=table[bx];
+ ah=table[di];
+ al=table[si];
+ si--;
+ WriteDAC(dl,ah,al,dh);
+ } /* for 3 */
+ dl++;
+ } /* for 3 */
+ si=si+5;
+ } /* for 9 */
+ }
+}
+
+VOID WriteDAC(USHORT dl, USHORT ah, USHORT al, USHORT dh)
+{
+ USHORT temp;
+ USHORT bh,bl;
+
+ bh=ah;
+ bl=al;
+ if(dl!=0) {
+ temp=bh;
+ bh=dh;
+ dh=temp;
+ if(dl==1) {
+ temp=bl;
+ bl=dh;
+ dh=temp;
+ }
+ else {
+ temp=bl;
+ bl=bh;
+ bh=temp;
+ }
+ }
+ SetReg3(P3c9,(USHORT)dh);
+ SetReg3(P3c9,(USHORT)bh);
+ SetReg3(P3c9,(USHORT)bl);
+}
+
+VOID DisplayOn()
+{
+ USHORT data;
+
+ data=GetReg1(P3c4,0x01);
+ data=data&0xDF;
+ SetReg1(P3c4,0x01,data);
+}
+
+VOID SetReg1(USHORT port, USHORT index, USHORT data)
+{
+ outb(port ,(UCHAR)(index & 0xff));
+ port++;
+ outb(port ,(UCHAR)(data & 0xff));
+}
+
+VOID SetReg3(USHORT port, USHORT data)
+{
+ outb(port, (UCHAR)(data & 0xff));
+}
+
+USHORT GetReg1(USHORT port, USHORT index)
+{
+ UCHAR data;
+
+ outb(port, (UCHAR)(index & 0xff));
+ port += 1;
+ data = inb(port);
+ return(data);
+}
+
+USHORT GetReg2(USHORT port)
+{
+ UCHAR data;
+
+ data = inb(port);
+
+ return(data);
+}
+
+USHORT GetModeIDLength(ULONG ROMAddr, USHORT ModeNo)
+{
+ UCHAR ModeID;
+ USHORT modeidlength;
+ USHORT usModeIDOffset;
+
+ return(10);
+ modeidlength=0;
+ usModeIDOffset=*((USHORT *)(ROMAddr+0x20A)); /* Get EModeIDTable */
+ ModeID=*((UCHAR *)(ROMAddr+usModeIDOffset)); /* Offset 0x20A */
+ while(ModeID!=0x2E) {
+ modeidlength++;
+ usModeIDOffset=usModeIDOffset+1; /* 10 <= ExtStructSize */
+ ModeID=*((UCHAR *)(ROMAddr+usModeIDOffset));
+ }
+ return(modeidlength);
+}
+
+USHORT GetRefindexLength(ULONG ROMAddr, USHORT ModeNo)
+{
+ UCHAR ModeID;
+ UCHAR temp;
+ USHORT refindexlength;
+ USHORT usModeIDOffset;
+ USHORT usREFIndex;
+ USHORT usIDLength;
+
+ usModeIDOffset=*((USHORT *)(ROMAddr+0x20A)); /* Get EModeIDTable */
+ ModeID=*((UCHAR *)(ROMAddr+usModeIDOffset)); /* Offset 0x20A */
+ usIDLength = GetModeIDLength(ROMAddr, ModeNo);
+ while(ModeID!=0x40) {
+ usModeIDOffset=usModeIDOffset+usIDLength; /*10 <= ExtStructSize */
+ ModeID=*((UCHAR *)(ROMAddr+usModeIDOffset));
+ }
+
+ refindexlength=1;
+ usREFIndex=*((USHORT *)(ROMAddr+usModeIDOffset+0x04)); /* si+Ext_point */
+ usREFIndex++;
+ temp=*((UCHAR *)(ROMAddr+usREFIndex)); /* di => REFIndex */
+ while(temp!=0xFF) {
+ refindexlength++;
+ usREFIndex++;
+ temp=*((UCHAR *)(ROMAddr+usREFIndex)); /* di => REFIndex */
+ }
+ return(refindexlength);
+}
+
+VOID SetInterlace(ULONG ROMAddr, USHORT ModeNo)
+{
+ ULONG Temp;
+ USHORT data,Temp2;
+
+ Temp = (ULONG)GetReg1(P3d4, 0x01);
+ Temp++;
+ Temp=Temp*8;
+
+ if(Temp==1024) data=0x0035;
+ else if(Temp==1280) data=0x0048;
+ else data=0x0000;
+
+ Temp2=*((USHORT *)(ROMAddr+REFIndex+0x00));
+ Temp2 &= InterlaceMode;
+ if(Temp2 == 0) data=0x0000;
+
+ SetReg1(P3d4,0x19,data);
+
+ Temp = (ULONG)GetReg1(P3d4, 0x1A);
+ Temp2= (USHORT)(Temp & 0xFC);
+ SetReg1(P3d4,0x1A,(USHORT)Temp);
+
+ Temp = (ULONG)GetReg1(P3c4, 0x0f);
+ Temp2= (USHORT)Temp & 0xBF;
+ if(ModeNo==0x37) Temp2=Temp2|0x40;
+ SetReg1(P3d4,0x1A,(USHORT)Temp2);
+}
+
+VOID SetCRT1FIFO(ULONG ROMAddr)
+{
+ USHORT index,data,VCLK,data2,MCLKOffset,MCLK,colorth=0;
+ USHORT ah,bl,A,B;
+
+ index=*((UCHAR *)(ROMAddr+REFIndex+0x03));
+ CRT1VCLKLen=GetVCLKLen(ROMAddr);
+ data=index*CRT1VCLKLen;
+ VCLKData=*((USHORT *)(ROMAddr+0x208));
+ VCLKData=VCLKData+data+(CRT1VCLKLen-2);
+ VCLK=*((USHORT *)(ROMAddr+VCLKData)); /* Get VCLK */
+
+ MCLKOffset=*((USHORT *)(ROMAddr+0x20C));
+ index=GetReg1(P3c4,0x3A);
+ index=index&07;
+ MCLKOffset=MCLKOffset+index*5;
+ MCLK=*((UCHAR *)(ROMAddr+MCLKOffset+0x03)); /* Get MCLK */
+
+ data2=ModeType-0x02;
+ switch (data2) {
+ case 0 : colorth=1; break;
+ case 1 : colorth=2; break;
+ case 2 : colorth=4; break;
+ case 3 : colorth=4; break;
+ case 4 : colorth=6; break;
+ case 5 : colorth=8; break;
+ }
+
+ do{
+/*==============*/
+ B=(USHORT)(CalcDelay(ROMAddr,0)*VCLK*colorth);
+ B=B/(16*MCLK);
+ B++;
+
+ A=(CalcDelay(ROMAddr,1)*VCLK*colorth);
+ A=A/(16*MCLK);
+ A++;
+
+ if(A<4) A=0;
+ else A=A-4;
+
+ if(A>B) bl=A;
+ else bl=B;
+
+ bl++;
+ if(bl>0x13) {
+ data=GetReg1(P3c4,0x16);
+ data=data>>6;
+ if(data!=0) {
+ data--;
+ data=data<<6;
+ data2=GetReg1(P3c4,0x16);
+ data2=(data2&0x3f)|data;
+ SetReg1(P3c4,0x16,data2);
+ }
+ else bl=0x13;
+ }
+/*==============*/
+ } while(bl>0x13);
+
+ ah=bl;
+ ah=ah<<4;
+ ah=ah|0x0f;
+ SetReg1(P3c4,0x08,ah);
+
+ data=bl;
+ data=data&0x10;
+ data=data<<1;
+ data2=GetReg1(P3c4,0x0F);
+ data2=data2&0x9f;
+ data2=data2|data;
+ SetReg1(P3c4,0x0F,data2);
+
+ data=bl+3;
+ if(data>0x0f) data=0x0f;
+ SetReg1(P3c4,0x3b,0x00);
+ data2=GetReg1(P3c4,0x09);
+ data2=data2&0xF0;
+ data2=data2|data;
+ SetReg1(P3c4,0x09,data2);
+}
+
+USHORT CalcDelay(ULONG ROMAddr,USHORT key)
+{
+ USHORT data,data2,temp0,temp1;
+ UCHAR ThLowA[]= {61,3,52,5,68,7,100,11,
+ 43,3,42,5,54,7, 78,11,
+ 34,3,37,5,47,7, 67,11};
+ UCHAR ThLowB[]= {81,4,72,6,88,8,120,12,
+ 55,4,54,6,66,8, 90,12,
+ 42,4,45,6,55,8, 75,12};
+ UCHAR ThTiming[]= {1,2,2,3,0,1,1,2};
+
+ data=GetReg1(P3c4,0x16);
+ data=data>>6;
+ data2=GetReg1(P3c4,0x14);
+ data2=(data2>>4)&0x0C;
+ data=data|data2;
+ data=data<1;
+ if(key==0) {
+ temp0=(USHORT)ThLowA[data];
+ temp1=(USHORT)ThLowA[data+1];
+ }
+ else {
+ temp0=(USHORT)ThLowB[data];
+ temp1=(USHORT)ThLowB[data+1];
+ }
+
+ data2=0;
+ data=GetReg1(P3c4,0x18);
+ if(data&0x02) data2=data2|0x01;
+ if(data&0x20) data2=data2|0x02;
+ if(data&0x40) data2=data2|0x04;
+
+ data=temp1*ThTiming[data2]+temp0;
+ return(data);
+}
+
+VOID SetCRT1FIFO2(ULONG ROMAddr)
+{
+ USHORT index,data,VCLK,data2,MCLKOffset,MCLK,colorth=0;
+ USHORT ah,bl,B;
+ ULONG eax;
+
+ index=*((UCHAR *)(ROMAddr+REFIndex+0x03));
+ CRT1VCLKLen=GetVCLKLen(ROMAddr);
+ data=index*CRT1VCLKLen;
+ VCLKData=*((USHORT *)(ROMAddr+0x208));
+ VCLKData=VCLKData+data+(CRT1VCLKLen-2);
+ VCLK=*((USHORT *)(ROMAddr+VCLKData)); /* Get VCLK */
+
+ MCLKOffset=*((USHORT *)(ROMAddr+0x20C));
+ index=GetReg1(P3c4,0x1A);
+ index=index&07;
+ MCLKOffset=MCLKOffset+index*5;
+ MCLK=*((USHORT *)(ROMAddr+MCLKOffset+0x03)); /* Get MCLK */
+
+ data2=ModeType-0x02;
+ switch (data2) {
+ case 0 : colorth=1; break;
+ case 1 : colorth=1; break;
+ case 2 : colorth=2; break;
+ case 3 : colorth=2; break;
+ case 4 : colorth=3; break;
+ case 5 : colorth=4; break;
+ }
+
+ do{
+/*==============*/
+ B=(CalcDelay2(ROMAddr,0)*VCLK*colorth);
+ if (B%(16*MCLK) == 0)
+ {
+ B=B/(16*MCLK);
+ bl=B+1;
+ }
+ else
+ {
+ B=B/(16*MCLK);
+ bl=B+2;
+ }
+
+ if(bl>0x13) {
+ data=GetReg1(P3c4,0x15);
+ data=data&0xf0;
+ if(data!=0xb0) {
+ data=data+0x20;
+ if(data==0xa0) data=0x30;
+
+ data2=GetReg1(P3c4,0x15);
+ data2=(data2&0x0f)|data;
+ SetReg1(P3c4,0x15,data2);
+ }
+ else bl=0x13;
+ }
+/*==============*/
+ } while(bl>0x13);
+
+ data2=GetReg1(P3c4,0x15);
+ data2=(data2&0xf0)>>4;
+ data2=data2<<24;
+
+/* ========================*/
+ SetReg4(0xcf8,0x80000050);
+ eax=GetReg3(0xcfc);
+ eax=eax&0x0f0ffffff;
+ eax=eax|data2;
+ SetReg4(0xcfc,eax);
+/* ========================*/
+
+ ah=bl;
+ ah=ah<<4;
+ ah=ah|0x0f;
+ SetReg1(P3c4,0x08,ah);
+
+ data=bl;
+ data=data&0x10;
+ data=data<<1;
+ data2=GetReg1(P3c4,0x0F);
+ data2=data2&0x9f;
+ data2=data2|data;
+ SetReg1(P3c4,0x0F,data2);
+
+ data=bl+3;
+ if(data>0x0f) data=0x0f;
+ SetReg1(P3c4,0x3b,0x00);
+ data2=GetReg1(P3c4,0x09);
+ data2=data2&0xF0;
+ data2=data2|data;
+ SetReg1(P3c4,0x09,data2);
+}
+
+USHORT CalcDelay2(ULONG ROMAddr,USHORT key)
+{
+ USHORT data,index;
+ UCHAR LatencyFactor[]={88,80,78,72,70,00,
+ 00,79,77,71,69,49,
+ 88,80,78,72,70,00,
+ 00,72,70,64,62,44};
+
+ index=0;
+ data=GetReg1(P3c4,0x14);
+ if(data&0x80) index=index+12;
+
+ data=GetReg1(P3c4,0x15);
+ data=(data&0xf0)>>4;
+ if(data&0x01) index=index+6;
+
+ data=data>>1;
+ index=index+data;
+ data=LatencyFactor[index];
+
+ return(data);
+}
+
+VOID SetReg4(USHORT port, ULONG data)
+{
+ outl(port, (ULONG)(data & 0xffffffff));
+}
+
+ULONG GetReg3(USHORT port)
+{
+ ULONG data;
+
+ data = inl(port);
+ return(data);
+}
+
+VOID SetPitch(ScrnInfoPtr pScrn, USHORT BaseAddr)
+{
+ SISPtr pSiS = SISPTR(pScrn);
+ ULONG HDisplay;
+ ULONG temp;
+ USHORT Port = BaseAddr + IND_SIS_CRT2_PORT_04;
+
+ HDisplay = pSiS->scrnOffset / 8;
+ SetReg1(P3d4, 0x13, HDisplay);
+ temp = (GetReg1(P3c4, 0x0E) & 0xF0) | (HDisplay>>8);
+ SetReg1(P3c4, 0x0E, temp);
+
+ SetReg1(Port, 0x24, 1);
+ SetReg1(Port, 0x07, HDisplay);
+ temp = (GetReg1(Port, 0x09) & 0xF0) | (HDisplay>>8);
+ SetReg1(Port, 0x09, temp);
+
+
+}
+USHORT CalcModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ USHORT i = (pScrn->bitsPerPixel+7)/8 - 1;
+ USHORT ModeIndex = 0;
+ switch(mode->HDisplay)
+ {
+ case 640:
+ ModeIndex = ModeIndex_640x480[i];
+ break;
+ case 800:
+ ModeIndex = ModeIndex_800x600[i];
+ break;
+ case 1024:
+ ModeIndex = ModeIndex_1024x768[i];
+ break;
+ case 1280:
+ ModeIndex = ModeIndex_1280x1024[i];
+ break;
+ case 1600:
+ ModeIndex = ModeIndex_1600x1200[i];
+ break;
+ }
+
+ return(ModeIndex);
+}
+USHORT CalcRefreshRate(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ SISPtr pSiS = SISPTR(pScrn);
+ USHORT Index=0;
+ USHORT i=0;
+ USHORT Rate=1;
+ USHORT temp = (int)(mode->VRefresh+0.5);
+
+ switch(mode->HDisplay)
+ {
+ case 640:
+ Index = 0;
+ break;
+ case 800:
+ Index = 1;
+ break;
+ case 1024:
+ Index = 2;
+ Rate = 2;
+ break;
+ case 1280:
+ Index = 3;
+ Rate = 2;
+ break;
+ case 1600:
+ Index = 4;
+ break;
+
+ }
+ while(RefreshRate[Index][i] != 0)
+ {
+ if(temp == RefreshRate[Index][i])
+ {
+ Rate=i+1;
+ break;
+ }
+ else
+ i++;
+ }
+ if(pSiS->VBFlags & CRT2_VGA)
+ Rate |= Rate << 4;
+ return(Rate);
+}