Fix BIOS read on 650 and 760. (#19070)
[xf86-video-sis/mirage.git] / src / sis_setup.c
blob253e9061485e818c3aa6854137f5dfc9f44cea03
1 /*
2 * Basic hardware and memory detection
4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1) Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2) Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3) The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Author: Thomas Winischhofer <thomas@winischhofer.net>
30 * Ideas and methods for old series based on code by Can-Ru Yeou, SiS Inc.
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
38 #include "sis.h"
39 #define SIS_NEED_inSISREGW
40 #define SIS_NEED_inSISREGL
41 #define SIS_NEED_outSISREGW
42 #define SIS_NEED_outSISREGL
43 #define SIS_NEED_inSISIDXREG
44 #define SIS_NEED_outSISIDXREG
45 #include "sis_regs.h"
47 extern int SiSMclk(SISPtr pSiS);
49 static const char *dramTypeStr[] = {
50 "Fast Page DRAM",
51 "2 cycle EDO RAM",
52 "1 cycle EDO RAM",
53 "SDRAM/SGRAM",
54 "SDR SDRAM",
55 "SGRAM",
56 "ESDRAM",
57 "DDR SDRAM", /* for 550/650/etc */
58 "DDR SDRAM", /* for 550/650/etc */
59 "VCM", /* for 630 */
60 "DDR2 SDRAM", /* for 340, 662 */
64 /* MCLK tables for SiS6326 */
65 static const int SiS6326MCLKIndex[4][8] = {
66 { 10, 12, 14, 16, 17, 18, 19, 7 }, /* SGRAM */
67 { 4, 6, 8, 10, 11, 12, 13, 3 }, /* Fast Page */
68 { 9, 11, 12, 13, 15, 16, 5, 7 }, /* 2 cycle EDO */
69 { 10, 12, 14, 16, 17, 18, 19, 7 } /* ? (Not 1 cycle EDO) */
72 static const struct _sis6326mclk {
73 CARD16 mclk;
74 UChar sr13;
75 UChar sr28;
76 UChar sr29;
77 } SiS6326MCLK[] = {
78 { 0, 0, 0, 0 },
79 { 0, 0, 0, 0 },
80 { 0, 0, 0, 0 },
81 { 45, 0, 0x2b, 0x26 },
82 { 53, 0, 0x49, 0xe4 },
83 { 55, 0, 0x7c, 0xe7 },
84 { 56, 0, 0x7c, 0xe7 },
85 { 60, 0, 0x42, 0xe3 },
86 { 61, 0, 0x21, 0xe1 },
87 { 65, 0, 0x5a, 0xe4 },
88 { 66, 0, 0x5a, 0xe4 },
89 { 70, 0, 0x61, 0xe4 },
90 { 75, 0, 0x3e, 0xe2 },
91 { 80, 0, 0x42, 0xe2 },
92 { 83, 0, 0xb3, 0xc5 },
93 { 85, 0, 0x5e, 0xe3 },
94 { 90, 0, 0xae, 0xc4 },
95 {100, 0, 0x37, 0xe1 },
96 {115, 0, 0x78, 0x0e },
97 {134, 0, 0x4a, 0xa3 }
100 #ifdef XSERVER_LIBPCIACCESS
101 struct pci_device *
102 sis_get_device (int device)
104 struct pci_slot_match bridge_match = {
105 0, 0, device, PCI_MATCH_ANY, 0
107 struct pci_device_iterator *slot_iterator;
108 struct pci_device *bridge;
110 slot_iterator = pci_slot_match_iterator_create (&bridge_match);
111 bridge = pci_device_next (slot_iterator);
112 pci_iterator_destroy (slot_iterator);
113 return bridge;
116 unsigned int
117 sis_pci_read_device_u32(int device, int offset)
119 struct pci_device *host_bridge = sis_get_device(device);
120 unsigned int result;
122 pci_device_cfg_read_u32(host_bridge, &result, offset);
123 return result;
126 unsigned char
127 sis_pci_read_device_u8(int device, int offset)
129 struct pci_device *host_bridge = sis_get_device(device);
130 unsigned char result;
132 pci_device_cfg_read_u8(host_bridge, &result, offset);
133 return result;
136 void
137 sis_pci_write_host_bridge_u32(int offset, unsigned int value)
139 struct pci_device *host_bridge = sis_get_device(0);
140 pci_device_cfg_write_u32(host_bridge, value, offset);
143 void
144 sis_pci_write_host_bridge_u8(int offset, unsigned char value)
146 struct pci_device *host_bridge = sis_get_device(0);
147 pci_device_cfg_write_u8(host_bridge, value, offset);
150 #else
151 unsigned int
152 sis_pci_read_device_u32(int device, int offset)
154 PCITAG tag = pciTag(0, device, 0);
155 return pciReadLong(tag, offset);
158 unsigned char
159 sis_pci_read_device_u8(int device, int offset)
161 PCITAG tag = pciTag(0, device, 0);
162 return pciReadByte(tag, offset);
165 void
166 sis_pci_write_host_bridge_u32(int offset, unsigned int value)
168 pciWriteLong(0x00000000, offset, value);
171 void
172 sis_pci_write_host_bridge_u8(int offset, unsigned char value)
174 pciWriteByte(0x00000000, offset, value);
178 #endif
180 unsigned int
181 sis_pci_read_host_bridge_u32(int offset)
183 return sis_pci_read_device_u32(0, offset);
186 unsigned char
187 sis_pci_read_host_bridge_u8(int offset)
189 return sis_pci_read_device_u8(0, offset);
192 static int sisESSPresent(ScrnInfoPtr pScrn)
194 int flags = 0;
195 #ifndef XSERVER_LIBPCIACCESS
196 int i;
197 pciConfigPtr pdptr, *systemPCIdevices = NULL;
199 if((systemPCIdevices = xf86GetPciConfigInfo())) {
200 i = 0;
201 while((pdptr = systemPCIdevices[i])) {
202 if((pdptr->pci_vendor == 0x1274) &&
203 ((pdptr->pci_device == 0x5000) ||
204 ((pdptr->pci_device & 0xFFF0) == 0x1370))) {
205 flags |= ESS137xPRESENT;
206 break;
208 i++;
211 return flags;
212 #else
213 struct pci_id_match id_match = { 0x1274, PCI_MATCH_ANY,
214 PCI_MATCH_ANY, PCI_MATCH_ANY,
215 PCI_MATCH_ANY, PCI_MATCH_ANY,
216 0 };
217 struct pci_device_iterator *id_iterator;
218 struct pci_device *ess137x;
220 id_iterator = pci_id_match_iterator_create(&id_match);
222 ess137x = pci_device_next(id_iterator);
223 while (ess137x) {
224 if ((ess137x->device_id == 0x5000) ||
225 ((ess137x->device_id & 0xfff0) == 0x1370)) {
226 flags |= ESS137xPRESENT;
228 ess137x = pci_device_next(id_iterator);
230 return flags;
231 #endif
234 /* For old chipsets, 5597, 6326, 530/620 */
235 static void
236 sisOldSetup(ScrnInfoPtr pScrn)
238 SISPtr pSiS = SISPTR(pScrn);
239 int ramsize[8] = { 1, 2, 4, 0, 0, 2, 4, 8};
240 int buswidth[8] = {32, 64, 64, 0, 0, 32, 32, 64 };
241 int clockTable[4] = { 66, 75, 83, 100 };
242 int ramtype[4] = { 5, 0, 1, 3 };
243 int config, temp, i;
244 UChar sr23, sr33, sr37;
245 #if 0
246 UChar newsr13, newsr28, newsr29;
247 #endif
248 #ifndef XSERVER_LIBPCIACCESS
249 pciConfigPtr pdptr, *systemPCIdevices = NULL;
250 #endif
252 if(pSiS->oldChipset <= OC_SIS6225) {
253 inSISIDXREG(SISSR, 0x0F, temp);
254 pScrn->videoRam = (1 << (temp & 0x03)) * 1024;
255 if(pScrn->videoRam > 4096) pScrn->videoRam = 4096;
256 pSiS->BusWidth = 32;
257 } else if(pSiS->Chipset == PCI_CHIP_SIS5597) {
258 inSISIDXREG(SISSR, 0x2F, temp);
259 pScrn->videoRam = ((temp & 0x07) + 1) * 256;
260 inSISIDXREG(SISSR, 0x0C, temp);
261 if(temp & 0x06) {
262 pScrn->videoRam *= 2;
263 pSiS->BusWidth = 64;
264 } else pSiS->BusWidth = 32;
265 } else {
266 inSISIDXREG(SISSR, 0x0C, temp);
267 config = ((temp & 0x10) >> 2 ) | ((temp & 0x06) >> 1);
268 pScrn->videoRam = ramsize[config] * 1024;
269 pSiS->BusWidth = buswidth[config];
272 if(pSiS->Chipset == PCI_CHIP_SIS530) {
274 inSISIDXREG(SISSR, 0x0D, temp);
275 pSiS->Flags &= ~(UMA);
276 if(temp & 0x01) {
277 pSiS->Flags |= UMA; /* Shared fb mode */
278 inSISIDXREG(SISSR, 0x10, temp);
279 pSiS->MemClock = clockTable[temp & 0x03] * 1000;
280 } else {
281 pSiS->MemClock = SiSMclk(pSiS); /* Local fb mode */
284 } else if(pSiS->Chipset == PCI_CHIP_SIS6326) {
286 inSISIDXREG(SISSR,0x0e,temp);
288 i = temp & 0x03;
290 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
291 "DRAM type: %s\n",
292 dramTypeStr[ramtype[i]]);
294 temp = (temp >> 5) & 0x07;
295 i = SiS6326MCLKIndex[i][temp];
296 pSiS->MemClock = SiS6326MCLK[i].mclk;
297 #if 0
298 /* Correct invalid MCLK settings by old BIOSes */
299 newsr13 = SiS6326MCLK[i].sr13;
300 newsr28 = SiS6326MCLK[i].sr28;
301 newsr29 = SiS6326MCLK[i].sr29;
302 if((pSiS->ChipRev == 0x92) ||
303 (pSiS->ChipRev == 0xd1) ||
304 (pSiS->ChipRev == 0xd2)) {
305 if(pSiS->MemClock == 60) {
306 newsr28 = 0xae;
307 newsr29 = 0xc4;
310 #endif
311 pSiS->MemClock *= 1000;
312 #if 0
313 inSISIDXREG(SISSR, 0x13, temp);
314 temp &= 0x80;
315 temp |= (newsr13 & 0x80);
316 outSISIDXREG(SISSR,0x13,temp);
317 outSISIDXREG(SISSR,0x28,newsr28);
318 outSISIDXREG(SISSR,0x29,newsr29);
319 #endif
321 } else {
323 pSiS->MemClock = SiSMclk(pSiS);
327 pSiS->Flags &= ~(SYNCDRAM | RAMFLAG);
328 if(pSiS->oldChipset >= OC_SIS82204) {
329 inSISIDXREG(SISSR, 0x23, sr23);
330 inSISIDXREG(SISSR, 0x33, sr33);
331 if(pSiS->oldChipset >= OC_SIS530A) sr33 &= ~0x08;
332 if(sr33 & 0x09) { /* 5597: Sync DRAM timing | One cycle EDO ram; */
333 pSiS->Flags |= (sr33 & SYNCDRAM); /* 6326: Enable SGRam timing | One cycle EDO ram */
334 pSiS->Flags |= RAMFLAG; /* 530: Enable SGRAM timing | reserved (0) */
335 } else if((pSiS->oldChipset < OC_SIS530A) && (sr23 & 0x20)) {
336 pSiS->Flags |= SYNCDRAM; /* 5597, 6326: EDO DRAM enabled */
337 } /* 530/620: reserved (0) */
340 pSiS->Flags &= ~(ESS137xPRESENT);
341 if(pSiS->Chipset == PCI_CHIP_SIS530) {
342 if(pSiS->oldChipset == OC_SIS530A) {
343 #ifndef XSERVER_LIBPCIACCESS
344 if((systemPCIdevices = xf86GetPciConfigInfo())) {
345 i = 0;
346 while((pdptr = systemPCIdevices[i])) {
347 if((pdptr->pci_vendor == 0x1274) &&
348 ((pdptr->pci_device == 0x5000) ||
349 ((pdptr->pci_device & 0xFFF0) == 0x1370))) {
350 pSiS->Flags |= ESS137xPRESENT;
351 break;
353 i++;
356 #else
357 /* FIXME maybe actually do hte detection? */
358 pSiS->Flags |= ESS137xPRESENT;
359 #endif
360 if(pSiS->Flags & ESS137xPRESENT) {
361 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
362 "SiS530/620: Found ESS device\n");
367 pSiS->Flags &= ~(SECRETFLAG);
368 if(pSiS->oldChipset >= OC_SIS5597) {
369 inSISIDXREG(SISSR, 0x37, sr37);
370 if(sr37 & 0x80) pSiS->Flags |= SECRETFLAG;
373 pSiS->Flags &= ~(A6326REVAB);
374 if(pSiS->Chipset == PCI_CHIP_SIS6326) {
375 if(((pSiS->ChipRev & 0x0f) == 0x0a) ||
376 ((pSiS->ChipRev & 0x0f) == 0x0b)) {
377 pSiS->Flags |= A6326REVAB;
381 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
382 "Memory clock: %3.3f MHz\n",
383 pSiS->MemClock/1000.0);
385 if(pSiS->oldChipset > OC_SIS6225) {
386 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
387 "DRAM bus width: %d bit\n",
388 pSiS->BusWidth);
391 #ifdef TWDEBUG
392 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
393 "oldChipset = %d, Flags %x\n", pSiS->oldChipset, pSiS->Flags);
394 #endif
397 static void
398 sis300Setup(ScrnInfoPtr pScrn)
400 SISPtr pSiS = SISPTR(pScrn);
401 const int bus[4] = {32, 64, 128, 32};
402 const int adaptermclk[8] = { 66, 83, 100, 133,
403 100, 100, 100, 100};
404 const int adaptermclk300[8] = { 125, 125, 125, 100,
405 100, 100, 100, 100};
406 unsigned int config, pciconfig, sr3a, ramtype;
407 UChar temp;
408 int cpubuswidth;
409 MessageType from = X_PROBED;
411 pSiS->MemClock = SiSMclk(pSiS);
413 inSISIDXREG(SISSR, 0x14, config);
414 cpubuswidth = bus[config >> 6];
416 inSISIDXREG(SISSR, 0x3A, sr3a);
417 ramtype = (sr3a & 0x03) + 4;
419 pSiS->IsPCIExpress = FALSE;
421 switch(pSiS->Chipset) {
422 case PCI_CHIP_SIS300:
423 pScrn->videoRam = ((config & 0x3F) + 1) * 1024;
424 pSiS->LFBsize = pScrn->videoRam;
425 pSiS->BusWidth = cpubuswidth;
426 pSiS->IsAGPCard = ((sr3a & 0x30) == 0x30) ? FALSE : TRUE;
427 break;
428 case PCI_CHIP_SIS540:
429 case PCI_CHIP_SIS630:
430 pSiS->IsAGPCard = TRUE;
431 pciconfig = sis_pci_read_host_bridge_u8(0x63);
432 if(pciconfig & 0x80) {
433 pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 21)) / 1024;
434 pSiS->BusWidth = 64;
435 pciconfig = sis_pci_read_host_bridge_u8(0x64);
436 if((pciconfig & 0x30) == 0x30) {
437 pSiS->BusWidth = 128;
438 pScrn->videoRam <<= 1;
440 ramtype = sis_pci_read_host_bridge_u8(0x65);
441 ramtype &= 0x03;
442 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
443 "Shared Memory Area is on DIMM%d\n", ramtype);
444 ramtype = sis_pci_read_host_bridge_u8(0x60 + ramtype);
445 if(ramtype & 0x80) ramtype = 9;
446 else ramtype = 4;
447 pSiS->UMAsize = pScrn->videoRam;
448 } else {
449 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
450 "Shared Memory Area is disabled - awaiting doom\n");
451 pScrn->videoRam = ((config & 0x3F) + 1) * 1024;
452 pSiS->UMAsize = pScrn->videoRam;
453 pSiS->BusWidth = 64;
454 ramtype = 4;
455 from = X_INFO;
457 break;
458 default:
459 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
460 "Internal error: sis300setup() called with invalid chipset!\n");
461 pSiS->BusWidth = 64;
462 from = X_INFO;
465 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
466 "DRAM type: %s\n",
467 dramTypeStr[ramtype]);
469 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
470 "Memory clock: %3.3f MHz\n",
471 pSiS->MemClock/1000.0);
473 if(pSiS->Chipset == PCI_CHIP_SIS300) {
474 if(pSiS->ChipRev > 0x13) {
475 inSISIDXREG(SISSR, 0x3A, temp);
476 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
477 "(Adapter assumes MCLK being %d Mhz)\n",
478 adaptermclk300[(temp & 0x07)]);
480 } else {
481 inSISIDXREG(SISSR, 0x1A, temp);
482 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
483 "(Adapter assumes MCLK being %d Mhz)\n",
484 adaptermclk[(temp & 0x07)]);
487 xf86DrvMsg(pScrn->scrnIndex, from,
488 "DRAM bus width: %d bit\n",
489 pSiS->BusWidth);
492 /* For 315, 315H, 315PRO/E, 330, 340 */
493 static void
494 sis315Setup(ScrnInfoPtr pScrn)
496 SISPtr pSiS = SISPTR(pScrn);
497 int busSDR[4] = {64, 64, 128, 128};
498 int busDDR[4] = {32, 32, 64, 64};
499 int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
500 unsigned int config, config1, config2, sr3a, cr5f;
501 char *dramTypeStr315[] = {
502 "Single channel 1 rank SDR SDRAM",
503 "Single channel 1 rank SDR SGRAM",
504 "Single channel 1 rank DDR SDRAM",
505 "Single channel 1 rank DDR SGRAM",
506 "Single channel 2 rank SDR SDRAM",
507 "Single channel 2 rank SDR SGRAM",
508 "Single channel 2 rank DDR SDRAM",
509 "Single channel 2 rank DDR SGRAM",
510 "Asymmetric SDR SDRAM",
511 "Asymmetric SDR SGRAM",
512 "Asymmetric DDR SDRAM",
513 "Asymmetric DDR SGRAM",
514 "Dual channel SDR SDRAM",
515 "Dual channel SDR SGRAM",
516 "Dual channel DDR SDRAM",
517 "Dual channel DDR SGRAM"
519 char *dramTypeStr330[] = {
520 "Single Channel SDR SDRAM",
522 "Single Channel DDR SDRAM",
524 "--unknown--",
526 "--unknown--",
528 "Asymetric Dual Channel SDR SDRAM",
530 "Asymetric Dual Channel DDR SDRAM",
532 "Dual channel SDR SDRAM",
534 "Dual channel DDR SDRAM",
537 char *dramTypeStr340[] = {
538 "Single channel DDR SDRAM",
539 "Single channel DDR2 SDRAM",
540 "Single channel DDR2x SDRAM",
542 "Dual channel DDR SDRAM",
543 "Dual channel DDR2 SDRAM",
544 "Dual channel DDR2x SDRAM",
546 "Dual channel DDR SDRAM",
547 "Dual channel DDR2 SDRAM",
548 "Dual channel DDR2x SDRAM",
550 "Quad channel DDR SDRAM",
551 "Quad channel DDR2 SDRAM",
552 "Quad channel DDR2x SDRAM",
556 inSISIDXREG(SISSR, 0x14, config);
557 config1 = (config & 0x0C) >> 2;
559 inSISIDXREG(SISSR, 0x3a, sr3a);
560 config2 = sr3a & 0x03;
562 inSISIDXREG(SISCR,0x5f,cr5f);
564 pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
566 pSiS->IsPCIExpress = FALSE;
568 switch(pSiS->Chipset) {
570 case PCI_CHIP_SIS340:
571 case PCI_CHIP_XGIXG20:
572 case PCI_CHIP_XGIXG40:
574 if(pSiS->ChipType != XGI_20) { /* SIS340, XGI_40 */
576 pSiS->IsAGPCard = TRUE;
578 if(pSiS->ChipRev == 2) {
579 if(config1 & 0x01) config1 = 0x02;
580 else config1 = 0x00;
582 if(config1 == 0x02) pScrn->videoRam <<= 1; /* dual rank */
583 else if(config1 == 0x03) pScrn->videoRam <<= 2; /* quad rank */
585 inSISIDXREG(SISSR, 0x39, config2);
586 config2 &= 0x02;
587 if(!config2) {
588 inSISIDXREG(SISSR, 0x3a, config2);
589 config2 = (config2 & 0x02) >> 1;
592 pSiS->BusWidth = (config & 0x02) ? 64 : 32;
594 } else { /* XGI_20 (Z7) */
596 config1 = 0x00;
597 inSISIDXREG(SISCR, 0x97, config2);
598 config2 &= 0x01;
599 config2 <<= 1; /* 0 or 2 */
601 pSiS->BusWidth = (config & 0x02) ? 32 :
602 ((config & 0x01) ? 16 : 8);
606 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
607 "DRAM type: %s\n", dramTypeStr340[(config1 * 4) + (config2 & 0x03)]);
609 pSiS->MemClock = SiSMclk(pSiS);
611 pSiS->MemClock *= 2; /* at least DDR */
613 break;
615 case PCI_CHIP_SIS330:
617 pSiS->IsAGPCard = TRUE;
619 if(config1) pScrn->videoRam <<= 1;
621 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
622 "DRAM type: %s\n", dramTypeStr330[(config1 * 4) + (config2 & 0x02)]);
624 pSiS->MemClock = SiSMclk(pSiS);
626 if(config2 & 0x02) {
627 pSiS->MemClock *= 2;
628 if(config1 == 0x02) {
629 pSiS->BusWidth = busDDRA[0];
630 } else {
631 pSiS->BusWidth = busDDR[(config & 0x02)];
633 } else {
634 if(config1 == 0x02) {
635 pSiS->BusWidth = busDDRA[2];
636 } else {
637 pSiS->BusWidth = busSDR[(config & 0x02)];
641 break;
643 default: /* 315 */
645 pSiS->IsAGPCard = ((sr3a & 0x30) == 0x30) ? FALSE : TRUE;
647 if(cr5f & 0x10) pSiS->ChipFlags |= SiSCF_Is315E;
649 /* If SINGLE_CHANNEL_2_RANK or DUAL_CHANNEL_1_RANK -> mem * 2 */
650 if((config1 == 0x01) || (config1 == 0x03)) pScrn->videoRam <<= 1;
652 /* If DDR asymetric -> mem * 1,5 */
653 if(config1 == 0x02) pScrn->videoRam += pScrn->videoRam/2;
655 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
656 "DRAM type: %s\n", dramTypeStr315[(config1 * 4) + config2]);
658 pSiS->MemClock = SiSMclk(pSiS);
660 /* If DDR -> memclock * 2 */
661 if(config2 & 0x02) pSiS->MemClock *= 2;
663 if(config1 == 0x02)
664 pSiS->BusWidth = busDDRA[(config & 0x03)];
665 else if(config2 & 0x02)
666 pSiS->BusWidth = busDDR[(config & 0x03)];
667 else
668 pSiS->BusWidth = busSDR[(config & 0x03)];
670 if(pSiS->ChipFlags & SiSCF_Is315E) {
671 inSISIDXREG(SISSR,0x15,config);
672 if(config & 0x10) pSiS->BusWidth = 32;
677 pSiS->LFBsize = pScrn->videoRam;
679 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
680 "Memory clock: %3.3f MHz\n",
681 pSiS->MemClock/1000.0);
683 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
684 "DRAM bus width: %d bit\n",
685 pSiS->BusWidth);
688 /* For 550, 65x, 740, 661, 741, 660, 760, 761, 670, 770, 662 */
689 static void
690 sis550Setup(ScrnInfoPtr pScrn)
692 SISPtr pSiS = SISPTR(pScrn);
693 unsigned int config, ramtype=0, i;
694 CARD8 pciconfig, temp;
695 Bool alldone = FALSE;
696 Bool ddrtimes2 = TRUE;
698 pSiS->IsAGPCard = TRUE;
699 pSiS->IsPCIExpress = FALSE;
700 pSiS->ChipFlags &= ~(SiSCF_760UMA | SiSCF_760LFB);
702 pSiS->MemClock = SiSMclk(pSiS);
704 if(pSiS->Chipset == PCI_CHIP_SIS670) {
706 /* TEMP - FIXME */
707 pScrn->videoRam = 0;
708 pciconfig = sis_pci_read_host_bridge_u8(0x4c);
709 if(pciconfig & 0xe0) {
710 pScrn->videoRam = (1 << (((pciconfig & 0xe0) >> 5) - 2)) * 32768;
711 pSiS->ChipFlags |= SiSCF_760UMA;
712 pSiS->SiS76xUMASize = pScrn->videoRam * 1024;
713 pSiS->UMAsize = pScrn->videoRam;
714 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
715 "%dK shared video RAM (UMA)\n",
716 pScrn->videoRam);
717 pSiS->BusWidth = 64;
718 ramtype = 8;
719 alldone = TRUE;
722 } else if(pSiS->Chipset == PCI_CHIP_SIS660) {
724 if(pSiS->ChipType >= SIS_660 && pSiS->ChipType <= SIS_761) {
726 /* 660, 760 */
728 /* UMA - shared fb */
729 pScrn->videoRam = 0;
730 pciconfig = sis_pci_read_host_bridge_u8(0x4c);
731 if(pciconfig & 0xe0) {
732 pScrn->videoRam = (1 << (((pciconfig & 0xe0) >> 5) - 2)) * 32768;
733 pSiS->ChipFlags |= SiSCF_760UMA;
734 pSiS->SiS76xUMASize = pScrn->videoRam * 1024;
735 pSiS->UMAsize = pScrn->videoRam;
736 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
737 "%dK shared video RAM (UMA)\n",
738 pScrn->videoRam);
741 /* LFB - local framebuffer: PCI reg hold total RAM (but configurable in BIOS) */
742 pciconfig = pciReadByte(0x00000800, 0xcd);
743 pciconfig = (pciconfig >> 1) & 0x03;
744 i = 0;
745 if(pciconfig == 0x01) i = 32768;
746 else if(pciconfig == 0x03) i = 65536;
747 if(i) {
748 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%dK total local video RAM (LFB)\n", i);
751 /* LFB: CR78 holds amount of LFB memory configured in the BIOS setup */
752 inSISIDXREG(SISCR, 0x78, config);
753 config &= 0x30;
754 if(config) {
755 i = 0;
756 if(config == 0x10) i = 32768;
757 else if(config == 0x30) i = 65536;
758 if(i) {
759 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%dK configured local video RAM (LFB)\n", i);
760 pScrn->videoRam += i;
761 pSiS->ChipFlags |= SiSCF_760LFB;
762 pSiS->SiS76xLFBSize = i * 1024;
763 pSiS->LFBsize = i;
767 if((pScrn->videoRam < 32768) || (pScrn->videoRam > 131072)) {
768 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
769 "Illegal video RAM size (%dK) detected, using BIOS provided setting\n",
770 pScrn->videoRam);
771 pSiS->ChipFlags &= ~(SiSCF_760LFB | SiSCF_760UMA);
772 } else {
773 pSiS->BusWidth = 64;
774 ramtype = 8;
775 alldone = TRUE;
778 if(pSiS->ChipType >= SIS_761) {
779 pSiS->IsAGPCard = FALSE;
780 pSiS->IsPCIExpress = TRUE;
783 } else if(pSiS->ChipType >= SIS_662) {
785 /* 662 - This crap written by SiS. FIXME!!! */
787 int dimmnum = 4; /* ? */
789 if(pSiS->ChipType == SIS_662) {
790 dimmnum = 2;
793 pciconfig = sis_pci_read_host_bridge_u8(0x64);
794 if(pciconfig & 0x80) {
795 pScrn->videoRam = (1 << (((pciconfig & 0x60) >> 5))) * 32768;
796 pSiS->UMAsize = pScrn->videoRam;
797 if((pScrn->videoRam < 32768) || (pScrn->videoRam > (128 * 1024))) {
798 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
799 "Illegal video RAM size (%dK) detected, using BIOS-provided info\n",
800 pScrn->videoRam);
801 } else {
802 pSiS->BusWidth = 64;
803 for(i = 0; i <= (dimmnum - 1); i++) {
804 if(pciconfig & (1 << i)) {
805 temp = sis_pci_read_host_bridge_u8(0x60 + i);
806 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
807 "DIMM%d is %s SDRAM\n",
808 i, (temp & 0x40) ? "DDR2" : "non-DDR2");
809 } else {
810 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
811 "DIMM%d is not installed\n", i);
814 alldone = FALSE; /* Why, oh why??? */
818 } else {
820 /* 661, 741 */
822 int dimmnum;
824 if(pSiS->ChipType == SIS_741) {
825 dimmnum = 4;
826 } else {
827 dimmnum = 3;
830 pciconfig = sis_pci_read_host_bridge_u8(0x64);
831 if(pciconfig & 0x80) {
832 pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) - 1)) * 32768;
833 pSiS->UMAsize = pScrn->videoRam;
834 if((pScrn->videoRam < 32768) || (pScrn->videoRam > (128 * 1024))) {
835 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
836 "Illegal video RAM size (%dK) detected, using BIOS-provided info\n",
837 pScrn->videoRam);
838 } else {
839 pSiS->BusWidth = 64;
840 for(i = 0; i <= (dimmnum - 1); i++) {
841 if(pciconfig & (1 << i)) {
842 temp = sis_pci_read_host_bridge_u8(0x60 + i);
843 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
844 "DIMM%d is %s SDRAM\n",
845 i, (temp & 0x40) ? "DDR" : "SDR");
846 } else {
847 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
848 "DIMM%d is not installed\n", i);
851 pciconfig = sis_pci_read_host_bridge_u8(0x7c);
852 ramtype = (pciconfig & 0x02) ? 8 : 4;
853 alldone = TRUE;
859 } else if(pSiS->Chipset == PCI_CHIP_SIS650) {
861 /* 65x, 741 */
863 pciconfig = sis_pci_read_host_bridge_u8(0x64);
864 if(pciconfig & 0x80) {
865 pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 22)) / 1024;
866 pSiS->UMAsize = pScrn->videoRam;
867 pSiS->BusWidth = 64;
868 for(i=0; i<=3; i++) {
869 if(pciconfig & (1 << i)) {
870 temp = sis_pci_read_host_bridge_u8(0x60 + i);
871 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
872 "DIMM%d is %s SDRAM\n",
873 i, (temp & 0x40) ? "DDR" : "SDR");
874 } else {
875 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
876 "DIMM%d is not installed\n", i);
879 pciconfig = sis_pci_read_host_bridge_u8(0x7c);
880 if(pciconfig & 0x02) ramtype = 8;
881 else ramtype = 4;
882 alldone = TRUE;
885 } else {
887 /* 550 */
889 pciconfig = sis_pci_read_host_bridge_u8(0x63);
890 if(pciconfig & 0x80) {
891 pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 21)) / 1024;
892 pSiS->UMAsize = pScrn->videoRam;
893 pSiS->BusWidth = 64;
894 ramtype = sis_pci_read_host_bridge_u8(0x65);
895 ramtype &= 0x01;
896 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
897 "Shared Memory Area is on DIMM%d\n", ramtype);
898 ramtype = 4;
899 alldone = TRUE;
904 /* Fall back to BIOS detection results in case of problems: */
906 if(!alldone) {
908 pSiS->SiS76xLFBSize = pSiS->SiS76xUMASize = 0;
909 pSiS->UMAsize = pSiS->LFBsize = 0;
911 if(pSiS->Chipset == PCI_CHIP_SIS670) {
913 /* TEMP - FIXME */
914 pScrn->videoRam = 0;
915 inSISIDXREG(SISCR, 0x78, config);
916 if(config & 0xf0) {
917 pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
918 pSiS->UMAsize = pScrn->videoRam;
919 pSiS->ChipFlags |= SiSCF_760UMA;
920 pSiS->SiS76xUMASize = pScrn->videoRam * 1024;
921 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
922 "%dK shared video RAM (UMA)\n",
923 pScrn->videoRam);
926 } else if(pSiS->Chipset == PCI_CHIP_SIS660) {
928 inSISIDXREG(SISCR, 0x79, config);
929 pSiS->BusWidth = (config & 0x04) ? 128 : 64;
931 if(pSiS->ChipType == SIS_662) {
932 switch(config&0x03) {
933 case 1:
934 ramtype = 8;
935 break;
936 case 2:
937 default:
938 ramtype = 0xa;
939 break;
941 } else {
942 ramtype = (config & 0x01) ? 8 : 4;
945 if(pSiS->ChipType >= SIS_660) {
946 pScrn->videoRam = 0;
947 if(config & 0xf0) {
948 pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
949 pSiS->UMAsize = pScrn->videoRam;
950 pSiS->ChipFlags |= SiSCF_760UMA;
951 pSiS->SiS76xUMASize = pScrn->videoRam * 1024;
952 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
953 "%dK shared video RAM (UMA)\n",
954 pScrn->videoRam);
956 if(pSiS->ChipType < SIS_662) {
957 inSISIDXREG(SISCR, 0x78, config);
958 config &= 0x30;
959 if(config) {
960 i = 0;
961 if(config == 0x10) i = 32768;
962 else if(config == 0x30) i = 65536;
963 if(i) {
964 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
965 "%dK configured local video RAM (LFB)\n", i);
966 pScrn->videoRam += i;
967 pSiS->SiS76xLFBSize = i * 1024;
968 pSiS->LFBsize = i;
969 pSiS->ChipFlags |= SiSCF_760LFB;
973 } else {
974 pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
975 pSiS->UMAsize = pScrn->videoRam;
978 } else {
980 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
981 "Shared Memory Area is disabled - awaiting doom\n");
982 inSISIDXREG(SISSR, 0x14, config);
983 pScrn->videoRam = (((config & 0x3F) + 1) * 4) * 1024;
984 pSiS->UMAsize = pScrn->videoRam;
985 if(pSiS->Chipset == PCI_CHIP_SIS650) {
986 ramtype = (((config & 0x80) >> 7) << 2) + 4;
987 pSiS->BusWidth = 64; /* (config & 0x40) ? 128 : 64; */
988 } else {
989 ramtype = 4;
990 pSiS->BusWidth = 64;
995 /* These (might) need special attention: Memory controller in CPU, hence
996 * - no DDR * 2 for bandwidth calculation,
997 * - overlay magic (bandwidth dependent one/two overlay stuff)
999 switch(pSiS->ChipType) {
1000 case SIS_760:
1001 #ifdef SIS761MEMFIX
1002 case SIS_761:
1003 case SIS_762:
1004 #endif
1005 #ifdef SIS770MEMFIX
1006 case SIS_770:
1007 #endif
1008 if(!(pSiS->ChipFlags & SiSCF_760LFB)) {
1009 ddrtimes2 = FALSE;
1010 pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT760OO;
1014 /* DDR -> Mclk * 2 - needed for bandwidth calculation */
1015 if(ddrtimes2) {
1016 if(ramtype == 8) pSiS->MemClock *= 2;
1017 if(ramtype == 0xa) pSiS->MemClock *= 2;
1020 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1021 "DRAM type: %s\n",
1022 dramTypeStr[ramtype]);
1024 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1025 "Memory clock: %3.3f MHz\n",
1026 pSiS->MemClock/1000.0);
1028 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1029 "DRAM bus width: %d bit\n",
1030 pSiS->BusWidth);
1033 void
1034 SiSSetup(ScrnInfoPtr pScrn)
1036 SISPtr pSiS = SISPTR(pScrn);
1038 pSiS->Flags = 0;
1039 pSiS->VBFlags = 0;
1040 pSiS->SiS76xLFBSize = pSiS->SiS76xUMASize = 0;
1041 pSiS->UMAsize = pSiS->LFBsize = 0;
1043 switch(pSiS->Chipset) {
1044 case PCI_CHIP_SIS300:
1045 case PCI_CHIP_SIS630: /* +730 */
1046 case PCI_CHIP_SIS540:
1047 sis300Setup(pScrn);
1048 break;
1049 case PCI_CHIP_SIS315:
1050 case PCI_CHIP_SIS315H:
1051 case PCI_CHIP_SIS315PRO:
1052 case PCI_CHIP_SIS330:
1053 case PCI_CHIP_SIS340:
1054 case PCI_CHIP_XGIXG20:
1055 case PCI_CHIP_XGIXG40:
1056 sis315Setup(pScrn);
1057 break;
1058 case PCI_CHIP_SIS550:
1059 case PCI_CHIP_SIS650: /* + 740, M650, 651 */
1060 case PCI_CHIP_SIS660: /* + (M)661, (M)741, (M)760(GX), (M)761(GX), 662 */
1061 case PCI_CHIP_SIS670: /* 670, 770 */
1062 sis550Setup(pScrn);
1063 break;
1064 case PCI_CHIP_SIS5597:
1065 case PCI_CHIP_SIS6326:
1066 case PCI_CHIP_SIS530:
1067 default:
1068 sisOldSetup(pScrn);
1069 break;