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