1 /*
2 SIS chipset driver
3 
4 Matan Ziv-Av <matan@svgalib.org>
5 
6 Fixes for 530 and for vesafb by Marcelo de Paula Bezerra
7 <mosca@internetaddress.com>.
8 
9 
10 This driver is based on the XFree86 sis driver, written by
11 
12  Alan Hourihane
13 
14 and modified by
15  Xavier Ducoin,
16  Mike Chapman,
17  Juanjo Santamarta,
18  Mitani Hiroshi,
19  David Thomas.
20 
21 And on the documentation availbale from sis's web pages (not many
22 chipset companies still do this).
23 
24 */
25 
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include "vga.h"
31 #include "libvga.h"
32 #include "driver.h"
33 #include "timing.h"
34 #include "vgaregs.h"
35 #include "interface.h"
36 #include "accel.h"
37 #include "vgapci.h"
38 
39 #define SISREG_SAVE(i) (VGA_TOTAL_REGS+i)
40 #define SIS_TOTAL_REGS (VGA_TOTAL_REGS + 0x48 - 5)
41 
42 #define XR(i) (VGA_TOTAL_REGS+i-5)
43 
44 #define PCI_CHIP_SG86C201       0x0001
45 #define PCI_CHIP_SG86C202       0x0002
46 #define PCI_CHIP_SG86C205       0x0205
47 #define PCI_CHIP_SG86C215       0x0215
48 #define PCI_CHIP_SG86C225       0x0225
49 #define PCI_CHIP_SIS5598        0x0200
50 #define PCI_CHIP_SIS5597        0x0200
51 #define PCI_CHIP_SIS6326        0x6326
52 #define PCI_CHIP_SIS530        0x6306
53 #define PCI_CHIP_SIS300         0x0300
54 #define PCI_CHIP_SIS540         0x5300
55 #define PCI_CHIP_SIS630         0x6300
56 
57 #define ClockReg	XR(0x07)
58 #define DualBanks	XR(0x0B)
59 #define BankReg		XR(0x06)
60 #define CRTCOff		XR(0x0A)
61 #define DispCRT		XR(0x27)
62 #define Unknown		XR(0x08)
63 #define LinearAddr0	XR(0x20)
64 #define LinearAddr1	XR(0x21)
65 
66 enum { SIS_86C201=0, SIS_86C202, SIS_86C205, SIS_86C215, SIS_86C225,
67        SIS_5597, SIS_5598, SIS_6326, SIS_530 };
68 
69 #define write_xr(num,val) {outb(SEQ_I, num);outb(SEQ_D, val);}
70 #define read_xr(num,var) {outb(SEQ_I, num);var=inb(SEQ_D);}
71 
72 static int sis_init(int, int, int);
73 static void sis_unlock(void);
74 static void sis_lock(void);
75 static void sisClockLoad(int, unsigned char *);
76 static void sis_CPUthreshold(int,int,int *,int *);
77 
78 void __svgalib_sisaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels);
79 
80 static int sis_memory;
81 static int sis_is_linear, sis_linear_base;
82 static int sis_chiptype;
83 
84 static int sis_edo_vram = 0, sis_host_bus = 0, sis_fast_vram = 0,
85            sis_pci_burst_on = 0, sis_pci_burst_off = 0;
86 
87 static CardSpecs *cardspecs;
88 
sis_setpage(int page)89 static void sis_setpage(int page)
90 {
91         char tmp;
92 
93         read_xr(0x0b,tmp);
94         if (tmp&8) {
95             outb(0x3cb,page);
96             outb(0x3cd,page);
97         } else
98             outb(0x3cd,page|(page<<4));
99 }
100 
__svgalib_sis_inlinearmode(void)101 static int __svgalib_sis_inlinearmode(void)
102 {
103 return sis_is_linear;
104 }
105 
106 /* Fill in chipset specific mode information */
107 
sis_getmodeinfo(int mode,vga_modeinfo * modeinfo)108 static void sis_getmodeinfo(int mode, vga_modeinfo *modeinfo)
109 {
110 
111     if(modeinfo->colors==16)return;
112 
113     modeinfo->maxpixels = sis_memory*1024/modeinfo->bytesperpixel;
114     modeinfo->maxlogicalwidth = 4088;
115     modeinfo->startaddressrange = sis_memory * 1024 - 1;
116     modeinfo->haveblit = 0;
117     modeinfo->flags &= ~HAVE_RWPAGE;
118 
119     if (modeinfo->bytesperpixel >= 1) {
120 	if(sis_linear_base)modeinfo->flags |= CAPABLE_LINEAR;
121         if (__svgalib_sis_inlinearmode())
122 	    modeinfo->flags |= IS_LINEAR;
123     }
124 }
125 
126 /* Read and save chipset-specific registers */
127 
sis_saveregs(unsigned char regs[])128 static int sis_saveregs(unsigned char regs[])
129 {
130     int i;
131 
132     sis_unlock();
133 
134     regs[XR(0x40)] = inb(0x3cb);
135     regs[XR(0x41)] = inb(0x3cd);
136 
137     if(sis_chiptype==SIS_5597)
138        for(i=0x38; i<0x3a;i++)read_xr(i,regs[XR(i)]);
139 
140     if(sis_chiptype==SIS_6326)
141        for(i=0x38; i<0x3d;i++)read_xr(i,regs[XR(i)]);
142 
143     if(sis_chiptype==SIS_530)
144        for(i=0x38; i<0x40 ; i++)read_xr(i,regs[XR(i)]);
145 
146     /* get all the clocks */
147     if (sis_chiptype==SIS_5597 || sis_chiptype==SIS_6326 || sis_chiptype==SIS_530) {
148        i = regs[XR(0x38)] & 0xfc;
149        write_xr(0x38,i|1);
150        read_xr(0x13,regs[XR(0x42)]);
151        read_xr(0x2a,regs[XR(0x43)]);
152        read_xr(0x2b,regs[XR(0x44)]);
153        write_xr(0x38,i|2);
154        read_xr(0x13,regs[XR(0x45)]);
155        read_xr(0x2a,regs[XR(0x46)]);
156        read_xr(0x2b,regs[XR(0x47)]);
157        write_xr(0x38,i); /* Make sure that the loop gets the internal VCLK registers */
158     }
159 
160     for(i=5; i<0x38;i++)read_xr(i,regs[XR(i)]);
161 
162     if (sis_chiptype==SIS_5597 || sis_chiptype==SIS_6326 || sis_chiptype==SIS_530)
163        write_xr(0x38,regs[XR(0x38)]);
164 
165     return SIS_TOTAL_REGS - VGA_TOTAL_REGS;
166 }
167 
168 /* Set chipset-specific registers */
169 
sis_setregs(const unsigned char regs[],int mode)170 static void sis_setregs(const unsigned char regs[], int mode)
171 {
172     int i;
173 
174     sis_unlock();
175 
176     outb(0x3cb,regs[XR(0x40)]);
177     outb(0x3cd,regs[XR(0x41)]);
178 
179     /* set all the clocks */
180     if (sis_chiptype==SIS_5597 || sis_chiptype==SIS_6326 || sis_chiptype==SIS_530) {
181        i = regs[XR(0x38)] & 0xfc;
182        write_xr(0x38,i|1);
183        write_xr(0x13,regs[XR(0x42)]);
184        write_xr(0x2a,regs[XR(0x43)]);
185        write_xr(0x2b,regs[XR(0x44)]);
186        write_xr(0x38,i|2);
187        write_xr(0x13,regs[XR(0x45)]);
188        write_xr(0x2a,regs[XR(0x46)]);
189        write_xr(0x2b,regs[XR(0x47)]);
190        write_xr(0x38,i); /* Make sure that the loop puts the internal VCLK registers */
191     }
192 
193     for(i=6; i<0x38;i++)write_xr(i,regs[XR(i)]);
194 
195     if(sis_chiptype==SIS_5597)
196        for(i=0x38; i<0x3a;i++)write_xr(i,regs[XR(i)]);
197 
198     if(sis_chiptype==SIS_6326)
199        for(i=0x38; i<0x3d;i++)write_xr(i,regs[XR(i)]);
200 
201     if(sis_chiptype==SIS_530)
202        for(i=0x38; i<0x40;i++)write_xr(i,regs[XR(i)]);
203 }
204 
205 
206 /* Return nonzero if mode is available */
207 
sis_modeavailable(int mode)208 static int sis_modeavailable(int mode)
209 {
210     struct info *info;
211     ModeTiming *modetiming;
212     ModeInfo *modeinfo;
213 
214     if ((mode < G640x480x256 )
215 	|| mode == G720x348x2)
216 	return __svgalib_vga_driverspecs.modeavailable(mode);
217 
218     info = &__svgalib_infotable[mode];
219     if (sis_memory * 1024 < info->ydim * info->xbytes)
220 	return 0;
221 
222     modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
223 
224     if(modeinfo->bytesPerPixel==4){
225         free(modeinfo);
226         return 0;
227     };
228 
229     modetiming = malloc(sizeof(ModeTiming));
230     if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
231 	free(modetiming);
232 	free(modeinfo);
233 	return 0;
234     }
235     free(modetiming);
236     free(modeinfo);
237 
238     return SVGADRV;
239 }
240 
241 /* Local, called by sis_setmode(). */
242 
sis_initializemode(unsigned char * moderegs,ModeTiming * modetiming,ModeInfo * modeinfo,int mode)243 static void sis_initializemode(unsigned char *moderegs,
244 			    ModeTiming * modetiming, ModeInfo * modeinfo, int mode)
245 { /* long k; */
246     int offset;
247 
248     __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo);
249 
250     sis_saveregs(moderegs);
251 
252     sisClockLoad(modetiming->pixelClock,moderegs);
253     offset = modetiming->CrtcHDisplay >>
254              ((modetiming->flags & INTERLACED) ? 2 : 3);
255 
256     moderegs[ATT+16] = 0x01;
257     moderegs[20] = 0x40;
258     moderegs[23] = 0xA3;
259 
260     moderegs[ATT+0x10] = 0x01;   /* mode */
261     moderegs[ATT+0x11] = 0x00;   /* overscan (border) color */
262     moderegs[ATT+0x12] = 0x0F;   /* enable all color planes */
263     moderegs[ATT+0x13] = 0x00;   /* horiz pixel panning 0 */
264 
265     if ( (modeinfo->bitsPerPixel == 16) || (modeinfo->bitsPerPixel == 24) )
266 	    moderegs[GRA+0x05] = 0x00;    /* normal read/write mode */
267 
268     if (modeinfo->bitsPerPixel == 16) {
269 	    offset <<= 1;	       /* double the width of the buffer */
270     } else if (modeinfo->bitsPerPixel == 24) {
271 	    offset += offset << 1;
272     }
273 
274     moderegs[BankReg] = 0x02;
275     moderegs[DualBanks] = 0x00;
276 
277     if ( sis_is_linear ) {
278 	    moderegs[BankReg] |= 0x80;  	/* enable linear mode addressing */
279 	    moderegs[LinearAddr0] = (sis_linear_base & 0x07f80000) >> 19 ;
280             moderegs[LinearAddr1] = ((sis_linear_base & 0xf8000000) >> 27) |
281 		                (0x60) ; /* Enable Linear with max 4 mb*/
282     } else moderegs[DualBanks] |= 0x08;
283 
284     if (modeinfo->bitsPerPixel == 16) {
285 	    if (modeinfo->greenWeight == 5)
286 		moderegs[BankReg] |= 0x04;	/* 16bpp = 5-5-5 */
287 	    else
288 		moderegs[BankReg] |= 0x08;	/* 16bpp = 5-6-5 */
289     }
290 
291     if (modeinfo->bitsPerPixel == 24) {
292 	    moderegs[BankReg] |= 0x10;
293             moderegs[DualBanks] |= 0x80;
294     }
295 
296     moderegs[0x13] = offset & 0xFF;
297     moderegs[CRTCOff] = ((offset & 0xF00) >> 4) |
298 	    (((modetiming->CrtcVTotal-2) & 0x400) >> 10 ) |
299             (((modetiming->CrtcVDisplay-1) & 0x400) >> 9 ) |
300             (((modetiming->CrtcVSyncStart) & 0x400) >> 8 ) |
301             (((modetiming->CrtcVSyncStart) & 0x400) >> 7 ) ;
302 
303     if (modetiming->flags & INTERLACED)
304 		moderegs[BankReg] |= 0x20;
305 
306     if ((sis_chiptype == SIS_5597) ||
307         (sis_chiptype == SIS_6326) ||
308         (sis_chiptype == SIS_530)) {
309                moderegs[XR(0x0C)] |= 0x20; /* readahead cache */
310                moderegs[XR(0x07)] |= 0x80; /* combine FIFOs */
311     }
312 
313     if((sis_chiptype == SIS_530) || (sis_chiptype==SIS_5597)) {
314 	moderegs[XR(0x0c)] |= 0x80; /* 32 bit memory access */
315         moderegs[XR(0x26)]&=0xfe; /* zero bit 20 of start address */
316     };
317 
318     /* makes SR27 d[3:1]=0; If yes, I believe this is the offset for the
319        scroll, or somthing like that... */
320     moderegs[XR(0x27)]&=0xf0;
321 
322     {
323         int CRT_ENGthreshold,CRT_CPUthresholdLow, CRT_CPUthresholdHigh;
324 
325         CRT_ENGthreshold = 0x1F;
326         sis_CPUthreshold(modetiming->pixelClock, modeinfo->bitsPerPixel,
327 			     &CRT_CPUthresholdLow, &CRT_CPUthresholdHigh);
328         moderegs[XR(0x08)] = (CRT_ENGthreshold & 0x0F) |
329 	    (CRT_CPUthresholdLow & 0x0F)<<4 ;
330         moderegs[XR(0x09)] &= 0xF0;  /* Yeou */
331         moderegs[XR(0x09)] |= (CRT_CPUthresholdHigh & 0x0F); /* Yeou */
332 
333         if (sis_chiptype == SIS_530) {
334 	        /* CRT/CPU/Engine Threshold Bit[4] */
335 	        moderegs[XR(0x3F)] &= 0xE3;
336                 moderegs[XR(0x3F)] |= ((CRT_CPUthresholdHigh & 0x10) |
337 				        ((CRT_ENGthreshold & 0x10) >> 1) |
338 				        ((CRT_CPUthresholdLow & 0x10) >> 2));
339         }
340     }
341 
342     moderegs[59]=0x6f;
343 
344     return ;
345 }
346 
347 
sis_setmode(int mode,int prv_mode)348 static int sis_setmode(int mode, int prv_mode)
349 {
350     unsigned char *moderegs;
351     ModeTiming *modetiming;
352     ModeInfo *modeinfo;
353     int tmp, var;
354 
355     if ((mode < G640x480x256)||(mode==G720x348x2)) {
356         if(sis_chiptype >= SIS_5597) {
357 		/* Work Around for vesafb case */
358                 read_xr(0x06,tmp);
359                 tmp&=~(0x1E); /* Depth registers */
360                 write_xr(0x06,tmp);
361 		/* program the 25 and 28 Mhz clocks */
362 		if (sis_chiptype==SIS_5597 || sis_chiptype==SIS_6326 || sis_chiptype==SIS_530) {
363                    read_xr(0x38,tmp);
364                    tmp &= 0xfc;
365                    write_xr(0x38,tmp|1);
366 	           read_xr(0x13,var);
367                    write_xr(0x13,var|0x40);
368                    write_xr(0x2a,0x1b);
369                    write_xr(0x2b,0xe1);
370                    write_xr(0x38,tmp|2);
371                    read_xr(0x13,var);
372                    write_xr(0x13,var|0x40);
373                    write_xr(0x2a,0x4e);
374                    write_xr(0x2b,0xe4);
375                    write_xr(0x38,tmp);
376 		}
377         }
378 
379 	return __svgalib_vga_driverspecs.setmode(mode, prv_mode);
380     }
381     if (!sis_modeavailable(mode))
382 	return 1;
383 
384     modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
385 
386     modetiming = malloc(sizeof(ModeTiming));
387     if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
388 	free(modetiming);
389 	free(modeinfo);
390 	return 1;
391     }
392 
393     moderegs = malloc(SIS_TOTAL_REGS);
394 
395     sis_initializemode(moderegs, modetiming, modeinfo, mode);
396 
397 
398     free(modetiming);
399 
400     __svgalib_setregs(moderegs);	/* Set standard regs. */
401     sis_setregs(moderegs, mode);		/* Set extended regs. */
402     free(moderegs);
403 
404     __svgalib_InitializeAcceleratorInterface(modeinfo);
405 
406     free(modeinfo);
407     return 0;
408 }
409 
410 
411 /* Unlock chipset-specific registers */
412 
sis_unlock(void)413 static void sis_unlock(void)
414 {
415     int vgaIOBase, temp;
416 
417     vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
418     outb(vgaIOBase + 4, 0x11);
419     temp = inb(vgaIOBase + 5);
420     outb(vgaIOBase + 5, temp & 0x7F);
421 
422     outw(SEQ_I,0x8605);
423 
424 }
425 
sis_lock(void)426 static void sis_lock(void)
427 {
428     int vgaIOBase, temp;
429 
430     vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
431     outb(vgaIOBase + 4, 0x11);
432     temp = inb(vgaIOBase + 5);
433     outb(vgaIOBase + 5, temp & 0x7F);
434 
435     outw(SEQ_I,0x0005);
436 
437 }
438 
439 #define VENDOR_ID 0x1039
440 
441 /* Indentify chipset, initialize and return non-zero if detected */
442 
sis_test(void)443 static int sis_test(void)
444 {
445     int _ioperm=0, found;
446     long buf[64];
447 
448     if (getenv("IOPERM") == NULL) {
449       _ioperm=1;
450       if (iopl(3) < 0) {
451         printf("svgalib: cannot get I/O permissions\n");
452         exit(1);
453       }
454     }
455 
456     found=__svgalib_pci_find_vendor_vga(VENDOR_ID,buf,0);
457 
458     if (_ioperm) iopl(0);
459 
460     if(!found&&(
461        (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C201)||
462        (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C202)||
463        (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C205)||
464        (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C215)||
465        (((buf[0]>>16)&0xffff)==PCI_CHIP_SG86C225)||
466        (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS5597)||
467        (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS5598)||
468        (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS530)||
469        (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS540)||
470        (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS630)||
471        (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS300)||
472        (((buf[0]>>16)&0xffff)==PCI_CHIP_SIS6326)
473        )){
474        sis_init(0,0,0);
475        return 1;
476     };
477     return 0;
478 }
479 
480 
481 /* Set display start address (not for 16 color modes) */
482 /* Cirrus supports any address in video memory (up to 2Mb) */
483 
sis_setdisplaystart(int address)484 static void sis_setdisplaystart(int address)
485 {
486   int temp;
487   address=address >> 2;
488   outw(CRT_IC, (address & 0x00FF00) | 0x0C);
489   outw(CRT_IC, ((address & 0x00FF) << 8) | 0x0D);
490 
491   read_xr(0x27,temp);
492   temp &= 0xf0;
493   temp |= (address&0xf0000)>>16;
494   write_xr(0x27,temp);
495 }
496 
497 
498 /* Set logical scanline length (usually multiple of 8) */
499 /* Cirrus supports multiples of 8, up to 4088 */
500 
sis_setlogicalwidth(int width)501 static void sis_setlogicalwidth(int width)
502 {
503     int offset = width >> 3;
504     int temp;
505 
506     __svgalib_outCR(0x13,offset&0xff);
507     read_xr(0x0a,temp);
508     temp &= 0xf;
509     temp |= (offset&0xf00)>>4;
510     write_xr(0x0a,temp);
511 }
512 
sis_linear(int op,int param)513 static int sis_linear(int op, int param)
514 {
515     if (op==LINEAR_ENABLE){
516         int temp;
517 
518         sis_is_linear=1;
519         read_xr(6,temp);
520         temp |=0x80;
521         write_xr(0x20,(sis_linear_base & 0x07f80000) >> 19) ;
522         write_xr(0x21,((sis_linear_base & 0xf8000000) >> 27) |
523 		                (0x60)) ; /* Enable Linear with max 4 mb*/
524         write_xr(6,temp);
525         return 0;
526     };
527     if (op==LINEAR_DISABLE){
528         int temp;
529 
530         sis_is_linear=0;
531         read_xr(6,temp);
532         temp &=0x7f;
533         write_xr(0x20,0) ;
534         write_xr(0x21,0) ;
535         write_xr(6,temp);
536         return 0;
537     };
538     if (op==LINEAR_QUERY_BASE) return sis_linear_base;
539     if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0;		/* No granularity or range. */
540         else return -1;		/* Unknown function. */
541 }
542 
sis_match_programmable_clock(int clock)543 static int sis_match_programmable_clock(int clock)
544 {
545 return clock ;
546 }
547 
sis_map_clock(int bpp,int clock)548 static int sis_map_clock(int bpp, int clock)
549 {
550 return clock ;
551 }
552 
sis_map_horizontal_crtc(int bpp,int pixelclock,int htiming)553 static int sis_map_horizontal_crtc(int bpp, int pixelclock, int htiming)
554 {
555 return htiming;
556 }
557 
558 /* Function table (exported) */
559 
560 DriverSpecs __svgalib_sis_driverspecs =
561 {
562     sis_saveregs,
563     sis_setregs,
564     sis_unlock,
565     sis_lock,
566     sis_test,
567     sis_init,
568     sis_setpage,
569     NULL,
570     NULL,
571     sis_setmode,
572     sis_modeavailable,
573     sis_setdisplaystart,
574     sis_setlogicalwidth,
575     sis_getmodeinfo,
576     0,				/* old blit funcs */
577     0,
578     0,
579     0,
580     0,
581     0,				/* ext_set */
582     0,				/* accel */
583     sis_linear,
584     0,				/* accelspecs, filled in during init. */
585     NULL,                       /* Emulation */
586 };
587 
588 /* Initialize chipset (called after detection) */
589 
sis_init(int force,int par1,int par2)590 static int sis_init(int force, int par1, int par2)
591 {
592     unsigned long buf[64];
593     int found=0;
594     int _ioperm=0;
595 
596     sis_unlock();
597     if (force) {
598 	sis_memory = par1;
599         sis_chiptype = par2;
600     } else {
601 
602     };
603 
604     if (getenv("IOPERM") == NULL) {
605       _ioperm=1;
606       if (iopl(3) < 0) {
607         printf("svgalib: cannot get I/O permissions\n");
608         exit(1);
609       }
610     }
611     found=__svgalib_pci_find_vendor_vga(VENDOR_ID,buf,0);
612     if (_ioperm) iopl(0);
613     sis_linear_base=0;
614     sis_chiptype=0;
615     if (!found){
616        sis_linear_base=buf[4]&0xffffff00;
617        switch((buf[0]>>16)&0xffff) {
618             case PCI_CHIP_SG86C201: sis_chiptype=SIS_86C201; break;
619             case PCI_CHIP_SG86C202: sis_chiptype=SIS_86C202; break;
620             case PCI_CHIP_SG86C205: sis_chiptype=SIS_86C205; break;
621             case PCI_CHIP_SG86C215: sis_chiptype=SIS_86C215; break;
622             case PCI_CHIP_SG86C225: sis_chiptype=SIS_86C225; break;
623             case PCI_CHIP_SIS5597: sis_chiptype=SIS_5597; break;
624             case PCI_CHIP_SIS300:
625             case PCI_CHIP_SIS540:
626             case PCI_CHIP_SIS630:
627             case PCI_CHIP_SIS530: sis_chiptype=SIS_530; break;
628 /*            case PCI_CHIP_SIS5598: sis_chiptype=SIS_5598; break;*/
629             case PCI_CHIP_SIS6326: sis_chiptype=SIS_6326; break;
630        };
631     };
632 
633     if(sis_memory==0){
634         if ((sis_chiptype == SIS_6326)||(sis_chiptype==SIS_530)){
635             int temp;
636             read_xr(0x0C,temp);
637             temp >>= 1;
638             sis_memory=1024<<(temp&0x03);
639         };
640         if ( sis_chiptype == SIS_5597) {
641             int temp,bsiz;
642 		/* Because 5597 shares main memory,
643 		   I test for BIOS CONFIGURED memory.*/
644 
645             read_xr(0x0C,temp);
646             bsiz = (temp >> 1) & 3;
647 
648             read_xr(0x2F,temp);
649             temp &= 7;
650             temp++;
651             if (bsiz > 0) temp = temp << 1;
652             sis_memory = 256 * temp;
653 
654         };
655         if(sis_chiptype<SIS_5597) {
656             int temp;
657             read_xr(0x0F,temp);
658 
659             sis_memory=1024<<(temp&0x03);
660         };
661     };
662     if (__svgalib_driver_report) {
663 	printf("Using SIS driver, %iKB. Chiptype=%i\n",sis_memory,sis_chiptype);
664     };
665 
666     cardspecs = malloc(sizeof(CardSpecs));
667     cardspecs->videoMemory = sis_memory;
668     cardspecs->maxPixelClock4bpp = 75000;
669     cardspecs->maxPixelClock8bpp = 135000;
670     cardspecs->maxPixelClock16bpp = 135000;
671     cardspecs->maxPixelClock24bpp = 135000;
672     cardspecs->maxPixelClock32bpp = 0;
673     cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE;
674     cardspecs->maxHorizontalCrtc = 2040;
675     cardspecs->maxPixelClock4bpp = 0;
676     cardspecs->nClocks =0;
677     cardspecs->mapClock = sis_map_clock;
678     cardspecs->mapHorizontalCrtc = sis_map_horizontal_crtc;
679     cardspecs->matchProgrammableClock=sis_match_programmable_clock;
680     __svgalib_driverspecs = &__svgalib_sis_driverspecs;
681     __svgalib_banked_mem_base=0xa0000;
682     __svgalib_banked_mem_size=0x10000;
683     __svgalib_linear_mem_base=sis_linear_base;
684     __svgalib_linear_mem_size=sis_memory*0x400;
685     return 0;
686 }
687 
688 static void
sisCalcClock(int Clock,int max_VLD,unsigned int * vclk)689 sisCalcClock(int Clock, int max_VLD, unsigned int *vclk)
690 {
691     int M, N, P, PSN, VLD, PSNx;
692 
693     int bestM=0, bestN=0, bestP=0, bestPSN=0, bestVLD=0;
694     double bestError, abest = 42.0, bestFout;
695     double target;
696 
697     double Fvco, Fout;
698     double error, aerror;
699 
700     /*
701      *	fd = fref*(Numerator/Denumerator)*(Divider/PostScaler)
702      *
703      *	M 	= Numerator [1:128]
704      *  N 	= DeNumerator [1:32]
705      *  VLD	= Divider (Vco Loop Divider) : divide by 1, 2
706      *  P	= Post Scaler : divide by 1, 2, 3, 4
707      *  PSN     = Pre Scaler (Reference Divisor Select)
708      *
709      * result in vclk[]
710      */
711 #define Midx 	0
712 #define Nidx 	1
713 #define VLDidx 	2
714 #define Pidx 	3
715 #define PSNidx 	4
716 #define Fref 14318180
717 /* stability constraints for internal VCO -- MAX_VCO also determines
718  * the maximum Video pixel clock */
719 #define MIN_VCO Fref
720 #define MAX_VCO 135000000
721 #define MAX_VCO_5597 353000000
722 #define MAX_PSN 0 /* no pre scaler for this chip */
723 #define TOLERANCE 0.01	/* search smallest M and N in this tolerance */
724 
725   int M_min = 2;
726   int M_max = 128;
727 
728 /*  abest=10000.0; */
729 
730   target = Clock * 1000;
731 
732      if ((sis_chiptype == SIS_5597) || (sis_chiptype == SIS_6326)){
733  	int low_N = 2;
734  	int high_N = 5;
735  	int PSN = 1;
736 
737  	P = 1;
738  	if (target < MAX_VCO_5597 / 2)
739  	    P = 2;
740  	if (target < MAX_VCO_5597 / 3)
741  	    P = 3;
742  	if (target < MAX_VCO_5597 / 4)
743  	    P = 4;
744  	if (target < MAX_VCO_5597 / 6)
745  	    P = 6;
746  	if (target < MAX_VCO_5597 / 8)
747  	    P = 8;
748 
749  	Fvco = P * target;
750 
751  	for (N = low_N; N <= high_N; N++){
752  	    double M_desired = Fvco / Fref * N;
753  	    if (M_desired > M_max * max_VLD)
754  		continue;
755 
756  	    if ( M_desired > M_max ) {
757  		M = M_desired / 2 + 0.5;
758  		VLD = 2;
759  	    } else {
760  		M = Fvco / Fref * N + 0.5;
761  		VLD = 1;
762  	    };
763 
764  	    Fout = (double)Fref * (M * VLD)/(N * P);
765 
766  	    error = (target - Fout) / target;
767  	    aerror = (error < 0) ? -error : error;
768 /* 	    if (aerror < abest && abest > TOLERANCE) {*/
769  	    if (aerror < abest) {
770  	        abest = aerror;
771  	        bestError = error;
772  	        bestM = M;
773  	        bestN = N;
774  	        bestP = P;
775  	        bestPSN = PSN;
776  	        bestVLD = VLD;
777  	        bestFout = Fout;
778  	    }
779  	}
780      }
781      else {
782          for (PSNx = 0; PSNx <= MAX_PSN ; PSNx++) {
783  	    int low_N, high_N;
784  	    double FrefVLDPSN;
785 
786  	    PSN = !PSNx ? 1 : 4;
787 
788  	    low_N = 2;
789  	    high_N = 32;
790 
791  	    for ( VLD = 1 ; VLD <= max_VLD ; VLD++ ) {
792 
793  	        FrefVLDPSN = (double)Fref * VLD / PSN;
794  	        for (N = low_N; N <= high_N; N++) {
795  		    double tmp = FrefVLDPSN / N;
796 
797  		    for (P = 1; P <= 4; P++) {
798  		        double Fvco_desired = target * ( P );
799  		        double M_desired = Fvco_desired / tmp;
800 
801  		        /* Which way will M_desired be rounded?
802  		         *  Do all three just to be safe.
803  		         */
804  		        int M_low = M_desired - 1;
805  		        int M_hi = M_desired + 1;
806 
807  		        if (M_hi < M_min || M_low > M_max)
808  			    continue;
809 
810  		        if (M_low < M_min)
811  			    M_low = M_min;
812  		        if (M_hi > M_max)
813  			    M_hi = M_max;
814 
815  		        for (M = M_low; M <= M_hi; M++) {
816  			    Fvco = tmp * M;
817  			    if (Fvco <= MIN_VCO)
818  			        continue;
819  			    if (Fvco > MAX_VCO)
820  			        break;
821 
822  			    Fout = Fvco / ( P );
823 
824  			    error = (target - Fout) / target;
825  			    aerror = (error < 0) ? -error : error;
826  			    if (aerror < abest) {
827  			        abest = aerror;
828  			        bestError = error;
829  			        bestM = M;
830  			        bestN = N;
831  			        bestP = P;
832  			        bestPSN = PSN;
833  			        bestVLD = VLD;
834  			        bestFout = Fout;
835  			    }
836  		        }
837  		    }
838  	        }
839  	    }
840          }
841   }
842   vclk[Midx]    = bestM;
843   vclk[Nidx]    = bestN;
844   vclk[VLDidx]  = bestVLD;
845   vclk[Pidx]    = bestP;
846   vclk[PSNidx]  = bestPSN;
847 };
848 
849 static void
sisClockLoad(int Clock,unsigned char * regs)850 sisClockLoad(int Clock, unsigned char *regs)
851  {
852     unsigned int 	vclk[5];
853     unsigned char 	temp, xr2a, xr2b;
854 
855     sisCalcClock(Clock, 2, vclk);
856 
857     xr2a = (vclk[Midx] - 1) & 0x7f ;
858     xr2a |= ((vclk[VLDidx] == 2 ) ? 1 : 0 ) << 7 ;
859     xr2b  = (vclk[Nidx] -1) & 0x1f ;	/* bits [4:0] contain denumerator -MC */
860     if (vclk[Pidx] <= 4){
861  	    xr2b |= (vclk[Pidx] -1 ) << 5 ; /* postscale 1,2,3,4 */
862             temp=regs[XR(0x13)];
863  	    temp &= 0xBF;
864             regs[XR(0x13)]=temp;
865     } else {
866 	    xr2b |= ((vclk[Pidx] / 2) -1 ) << 5 ;  /* postscale 6,8 */
867 
868             temp=regs[XR(0x13)];
869  	    temp |= 0x40;
870             regs[XR(0x13)]=temp;
871     };
872     xr2b |= 0x80 ;   /* gain for high frequency */
873 
874     regs[XR(0x2a)]=xr2a;
875     regs[XR(0x2b)]=xr2b;
876 
877     if (sis_chiptype == SIS_5597 || sis_chiptype == SIS_6326) {
878         temp=regs[XR(0x23)];
879  	if (sis_edo_vram)
880  	    temp |= 0x40;
881         regs[XR(0x23)]=temp;
882     }
883 
884     if (sis_chiptype == SIS_5597 || sis_chiptype == SIS_6326 || sis_chiptype == SIS_530) {
885  	/*write_xr(0x3B, 0x08 );*/
886         if (sis_chiptype == SIS_5597) {
887             temp=regs[XR(0x34)];
888  	    if (sis_host_bus)
889  	    	temp |= 0x18;
890  	    else temp &= ~0x18;
891             regs[XR(0x34)]=temp;
892 
893             temp=regs[XR(0x3D)];
894  	    if (sis_host_bus)
895  	     	  temp &= 0x0F;
896             regs[XR(0x3D)]=temp;
897 	}
898 
899  	/* One-Cycle VRAM */
900         temp=regs[XR(0x34)];
901  	if (sis_fast_vram)
902             regs[XR(0x34)]=temp;
903 
904  	/* pci burst */
905         temp=regs[XR(0x35)];
906  	if (sis_pci_burst_on)
907  	    temp |= 0x10;
908  	else if (sis_pci_burst_off)
909  	    temp &= ~0x10;
910         regs[XR(0x35)]=temp;
911 
912  	/* pci burst,also */
913 	if (sis_chiptype != SIS_530) {
914                 temp=regs[XR(0x26)];
915 		if (sis_pci_burst_on)
916 			temp |= 0x20;
917 		else if (sis_pci_burst_off)
918 			temp &= ~0x20;
919                 regs[XR(0x26)]=temp;
920 	}
921 /* Merge FIFOs */
922    	temp=regs[XR(0x07)];
923         temp |= 0x80;
924         regs[XR(0x07)]=temp;
925     };
926 
927 }
928 
sisMClk(void)929 static int sisMClk(void)
930 { int mclk;
931   unsigned char xr28, xr29, xr13, xr10;
932 
933     if (sis_chiptype == SIS_530) {
934 	/* The MCLK in SiS530/620 is set by BIOS in SR10 */
935 	read_xr(0x10, xr10);
936 	switch(xr10 & 0x0f) {
937 	case 1:
938 		mclk = 75000; /* 75 Mhz */
939 		break;
940 	case 2:
941 		mclk = 83000; /* 83 Mhz */
942 		break;
943 	case 3:
944 		mclk = 100000;/* 100 Mhz */
945 		break;
946 	case 0:
947 	default:
948 		mclk = 66000; /* 66 Mhz */
949 	}
950 	return(mclk);
951     }
952     /* Numerator */
953     read_xr(0x28,xr28);
954     mclk=14318*((xr28 & 0x7f)+1);
955 
956     /* Denumerator */
957     read_xr(0x29,xr29);
958     mclk=mclk/((xr29 & 0x1f)+1);
959 
960   /* Divider. Does not seem to work for mclk for older cards */
961   if ( (sis_chiptype==SIS_6326) &&
962         ((xr28 & 0x80)!=0 ) ) {
963          mclk = mclk*2;
964     }
965     /* Post-scaler. Values depends on SR13 bit 7  */
966     read_xr(0x13,xr13);
967 
968     if ( (xr13 & 0x80)==0 ) {
969       mclk = mclk / (((xr29 & 0x60) >> 5)+1);
970     }
971     else {
972       /* Values 00 and 01 are reserved */
973       if ((xr29 & 0x60) == 0x40) mclk=mclk/6;
974       if ((xr29 & 0x60) == 0x60) mclk=mclk/8;
975     }
976 
977     return(mclk);
978 }
979 
980 static void
sis_CPUthreshold(int dotClock,int bpp,int * thresholdLow,int * thresholdHigh)981 sis_CPUthreshold(int dotClock,int bpp,int *thresholdLow,int *thresholdHigh)
982 {
983     unsigned char temp;
984     int mclk;
985     int safetymargin, gap;
986     float z, z1, z2; /* Yeou */
987     int factor;
988 
989     mclk=sisMClk();
990 
991     if (sis_chiptype == SIS_530) /* Yeou for 530 thresholod */
992     {
993         /* z = f *((dotClock * bpp)/(buswidth*mclk);
994            thresholdLow  = (z+1)/2 + 4;
995            thresholdHigh = 0x1F;
996 
997            where f = 0x60 when UMA (SR0D D[0] = 1)
998                      0x30      LFB (SR0D D[0] = 0)
999         */
1000         read_xr (0x0d, temp);
1001 	if (temp & 0x01) factor = 0x60;
1002         else factor = 0x30;
1003 
1004         z1 = (float)(dotClock * bpp);
1005         z2 = (float)(64.0 * mclk);
1006  	z = ((float) factor * (z1 / z2));
1007         *thresholdLow = ((int)z + 1) / 2 + 4 ;
1008         *thresholdHigh = 0x1F;
1009     }
1010     else {   /* For sis other product */
1011         /* Adjust thresholds. Safetymargin is to be adjusted by fifo_XXX
1012            options. Try to mantain a fifo margin of gap. At high Vclk*bpp
1013            this isn't possible, so limit the thresholds.
1014 
1015            The values I guess are :
1016 
1017            FIFO_CONSERVATIVE : safetymargin = 5 ;
1018            FIFO_MODERATE     : safetymargin = 3 ;
1019            Default           : safetymargin = 1 ;  (good enough in many cases)
1020            FIFO_AGGRESSIVE   : safetymargin = 0 ;
1021 
1022            gap=4 seems to be the best value in either case...
1023        */
1024 
1025        safetymargin=3;
1026 
1027        gap = 4;
1028        *thresholdLow = ((bpp*dotClock) / mclk)+safetymargin;
1029        *thresholdHigh = ((bpp*dotClock) / mclk)+gap+safetymargin;
1030 
1031        /* 24 bpp seems to need lower FIFO limits.
1032           At 16bpp is possible to put a thresholdHigh of 0 (0x10) with
1033           good results on my system(good performance, and virtually no noise) */
1034 
1035         if ( *thresholdLow > (bpp < 24 ? 0xe:0x0d) ) {
1036     	     *thresholdLow = (bpp < 24 ? 0xe:0x0d);
1037  	}
1038 
1039         if ( *thresholdHigh > (bpp < 24 ? 0x10:0x0f) ) {
1040  	     *thresholdHigh = (bpp < 24 ? 0x10:0x0f);
1041 	}
1042     }; /* sis530 */
1043 }
1044 
1045