sis_setup.c revision 72b676d7
1/* $XFree86$ */
2/* $XdotOrg$ */
3/*
4 * Basic hardware and memory detection
5 *
6 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1) Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2) Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3) The name of the author may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Author:  	Thomas Winischhofer <thomas@winischhofer.net>
31 *
32 * Ideas and methods for old series based on code by Can-Ru Yeou, SiS Inc.
33 *
34 */
35
36#ifdef HAVE_CONFIG_H
37#include "config.h"
38#endif
39
40#include "sis.h"
41#define SIS_NEED_inSISREGW
42#define SIS_NEED_inSISREGL
43#define SIS_NEED_outSISREGW
44#define SIS_NEED_outSISREGL
45#define SIS_NEED_inSISIDXREG
46#define SIS_NEED_outSISIDXREG
47#include "sis_regs.h"
48
49extern int SiSMclk(SISPtr pSiS);
50
51static const char *dramTypeStr[] = {
52	"Fast Page DRAM",
53	"2 cycle EDO RAM",
54	"1 cycle EDO RAM",
55	"SDRAM/SGRAM",
56	"SDR SDRAM",
57	"SGRAM",
58	"ESDRAM",
59	"DDR SDRAM",  /* for 550/650/etc */
60	"DDR SDRAM",  /* for 550/650/etc */
61	"VCM",	      /* for 630 */
62	"DDR2 SDRAM", /* for 340 */
63	""
64};
65
66/* MCLK tables for SiS6326 */
67static const int SiS6326MCLKIndex[4][8] = {
68	{ 10, 12, 14, 16, 17, 18, 19,  7 },  /* SGRAM */
69	{  4,  6,  8, 10, 11, 12, 13,  3 },  /* Fast Page */
70	{  9, 11, 12, 13, 15, 16,  5,  7 },  /* 2 cycle EDO */
71	{ 10, 12, 14, 16, 17, 18, 19,  7 }   /* ? (Not 1 cycle EDO) */
72};
73
74static const struct _sis6326mclk {
75    CARD16 mclk;
76    UChar  sr13;
77    UChar  sr28;
78    UChar  sr29;
79} SiS6326MCLK[] = {
80	{  0, 0,    0,    0 },
81	{  0, 0,    0,    0 },
82	{  0, 0,    0,    0 },
83	{ 45, 0, 0x2b, 0x26 },
84	{ 53, 0, 0x49, 0xe4 },
85	{ 55, 0, 0x7c, 0xe7 },
86	{ 56, 0, 0x7c, 0xe7 },
87	{ 60, 0, 0x42, 0xe3 },
88	{ 61, 0, 0x21, 0xe1 },
89	{ 65, 0, 0x5a, 0xe4 },
90	{ 66, 0, 0x5a, 0xe4 },
91	{ 70, 0, 0x61, 0xe4 },
92	{ 75, 0, 0x3e, 0xe2 },
93	{ 80, 0, 0x42, 0xe2 },
94	{ 83, 0, 0xb3, 0xc5 },
95	{ 85, 0, 0x5e, 0xe3 },
96	{ 90, 0, 0xae, 0xc4 },
97	{100, 0, 0x37, 0xe1 },
98	{115, 0, 0x78, 0x0e },
99	{134, 0, 0x4a, 0xa3 }
100};
101
102/* For old chipsets, 5597, 6326, 530/620 */
103static void
104sisOldSetup(ScrnInfoPtr pScrn)
105{
106    SISPtr pSiS = SISPTR(pScrn);
107    int    ramsize[8]  = { 1,  2,  4, 0, 0,  2,  4,  8};
108    int    buswidth[8] = {32, 64, 64, 0, 0, 32, 32, 64 };
109    int    clockTable[4] = { 66, 75, 83, 100 };
110    int    ramtype[4]  = { 5, 0, 1, 3 };
111    int    config, temp, i;
112    UChar  sr23, sr33, sr37;
113#if 0
114    UChar  newsr13, newsr28, newsr29;
115#endif
116    pciConfigPtr pdptr, *systemPCIdevices = NULL;
117
118    if(pSiS->oldChipset <= OC_SIS6225) {
119	inSISIDXREG(SISSR, 0x0F, temp);
120	pScrn->videoRam = (1 << (temp & 0x03)) * 1024;
121	if(pScrn->videoRam > 4096) pScrn->videoRam = 4096;
122	pSiS->BusWidth = 32;
123    } else if(pSiS->Chipset == PCI_CHIP_SIS5597) {
124	inSISIDXREG(SISSR, 0x2F, temp);
125	pScrn->videoRam = ((temp & 0x07) + 1) * 256;
126	inSISIDXREG(SISSR, 0x0C, temp);
127	if(temp & 0x06) {
128		pScrn->videoRam *= 2;
129		pSiS->BusWidth = 64;
130	} else  pSiS->BusWidth = 32;
131    } else {
132	inSISIDXREG(SISSR, 0x0C, temp);
133	config = ((temp & 0x10) >> 2 ) | ((temp & 0x06) >> 1);
134	pScrn->videoRam = ramsize[config] * 1024;
135	pSiS->BusWidth = buswidth[config];
136    }
137
138    if(pSiS->Chipset == PCI_CHIP_SIS530)  {
139
140	inSISIDXREG(SISSR, 0x0D, temp);
141	pSiS->Flags &= ~(UMA);
142	if(temp & 0x01) {
143		pSiS->Flags |= UMA;  		/* Shared fb mode */
144		inSISIDXREG(SISSR, 0x10, temp);
145		pSiS->MemClock = clockTable[temp & 0x03] * 1000;
146	} else  {
147		pSiS->MemClock = SiSMclk(pSiS); /* Local fb mode */
148	}
149
150    } else if(pSiS->Chipset == PCI_CHIP_SIS6326) {
151
152	inSISIDXREG(SISSR,0x0e,temp);
153
154	i = temp & 0x03;
155
156	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
157	    "DRAM type: %s\n",
158	    dramTypeStr[ramtype[i]]);
159
160	temp = (temp >> 5) & 0x07;
161	i = SiS6326MCLKIndex[i][temp];
162	pSiS->MemClock = SiS6326MCLK[i].mclk;
163#if 0
164	/* Correct invalid MCLK settings by old BIOSes */
165	newsr13 = SiS6326MCLK[i].sr13;
166	newsr28 = SiS6326MCLK[i].sr28;
167	newsr29 = SiS6326MCLK[i].sr29;
168	if((pSiS->ChipRev == 0x92) ||
169	   (pSiS->ChipRev == 0xd1) ||
170	   (pSiS->ChipRev == 0xd2)) {
171	   if(pSiS->MemClock == 60) {
172	      newsr28 = 0xae;
173	      newsr29 = 0xc4;
174	   }
175	}
176#endif
177	pSiS->MemClock *= 1000;
178#if 0
179	inSISIDXREG(SISSR, 0x13, temp);
180	temp &= 0x80;
181	temp |= (newsr13 & 0x80);
182	outSISIDXREG(SISSR,0x13,temp);
183	outSISIDXREG(SISSR,0x28,newsr28);
184	outSISIDXREG(SISSR,0x29,newsr29);
185#endif
186
187    } else {
188
189	pSiS->MemClock = SiSMclk(pSiS);
190
191    }
192
193    pSiS->Flags &= ~(SYNCDRAM | RAMFLAG);
194    if(pSiS->oldChipset >= OC_SIS82204) {
195       inSISIDXREG(SISSR, 0x23, sr23);
196       inSISIDXREG(SISSR, 0x33, sr33);
197       if(pSiS->oldChipset >= OC_SIS530A) sr33 &= ~0x08;
198       if(sr33 & 0x09) {				/* 5597: Sync DRAM timing | One cycle EDO ram;   */
199		pSiS->Flags |= (sr33 & SYNCDRAM);	/* 6326: Enable SGRam timing | One cycle EDO ram */
200		pSiS->Flags |= RAMFLAG;			/* 530:  Enable SGRAM timing | reserved (0)      */
201       } else if((pSiS->oldChipset < OC_SIS530A) && (sr23 & 0x20)) {
202		pSiS->Flags |= SYNCDRAM;		/* 5597, 6326: EDO DRAM enabled */
203       }						/* 530/620:    reserved (0)     */
204    }
205
206    pSiS->Flags &= ~(ESS137xPRESENT);
207    if(pSiS->Chipset == PCI_CHIP_SIS530) {
208       if(pSiS->oldChipset == OC_SIS530A) {
209          if((systemPCIdevices = xf86GetPciConfigInfo())) {
210	      i = 0;
211	      while((pdptr = systemPCIdevices[i])) {
212		 if((pdptr->pci_vendor == 0x1274) &&
213		    ((pdptr->pci_device == 0x5000) ||
214		     ((pdptr->pci_device & 0xFFF0) == 0x1370))) {
215		     pSiS->Flags |= ESS137xPRESENT;
216		     break;
217		 }
218		 i++;
219	      }
220	  }
221	  if(pSiS->Flags & ESS137xPRESENT) {
222	     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
223		 "SiS530/620: Found ESS device\n");
224	  }
225       }
226    }
227
228    pSiS->Flags &= ~(SECRETFLAG);
229    if(pSiS->oldChipset >= OC_SIS5597) {
230	inSISIDXREG(SISSR, 0x37, sr37);
231	if(sr37 & 0x80) pSiS->Flags |= SECRETFLAG;
232    }
233
234    pSiS->Flags &= ~(A6326REVAB);
235    if(pSiS->Chipset == PCI_CHIP_SIS6326) {
236       if(((pSiS->ChipRev & 0x0f) == 0x0a) ||
237	  ((pSiS->ChipRev & 0x0f) == 0x0b)) {
238	    pSiS->Flags |= A6326REVAB;
239       }
240    }
241
242    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
243	       "Memory clock: %3.3f MHz\n",
244	       pSiS->MemClock/1000.0);
245
246    if(pSiS->oldChipset > OC_SIS6225) {
247       xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
248	       "DRAM bus width: %d bit\n",
249	       pSiS->BusWidth);
250    }
251
252#ifdef TWDEBUG
253    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
254		"oldChipset = %d, Flags %x\n", pSiS->oldChipset, pSiS->Flags);
255#endif
256}
257
258static void
259sis300Setup(ScrnInfoPtr pScrn)
260{
261    SISPtr    pSiS = SISPTR(pScrn);
262    const int bus[4] = {32, 64, 128, 32};
263    const int adaptermclk[8]    = {  66,  83, 100, 133,
264                                    100, 100, 100, 100};
265    const int adaptermclk300[8] = { 125, 125, 125, 100,
266                                    100, 100, 100, 100};
267    unsigned int config, pciconfig, sr3a, ramtype;
268    UChar        temp;
269    int		 cpubuswidth;
270    MessageType	 from = X_PROBED;
271
272    pSiS->MemClock = SiSMclk(pSiS);
273
274    inSISIDXREG(SISSR, 0x14, config);
275    cpubuswidth = bus[config >> 6];
276
277    inSISIDXREG(SISSR, 0x3A, sr3a);
278    ramtype = (sr3a & 0x03) + 4;
279
280    pSiS->IsPCIExpress = FALSE;
281
282    switch(pSiS->Chipset) {
283    case PCI_CHIP_SIS300:
284	pScrn->videoRam = ((config & 0x3F) + 1) * 1024;
285	pSiS->LFBsize = pScrn->videoRam;
286	pSiS->BusWidth = cpubuswidth;
287	pSiS->IsAGPCard = ((sr3a & 0x30) == 0x30) ? FALSE : TRUE;
288	break;
289    case PCI_CHIP_SIS540:
290    case PCI_CHIP_SIS630:
291	pSiS->IsAGPCard = TRUE;
292	pciconfig = pciReadByte(0x00000000, 0x63);
293	if(pciconfig & 0x80) {
294	   pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 21)) / 1024;
295	   pSiS->BusWidth = 64;
296	   pciconfig = pciReadByte(0x00000000, 0x64);
297	   if((pciconfig & 0x30) == 0x30) {
298	      pSiS->BusWidth = 128;
299	      pScrn->videoRam <<= 1;
300	   }
301	   ramtype = pciReadByte(0x00000000,0x65);
302	   ramtype &= 0x03;
303	   xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
304		"Shared Memory Area is on DIMM%d\n", ramtype);
305	   ramtype = pciReadByte(0x00000000,(0x60 + ramtype));
306	   if(ramtype & 0x80) ramtype = 9;
307	   else               ramtype = 4;
308	   pSiS->UMAsize = pScrn->videoRam;
309	} else {
310	   xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
311		"Shared Memory Area is disabled - awaiting doom\n");
312	   pScrn->videoRam = ((config & 0x3F) + 1) * 1024;
313	   pSiS->UMAsize = pScrn->videoRam;
314	   pSiS->BusWidth = 64;
315	   ramtype = 4;
316	   from = X_INFO;
317	}
318	break;
319    default:
320	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
321		"Internal error: sis300setup() called with invalid chipset!\n");
322	pSiS->BusWidth = 64;
323	from = X_INFO;
324    }
325
326    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
327	    "DRAM type: %s\n",
328	    dramTypeStr[ramtype]);
329
330    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
331	    "Memory clock: %3.3f MHz\n",
332	    pSiS->MemClock/1000.0);
333
334    if(pSiS->Chipset == PCI_CHIP_SIS300) {
335       if(pSiS->ChipRev > 0x13) {
336	  inSISIDXREG(SISSR, 0x3A, temp);
337	  xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
338	     "(Adapter assumes MCLK being %d Mhz)\n",
339	     adaptermclk300[(temp & 0x07)]);
340       }
341    } else {
342       inSISIDXREG(SISSR, 0x1A, temp);
343       xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
344	    "(Adapter assumes MCLK being %d Mhz)\n",
345	    adaptermclk[(temp & 0x07)]);
346    }
347
348    xf86DrvMsg(pScrn->scrnIndex, from,
349	    "DRAM bus width: %d bit\n",
350	    pSiS->BusWidth);
351}
352
353/* For 315, 315H, 315PRO/E, 330, 340 */
354static void
355sis315Setup(ScrnInfoPtr pScrn)
356{
357    SISPtr  pSiS = SISPTR(pScrn);
358    int     busSDR[4]  = {64, 64, 128, 128};
359    int     busDDR[4]  = {32, 32,  64,  64};
360    int     busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
361    unsigned int config, config1, config2, sr3a, cr5f;
362    char    *dramTypeStr315[] = {
363	"Single channel 1 rank SDR SDRAM",
364	"Single channel 1 rank SDR SGRAM",
365	"Single channel 1 rank DDR SDRAM",
366	"Single channel 1 rank DDR SGRAM",
367	"Single channel 2 rank SDR SDRAM",
368	"Single channel 2 rank SDR SGRAM",
369	"Single channel 2 rank DDR SDRAM",
370	"Single channel 2 rank DDR SGRAM",
371	"Asymmetric SDR SDRAM",
372	"Asymmetric SDR SGRAM",
373	"Asymmetric DDR SDRAM",
374	"Asymmetric DDR SGRAM",
375	"Dual channel SDR SDRAM",
376	"Dual channel SDR SGRAM",
377	"Dual channel DDR SDRAM",
378	"Dual channel DDR SGRAM"
379    };
380    char    *dramTypeStr330[] = {
381	"Single Channel SDR SDRAM",
382	"",
383	"Single Channel DDR SDRAM",
384	"",
385	"--unknown--",
386	"",
387	"--unknown--",
388	"",
389	"Asymetric Dual Channel SDR SDRAM",
390	"",
391	"Asymetric Dual Channel DDR SDRAM",
392	"",
393	"Dual channel SDR SDRAM",
394	"",
395	"Dual channel DDR SDRAM",
396	""
397    };
398    char    *dramTypeStr340[] = {
399	"Single channel DDR SDRAM",
400	"Single channel DDR2 SDRAM",
401	"Single channel DDR2x SDRAM",
402	"",
403	"Dual channel DDR SDRAM",
404	"Dual channel DDR2 SDRAM",
405	"Dual channel DDR2x SDRAM",
406	"",
407	"Dual channel DDR SDRAM",
408	"Dual channel DDR2 SDRAM",
409	"Dual channel DDR2x SDRAM",
410	"",
411	"Quad channel DDR SDRAM",
412	"Quad channel DDR2 SDRAM",
413	"Quad channel DDR2x SDRAM",
414	""
415    };
416
417    inSISIDXREG(SISSR, 0x14, config);
418    config1 = (config & 0x0C) >> 2;
419
420    inSISIDXREG(SISSR, 0x3a, sr3a);
421    config2 = sr3a & 0x03;
422
423    inSISIDXREG(SISCR,0x5f,cr5f);
424
425    pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
426
427    pSiS->IsPCIExpress = FALSE;
428
429    switch(pSiS->Chipset) {
430
431    case PCI_CHIP_SIS340:
432    case PCI_CHIP_XGIXG20:
433    case PCI_CHIP_XGIXG40:
434
435       if(pSiS->ChipType != XGI_20) {	/* SIS340, XGI_40 */
436
437          pSiS->IsAGPCard = TRUE;
438
439          if(pSiS->ChipRev == 2) {
440	     if(config1 & 0x01) config1 = 0x02;
441	     else               config1 = 0x00;
442          }
443          if(config1 == 0x02)      pScrn->videoRam <<= 1; /* dual rank */
444          else if(config1 == 0x03) pScrn->videoRam <<= 2; /* quad rank */
445
446	  inSISIDXREG(SISSR, 0x39, config2);
447	  config2 &= 0x02;
448	  if(!config2) {
449	     inSISIDXREG(SISSR, 0x3a, config2);
450	     config2 = (config2 & 0x02) >> 1;
451          }
452
453	  pSiS->BusWidth = (config & 0x02) ? 64 : 32;
454
455       } else {				/* XGI_20 (Z7) */
456
457	  config1 = 0x00;
458	  inSISIDXREG(SISCR, 0x97, config2);
459	  config2 &= 0x01;
460	  config2 <<= 1;	/* 0 or 2 */
461
462	  pSiS->BusWidth = (config & 0x02) ? 32 :
463				((config & 0x01) ? 16 : 8);
464
465       }
466
467       xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
468	    "DRAM type: %s\n", dramTypeStr340[(config1 * 4) + (config2 & 0x03)]);
469
470       pSiS->MemClock = SiSMclk(pSiS);
471
472       pSiS->MemClock *= 2; /* at least DDR */
473
474       break;
475
476    case PCI_CHIP_SIS330:
477
478       pSiS->IsAGPCard = TRUE;
479
480       if(config1) pScrn->videoRam <<= 1;
481
482       xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
483	   "DRAM type: %s\n", dramTypeStr330[(config1 * 4) + (config2 & 0x02)]);
484
485       pSiS->MemClock = SiSMclk(pSiS);
486
487       if(config2 & 0x02) {
488	  pSiS->MemClock *= 2;
489	  if(config1 == 0x02) {
490	     pSiS->BusWidth = busDDRA[0];
491	  } else {
492	     pSiS->BusWidth = busDDR[(config & 0x02)];
493	  }
494       } else {
495	  if(config1 == 0x02) {
496	     pSiS->BusWidth = busDDRA[2];
497	  } else {
498	     pSiS->BusWidth = busSDR[(config & 0x02)];
499	  }
500       }
501
502       break;
503
504    default: /* 315 */
505
506       pSiS->IsAGPCard = ((sr3a & 0x30) == 0x30) ? FALSE : TRUE;
507
508       if(cr5f & 0x10) pSiS->ChipFlags |= SiSCF_Is315E;
509
510       /* If SINGLE_CHANNEL_2_RANK or DUAL_CHANNEL_1_RANK -> mem * 2 */
511       if((config1 == 0x01) || (config1 == 0x03)) pScrn->videoRam <<= 1;
512
513       /* If DDR asymetric -> mem * 1,5 */
514       if(config1 == 0x02) pScrn->videoRam += pScrn->videoRam/2;
515
516       xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
517	    "DRAM type: %s\n", dramTypeStr315[(config1 * 4) + config2]);
518
519       pSiS->MemClock = SiSMclk(pSiS);
520
521       /* If DDR -> memclock * 2 */
522       if(config2 & 0x02) pSiS->MemClock *= 2;
523
524       if(config1 == 0x02)
525	  pSiS->BusWidth = busDDRA[(config & 0x03)];
526       else if(config2 & 0x02)
527	  pSiS->BusWidth = busDDR[(config & 0x03)];
528       else
529	  pSiS->BusWidth = busSDR[(config & 0x03)];
530
531       if(pSiS->ChipFlags & SiSCF_Is315E) {
532	  inSISIDXREG(SISSR,0x15,config);
533	  if(config & 0x10) pSiS->BusWidth = 32;
534       }
535
536    }
537
538    pSiS->LFBsize = pScrn->videoRam;
539
540    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
541		"Memory clock: %3.3f MHz\n",
542		pSiS->MemClock/1000.0);
543
544    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
545		"DRAM bus width: %d bit\n",
546		pSiS->BusWidth);
547}
548
549/* For 550, 65x, 740, 661, 741, 660, 760, 761 */
550static void
551sis550Setup(ScrnInfoPtr pScrn)
552{
553    SISPtr       pSiS = SISPTR(pScrn);
554    unsigned int config, ramtype=0, i;
555    CARD8	 pciconfig, temp;
556    Bool	 alldone = FALSE;
557    Bool	 ddrtimes2 = TRUE;
558
559    pSiS->IsAGPCard = TRUE;
560    pSiS->IsPCIExpress = FALSE;
561    pSiS->ChipFlags &= ~(SiSCF_760UMA | SiSCF_760LFB);
562
563    pSiS->MemClock = SiSMclk(pSiS);
564
565    if(pSiS->Chipset == PCI_CHIP_SIS660) {
566
567       if(pSiS->ChipType >= SIS_660) {
568
569	  /* UMA - shared fb */
570	  pScrn->videoRam = 0;
571	  pciconfig = pciReadByte(0x00000000, 0x4c);
572	  if(pciconfig & 0xe0) {
573	     pScrn->videoRam = (1 << (((pciconfig & 0xe0) >> 5) - 2)) * 32768;
574	     pSiS->ChipFlags |= SiSCF_760UMA;
575	     pSiS->SiS76xUMASize = pScrn->videoRam * 1024;
576	     pSiS->UMAsize = pScrn->videoRam;
577	     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
578		"%dK shared video RAM (UMA)\n",
579		pScrn->videoRam);
580	  }
581
582	  /* LFB - local framebuffer: PCI reg hold total RAM (but configurable in BIOS) */
583	  pciconfig = pciReadByte(0x00000800, 0xcd);
584	  pciconfig = (pciconfig >> 1) & 0x03;
585	  i = 0;
586	  if(pciconfig == 0x01)      i = 32768;
587	  else if(pciconfig == 0x03) i = 65536;
588	  if(i) {
589	     xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%dK total local video RAM (LFB)\n", i);
590	  }
591
592	  /* LFB: CR78 holds amount of LFB memory configured in the BIOS setup */
593	  inSISIDXREG(SISCR, 0x78, config);
594	  config &= 0x30;
595	  if(config) {
596	     i = 0;
597	     if(config == 0x10)      i = 32768;
598	     else if(config == 0x30) i = 65536;
599	     if(i) {
600		xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%dK configured local video RAM (LFB)\n", i);
601		pScrn->videoRam += i;
602		pSiS->ChipFlags |= SiSCF_760LFB;
603		pSiS->SiS76xLFBSize = i * 1024;
604		pSiS->LFBsize = i;
605	     }
606	  }
607
608	  if((pScrn->videoRam < 32768) || (pScrn->videoRam > 131072)) {
609	     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
610		 "Illegal video RAM size (%dK) detected, using BIOS provided setting\n",
611		 pScrn->videoRam);
612	     pSiS->ChipFlags &= ~(SiSCF_760LFB | SiSCF_760UMA);
613	  } else {
614	     pSiS->BusWidth = 64;
615	     ramtype = 8;
616	     alldone = TRUE;
617	  }
618
619	  if(pSiS->ChipType >= SIS_761) {
620	     pSiS->IsAGPCard = FALSE;
621	     pSiS->IsPCIExpress = TRUE;
622	  }
623
624       } else {  /* 661, 741 */
625
626	  int dimmnum;
627
628	  if(pSiS->ChipType == SIS_741) {
629	     dimmnum = 4;
630	  } else {
631	     dimmnum = 3;
632	  }
633
634	  pciconfig = pciReadByte(0x00000000, 0x64);
635	  if(pciconfig & 0x80) {
636	     pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) - 1)) * 32768;
637	     pSiS->UMAsize = pScrn->videoRam;
638	     if((pScrn->videoRam < 32768) || (pScrn->videoRam > (128 * 1024))) {
639		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
640			"Illegal video RAM size (%dK) detected, using BIOS-provided info\n",
641			pScrn->videoRam);
642	     } else {
643		pSiS->BusWidth = 64;
644		for(i = 0; i <= (dimmnum - 1); i++) {
645		   if(pciconfig & (1 << i)) {
646		      temp = pciReadByte(0x00000000, 0x60 + i);
647		      xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
648			  "DIMM%d is %s SDRAM\n",
649			  i, (temp & 0x40) ? "DDR" : "SDR");
650		   } else {
651		      xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
652			  "DIMM%d is not installed\n", i);
653		   }
654		}
655		pciconfig = pciReadByte(0x00000000, 0x7c);
656		ramtype = (pciconfig & 0x02) ? 8 : 4;
657		alldone = TRUE;
658	     }
659          }
660
661       }
662
663    } else if(pSiS->Chipset == PCI_CHIP_SIS650) {
664
665       pciconfig = pciReadByte(0x00000000, 0x64);
666       if(pciconfig & 0x80) {
667          pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 22)) / 1024;
668	  pSiS->UMAsize = pScrn->videoRam;
669	  pSiS->BusWidth = 64;
670	  for(i=0; i<=3; i++) {
671	     if(pciconfig & (1 << i)) {
672		temp = pciReadByte(0x00000000, 0x60 + i);
673		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
674		   "DIMM%d is %s SDRAM\n",
675		   i, (temp & 0x40) ? "DDR" : "SDR");
676	     } else {
677		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
678		   "DIMM%d is not installed\n", i);
679	     }
680	  }
681	  pciconfig = pciReadByte(0x00000000, 0x7c);
682	  if(pciconfig & 0x02) ramtype = 8;
683	  else                 ramtype = 4;
684	  alldone = TRUE;
685       }
686
687    } else {
688
689       pciconfig = pciReadByte(0x00000000, 0x63);
690       if(pciconfig & 0x80) {
691	  pScrn->videoRam = (1 << (((pciconfig & 0x70) >> 4) + 21)) / 1024;
692	  pSiS->UMAsize = pScrn->videoRam;
693	  pSiS->BusWidth = 64;
694	  ramtype = pciReadByte(0x00000000,0x65);
695	  ramtype &= 0x01;
696	  xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
697	   	"Shared Memory Area is on DIMM%d\n", ramtype);
698	  ramtype = 4;
699	  alldone = TRUE;
700       }
701
702    }
703
704    /* Fall back to BIOS detection results in case of problems: */
705
706    if(!alldone) {
707
708       pSiS->SiS76xLFBSize = pSiS->SiS76xUMASize = 0;
709       pSiS->UMAsize = pSiS->LFBsize = 0;
710
711       if(pSiS->Chipset == PCI_CHIP_SIS660) {
712	  inSISIDXREG(SISCR, 0x79, config);
713	  pSiS->BusWidth = (config & 0x04) ? 128 : 64;
714	  ramtype = (config & 0x01) ? 8 : 4;
715	  if(pSiS->ChipType >= SIS_660) {
716	     pScrn->videoRam = 0;
717	     if(config & 0xf0) {
718		pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
719		pSiS->UMAsize = pScrn->videoRam;
720		pSiS->ChipFlags |= SiSCF_760UMA;
721		pSiS->SiS76xUMASize = pScrn->videoRam * 1024;
722		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
723				"%dK shared video RAM (UMA)\n",
724				pScrn->videoRam);
725	     }
726	     inSISIDXREG(SISCR, 0x78, config);
727	     config &= 0x30;
728	     if(config) {
729	        i = 0;
730		if(config == 0x10)      i = 32768;
731		else if(config == 0x30) i = 65536;
732		if(i) {
733		   xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
734				"%dK configured local video RAM (LFB)\n", i);
735		   pScrn->videoRam += i;
736		   pSiS->SiS76xLFBSize = i * 1024;
737		   pSiS->LFBsize = i;
738		   pSiS->ChipFlags |= SiSCF_760LFB;
739
740		}
741	     }
742	  } else {
743	     pScrn->videoRam = (1 << ((config & 0xf0) >> 4)) * 1024;
744	     pSiS->UMAsize = pScrn->videoRam;
745	  }
746       } else {
747	  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
748	      "Shared Memory Area is disabled - awaiting doom\n");
749	  inSISIDXREG(SISSR, 0x14, config);
750	  pScrn->videoRam = (((config & 0x3F) + 1) * 4) * 1024;
751	  pSiS->UMAsize = pScrn->videoRam;
752	  if(pSiS->Chipset == PCI_CHIP_SIS650) {
753	     ramtype = (((config & 0x80) >> 7) << 2) + 4;
754	     pSiS->BusWidth = 64;   /* (config & 0x40) ? 128 : 64; */
755	  } else {
756	     ramtype = 4;
757	     pSiS->BusWidth = 64;
758	  }
759       }
760    }
761
762    /* These need special attention: Memory controller in CPU, hence
763     * - no DDR * 2 for bandwidth calculation,
764     * - overlay magic (bandwidth dependent one/two overlay stuff)
765     */
766    if((pSiS->ChipType >= SIS_760) && (pSiS->ChipType <= SIS_770)) {
767       if(!(pSiS->ChipFlags & SiSCF_760LFB)) {
768	  ddrtimes2 = FALSE;
769	  pSiS->SiS_SD2_Flags |= SiS_SD2_SUPPORT760OO;
770       }
771    }
772
773    /* DDR -> Mclk * 2 - needed for bandwidth calculation */
774    if(ddrtimes2) {
775       if(ramtype == 8) pSiS->MemClock *= 2;
776    }
777
778    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
779		"DRAM type: %s\n",
780		dramTypeStr[ramtype]);
781
782    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
783		"Memory clock: %3.3f MHz\n",
784		pSiS->MemClock/1000.0);
785
786    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
787		"DRAM bus width: %d bit\n",
788		pSiS->BusWidth);
789}
790
791void
792SiSSetup(ScrnInfoPtr pScrn)
793{
794    SISPtr pSiS = SISPTR(pScrn);
795
796    pSiS->Flags = 0;
797    pSiS->VBFlags = 0;
798    pSiS->SiS76xLFBSize = pSiS->SiS76xUMASize = 0;
799    pSiS->UMAsize = pSiS->LFBsize = 0;
800
801    switch (SISPTR(pScrn)->Chipset) {
802    case PCI_CHIP_SIS300:
803    case PCI_CHIP_SIS630:  /* +730 */
804    case PCI_CHIP_SIS540:
805        sis300Setup(pScrn);
806        break;
807    case PCI_CHIP_SIS315:
808    case PCI_CHIP_SIS315H:
809    case PCI_CHIP_SIS315PRO:
810    case PCI_CHIP_SIS330:
811    case PCI_CHIP_SIS340:
812    case PCI_CHIP_XGIXG20:
813    case PCI_CHIP_XGIXG40:
814    	sis315Setup(pScrn);
815	break;
816    case PCI_CHIP_SIS550:
817    case PCI_CHIP_SIS650: /* + 740,M650,651 */
818    case PCI_CHIP_SIS660: /* + (M)661,(M)741,(M)760(GX), (M)761(GX), 770? */
819        sis550Setup(pScrn);
820	break;
821    case PCI_CHIP_SIS5597:
822    case PCI_CHIP_SIS6326:
823    case PCI_CHIP_SIS530:
824    default:
825        sisOldSetup(pScrn);
826        break;
827    }
828}
829
830
831