1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #include "pci.h"
6 #include "vga.h"
7
8 /*
9 * S3 Trio/ViRGE/Savage4
10 * Requires work.
11 */
12
13 /* on some cards, savage4mem[1] == 8, but i don't know how to tell. -rsc */
14 static uchar savage4mem[] = { 2, 4, 8, 12, 16, 32, 0, 32};
15 static void
snarf(Vga * vga,Ctlr * ctlr)16 snarf(Vga* vga, Ctlr* ctlr)
17 {
18 int i, id;
19 char *p;
20
21 /*
22 * The Trio/ViRGE variants have some extra sequencer registers
23 * which need to be unlocked for access.
24 */
25 vgaxo(Seqx, 0x08, 0x06);
26 s3generic.snarf(vga, ctlr);
27
28 for(i = 0x08; i < 0x4F; i++)
29 vga->sequencer[i] = vgaxi(Seqx, i);
30 vga->crt[0x2D] = vgaxi(Crtx, 0x2D);
31 vga->crt[0x2E] = vgaxi(Crtx, 0x2E);
32 vga->crt[0x2F] = vgaxi(Crtx, 0x2F);
33 for(i = 0x70; i < 0x99; i++)
34 vga->crt[i] = vgaxi(Crtx, i);
35
36 id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
37 switch(id){
38
39 default:
40 trace("Unknown ViRGE/Trio64+ - 0x%4.4uX\n",
41 (vga->crt[0x2D]<<8)|vga->crt[0x2E]);
42 /*FALLTHROUGH*/
43
44 case 0x8810: /* Microsoft Virtual PC 2004 */
45 case 0x8811: /* Trio64+ */
46 vga->r[1] = 3;
47 vga->m[1] = 127;
48 vga->n[1] = 31;
49 vga->f[1] = 135000000;
50 trace("Trio64+\n");
51 break;
52
53 case 0x8812: /* Aurora64V+ */
54 vga->r[1] = 3;
55 vga->m[1] = 127;
56 vga->n[1] = 63;
57 vga->f[1] = 135000000;
58 trace("Aurora64V+\n");
59 break;
60
61 case 0x8901: /* Trio64V2 */
62 vga->r[1] = 4;
63 vga->m[1] = 127;
64 vga->n[1] = 31;
65 vga->f[1] = 170000000;
66 trace("Trio64V2\n");
67 break;
68
69 case 0x5631: /* ViRGE */
70 vga->r[1] = 3;
71 vga->m[1] = 127;
72 vga->n[1] = 31;
73 vga->f[1] = 135000000;
74 vga->apz = 64*1024*1024;
75 trace("ViRGE\n");
76 break;
77
78 case 0x8A01: /* ViRGE/[DG]X */
79 vga->r[1] = 4;
80 vga->m[1] = 127;
81 vga->n[1] = 31;
82 vga->f[1] = 170000000;
83 trace("ViRGE/[DG]X\n");
84 break;
85
86 case 0x8A10: /* ViRGE/GX2 */
87 vga->r[1] = 4;
88 vga->m[1] = 127;
89 vga->n[1] = 31;
90 vga->f[1] = 170000000;
91 vga->apz = 64*1024*1024;
92 trace("ViRGE/GX2\n");
93 /*
94 * Memory encoding on the ViRGE/GX2 is different.
95 */
96 switch((vga->crt[0x36]>>6) & 0x03){
97
98 case 0x01:
99 vga->vmz = 4*1024*1024;
100 break;
101
102 case 0x03:
103 vga->vmz = 2*1024*1024;
104 break;
105 }
106 break;
107
108 case 0x883D: /* ViRGE/VX */
109 vga->r[1] = 4;
110 vga->m[1] = 127;
111 vga->n[1] = 31;
112 vga->f[1] = 220000000;
113 vga->apz = 64*1024*1024;
114 trace("ViRGE/VX\n");
115 /*
116 * Memory encoding on the ViRGE/VX is different.
117 */
118 vga->vmz = (2*(((vga->crt[0x36]>>5) & 0x03)+1)) * 1*1024*1024;
119 break;
120
121 case 0x8C10: /* Savage MX/MV */
122 case 0x8C12: /* Savage4/IX-MV */
123 vga->r[1] = 4;
124 vga->m[1] = 127;
125 vga->n[1] = 127;
126 vga->f[1] = 135000000; /* without clock-doubling */
127 for(i = 0x50; i < 0x70; i++)
128 vga->sequencer[i] = vgaxi(Seqx, i);
129 vga->apz = 128*1024*1024;
130 vga->vmz = savage4mem[vga->crt[0x36]>>5] * 1024 * 1024;
131 trace("Savage4/IX-MV\n");
132 break;
133
134 case 0x8C2E: /* SuperSavage/IXC16 */
135 /*
136 * This is all guessed, from the Savage4/IX,
137 * inspection of the card (apz), and web pages
138 * talking about the chip (f[1]). It seems to
139 * work on the IBM Thinkpad T23.
140 *
141 * XXX only 1024x768 works, not 1400x1050.
142 */
143 vga->r[1] = 4;
144 vga->m[1] = 127;
145 vga->n[1] = 127;
146 vga->f[1] = 135000000; /* 300000000 after doubling? */
147 for(i = 0x50; i < 0x70; i++)
148 vga->sequencer[i] = vgaxi(Seqx, i);
149 vga->apz = 64*1024*1024;
150 vga->vmz = savage4mem[vga->crt[0x36]>>5] * 1024 * 1024;
151 trace("SuperSavage/IXC16\n");
152 break;
153
154 case 0x8A22: /* Savage4 */
155 case 0x8A25: /* ProSavage PN133 */
156 case 0x8A26: /* ProSavage KN133 */
157 case 0x8D04: /* ProSavage DDR, K.Okamoto */
158 vga->r[1] = 4;
159 vga->m[1] = 511;
160 vga->n[1] = 127;
161 vga->f[1] = 300000000;
162
163 vga->apz = 128*1024*1024;
164 vga->vmz = savage4mem[vga->crt[0x36]>>5] * 1024 * 1024;
165 trace("Savage4\n");
166 break;
167 }
168
169 /*
170 * Work out the part speed-grade from name. Name can have,
171 * e.g. '-135' on the end for 135MHz part.
172 */
173 if(p = strrchr(ctlr->name, '-'))
174 vga->f[1] = strtoul(p+1, 0, 0) * 1000000;
175
176 ctlr->flag |= Fsnarf;
177 }
178
179 static void
options(Vga * vga,Ctlr * ctlr)180 options(Vga *vga, Ctlr* ctlr)
181 {
182 int id;
183
184 id = (vga->crt[0x2D]<<8)|(vga->crt[0x2E]);
185 switch(id){
186 case 0x8C2E: /* SuperSavage/IXC16 */
187 case 0x8C10: /* Savage MX/MV */
188 case 0x8C12: /* Savage4/IX-MV */
189 case 0x8A22: /* Savage4 */
190 case 0x8A25: /* ProSavage PN133 */
191 case 0x8A26: /* ProSavage KN133 */
192 case 0x8D04: /* ProSavabe DDR, K.Okamoto */
193 /*
194 * Round up so stride is multiple of 16.
195 */
196 if(vga->virtx%16)
197 vga->virtx = (vga->virtx+15)&~15;
198 break;
199 }
200
201 ctlr->flag |= Hlinear|Hpclk2x8|Henhanced|Foptions;
202 }
203
204 static void
init(Vga * vga,Ctlr * ctlr)205 init(Vga* vga, Ctlr* ctlr)
206 {
207 char *p, *val;
208 Mode *mode;
209 ulong pclk, x;
210 int id, noclockset, width;
211
212 id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
213 mode = vga->mode;
214
215 /*
216 * double 16bpp horizontal timings on ViRGE/[DG]X
217 * leaves overflow bit-fiddling to s3generic.init
218 */
219 if((id == 0x8A01) && ((mode->z+7)/8 == 2)){
220 resyncinit(vga, ctlr, Uenhanced, 0);
221 vga->crt[0x00] = ((mode->ht * 2) >> 3) - 5;
222 vga->crt[0x01] = ((mode->x * 2) >> 3) - 1;
223 vga->crt[0x02] = ((mode->shb * 2) >> 3) - 1;
224 x = (mode->ehb * 2) >> 3;
225 vga->crt[0x03] = 0x80 | (x & 0x1F);
226 vga->crt[0x04] = (mode->shs * 2) >> 3;
227 vga->crt[0x05] = ((mode->ehs * 2) >> 3) & 0x1F;
228 if(x & 0x20)
229 vga->crt[0x05] |= 0x80;
230 }
231 s3generic.init(vga, ctlr);
232
233 /*
234 * Work out the part speed-grade from name. Name can have,
235 * e.g. '-135' on the end for 135MHz part.
236 */
237 noclockset = 0;
238 if(p = strrchr(ctlr->name, '-'))
239 vga->f[1] = strtoul(p+1, 0, 0) * 1000000;
240 pclk = vga->f[1];
241
242 if(vga->mode->z > 8)
243 width = vga->virtx*(vga->mode->z/8);
244 else
245 width = vga->virtx*(8/vga->mode->z);
246
247 switch(id){
248
249 case 0x8810: /* Microsoft Virtual PC 2004 */
250 case 0x8811: /* Trio64+ */
251 /*
252 * Part comes in -135MHz speed grade. In 8-bit mode
253 * the maximum DCLK is 80MHz. In 2x8-bit mode the maximum
254 * DCLK is 135MHz using the internal clock doubler.
255 */
256 if((ctlr->flag & Hpclk2x8) && vga->mode->z == 8){
257 if(vga->f[0] > 80000000)
258 ctlr->flag |= Upclk2x8;
259 }
260 else
261 pclk = 80000000;
262
263 vga->crt[0x67] &= ~0xF2;
264 if(ctlr->flag & Upclk2x8){
265 vga->sequencer[0x15] |= 0x10;
266 vga->sequencer[0x18] |= 0x80;
267 /*
268 * There's a little strip of the border
269 * appears on the left in resolutions
270 * 1280 and above if the 0x02 bit isn't
271 * set (when it appears on the right...).
272 */
273 vga->crt[0x67] |= 0x10;
274 }
275
276 /*
277 * VLB address latch delay.
278 */
279 if((vga->crt[0x36] & 0x03) == 0x01)
280 vga->crt[0x58] &= ~0x08;
281
282 /*
283 * Display memory access control.
284 */
285 vga->crt[0x60] = 0xFF;
286
287 if(vga->mode->z > 8)
288 error("trio64: depth %d not supported\n", vga->mode->z);
289 break;
290
291 case 0x8901: /* Trio64V2 */
292 vga->crt[0x90] = 0;
293 vga->crt[0x91] = 0;
294 break;
295 case 0x8A10: /* ViRGE/GX2 */
296 vga->crt[0x90] = 0;
297
298 vga->crt[0x31] |= 0x08;
299
300 vga->crt[0x13] = (width>>3) & 0xFF;
301 vga->crt[0x51] &= ~0x30;
302 vga->crt[0x51] |= (width>>7) & 0x30;
303
304 /*
305 * Increase primary FIFO threshold
306 * to reduce flicker and tearing.
307 */
308 vga->crt[0x85] = 0x0F;
309
310 /*FALLTHROUGH*/
311 case 0x5631: /* ViRGE */
312 case 0x8A01: /* ViRGE/[DG]X */
313 if(id == 0x8A01){
314 x = mode->x * ((mode->z + 7) / 8);
315 x = (x + 7) / 8;
316 vga->crt[0x91] = x & 0xFF;
317 vga->crt[0x90] = (x >> 8) | 0x80;
318 }
319 case 0x883D: /* ViRGE/VX */
320 vga->crt[0x60] &= 0x0F;
321 /*FALLTHROUGH*/
322 case 0x8812: /* Aurora64V+ */
323 if(id == 0x8812) /* Aurora64V+ */
324 noclockset = 1;
325 vga->crt[0x65] = 0;
326 vga->crt[0x66] = 0x89;
327 vga->crt[0x67] = 0;
328
329 if(id == 0x883D){ /* ViRGE/VX */
330 /*
331 * Put the VRAM in 1-cycle EDO mode.
332 * If it is not put in this mode, hardware acceleration
333 * will leave little turds on the screen when hwfill is used.
334 */
335 vga->crt[0x36] &= ~0x0C;
336
337 if(vga->mode->x > 800 && vga->mode->z == 8)
338 vga->crt[0x67] = 0x10;
339 else
340 vga->crt[0x67] = 0;
341
342 /*
343 * Adjustments to the generic settings:
344 * heuristic fiddling.
345 *
346 * We used to set crt[0x66] to 0x89, but setting it
347 * to 0x90 seems to allow us (and more importantly the card)
348 * to access more than 2MB of memory.
349 */
350 vga->crt[0x66] = 0x90;
351 vga->crt[0x58] &= ~0x88;
352 vga->crt[0x58] |= 0x40;
353 if(vga->mode->x > 640 && vga->mode->z >= 8)
354 vga->crt[0x63] |= 0x01;
355 else
356 vga->crt[0x63] &= ~0x01;
357 }
358
359 /*
360 * The high nibble is the mode; or'ing in 0x02 turns
361 * on support for gamma correction via the DACs, but I
362 * haven't figured out how to turn on the 8-bit DACs,
363 * so gamma correction stays off.
364 */
365 switch(vga->mode->z){
366 case 1:
367 case 2:
368 case 4:
369 case 8:
370 default:
371 vga->crt[0x67] |= 0x00;
372 break;
373 case 15:
374 vga->crt[0x67] |= 0x30;
375 break;
376 case 16:
377 vga->crt[0x67] |= 0x50;
378 break;
379 case 24:
380 if(id == 0x8A10) /* GX2 has to be different */
381 vga->crt[0x67] |= 0x70;
382 else
383 vga->crt[0x67] |= 0xD0;
384 break;
385 case 32:
386 /*
387 * The ViRGE and ViRGE/VX manuals make no mention of
388 * 32-bit mode (which the GX/2 calls 24-bit unpacked mode).
389 */
390 if(id != 0x8A10)
391 error("32-bit mode only supported on the GX/2\n");
392 vga->crt[0x67] |= 0xD0;
393 break;
394 }
395
396 /*
397 * Set new MMIO method
398 */
399 vga->crt[0x53] &= ~0x18;
400 vga->crt[0x53] |= 0x08;
401
402 break;
403
404 case 0x8C2E: /* SuperSavage/IXC16 (let's try this -rsc) */
405 case 0x8C10: /* Savage MX/MV */
406 case 0x8C12: /* Savage4/IX-MV */
407 /*
408 * Experience shows the -1 (according to the manual)
409 * is incorrect.
410 */
411 x = width/8 /*-1*/;
412 vga->crt[0x91] = x;
413 vga->crt[0x90] &= ~0x07;
414 vga->crt[0x90] |= (x>>8) & 0x07;
415
416 case 0x8D04: /* ProSavage DDR, K.Okamoto */
417 x = mode->x * ((mode->z + 7) / 8);
418 x = (x + 7) / 8;
419 vga->crt[0x91] = x & 0xFF;
420 vga->crt[0x90] = (x >> 8) | 0x80;
421
422 /*FALLTHROUGH*/
423
424 case 0x8A22: /* Savage4 */
425 case 0x8A25: /* ProSavage PN133 */
426 case 0x8A26: /* ProSavage KN133 */
427 /*
428 * The Savage 4 is frustratingly similar to the
429 * ViRGE/GX2, but has enough slight differences
430 * to warrant special treatment. Blog.
431 */
432 vga->crt[0x66] = 0x89;
433 vga->crt[0x67] = 0;
434 vga->crt[0x85] = 0x02;
435 vga->crt[0x31] |= 0x08;
436
437 vga->crt[0x13] = (width>>3) & 0xFF;
438 vga->crt[0x51] &= ~0x30;
439 vga->crt[0x51] |= (width>>7) & 0x30;
440
441 /* pull screen width from GBD for graphics engine. */
442 vga->crt[0x50] = 0xC1; /* set color mode */
443
444 /*
445 * The high nibble is the mode; or'ing in 0x02 turns
446 * on support for gamma correction via the DACs, but I
447 * haven't figured out how to turn on the 8-bit DACs,
448 * so gamma correction stays off.
449 */
450 switch(vga->mode->z){
451 default:
452 error("%d-bit mode not supported on savage 4\n", vga->mode->z);
453 case 8:
454 vga->crt[0x67] |= 0x00;
455 vga->crt[0x50] |= 0<<4;
456 break;
457 case 15:
458 vga->crt[0x67] |= 0x20;
459 vga->crt[0x50] |= 1<<4;
460 break;
461 case 16:
462 vga->crt[0x67] |= 0x40;
463 vga->crt[0x50] |= 1<<4;
464 /*
465 * Manual says this should be accompanied by setting
466 * the clock-doubled modes but this seems to be the
467 * right answer.
468 * Should check if using doubled modes tidies any of
469 * this up.
470 */
471 if(id == 0x8C12 || id == 0x8C2E || id == 0x8C10)
472 vga->crt[0x67] |= 0x10;
473 break;
474 case 32:
475 vga->crt[0x67] |= 0xD0;
476 vga->crt[0x50] |= 3<<4;
477 break;
478 }
479 break;
480 }
481
482 /*
483 * Clock bits. If the desired video clock is
484 * one of the two standard VGA clocks it can just be
485 * set using bits <3:2> of vga->misc, otherwise we
486 * need to programme the DCLK PLL.
487 */
488 if(val = dbattr(vga->mode->attr, "noclockset")){
489 if((noclockset = strtol(val, &p, 0)) == 0 && p == val)
490 error("%s: invalid 'noclockset' attr\n", ctlr->name);
491 }
492 if(vga->f[0] == 0)
493 vga->f[0] = vga->mode->frequency;
494 vga->misc &= ~0x0C;
495 if(vga->f[0] == VgaFreq0){
496 /* nothing to do */;
497 }
498 else if(vga->f[0] == VgaFreq1)
499 vga->misc |= 0x04;
500 else if(noclockset){
501 /*
502 * Don't touch the clock on the Aurora64V+
503 * and optionally on some others.
504 */
505 vga->misc |= 0x0C;
506 }
507 else{
508 if(vga->f[0] > pclk)
509 error("%s: invalid pclk - %lud\n",
510 ctlr->name, vga->f[0]);
511
512 trio64clock(vga, ctlr);
513 switch(id){
514
515 case 0x8A10: /* ViRGE/GX2 */
516 vga->sequencer[0x12] = (vga->r[0]<<6)|vga->n[0];
517 if(vga->r[0] & 0x04)
518 vga->sequencer[0x29] |= 0x01;
519 else
520 vga->sequencer[0x29] &= ~0x01;
521 break;
522
523 case 0x8C2E: /* SuperSavage/IXC16 (let's try this -rsc) */
524 case 0x8C10: /* Savage MX/MV */
525 case 0x8C12: /* Savage4/IX-MV */
526 case 0x8A22: /* Savage4 */
527 case 0x8A25: /* ProSavage PN133 */
528 case 0x8A26: /* ProSavage KN133 */
529 case 0x8D04: /* ProSavage DDR, K.Okamoto */
530 vga->sequencer[0x12] = (vga->r[0]<<6)|(vga->n[0] & 0x3F);
531 vga->sequencer[0x39] &= ~0x01;
532 vga->sequencer[0x29] &= ~0x1C;
533 if(vga->r[0] & 0x04)
534 vga->sequencer[0x29] |= (1<<2);
535 if(vga->m[0] & 0x100)
536 vga->sequencer[0x29] |= (1<<3);
537 if(vga->n[0] & 0x40)
538 vga->sequencer[0x29] |= (1<<4);
539 break;
540
541 default:
542 vga->sequencer[0x12] = (vga->r[0]<<5)|vga->n[0];
543 break;
544 }
545 vga->sequencer[0x13] = vga->m[0];
546 vga->misc |= 0x0C;
547 }
548
549 /*
550 * Internal clock generator.
551 */
552 vga->sequencer[0x15] &= ~0x31;
553 vga->sequencer[0x15] |= 0x02;
554 vga->sequencer[0x18] &= ~0x80;
555
556 /*
557 * Start display FIFO fetch.
558 */
559 x = (vga->crt[0]+vga->crt[4]+1)/2;
560 vga->crt[0x3B] = x;
561 if(x & 0x100)
562 vga->crt[0x5D] |= 0x40;
563
564 /*
565 * Display memory access control.
566 * Calculation of the M-parameter (Crt54) is
567 * memory-system and dot-clock dependent, the
568 * values below are guesses from dumping
569 * registers.
570 * The Savage4 does not document 0x54,
571 * but we leave this anyway.
572 */
573 if(vga->mode->x <= 800)
574 vga->crt[0x54] = 0xE8;
575 else if(vga->mode->x <= 1024 && id != 0x8C12 && id != 0x8C2E)
576 vga->crt[0x54] = 0xA8;
577 else
578 vga->crt[0x54] = 0x00/*0x48*/;
579
580 ctlr->flag |= Finit;
581 }
582
583 static void
load(Vga * vga,Ctlr * ctlr)584 load(Vga* vga, Ctlr* ctlr)
585 {
586 int id;
587 ushort advfunc;
588
589 s3generic.load(vga, ctlr);
590
591 /*
592 * Load the PLL registers if necessary.
593 * Not sure if the variable-delay method of setting the
594 * PLL will work without a write here to vga->misc,
595 * so use the immediate-load method by toggling bit 5
596 * of Seq15 if necessary.
597 */
598 vgaxo(Seqx, 0x12, vga->sequencer[0x12]);
599 vgaxo(Seqx, 0x13, vga->sequencer[0x13]);
600 id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
601 switch(id){
602 case 0x883D: /* ViRGE/VX*/
603 vgaxo(Crtx, 0x36, vga->crt[0x36]);
604 break;
605 case 0x8A10: /* ViRGE/GX2 */
606 vgaxo(Seqx, 0x29, vga->sequencer[0x29]);
607 break;
608 case 0x8C2E: /* SuperSavage/IXC16 (let's try this -rsc) */
609 case 0x8C12: /* Savage4/IX-MV */
610 vgaxo(Crtx, 0x90, vga->crt[0x90]);
611 vgaxo(Crtx, 0x91, vga->crt[0x91]);
612 /*FALLTHROUGH*/
613 case 0x8A22: /* Savage4 */
614 case 0x8A25: /* ProSavage PN133 */
615 case 0x8A26: /* ProSavage KN133 */
616 case 0x8D04: /* ProSavage DDR, K.Okamoto */
617 vgaxo(Seqx, 0x29, vga->sequencer[0x29]);
618 vgaxo(Seqx, 0x39, vga->sequencer[0x39]);
619 break;
620 }
621 if((vga->misc & 0x0C) == 0x0C)
622 vgaxo(Seqx, 0x15, vga->sequencer[0x15]|0x20);
623 vgaxo(Seqx, 0x15, vga->sequencer[0x15]);
624 vgaxo(Seqx, 0x18, vga->sequencer[0x18]);
625
626 vgaxo(Crtx, 0x60, vga->crt[0x60]);
627 vgaxo(Crtx, 0x63, vga->crt[0x63]);
628 vgaxo(Crtx, 0x65, vga->crt[0x65]);
629 vgaxo(Crtx, 0x66, vga->crt[0x66]);
630 vgaxo(Crtx, 0x67, vga->crt[0x67]);
631
632 switch(id){
633
634 case 0x8810: /* Microsoft Virtual PC 2004 */
635 case 0x8811: /* Trio64+ */
636 advfunc = 0x0000;
637 if(ctlr->flag & Uenhanced)
638 advfunc = 0x0001;
639 outportw(0x4AE8, advfunc);
640 break;
641 case 0x8901: /* Trio64V2 */
642 case 0x8A01: /* ViRGE/[DG]X */
643 vgaxo(Crtx, 0x90, vga->crt[0x90]);
644 vgaxo(Crtx, 0x91, vga->crt[0x91]);
645 break;
646 case 0x8A10: /* ViRGE/GX2 */
647 vgaxo(Crtx, 0x90, vga->crt[0x90]);
648 vgaxo(Crtx, 0x31, vga->crt[0x31]);
649 vgaxo(Crtx, 0x13, vga->crt[0x13]);
650 vgaxo(Crtx, 0x51, vga->crt[0x51]);
651 vgaxo(Crtx, 0x85, vga->crt[0x85]);
652 break;
653 case 0x8D04: /* ProSavage DDR, K.Okamoto */
654 vgaxo(Crtx, 0x90, vga->crt[0x90]); //K.Okamoto
655 vgaxo(Crtx, 0x91, vga->crt[0x91]); //K.Okamoto
656 case 0x8C2E: /* SuperSavage/IXC16 (let's try this -rsc) */
657 case 0x8C12: /* Savage4/IX-MV */
658 case 0x8A22: /* Savage4 */
659 case 0x8A25: /* ProSavage PN133 */
660 case 0x8A26: /* ProSavage KN133 */
661 vgaxo(Crtx, 0x31, vga->crt[0x31]);
662 vgaxo(Crtx, 0x13, vga->crt[0x13]);
663 vgaxo(Crtx, 0x51, vga->crt[0x51]);
664 vgaxo(Crtx, 0x85, vga->crt[0x85]);
665 vgaxo(Crtx, 0x50, vga->crt[0x50]);
666 break;
667 }
668 }
669
670 static void
dump(Vga * vga,Ctlr * ctlr)671 dump(Vga* vga, Ctlr* ctlr)
672 {
673 int i, id;
674 ulong dclk, m, n, r;
675
676 s3generic.dump(vga, ctlr);
677 printitem(ctlr->name, "Crt70");
678 for(i = 0x70; i < 0x99; i++)
679 printreg(vga->crt[i]);
680
681 printitem(ctlr->name, "Seq08");
682 for(i = 0x08; i < 0x10; i++)
683 printreg(vga->sequencer[i]);
684 printitem(ctlr->name, "Seq10");
685 for(i = 0x10; i < 0x50; i++)
686 printreg(vga->sequencer[i]);
687 id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
688 switch(id){
689 default:
690 break;
691
692 case 0x8812: /* Aurora64V+ */
693 case 0x8C2E: /* SuperSavage/IXC16 (let's try this -rsc) */
694 case 0x8C12: /* Savage4/IX-MV */
695 printitem(ctlr->name, "Seq50");
696 for(i = 0x50; i < 0x70; i++)
697 printreg(vga->sequencer[i]);
698 break;
699 }
700
701 printitem(ctlr->name, "Crt2D");
702 printreg(vga->crt[0x2D]);
703 printreg(vga->crt[0x2E]);
704 printreg(vga->crt[0x2F]);
705
706 m = vga->sequencer[0x13] & vga->m[1];
707 n = vga->sequencer[0x12] & vga->n[1];
708 r = (vga->sequencer[0x12]>>5) & 0x03;
709
710 switch(id){
711 case 0x8812: /* Aurora64V+ */
712 r = (vga->sequencer[0x12]>>6) & 0x03;
713 break;
714 case 0x8A01: /* ViRGE/[DG]X */
715 r = (vga->sequencer[0x12]>>5) & 0x07;
716 break;
717 case 0x8A10: /* ViRGE/GX2 */
718 r = (vga->sequencer[0x12]>>6) & 0x03;
719 r |= (vga->sequencer[0x29] & 0x01)<<2;
720 break;
721 case 0x8C2E: /* SuperSavage/IXC16 (let's try this -rsc) */
722 case 0x8C12: /* Savage4/IX-MV */
723 case 0x8A22: /* Savage4 */
724 case 0x8A25: /* ProSavage PN133 */
725 case 0x8A26: /* ProSavage KN133 */
726 case 0x8D04: /* Prosavage DDR, K.Okamoto */
727 m = vga->sequencer[0x13] & 0xFF;
728 if(vga->sequencer[0x29] & (1<<3))
729 m |= 0x100;
730 if(vga->sequencer[0x29] & (1<<4))
731 n |= 0x40;
732 r = (vga->sequencer[0x12]>>6) & 0x03;
733 r |= (vga->sequencer[0x29] & (1<<2));
734 break;
735 }
736
737 dclk = (m+2)*RefFreq;
738 dclk /= (n+2)*(1<<r);
739 printitem(ctlr->name, "dclk m n r");
740 Bprint(&stdout, "%9ld %8ld - %8ld %8ld\n", dclk, m, n, r);
741
742 m = vga->sequencer[0x11] & 0x7F;
743 n = vga->sequencer[0x10] & 0x1F;
744 r = (vga->sequencer[0x10]>>5) & 0x03; /* might be GX/2 specific */
745 dclk = (m+2)*RefFreq;
746 dclk /= (n+2)*(1<<r);
747 printitem(ctlr->name, "mclk m n r");
748 Bprint(&stdout, "%9ld %8ld - %8ld %8ld\n", dclk, m, n, r);
749 }
750
751 Ctlr virge = {
752 "virge", /* name */
753 snarf, /* snarf */
754 options, /* options */
755 init, /* init */
756 load, /* load */
757 dump, /* dump */
758 };
759