Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
};