1 /*
2 3dfx Voodoo Banshee driver
3 */
4 
5 
6 #include <stdlib.h>
7 #include <stdio.h>		/* for printf */
8 #include <string.h>		/* for memset */
9 #include <unistd.h>
10 #include "vga.h"
11 #include "libvga.h"
12 #include "driver.h"
13 
14 
15 /* New style driver interface. */
16 #include "timing.h"
17 #include "vgaregs.h"
18 #include "interface.h"
19 #include "accel.h"
20 #include "vgapci.h"
21 
22 #define BANSHEEREG_SAVE(i) (VGA_TOTAL_REGS+i)
23 #define BANSHEE_TOTAL_REGS (VGA_TOTAL_REGS + 2 + 40)
24 
25 static int banshee_init(int, int, int);
26 static void banshee_unlock(void);
27 static void banshee_lock(void);
28 
29 void __svgalib_bansheeaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels);
30 
31 static int banshee_memory,banshee_chiptype;
32 static int banshee_is_linear, banshee_linear_base, banshee_io_base;
33 
34 static CardSpecs *cardspecs;
35 
banshee_setpage(int page)36 static void banshee_setpage(int page)
37 {
38    page<<=1;
39    outl(banshee_io_base+0x2c,(inl(banshee_io_base+0x2c)&0xfff00000)|(page)|(page<<10));
40 }
41 
__svgalib_banshee_inlinearmode(void)42 static int __svgalib_banshee_inlinearmode(void)
43 {
44 return banshee_is_linear;
45 }
46 
47 /* Fill in chipset specific mode information */
48 
banshee_getmodeinfo(int mode,vga_modeinfo * modeinfo)49 static void banshee_getmodeinfo(int mode, vga_modeinfo *modeinfo)
50 {
51 
52     if(modeinfo->colors==16)return;
53 
54     modeinfo->maxpixels = banshee_memory*1024/modeinfo->bytesperpixel;
55     modeinfo->maxlogicalwidth = 4088;
56     modeinfo->startaddressrange = banshee_memory * 1024 - 1;
57     modeinfo->haveblit = 0;
58     modeinfo->flags &= ~HAVE_RWPAGE;
59 
60     if (modeinfo->bytesperpixel >= 1) {
61 	if(banshee_linear_base)modeinfo->flags |= CAPABLE_LINEAR;
62         if (__svgalib_banshee_inlinearmode())
63 	    modeinfo->flags |= IS_LINEAR;
64     }
65 }
66 
67 /* Read and save chipset-specific registers */
68 
69 typedef struct {
70    unsigned int pllCtrl0, pllCtrl1, dacMode, dacAddr,
71       		vidProcCfg, vidScreenSize, vgaInit0,
72                 vgaInit1, vidDesktopStartAddr,vidDesktopOverlayStride;
73 } *HWRecPtr;
74 
banshee_saveregs(unsigned char regs[])75 static int banshee_saveregs(unsigned char regs[])
76 {
77   HWRecPtr save;
78 
79   banshee_unlock();		/* May be locked again by other programs (e.g. X) */
80 
81   save=(HWRecPtr)(regs+62);
82 
83   regs[BANSHEEREG_SAVE(0)]=__svgalib_inCR(0x1a);
84   regs[BANSHEEREG_SAVE(1)]=__svgalib_inCR(0x1b);
85   save->pllCtrl0=inl(banshee_io_base+0x40);
86   save->pllCtrl1=inl(banshee_io_base+0x44);
87   save->dacMode=inl(banshee_io_base+0x4c);
88   save->dacAddr=inl(banshee_io_base+0x50);
89   save->vidProcCfg=inl(banshee_io_base+0x5c);
90   save->vidScreenSize=inl(banshee_io_base+0x98);
91   save->vgaInit0=inl(banshee_io_base+0x28);
92   save->vgaInit1=inl(banshee_io_base+0x2c);
93   save->vidDesktopStartAddr=inl(banshee_io_base+0xe4);
94   save->vidDesktopOverlayStride=inl(banshee_io_base+0xe8);
95 
96   return BANSHEE_TOTAL_REGS - VGA_TOTAL_REGS;
97 }
98 
99 /* Set chipset-specific registers */
100 
banshee_setregs(const unsigned char regs[],int mode)101 static void banshee_setregs(const unsigned char regs[], int mode)
102 {
103     HWRecPtr restore;
104 
105     banshee_unlock();		/* May be locked again by other programs (eg. X) */
106 
107     restore=(HWRecPtr)(regs+62);
108 
109     __svgalib_outCR(0x1a,regs[BANSHEEREG_SAVE(0)]);
110     __svgalib_outCR(0x1b,regs[BANSHEEREG_SAVE(1)]);
111     outl(banshee_io_base+0x40,restore->pllCtrl0);
112     outl(banshee_io_base+0x44,restore->pllCtrl1);
113     outl(banshee_io_base+0x4c,restore->dacMode);
114     outl(banshee_io_base+0x50,restore->dacAddr);
115     outl(banshee_io_base+0x5c,restore->vidProcCfg);
116     outl(banshee_io_base+0x98,restore->vidScreenSize);
117     outl(banshee_io_base+0x28,restore->vgaInit0);
118     outl(banshee_io_base+0x2c,restore->vgaInit1);
119     outl(banshee_io_base+0xe4,restore->vidDesktopStartAddr);
120     outl(banshee_io_base+0xe8,restore->vidDesktopOverlayStride);
121     outl(banshee_io_base+0x5c,restore->vidProcCfg&0xfffffffe);
122     outl(banshee_io_base+0x5c,restore->vidProcCfg|1);
123     outl(banshee_io_base+0x5c,restore->vidProcCfg);
124 
125 }
126 
127 /* Return nonzero if mode is available */
128 
banshee_modeavailable(int mode)129 static int banshee_modeavailable(int mode)
130 {
131     struct info *info;
132     ModeTiming *modetiming;
133     ModeInfo *modeinfo;
134 
135     if ((mode < G640x480x256 )
136 	|| mode == G720x348x2)
137 	return __svgalib_vga_driverspecs.modeavailable(mode);
138 
139     info = &__svgalib_infotable[mode];
140     if (banshee_memory * 1024 < info->ydim * info->xbytes)
141 	return 0;
142 
143     modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
144 
145     if((modeinfo->bitsPerPixel==16)&&(modeinfo->greenWeight==5)) {
146 	free(modeinfo);
147         return 0;
148     }
149 
150     modetiming = malloc(sizeof(ModeTiming));
151     if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
152 	free(modetiming);
153 	return 0;
154     }
155     free(modetiming);
156     free(modeinfo);
157 
158     return SVGADRV;
159 }
160 
161 static unsigned comp_lmn(int freq) ;
162 /* Set a mode */
163 
164 /* Local, called by banshee_setmode(). */
165 
banshee_initializemode(unsigned char * moderegs,ModeTiming * modetiming,ModeInfo * modeinfo,int mode)166 static void banshee_initializemode(unsigned char *moderegs,
167 			    ModeTiming * modetiming, ModeInfo * modeinfo, int mode)
168 { /* long k; */
169 
170     int vd,vt,vbs,vbe,ht,hd,hss,hse;
171 
172     HWRecPtr banshee_regs;
173 
174     banshee_regs=(HWRecPtr)(moderegs+62);
175 
176     banshee_saveregs(moderegs);
177 
178     __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo);
179 
180     hd = (modetiming->CrtcHDisplay>>3)-1;
181     hss = (modetiming->CrtcHSyncStart>>3);
182     hse = (modetiming->CrtcHSyncEnd>>3);
183     ht = (modetiming->CrtcHTotal>>3)-5;
184     moderegs[BANSHEEREG_SAVE(0)]=((ht&0x100)>>8) |
185        			    ((hd&0x100)>>6) |
186                             ((hd&0x100)>>4) |
187                             ((ht&0x40)>>1) |
188                             ((hss&0x100)>>2) |
189                             ((hse&0x20)<<2) ;
190 
191     vd    = modetiming->CrtcVDisplay - 1;
192     vt = modetiming->CrtcVTotal - 2;
193     vbs  = modetiming->CrtcVSyncStart - 1;
194     vbe  = vt;
195     moderegs[BANSHEEREG_SAVE(1)]=((vt & 0x400)>>10) |
196 		            ((vd  & 0x400)>>8) |
197 		            ((vbs & 0x400)>>6) |
198 		            ((vbe & 0x400)>>4);
199 /*
200     if (modetiming->flags & INTERLACED)
201 	    moderegs[MXREG_SAVE(3)] |= 0x8;
202 */
203 
204     banshee_regs->vidProcCfg&=0xf7e30000;
205     banshee_regs->vidProcCfg|=0x00000c81;
206 
207     banshee_regs->vidScreenSize=modeinfo->width|(modeinfo->height<<12);
208 
209     if (modetiming->flags & DOUBLESCAN)
210 	    banshee_regs->vidProcCfg |= 0x10;
211 
212     switch (modeinfo->bitsPerPixel)
213     {
214 	    case 8:
215                	    banshee_regs->vidProcCfg|=0<<18;
216 		    break;
217 	    case 15:
218 	    case 16:if(modeinfo->greenWeight==5){
219                         banshee_regs->vidProcCfg|=1<<18;
220                     } else banshee_regs->vidProcCfg|=1<<18;
221 		    break;
222 	    case 24:
223                	    banshee_regs->vidProcCfg|=2<<18;
224 		    break;
225 	    case 32:
226                	    banshee_regs->vidProcCfg|=3<<18;
227 		    break;
228 	    default:
229 		    break;
230     }
231 
232     banshee_regs->vgaInit0&=0xfffffffb;
233     if(modeinfo->bitsPerPixel!=8){
234         banshee_regs->vgaInit0|=4;
235     };
236 
237     banshee_regs->pllCtrl0=comp_lmn(modetiming->pixelClock);
238     moderegs[VGA_MISCOUTPUT]|=0x0c;
239 
240     banshee_regs->vidDesktopStartAddr=0;
241     banshee_regs->vidDesktopOverlayStride=modeinfo->lineWidth;
242 
243     banshee_regs->vgaInit0=0x1140;
244     banshee_regs->vgaInit1=0x00100000;
245 
246     moderegs[41]=0;
247 
248     if(modeinfo->bitsPerPixel==8){
249        moderegs[79]=0;
250     };
251 
252     banshee_is_linear=0;
253 
254 return ;
255 
256 }
257 
banshee_setmode(int mode,int prv_mode)258 static int banshee_setmode(int mode, int prv_mode)
259 {
260     unsigned char *moderegs;
261     ModeTiming modetiming;
262     ModeInfo *modeinfo;
263 
264     if ((mode < G640x480x256 /*&& mode != G320x200x256*/)
265 	|| mode == G720x348x2) {
266 
267 	return __svgalib_vga_driverspecs.setmode(mode, prv_mode);
268     }
269     if (!banshee_modeavailable(mode))
270 	return 1;
271 
272     modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
273 
274     if (__svgalib_getmodetiming(&modetiming, modeinfo, cardspecs)) {
275 	free(modeinfo);
276 	return 1;
277     }
278 
279     moderegs = malloc(BANSHEE_TOTAL_REGS);
280 
281     banshee_initializemode(moderegs, &modetiming, modeinfo, mode);
282 
283     __svgalib_setregs(moderegs);	/* Set standard regs. */
284     banshee_setregs(moderegs, mode);		/* Set extended regs. */
285     free(moderegs);
286 
287     __svgalib_InitializeAcceleratorInterface(modeinfo);
288 
289     free(modeinfo);
290 
291 
292     return 0;
293 }
294 
295 
296 /* Unlock chipset-specific registers */
297 
banshee_unlock(void)298 static void banshee_unlock(void)
299 {
300     int vgaIOBase, temp;
301 
302     vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
303     outb(vgaIOBase + 4, 0x11);
304     temp = inb(vgaIOBase + 5);
305     outb(vgaIOBase + 5, temp & 0x7F);
306 
307     outl(banshee_io_base+0x28,(inl(banshee_io_base+0x28)&0xffffffbf)|(1<<6));
308 }
309 
banshee_lock(void)310 static void banshee_lock(void)
311 {
312     int vgaIOBase, temp;
313 
314     vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
315     outb(vgaIOBase + 4, 0x11);
316     temp = inb(vgaIOBase + 5);
317     outb(vgaIOBase + 5, temp & 0x7F);
318 
319     outl(banshee_io_base+0x28,(inl(banshee_io_base+0x28)&0xffffffbf));
320 }
321 
322 
323 /* Indentify chipset, initialize and return non-zero if detected */
324 
banshee_test(void)325 static int banshee_test(void)
326 {
327    int found,_ioperm=0;
328    unsigned long buf[64];
329 
330    if (getenv("IOPERM") == NULL) {
331       _ioperm=1;
332       if (iopl(3) < 0) {
333         printf("svgalib: banshee: cannot get I/O permissions\n");
334         exit(1);
335       }
336    }
337    found=(!__svgalib_pci_find_vendor_vga(0x121a,buf,0))&&
338           (((buf[0]>>16)==0x0003)||
339           ((buf[0]>>16)==0x0009)||
340           ((buf[0]>>16)==0x0005));
341 
342    if (_ioperm) iopl(0);
343 
344    if(found)banshee_init(0,0,0);
345    return found;
346 }
347 
348 
349 /* Set display start address (not for 16 color modes) */
350 /* Cirrus supports any address in video memory (up to 2Mb) */
351 
banshee_setdisplaystart(int address)352 static void banshee_setdisplaystart(int address)
353 {
354   outw(CRT_IC, ((address>>2) & 0x00FF00) | 0x0C);
355   outw(CRT_IC, (((address>>2) & 0x00FF) << 8) | 0x0D);
356   outl(banshee_io_base+0xe4,address);
357 
358 }
359 
360 
361 /* Set logical scanline length (usually multiple of 8) */
362 
banshee_setlogicalwidth(int width)363 static void banshee_setlogicalwidth(int width)
364 {
365     int offset = width >> 3;
366 
367     __svgalib_outCR(0x13,offset&0xff);
368     outl(banshee_io_base+0xe8,width);
369 }
370 
banshee_linear(int op,int param)371 static int banshee_linear(int op, int param)
372 {
373 if (op==LINEAR_ENABLE || op==LINEAR_DISABLE){ banshee_is_linear=1-banshee_is_linear; return 0;}
374 if (op==LINEAR_QUERY_BASE) return banshee_linear_base;
375 if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0;		/* No granularity or range. */
376     else return -1;		/* Unknown function. */
377 }
378 
banshee_match_programmable_clock(int clock)379 static int banshee_match_programmable_clock(int clock)
380 {
381 return clock ;
382 }
383 
banshee_map_clock(int bpp,int clock)384 static int banshee_map_clock(int bpp, int clock)
385 {
386 return clock ;
387 }
388 
banshee_map_horizontal_crtc(int bpp,int pixelclock,int htiming)389 static int banshee_map_horizontal_crtc(int bpp, int pixelclock, int htiming)
390 {
391 return htiming;
392 }
393 
394 /* Function table (exported) */
395 
396 DriverSpecs __svgalib_banshee_driverspecs =
397 {
398     banshee_saveregs,
399     banshee_setregs,
400     banshee_unlock,
401     banshee_lock,
402     banshee_test,
403     banshee_init,
404     banshee_setpage,
405     NULL,
406     NULL,
407     banshee_setmode,
408     banshee_modeavailable,
409     banshee_setdisplaystart,
410     banshee_setlogicalwidth,
411     banshee_getmodeinfo,
412     0,				/* old blit funcs */
413     0,
414     0,
415     0,
416     0,
417     0,				/* ext_set */
418     0,				/* accel */
419     banshee_linear,
420     0,				/* accelspecs, filled in during init. */
421     NULL,                       /* Emulation */
422 };
423 
424 /* Initialize chipset (called after detection) */
425 
banshee_init(int force,int par1,int par2)426 static int banshee_init(int force, int par1, int par2)
427 {
428     unsigned long buf[64];
429     int found=0;
430     int _ioperm=0;
431 
432     if (force) {
433 	banshee_memory = par1;
434         banshee_chiptype = par2;
435     } else {
436 
437     };
438 
439     if (getenv("IOPERM") == NULL) {
440       _ioperm=1;
441       if (iopl(3) < 0) {
442         printf("svgalib: banshee: cannot get I/O permissions\n");
443         exit(1);
444       }
445     }
446 
447     found=(!__svgalib_pci_find_vendor_vga(0x121a,buf,0))&&
448             (((buf[0]>>16)==0x0003)||
449             ((buf[0]>>16)==0x0009)||
450             ((buf[0]>>16)==0x0005));
451 
452 /*     if (_ioperm) iopl(0);*/
453     if (found){
454        banshee_linear_base=buf[5]&0xffffff00;
455        banshee_io_base=buf[6]&0xff00;
456     };
457 
458     if(banshee_memory==0) {
459        unsigned int draminit0,draminit1;
460 
461        draminit0=inl(banshee_io_base+0x18);
462        draminit1=inl(banshee_io_base+0x1c);
463        if(draminit1&0x40000000) {
464           /* SDRAM */
465           banshee_memory=16*1024;
466        } else {
467           /* SGRAM */
468           banshee_memory=1024*4*
469              (1+((draminit0>>27)&1))* /* SGRAM type - 8MBIT or 16MBIT */
470              (1+((draminit0>>26)&1)); /* Number of sgram chips (4 or 8) */
471        }
472     }
473 
474     banshee_unlock();
475 
476     if (__svgalib_driver_report) {
477 	printf("Using Banshee / Voodoo3 driver, %iKB.\n",banshee_memory);
478     }
479 
480     cardspecs = malloc(sizeof(CardSpecs));
481     cardspecs->videoMemory = banshee_memory;
482     cardspecs->maxPixelClock4bpp = 270000;
483     cardspecs->maxPixelClock8bpp = 270000;
484     cardspecs->maxPixelClock16bpp = 270000;
485     cardspecs->maxPixelClock24bpp = 270000;
486     cardspecs->maxPixelClock32bpp = 270000;
487     cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE;
488     cardspecs->maxHorizontalCrtc = 4088;
489     cardspecs->maxPixelClock4bpp = 0;
490     cardspecs->nClocks =0;
491     cardspecs->mapClock = banshee_map_clock;
492     cardspecs->mapHorizontalCrtc = banshee_map_horizontal_crtc;
493     cardspecs->matchProgrammableClock=banshee_match_programmable_clock;
494     __svgalib_driverspecs = &__svgalib_banshee_driverspecs;
495     __svgalib_banked_mem_base=0xa0000;
496     __svgalib_banked_mem_size=0x10000;
497     __svgalib_linear_mem_base=banshee_linear_base;
498     __svgalib_linear_mem_size=banshee_memory*0x400;
499     return 0;
500 }
501 
502 #define REFFREQ 14318.18
503 
504 static unsigned
comp_lmn(int freq)505 comp_lmn(int freq)
506 {
507   int m, n, k, best_m, best_n, best_k, f_cur, best_error;
508 
509   best_error=freq;
510   best_n=best_m=best_k=0;
511   for (n=1; n<256; n++) {
512     f_cur=REFFREQ*(n+2);
513     if (f_cur<freq) {
514       f_cur=f_cur/3;
515       if (freq-f_cur<best_error) {
516         best_error=freq-f_cur;
517         best_n=n;
518         best_m=1;
519         best_k=0;
520         continue;
521       }
522     }
523     for (m=1; m<64; m++) {
524       for (k=0; k<4; k++) {
525         f_cur=REFFREQ*(n+2)/(m+2)/(1<<k);
526         if (abs(f_cur-freq)<best_error) {
527           best_error=abs(f_cur-freq);
528           best_n=n;
529           best_m=m;
530           best_k=k;
531 	}
532       }
533     }
534   }
535   return (best_n << 8) | (best_m<<2) | best_k;
536 }
537 
538