#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "xf86.h"
#include "fb.h"
#include "xf1bpp.h"
#include "xf4bpp.h"
#include "xf86_OSproc.h"
#include "xf86Resources.h"
#include "xf86_ansic.h"
#include "xf86Version.h"
#include "xf86cmap.h"
#include "sis.h"
#include "sis_regs.h"
#include "sis_dac.h"
#define _XF86DGA_SERVER_
#include "extensions/xf86dgastr.h"
#include "globals.h"
#define DPMS_SERVER
#include "extensions/dpms.h"
static const char *dramTypeStr[] = {
"Fast Page DRAM",
"2 cycle EDO RAM",
"1 cycle EDO RAM",
"SDRAM/SGRAM",
"SDR SDRAM",
"SGRAM",
"ESDRAM",
"DDR SDRAM",
"DDR SDRAM",
"VCM"
"" };
static const int SiS6326MCLKIndex[4][8] = {
{ 10, 12, 14, 16, 17, 18, 19, 7 },
{ 4, 6, 8, 10, 11, 12, 13, 3 },
{ 9, 11, 12, 13, 15, 16, 5, 7 },
{ 10, 12, 14, 16, 17, 18, 19, 7 }
};
static const struct _sis6326mclk {
CARD16 mclk;
unsigned char sr13;
unsigned char sr28;
unsigned char sr29;
} SiS6326MCLK[] = {
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 45, 0, 0x2b, 0x26 },
{ 53, 0, 0x49, 0xe4 },
{ 55, 0, 0x7c, 0xe7 },
{ 56, 0, 0x7c, 0xe7 },
{ 60, 0, 0x42, 0xe3 },
{ 61, 0, 0x21, 0xe1 },
{ 65, 0, 0x5a, 0xe4 },
{ 66, 0, 0x5a, 0xe4 },
{ 70, 0, 0x61, 0xe4 },
{ 75, 0, 0x3e, 0xe2 },
{ 80, 0, 0x42, 0xe2 },
{ 83, 0, 0xb3, 0xc5 },
{ 85, 0, 0x5e, 0xe3 },
{ 90, 0, 0xae, 0xc4 },
{100, 0, 0x37, 0xe1 },
{115, 0, 0x78, 0x0e },
{134, 0, 0x4a, 0xa3 }
};
static void
sisOldSetup(ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
int ramsize[8] = { 1, 2, 4, 0, 0, 2, 4, 8};
int buswidth[8] = {32, 64, 64, 0, 0, 32, 32, 64 };
int clockTable[4] = { 66, 75, 83, 100 };
int ramtype[4] = { 5, 0, 1, 3 };
int config;
int temp, i;
unsigned char sr23, sr33, sr37;
#if 0
unsigned char newsr13, newsr28, newsr29;
#endif
pciConfigPtr pdptr, *systemPCIdevices = NULL;
if(pSiS->oldChipset <= OC_SIS6225) {
inSISIDXREG(SISSR, 0x0F, temp);
pScrn->videoRam = (1 << (temp & 0x03)) * 1024;
if(pScrn->videoRam > 4096) pScrn->videoRam = 4096;
pSiS->BusWidth = 32;
} else if(pSiS->Chipset == PCI_CHIP_SIS5597) {
inSISIDXREG(SISSR, 0x2F, temp);
pScrn->videoRam = ((temp & 0x07) + 1) * 256;
inSISIDXREG(SISSR, 0x0C, temp);
if(temp & 0x06) {
pScrn->videoRam *= 2;
pSiS->BusWidth = 64;
} else pSiS->BusWidth = 32;
} else {
inSISIDXREG(SISSR, 0x0C, temp);
config = ((temp & 0x10) >> 2 ) | ((temp & 0x06) >> 1);
pScrn->videoRam = ramsize[config] * 1024;
pSiS->BusWidth = buswidth[config];
}
if(pSiS->Chipset == PCI_CHIP_SIS530) {
inSISIDXREG(SISSR, 0x0D, temp);
pSiS->Flags &= ~(UMA);
if(temp & 0x01) {
pSiS->Flags |= UMA;
inSISIDXREG(SISSR, 0x10, temp);
pSiS->MemClock = clockTable[temp & 0x03] * 1000;
} else pSiS->MemClock = SiSMclk(pSiS);
} else if(pSiS->Chipset == PCI_CHIP_SIS6326) {
inSISIDXREG(SISSR,0x0e,temp);
i = temp & 0x03;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"DRAM type: %s\n",
dramTypeStr[ramtype[i]]);
temp = (temp >> 5) & 0x07;
i = SiS6326MCLKIndex[i][temp];
pSiS->MemClock = SiS6326MCLK[i].mclk;
#if 0
newsr13 = SiS6326MCLK[i].sr13;
newsr28 = SiS6326MCLK[i].sr28;
newsr29 = SiS6326MCLK[i].sr29;
if((pSiS->ChipRev == 0x92) ||
(pSiS->ChipRev == 0xd1) ||
(pSiS->ChipRev == 0xd2)) {
if(pSiS->MemClock == 60) {
newsr28 = 0xae;
newsr29 = 0xc4;
}
}
#endif
pSiS->MemClock *= 1000;
#if 0
inSISIDXREG(SISSR, 0x13, temp);
temp &= 0x80;
temp |= (newsr13 & 0x80);
outSISIDXREG(SISSR,0x13,temp);
outSISIDXREG(SISSR,0x28,newsr28);
outSISIDXREG(SISSR,0x29,newsr29);
#endif
} else {
pSiS->MemClock = SiSMclk(pSiS);
}
pSiS->Flags &= ~(SYNCDRAM | RAMFLAG);
if(pSiS->oldChipset >= OC_SIS82204) {
inSISIDXREG(SISSR, 0x23, sr23);
inSISIDXREG(SISSR, 0x33, sr33);
if(pSiS->oldChipset >= OC_SIS530A) sr33 &= ~0x08;
if(sr33 & 0x09) {
pSiS->Flags |= (sr33 & SYNCDRAM);
pSiS->Flags |= RAMFLAG;
} else if((pSiS->oldChipset < OC_SIS530A) && (sr23 & 0x20)) {
pSiS->Flags |= SYNCDRAM;
}
}
pSiS->Flags &= ~(ESS137xPRESENT);
if(pSiS->Chipset == PCI_CHIP_SIS530) {
if(pSiS->oldChipset == OC_SIS530A) {
if((systemPCIdevices = xf86GetPciConfigInfo())) {
i = 0;
while((pdptr = systemPCIdevices[i])) {
if((pdptr->pci_vendor == 0x1274) &&
((pdptr->pci_device == 0x5000) ||
((pdptr->pci_device & 0xFFF0) == 0x1370))) {
pSiS->Flags |= ESS137xPRESENT;
break;
}
i++;
}
}
if(pSiS->Flags & ESS137xPRESENT) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"SiS530/620: Found ESS device\n");
}
}
}
pSiS->Flags &= ~(SECRETFLAG);
if(pSiS->oldChipset >= OC_SIS5597) {
inSISIDXREG(SISSR, 0x37, sr37);
if(sr37 & 0x80) pSiS->Flags |= SECRETFLAG;
}
pSiS->Flags &= ~(A6326REVAB);
if(pSiS->Chipset == PCI_CHIP_SIS6326) {
if(((pSiS->ChipRev & 0x0f) == 0x0a) ||
((pSiS->ChipRev & 0x0f) == 0x0b)) {
pSiS->Flags |= A6326REVAB;
}
}
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Memory clock: %3.3f MHz\n",
pSiS->MemClock/1000.0);
if(pSiS->oldChipset > OC_SIS6225) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"DRAM bus width: %d bit\n",
pSiS->BusWidth);
}
#ifdef TWDEBUG
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"oldChipset = %d, Flags %x\n", pSiS->oldChipset, pSiS->Flags);
#endif
}
static void
sis300Setup(ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
const int bus[4] = {32, 64, 128, 32};
const int adaptermclk[8] = { 66, 83, 100, 133,
100, 100, 100, 100};
const int adaptermclk300[8] = { 125, 125, 125, 100,
100, 100, 100, 100};
unsigned int config, pciconfig, sr3a, ramtype;
unsigned char temp;
int cpubuswidth;
MessageType from = X_PROBED;
pSiS->MemClock = SiSMclk(pSiS);
inSISIDXREG(SISSR, 0x14, config);
cpubuswidth = bus[config >> 6];
inSISIDXREG(SISSR, 0x3A, sr3a);
ramtype = (sr3a & 0x03) + 4;
switch(pSiS->Chipset) {
case PCI_CHIP_SIS300:
pScrn->videoRam = ((config & 0x3F) + 1) * 1024;
pSiS->BusWidth = cpubuswidth;
pSiS->IsAGPCard = ((sr3a & 0x30) == 0x30) ? FALSE : TRUE;
break;
case PCI_CHIP_SIS540:
case PCI_CHIP_SIS630:
pSiS->IsAGPCard = TRUE;
pciconfig = pciReadByte(0x00000000, 0x63);
if(pciconfig & 0x80) {
pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 21)) / 1024;
pSiS->BusWidth = 64;
pciconfig = pciReadByte(0x00000000, 0x64);
if((pciconfig & 0x30) == 0x30) {
pSiS->BusWidth = 128;
pScrn->videoRam <<= 1;
}
ramtype = pciReadByte(0x00000000,0x65);
ramtype &= 0x03;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Shared Memory Area is on DIMM%d\n", ramtype);
ramtype = pciReadByte(0x00000000,(0x60 + ramtype));
if(ramtype & 0x80) ramtype = 9;
else ramtype = 4;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Shared Memory Area is disabled - awaiting doom\n");
pScrn->videoRam = ((config & 0x3F) + 1) * 1024;
pSiS->BusWidth = 64;
ramtype = 4;
from = X_INFO;
}
break;
default:
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Internal error: sis300setup() called with invalid chipset!\n");
pSiS->BusWidth = 64;
from = X_INFO;
}
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"DRAM type: %s\n",
dramTypeStr[ramtype]);
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Memory clock: %3.3f MHz\n",
pSiS->MemClock/1000.0);
if(pSiS->Chipset == PCI_CHIP_SIS300) {
if(pSiS->ChipRev > 0x13) {
inSISIDXREG(SISSR, 0x3A, temp);
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"(Adapter assumes MCLK being %d Mhz)\n",
adaptermclk300[(temp & 0x07)]);
}
} else {
inSISIDXREG(SISSR, 0x1A, temp);
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"(Adapter assumes MCLK being %d Mhz)\n",
adaptermclk[(temp & 0x07)]);
}
xf86DrvMsg(pScrn->scrnIndex, from,
"DRAM bus width: %d bit\n",
pSiS->BusWidth);
}
static void
sis315Setup(ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
int busSDR[4] = {64, 64, 128, 128};
int busDDR[4] = {32, 32, 64, 64};
int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
unsigned int config, config1, config2, sr3a;
char *dramTypeStr315[] = {
"Single Channel 1 rank SDR SDRAM",
"Single Channel 1 rank SDR SGRAM",
"Single Channel 1 rank DDR SDRAM",
"Single Channel 1 rank DDR SGRAM",
"Single Channel 2 rank SDR SDRAM",
"Single Channel 2 rank SDR SGRAM",
"Single Channel 2 rank DDR SDRAM",
"Single Channel 2 rank DDR SGRAM",
"Asymmetric SDR SDRAM",
"Asymmetric SDR SGRAM",
"Asymmetric DDR SDRAM",
"Asymmetric DDR SGRAM",
"Dual channel SDR SDRAM",
"Dual channel SDR SGRAM",
"Dual channel DDR SDRAM",
"Dual channel DDR SGRAM"};
char *dramTypeStr330[] = {
"Single Channel SDR SDRAM",
"",
"Single Channel DDR SDRAM",
"",
"--unknown--",
"",
"--unknown--",
"",
"Asymetric Dual Channel SDR SDRAM",
"",
"Asymetric Dual Channel DDR SDRAM",
"",
"Dual channel SDR SDRAM",
"",
"Dual channel DDR SDRAM",
""};
inSISIDXREG(SISSR, 0x14, config);
config1 = (config & 0x0C) >> 2;
inSISIDXREG(SISSR, 0x3A, sr3a);
config2 = sr3a & 0x03;
pScrn->videoRam = (1 << ((config & 0xF0) >> 4)) * 1024;
if(pSiS->Chipset == PCI_CHIP_SIS330) {
pSiS->IsAGPCard = TRUE;
if(config1) pScrn->videoRam <<= 1;
} else {
pSiS->IsAGPCard = ((sr3a & 0x30) == 0x30) ? FALSE : TRUE;
if((config1 == 0x01) || (config1 == 0x03))
pScrn->videoRam <<= 1;
if(config1 == 0x02)
pScrn->videoRam += pScrn->videoRam/2;
}
pSiS->MemClock = SiSMclk(pSiS);
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"DRAM type: %s\n",
(pSiS->Chipset == PCI_CHIP_SIS330) ?
dramTypeStr330[(config1 * 4) + (config2 & 0x02)] :
dramTypeStr315[(config1 * 4) + config2]);
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Memory clock: %3.3f MHz\n",
pSiS->MemClock/1000.0);
if(pSiS->Chipset == PCI_CHIP_SIS330) {
if(config2 & 0x02) {
pSiS->MemClock *= 2;
if(config1 == 0x02) {
pSiS->BusWidth = busDDRA[0];
} else {
pSiS->BusWidth = busDDR[(config & 0x02)];
}
} else {
if(config1 == 0x02) {
pSiS->BusWidth = busDDRA[2];
} else {
pSiS->BusWidth = busSDR[(config & 0x02)];
}
}
} else {
if(config2 & 0x02) pSiS->MemClock *= 2;
if(config1 == 0x02)
pSiS->BusWidth = busDDRA[(config & 0x03)];
else if(config2 & 0x02)
pSiS->BusWidth = busDDR[(config & 0x03)];
else
pSiS->BusWidth = busSDR[(config & 0x03)];
}
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"DRAM bus width: %d bit\n",
pSiS->BusWidth);
}
static void
sis550Setup(ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
unsigned int config, ramtype=0, i;
CARD8 pciconfig, temp;
BOOLEAN alldone = FALSE;
pSiS->IsAGPCard = TRUE;
pSiS->MemClock = SiSMclk(pSiS);
if(pSiS->Chipset == PCI_CHIP_SIS660) {
if(pSiS->sishw_ext.jChipType >= SIS_660) {
pSiS->ChipFlags &= ~SiSCF_760UMA;
pciconfig = pciReadByte(0x00000000, 0x4c);
if(pciconfig & 0xe0) {
pScrn->videoRam = ((1 << (pciconfig & 0xe0) >> 5) - 2) * 32768;
pSiS->ChipFlags |= SiSCF_760UMA;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"%dK shared video RAM\n",
pScrn->videoRam);
} else pScrn->videoRam = 0;
pciconfig = (pciReadByte(0x00000800, 0xcd) >> 1) & 0x03;
if(pciconfig == 0x01) pScrn->videoRam += 32768;
else if(pciconfig == 0x03) pScrn->videoRam += 65536;
if((pScrn->videoRam < 32768) || (pScrn->videoRam > 131072)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Illegal video Ram size (%d) detected, using BIOS setting\n",
pScrn->videoRam);
} else {
pSiS->BusWidth = 64;
ramtype = 8;
alldone = TRUE;
}
} else {
int dimmnum, maxmem;
if(pSiS->sishw_ext.jChipType == SIS_741) {
dimmnum = 4;
maxmem = 131072;
} else {
dimmnum = 3;
maxmem = 65536;
}
pciconfig = pciReadByte(0x00000000, 0x64);
if(pciconfig & 0x80) {
pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) - 1)) * 32768;
if((pScrn->videoRam < 32768) || (pScrn->videoRam > maxmem)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Illegal video RAM size (%d) detected, using BIOS setting\n",
pScrn->videoRam);
} else {
pSiS->BusWidth = 64;
for(i=0; i<=(dimmnum - 1); i++) {
if(pciconfig & (1 << i)) {
temp = pciReadByte(0x00000000, 0x60 + i);
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"DIMM%d is %s SDRAM\n",
i, (temp & 0x40) ? "DDR" : "SDR");
} else {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"DIMM%d is not installed\n", i);
}
}
pciconfig = pciReadByte(0x00000000, 0x7c);
if(pciconfig & 0x02) ramtype = 8;
else ramtype = 4;
if(pSiS->sishw_ext.jChipType == SIS_741) {
ramtype = 12 - ramtype;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"SiS741 PCI RamType %d\n", ramtype);
inSISIDXREG(SISSR, 0x79, config);
ramtype = (config & 0x01) ? 8 : 4;
}
alldone = TRUE;
}
}
}
} else if(pSiS->Chipset == PCI_CHIP_SIS650) {
pciconfig = pciReadByte(0x00000000, 0x64);
if(pciconfig & 0x80) {
pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 22)) / 1024;
pSiS->BusWidth = 64;
for(i=0; i<=3; i++) {
if(pciconfig & (1 << i)) {
temp = pciReadByte(0x00000000, 0x60 + i);
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"DIMM%d is %s SDRAM\n",
i, (temp & 0x40) ? "DDR" : "SDR");
} else {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"DIMM%d is not installed\n", i);
}
}
pciconfig = pciReadByte(0x00000000, 0x7c);
if(pciconfig & 0x02) ramtype = 8;
else ramtype = 4;
alldone = TRUE;
}
} else {
pciconfig = pciReadByte(0x00000000, 0x63);
if(pciconfig & 0x80) {
pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 21)) / 1024;
pSiS->BusWidth = 64;
ramtype = pciReadByte(0x00000000,0x65);
ramtype &= 0x01;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Shared Memory Area is on DIMM%d\n", ramtype);
ramtype = 4;
alldone = TRUE;
}
}
if(!alldone) {
if(pSiS->Chipset == PCI_CHIP_SIS660) {
inSISIDXREG(SISCR, 0x79, config);
pSiS->BusWidth = (config & 0x04) ? 128 : 64;
ramtype = (config & 0x01) ? 8 : 4;
if(pSiS->sishw_ext.jChipType >= SIS_660) {
pScrn->videoRam = 0;
if(config & 0xf0) {
pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
}
inSISIDXREG(SISCR, 0x78, config);
config &= 0x30;
if(config) {
if(config == 0x10) pScrn->videoRam += 32768;
else pScrn->videoRam += 65536;
}
} else {
pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
}
} else {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Shared Memory Area is disabled - awaiting doom\n");
inSISIDXREG(SISSR, 0x14, config);
pScrn->videoRam = (((config & 0x3F) + 1) * 4) * 1024;
if(pSiS->Chipset == PCI_CHIP_SIS650) {
ramtype = (((config & 0x80) >> 7) << 2) + 4;
pSiS->BusWidth = 64;
} else {
ramtype = 4;
pSiS->BusWidth = 64;
}
}
}
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"DRAM type: %s\n",
dramTypeStr[ramtype]);
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Memory clock: %3.3f MHz\n",
pSiS->MemClock/1000.0);
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"DRAM bus width: %d bit\n",
pSiS->BusWidth);
if(ramtype == 8) pSiS->MemClock *= 2;
}
void
SiSSetup(ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
pSiS->Flags = 0;
pSiS->VBFlags = 0;
switch (SISPTR(pScrn)->Chipset) {
case PCI_CHIP_SIS300:
case PCI_CHIP_SIS630:
case PCI_CHIP_SIS540:
sis300Setup(pScrn);
break;
case PCI_CHIP_SIS315:
case PCI_CHIP_SIS315H:
case PCI_CHIP_SIS315PRO:
case PCI_CHIP_SIS330:
sis315Setup(pScrn);
break;
case PCI_CHIP_SIS550:
case PCI_CHIP_SIS650:
case PCI_CHIP_SIS660:
sis550Setup(pScrn);
break;
case PCI_CHIP_SIS5597:
case PCI_CHIP_SIS6326:
case PCI_CHIP_SIS530:
default:
sisOldSetup(pScrn);
break;
}
}