xref: /plan9/sys/src/cmd/aux/vga/virge.c (revision 8cf6001e50e647a07ccf484b8e2f9940411befb9)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier 
59a747e4fSDavid du Colombier #include "pci.h"
67dd7cddfSDavid du Colombier #include "vga.h"
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier /*
914414594SDavid du Colombier  * S3 Trio/ViRGE/Savage4
107dd7cddfSDavid du Colombier  * Requires work.
117dd7cddfSDavid du Colombier  */
1214414594SDavid du Colombier 
1314414594SDavid du Colombier /* on some cards, savage4mem[1] == 8, but i don't know how to tell. -rsc */
1414414594SDavid du Colombier static uchar savage4mem[] = { 2, 4, 8, 12, 16, 32, 0, 32};
157dd7cddfSDavid du Colombier static void
snarf(Vga * vga,Ctlr * ctlr)167dd7cddfSDavid du Colombier snarf(Vga* vga, Ctlr* ctlr)
177dd7cddfSDavid du Colombier {
187dd7cddfSDavid du Colombier 	int i, id;
197dd7cddfSDavid du Colombier 	char *p;
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier 	/*
227dd7cddfSDavid du Colombier 	 * The Trio/ViRGE variants have some extra sequencer registers
237dd7cddfSDavid du Colombier 	 * which need to be unlocked for access.
247dd7cddfSDavid du Colombier 	 */
257dd7cddfSDavid du Colombier 	vgaxo(Seqx, 0x08, 0x06);
267dd7cddfSDavid du Colombier 	s3generic.snarf(vga, ctlr);
277dd7cddfSDavid du Colombier 
287dd7cddfSDavid du Colombier 	for(i = 0x08; i < 0x4F; i++)
297dd7cddfSDavid du Colombier 		vga->sequencer[i] = vgaxi(Seqx, i);
307dd7cddfSDavid du Colombier 	vga->crt[0x2D] = vgaxi(Crtx, 0x2D);
317dd7cddfSDavid du Colombier 	vga->crt[0x2E] = vgaxi(Crtx, 0x2E);
327dd7cddfSDavid du Colombier 	vga->crt[0x2F] = vgaxi(Crtx, 0x2F);
337dd7cddfSDavid du Colombier 	for(i = 0x70; i < 0x99; i++)
347dd7cddfSDavid du Colombier 		vga->crt[i] = vgaxi(Crtx, i);
357dd7cddfSDavid du Colombier 
3659cc4ca5SDavid du Colombier 	id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
377dd7cddfSDavid du Colombier 	switch(id){
387dd7cddfSDavid du Colombier 
397dd7cddfSDavid du Colombier 	default:
407dd7cddfSDavid du Colombier 		trace("Unknown ViRGE/Trio64+ - 0x%4.4uX\n",
4159cc4ca5SDavid du Colombier 			(vga->crt[0x2D]<<8)|vga->crt[0x2E]);
427dd7cddfSDavid du Colombier 		/*FALLTHROUGH*/
437dd7cddfSDavid du Colombier 
44a4285193SDavid du Colombier 	case 0x8810:				/* Microsoft Virtual PC 2004 */
4559cc4ca5SDavid du Colombier 	case 0x8811:				/* Trio64+ */
467dd7cddfSDavid du Colombier 		vga->r[1] = 3;
4714414594SDavid du Colombier 		vga->m[1] = 127;
4814414594SDavid du Colombier 		vga->n[1] = 31;
497dd7cddfSDavid du Colombier 		vga->f[1] = 135000000;
507dd7cddfSDavid du Colombier 		trace("Trio64+\n");
517dd7cddfSDavid du Colombier 		break;
527dd7cddfSDavid du Colombier 
5359cc4ca5SDavid du Colombier 	case 0x8812:				/* Aurora64V+ */
5459cc4ca5SDavid du Colombier 		vga->r[1] = 3;
5559cc4ca5SDavid du Colombier 		vga->m[1] = 127;
5659cc4ca5SDavid du Colombier 		vga->n[1] = 63;
5759cc4ca5SDavid du Colombier 		vga->f[1] = 135000000;
5859cc4ca5SDavid du Colombier 		trace("Aurora64V+\n");
5959cc4ca5SDavid du Colombier 		break;
6059cc4ca5SDavid du Colombier 
619a747e4fSDavid du Colombier 	case 0x8901:				/* Trio64V2 */
629a747e4fSDavid du Colombier 		vga->r[1] = 4;
639a747e4fSDavid du Colombier 		vga->m[1] = 127;
649a747e4fSDavid du Colombier 		vga->n[1] = 31;
659a747e4fSDavid du Colombier 		vga->f[1] = 170000000;
669a747e4fSDavid du Colombier 		trace("Trio64V2\n");
679a747e4fSDavid du Colombier 		break;
689a747e4fSDavid du Colombier 
6959cc4ca5SDavid du Colombier 	case 0x5631:				/* ViRGE */
707dd7cddfSDavid du Colombier 		vga->r[1] = 3;
7114414594SDavid du Colombier 		vga->m[1] = 127;
7214414594SDavid du Colombier 		vga->n[1] = 31;
737dd7cddfSDavid du Colombier 		vga->f[1] = 135000000;
747dd7cddfSDavid du Colombier 		vga->apz = 64*1024*1024;
757dd7cddfSDavid du Colombier 		trace("ViRGE\n");
767dd7cddfSDavid du Colombier 		break;
777dd7cddfSDavid du Colombier 
7859cc4ca5SDavid du Colombier 	case 0x8A01:				/* ViRGE/[DG]X */
797dd7cddfSDavid du Colombier 		vga->r[1] = 4;
8014414594SDavid du Colombier 		vga->m[1] = 127;
8114414594SDavid du Colombier 		vga->n[1] = 31;
827dd7cddfSDavid du Colombier 		vga->f[1] = 170000000;
837dd7cddfSDavid du Colombier 		trace("ViRGE/[DG]X\n");
847dd7cddfSDavid du Colombier 		break;
857dd7cddfSDavid du Colombier 
8659cc4ca5SDavid du Colombier 	case 0x8A10:				/* ViRGE/GX2 */
877dd7cddfSDavid du Colombier 		vga->r[1] = 4;
8814414594SDavid du Colombier 		vga->m[1] = 127;
8914414594SDavid du Colombier 		vga->n[1] = 31;
907dd7cddfSDavid du Colombier 		vga->f[1] = 170000000;
917dd7cddfSDavid du Colombier 		vga->apz = 64*1024*1024;
927dd7cddfSDavid du Colombier 		trace("ViRGE/GX2\n");
937dd7cddfSDavid du Colombier 		/*
947dd7cddfSDavid du Colombier 		 * Memory encoding on the ViRGE/GX2 is different.
957dd7cddfSDavid du Colombier 		 */
967dd7cddfSDavid du Colombier 		switch((vga->crt[0x36]>>6) & 0x03){
977dd7cddfSDavid du Colombier 
987dd7cddfSDavid du Colombier 		case 0x01:
997dd7cddfSDavid du Colombier 			vga->vmz = 4*1024*1024;
1007dd7cddfSDavid du Colombier 			break;
1017dd7cddfSDavid du Colombier 
1027dd7cddfSDavid du Colombier 		case 0x03:
1037dd7cddfSDavid du Colombier 			vga->vmz = 2*1024*1024;
1047dd7cddfSDavid du Colombier 			break;
1057dd7cddfSDavid du Colombier 		}
1067dd7cddfSDavid du Colombier 		break;
1077dd7cddfSDavid du Colombier 
10859cc4ca5SDavid du Colombier 	case 0x883D:				/* ViRGE/VX */
1097dd7cddfSDavid du Colombier 		vga->r[1] = 4;
11014414594SDavid du Colombier 		vga->m[1] = 127;
11114414594SDavid du Colombier 		vga->n[1] = 31;
1127dd7cddfSDavid du Colombier 		vga->f[1] = 220000000;
1137dd7cddfSDavid du Colombier 		vga->apz = 64*1024*1024;
1147dd7cddfSDavid du Colombier 		trace("ViRGE/VX\n");
1157dd7cddfSDavid du Colombier 		/*
1167dd7cddfSDavid du Colombier 		 * Memory encoding on the ViRGE/VX is different.
1177dd7cddfSDavid du Colombier 		 */
1187dd7cddfSDavid du Colombier 		vga->vmz = (2*(((vga->crt[0x36]>>5) & 0x03)+1)) * 1*1024*1024;
1197dd7cddfSDavid du Colombier 		break;
12014414594SDavid du Colombier 
1219a747e4fSDavid du Colombier 	case 0x8C10:				/* Savage MX/MV */
12259cc4ca5SDavid du Colombier 	case 0x8C12:				/* Savage4/IX-MV */
12359cc4ca5SDavid du Colombier 		vga->r[1] = 4;
12459cc4ca5SDavid du Colombier 		vga->m[1] = 127;
12559cc4ca5SDavid du Colombier 		vga->n[1] = 127;
12659cc4ca5SDavid du Colombier 		vga->f[1] = 135000000;		/* without clock-doubling */
12759cc4ca5SDavid du Colombier 		for(i = 0x50; i < 0x70; i++)
12859cc4ca5SDavid du Colombier 			vga->sequencer[i] = vgaxi(Seqx, i);
12959cc4ca5SDavid du Colombier 		vga->apz = 128*1024*1024;
13059cc4ca5SDavid du Colombier 		vga->vmz = savage4mem[vga->crt[0x36]>>5] * 1024 * 1024;
13159cc4ca5SDavid du Colombier 		trace("Savage4/IX-MV\n");
13259cc4ca5SDavid du Colombier 		break;
13359cc4ca5SDavid du Colombier 
1349a747e4fSDavid du Colombier 	case 0x8C2E:				/* SuperSavage/IXC16 */
1359a747e4fSDavid du Colombier 		/*
1369a747e4fSDavid du Colombier 		 * This is all guessed, from the Savage4/IX,
1379a747e4fSDavid du Colombier 		 * inspection of the card (apz), and web pages
1389a747e4fSDavid du Colombier 		 * talking about the chip (f[1]).  It seems to
1399a747e4fSDavid du Colombier 		 * work on the IBM Thinkpad T23.
1409a747e4fSDavid du Colombier 		 *
1419a747e4fSDavid du Colombier 		 * XXX only 1024x768 works, not 1400x1050.
1429a747e4fSDavid du Colombier 		 */
1439a747e4fSDavid du Colombier 		vga->r[1] = 4;
1449a747e4fSDavid du Colombier 		vga->m[1] = 127;
1459a747e4fSDavid du Colombier 		vga->n[1] = 127;
1469a747e4fSDavid du Colombier 		vga->f[1] = 135000000;		/* 300000000 after doubling? */
1479a747e4fSDavid du Colombier 		for(i = 0x50; i < 0x70; i++)
1489a747e4fSDavid du Colombier 			vga->sequencer[i] = vgaxi(Seqx, i);
1499a747e4fSDavid du Colombier 		vga->apz = 64*1024*1024;
1509a747e4fSDavid du Colombier 		vga->vmz = savage4mem[vga->crt[0x36]>>5] * 1024 * 1024;
1519a747e4fSDavid du Colombier 		trace("SuperSavage/IXC16\n");
1529a747e4fSDavid du Colombier 		break;
1539a747e4fSDavid du Colombier 
15459cc4ca5SDavid du Colombier 	case 0x8A22:				/* Savage4 */
1550b459c2cSDavid du Colombier 	case 0x8A25:				/* ProSavage PN133 */
1560b459c2cSDavid du Colombier 	case 0x8A26:				/* ProSavage KN133 */
1576042bf6dSDavid du Colombier 	case 0x8D04:				/* ProSavage DDR, K.Okamoto */
15814414594SDavid du Colombier 		vga->r[1] = 4;
15914414594SDavid du Colombier 		vga->m[1] = 511;
16014414594SDavid du Colombier 		vga->n[1] = 127;
16114414594SDavid du Colombier 		vga->f[1] = 300000000;
16214414594SDavid du Colombier 
16314414594SDavid du Colombier 		vga->apz = 128*1024*1024;
16414414594SDavid du Colombier 		vga->vmz = savage4mem[vga->crt[0x36]>>5] * 1024 * 1024;
16514414594SDavid du Colombier 		trace("Savage4\n");
16614414594SDavid du Colombier 		break;
1677dd7cddfSDavid du Colombier 	}
1687dd7cddfSDavid du Colombier 
1697dd7cddfSDavid du Colombier 	/*
1707dd7cddfSDavid du Colombier 	 * Work out the part speed-grade from name. Name can have,
1717dd7cddfSDavid du Colombier 	 * e.g. '-135' on the end for 135MHz part.
1727dd7cddfSDavid du Colombier 	 */
1737dd7cddfSDavid du Colombier 	if(p = strrchr(ctlr->name, '-'))
1747dd7cddfSDavid du Colombier 		vga->f[1] = strtoul(p+1, 0, 0) * 1000000;
1757dd7cddfSDavid du Colombier 
1767dd7cddfSDavid du Colombier 	ctlr->flag |= Fsnarf;
1777dd7cddfSDavid du Colombier }
1787dd7cddfSDavid du Colombier 
1797dd7cddfSDavid du Colombier static void
options(Vga * vga,Ctlr * ctlr)1809a747e4fSDavid du Colombier options(Vga *vga, Ctlr* ctlr)
1817dd7cddfSDavid du Colombier {
1829a747e4fSDavid du Colombier 	int id;
1839a747e4fSDavid du Colombier 
1849a747e4fSDavid du Colombier 	id = (vga->crt[0x2D]<<8)|(vga->crt[0x2E]);
1859a747e4fSDavid du Colombier 	switch(id){
1869a747e4fSDavid du Colombier 	case 0x8C2E:				/* SuperSavage/IXC16 */
1879a747e4fSDavid du Colombier 	case 0x8C10:				/* Savage MX/MV */
1889a747e4fSDavid du Colombier 	case 0x8C12:				/* Savage4/IX-MV */
1899a747e4fSDavid du Colombier 	case 0x8A22:				/* Savage4 */
1900b459c2cSDavid du Colombier 	case 0x8A25:				/* ProSavage PN133 */
1910b459c2cSDavid du Colombier 	case 0x8A26:				/* ProSavage KN133 */
1926042bf6dSDavid du Colombier 	case 0x8D04:				/* ProSavabe DDR, K.Okamoto */
1939a747e4fSDavid du Colombier 		/*
1949a747e4fSDavid du Colombier 		 * Round up so stride is multiple of 16.
1959a747e4fSDavid du Colombier 		 */
1969a747e4fSDavid du Colombier 		if(vga->virtx%16)
1979a747e4fSDavid du Colombier 			vga->virtx = (vga->virtx+15)&~15;
1989a747e4fSDavid du Colombier 		break;
1999a747e4fSDavid du Colombier 	}
2009a747e4fSDavid du Colombier 
2017dd7cddfSDavid du Colombier 	ctlr->flag |= Hlinear|Hpclk2x8|Henhanced|Foptions;
2027dd7cddfSDavid du Colombier }
2037dd7cddfSDavid du Colombier 
2047dd7cddfSDavid du Colombier static void
init(Vga * vga,Ctlr * ctlr)2057dd7cddfSDavid du Colombier init(Vga* vga, Ctlr* ctlr)
2067dd7cddfSDavid du Colombier {
2073ff48bf5SDavid du Colombier 	char *p, *val;
208fb7f0c93SDavid du Colombier 	Mode *mode;
2097dd7cddfSDavid du Colombier 	ulong pclk, x;
2103ff48bf5SDavid du Colombier 	int id, noclockset, width;
2117dd7cddfSDavid du Colombier 
212fb7f0c93SDavid du Colombier 	id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
213fb7f0c93SDavid du Colombier 	mode = vga->mode;
214fb7f0c93SDavid du Colombier 
215fb7f0c93SDavid du Colombier 	/*
216fb7f0c93SDavid du Colombier 	 * double 16bpp horizontal timings on ViRGE/[DG]X
217fb7f0c93SDavid du Colombier 	 * leaves overflow bit-fiddling to s3generic.init
218fb7f0c93SDavid du Colombier 	 */
219fb7f0c93SDavid du Colombier 	if((id == 0x8A01) && ((mode->z+7)/8 == 2)){
220fb7f0c93SDavid du Colombier 		resyncinit(vga, ctlr, Uenhanced, 0);
221fb7f0c93SDavid du Colombier 		vga->crt[0x00] = ((mode->ht * 2) >> 3) - 5;
222fb7f0c93SDavid du Colombier 		vga->crt[0x01] = ((mode->x * 2) >> 3) - 1;
223fb7f0c93SDavid du Colombier 		vga->crt[0x02] = ((mode->shb * 2) >> 3) - 1;
224fb7f0c93SDavid du Colombier 		x = (mode->ehb * 2) >> 3;
225fb7f0c93SDavid du Colombier 		vga->crt[0x03] = 0x80 | (x & 0x1F);
226fb7f0c93SDavid du Colombier 		vga->crt[0x04] = (mode->shs * 2) >> 3;
227fb7f0c93SDavid du Colombier 		vga->crt[0x05] = ((mode->ehs * 2) >> 3) & 0x1F;
228fb7f0c93SDavid du Colombier 		if(x & 0x20)
229fb7f0c93SDavid du Colombier 			vga->crt[0x05] |= 0x80;
230fb7f0c93SDavid du Colombier 	}
2317dd7cddfSDavid du Colombier 	s3generic.init(vga, ctlr);
2327dd7cddfSDavid du Colombier 
2337dd7cddfSDavid du Colombier 	/*
2347dd7cddfSDavid du Colombier 	 * Work out the part speed-grade from name. Name can have,
2357dd7cddfSDavid du Colombier 	 * e.g. '-135' on the end for 135MHz part.
2367dd7cddfSDavid du Colombier 	 */
2373ff48bf5SDavid du Colombier 	noclockset = 0;
2387dd7cddfSDavid du Colombier 	if(p = strrchr(ctlr->name, '-'))
2397dd7cddfSDavid du Colombier 		vga->f[1] = strtoul(p+1, 0, 0) * 1000000;
2407dd7cddfSDavid du Colombier 	pclk = vga->f[1];
2417dd7cddfSDavid du Colombier 
2429a747e4fSDavid du Colombier 	if(vga->mode->z > 8)
2439a747e4fSDavid du Colombier 		width = vga->virtx*(vga->mode->z/8);
2449a747e4fSDavid du Colombier 	else
2459a747e4fSDavid du Colombier 		width = vga->virtx*(8/vga->mode->z);
246fb7f0c93SDavid du Colombier 
2477dd7cddfSDavid du Colombier 	switch(id){
2487dd7cddfSDavid du Colombier 
249a4285193SDavid du Colombier 	case 0x8810:				/* Microsoft Virtual PC 2004 */
25059cc4ca5SDavid du Colombier 	case 0x8811:				/* Trio64+ */
2517dd7cddfSDavid du Colombier 		/*
2527dd7cddfSDavid du Colombier 		 * Part comes in -135MHz speed grade. In 8-bit mode
2537dd7cddfSDavid du Colombier 		 * the maximum DCLK is 80MHz. In 2x8-bit mode the maximum
2547dd7cddfSDavid du Colombier 		 * DCLK is 135MHz using the internal clock doubler.
2557dd7cddfSDavid du Colombier 		 */
2567dd7cddfSDavid du Colombier 		if((ctlr->flag & Hpclk2x8) && vga->mode->z == 8){
2577dd7cddfSDavid du Colombier 			if(vga->f[0] > 80000000)
2587dd7cddfSDavid du Colombier 				ctlr->flag |= Upclk2x8;
2597dd7cddfSDavid du Colombier 		}
2607dd7cddfSDavid du Colombier 		else
2617dd7cddfSDavid du Colombier 			pclk = 80000000;
2627dd7cddfSDavid du Colombier 
2637dd7cddfSDavid du Colombier 		vga->crt[0x67] &= ~0xF2;
2647dd7cddfSDavid du Colombier 		if(ctlr->flag & Upclk2x8){
2657dd7cddfSDavid du Colombier 			vga->sequencer[0x15] |= 0x10;
2667dd7cddfSDavid du Colombier 			vga->sequencer[0x18] |= 0x80;
2677dd7cddfSDavid du Colombier 			/*
2687dd7cddfSDavid du Colombier 			 * There's a little strip of the border
2697dd7cddfSDavid du Colombier 			 * appears on the left in resolutions
2707dd7cddfSDavid du Colombier 			 * 1280 and above if the 0x02 bit isn't
2717dd7cddfSDavid du Colombier 			 * set (when it appears on the right...).
2727dd7cddfSDavid du Colombier 			 */
2737dd7cddfSDavid du Colombier 			vga->crt[0x67] |= 0x10;
2747dd7cddfSDavid du Colombier 		}
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier 		/*
2777dd7cddfSDavid du Colombier 		 * VLB address latch delay.
2787dd7cddfSDavid du Colombier 		 */
2797dd7cddfSDavid du Colombier 		if((vga->crt[0x36] & 0x03) == 0x01)
2807dd7cddfSDavid du Colombier 			vga->crt[0x58] &= ~0x08;
2817dd7cddfSDavid du Colombier 
2827dd7cddfSDavid du Colombier 		/*
2837dd7cddfSDavid du Colombier 		 * Display memory access control.
2847dd7cddfSDavid du Colombier 		 */
2857dd7cddfSDavid du Colombier 		vga->crt[0x60] = 0xFF;
2867dd7cddfSDavid du Colombier 
2877dd7cddfSDavid du Colombier 		if(vga->mode->z > 8)
2887dd7cddfSDavid du Colombier 			error("trio64: depth %d not supported\n", vga->mode->z);
2897dd7cddfSDavid du Colombier 		break;
2907dd7cddfSDavid du Colombier 
2919a747e4fSDavid du Colombier 	case 0x8901:				/* Trio64V2 */
2929a747e4fSDavid du Colombier 		vga->crt[0x90] = 0;
2939a747e4fSDavid du Colombier 		vga->crt[0x91] = 0;
2949a747e4fSDavid du Colombier 		break;
29559cc4ca5SDavid du Colombier 	case 0x8A10:				/* ViRGE/GX2 */
2967dd7cddfSDavid du Colombier 		vga->crt[0x90] = 0;
2977dd7cddfSDavid du Colombier 
2987dd7cddfSDavid du Colombier 		vga->crt[0x31] |= 0x08;
2997dd7cddfSDavid du Colombier 
3007dd7cddfSDavid du Colombier 		vga->crt[0x13] = (width>>3) & 0xFF;
3017dd7cddfSDavid du Colombier 		vga->crt[0x51] &= ~0x30;
3027dd7cddfSDavid du Colombier 		vga->crt[0x51] |= (width>>7) & 0x30;
3037dd7cddfSDavid du Colombier 
3047dd7cddfSDavid du Colombier 		/*
3057dd7cddfSDavid du Colombier 		 * Increase primary FIFO threshold
3067dd7cddfSDavid du Colombier 	 	 * to reduce flicker and tearing.
3077dd7cddfSDavid du Colombier 		 */
3087dd7cddfSDavid du Colombier 		vga->crt[0x85] = 0x0F;
3097dd7cddfSDavid du Colombier 
3107dd7cddfSDavid du Colombier 		/*FALLTHROUGH*/
31159cc4ca5SDavid du Colombier 	case 0x5631:				/* ViRGE */
31259cc4ca5SDavid du Colombier 	case 0x8A01:				/* ViRGE/[DG]X */
313fb7f0c93SDavid du Colombier 		if(id == 0x8A01){
314fb7f0c93SDavid du Colombier 			x = mode->x * ((mode->z + 7) / 8);
315fb7f0c93SDavid du Colombier 			x = (x + 7) / 8;
316fb7f0c93SDavid du Colombier 			vga->crt[0x91] = x & 0xFF;
317fb7f0c93SDavid du Colombier 			vga->crt[0x90] = (x >> 8) | 0x80;
318fb7f0c93SDavid du Colombier 		}
31959cc4ca5SDavid du Colombier 	case 0x883D:				/* ViRGE/VX */
3207dd7cddfSDavid du Colombier 		vga->crt[0x60] &= 0x0F;
32159cc4ca5SDavid du Colombier 		/*FALLTHROUGH*/
32259cc4ca5SDavid du Colombier 	case 0x8812:				/* Aurora64V+ */
3233ff48bf5SDavid du Colombier 		if(id == 0x8812)		/* Aurora64V+ */
3243ff48bf5SDavid du Colombier 			noclockset = 1;
3257dd7cddfSDavid du Colombier 		vga->crt[0x65] = 0;
3267dd7cddfSDavid du Colombier 		vga->crt[0x66] = 0x89;
3277dd7cddfSDavid du Colombier 		vga->crt[0x67] = 0;
3287dd7cddfSDavid du Colombier 
32959cc4ca5SDavid du Colombier 		if(id == 0x883D){		/* ViRGE/VX */
3307dd7cddfSDavid du Colombier 			/*
3317dd7cddfSDavid du Colombier 			 * Put the VRAM in 1-cycle EDO mode.
3327dd7cddfSDavid du Colombier 			 * If it is not put in this mode, hardware acceleration
3337dd7cddfSDavid du Colombier 			 * will leave little turds on the screen when hwfill is used.
3347dd7cddfSDavid du Colombier 			 */
3357dd7cddfSDavid du Colombier 			vga->crt[0x36] &= ~0x0C;
3367dd7cddfSDavid du Colombier 
3377dd7cddfSDavid du Colombier 			if(vga->mode->x > 800 && vga->mode->z == 8)
3387dd7cddfSDavid du Colombier 				vga->crt[0x67] = 0x10;
3397dd7cddfSDavid du Colombier 			else
3407dd7cddfSDavid du Colombier 				vga->crt[0x67] = 0;
3417dd7cddfSDavid du Colombier 
3427dd7cddfSDavid du Colombier 	 		/*
3437dd7cddfSDavid du Colombier 			 * Adjustments to the generic settings:
3447dd7cddfSDavid du Colombier 			 *	heuristic fiddling.
3457dd7cddfSDavid du Colombier 			 *
3467dd7cddfSDavid du Colombier 			 * We used to set crt[0x66] to 0x89, but setting it
3477dd7cddfSDavid du Colombier 			 * to 0x90 seems to allow us (and more importantly the card)
3487dd7cddfSDavid du Colombier 			 * to access more than 2MB of memory.
3497dd7cddfSDavid du Colombier 			 */
3507dd7cddfSDavid du Colombier 			vga->crt[0x66] = 0x90;
3517dd7cddfSDavid du Colombier 			vga->crt[0x58] &= ~0x88;
3527dd7cddfSDavid du Colombier 			vga->crt[0x58] |= 0x40;
3537dd7cddfSDavid du Colombier 			if(vga->mode->x > 640 && vga->mode->z >= 8)
3547dd7cddfSDavid du Colombier 				vga->crt[0x63] |= 0x01;
3557dd7cddfSDavid du Colombier 			else
3567dd7cddfSDavid du Colombier 				vga->crt[0x63] &= ~0x01;
3577dd7cddfSDavid du Colombier 		}
3587dd7cddfSDavid du Colombier 
3597dd7cddfSDavid du Colombier 		/*
3607dd7cddfSDavid du Colombier 		 * The high nibble is the mode; or'ing in 0x02 turns
3617dd7cddfSDavid du Colombier 		 * on support for gamma correction via the DACs, but I
3627dd7cddfSDavid du Colombier 		 * haven't figured out how to turn on the 8-bit DACs,
3637dd7cddfSDavid du Colombier 		 * so gamma correction stays off.
3647dd7cddfSDavid du Colombier 		 */
3657dd7cddfSDavid du Colombier 		switch(vga->mode->z){
3667dd7cddfSDavid du Colombier 		case 1:
3677dd7cddfSDavid du Colombier 		case 2:
3687dd7cddfSDavid du Colombier 		case 4:
3697dd7cddfSDavid du Colombier 		case 8:
3707dd7cddfSDavid du Colombier 		default:
3717dd7cddfSDavid du Colombier 			vga->crt[0x67] |= 0x00;
3727dd7cddfSDavid du Colombier 			break;
3737dd7cddfSDavid du Colombier 		case 15:
3747dd7cddfSDavid du Colombier 			vga->crt[0x67] |= 0x30;
3757dd7cddfSDavid du Colombier 			break;
3767dd7cddfSDavid du Colombier 		case 16:
3777dd7cddfSDavid du Colombier 			vga->crt[0x67] |= 0x50;
3787dd7cddfSDavid du Colombier 			break;
3797dd7cddfSDavid du Colombier 		case 24:
38059cc4ca5SDavid du Colombier 			if(id == 0x8A10)	/* GX2 has to be different */
3817dd7cddfSDavid du Colombier 				vga->crt[0x67] |= 0x70;
3827dd7cddfSDavid du Colombier 			else
3837dd7cddfSDavid du Colombier 				vga->crt[0x67] |= 0xD0;
3847dd7cddfSDavid du Colombier 			break;
3857dd7cddfSDavid du Colombier 		case 32:
3867dd7cddfSDavid du Colombier 			/*
3877dd7cddfSDavid du Colombier 			 * The ViRGE and ViRGE/VX manuals make no mention of
3887dd7cddfSDavid du Colombier 			 * 32-bit mode (which the GX/2 calls 24-bit unpacked mode).
3897dd7cddfSDavid du Colombier 			 */
39059cc4ca5SDavid du Colombier 			if(id != 0x8A10)
391*8cf6001eSDavid du Colombier 				error("32-bit mode only supported on the GX/2\n");
3927dd7cddfSDavid du Colombier 			vga->crt[0x67] |= 0xD0;
3937dd7cddfSDavid du Colombier 			break;
3947dd7cddfSDavid du Colombier 		}
3957dd7cddfSDavid du Colombier 
3967dd7cddfSDavid du Colombier 		/*
3977dd7cddfSDavid du Colombier 		 * Set new MMIO method
3987dd7cddfSDavid du Colombier 		 */
3997dd7cddfSDavid du Colombier 		vga->crt[0x53] &= ~0x18;
4007dd7cddfSDavid du Colombier 		vga->crt[0x53] |= 0x08;
4017dd7cddfSDavid du Colombier 
4027dd7cddfSDavid du Colombier 		break;
40314414594SDavid du Colombier 
4049a747e4fSDavid du Colombier 	case 0x8C2E:				/* SuperSavage/IXC16 (let's try this -rsc) */
4059a747e4fSDavid du Colombier 	case 0x8C10:				/* Savage MX/MV */
40659cc4ca5SDavid du Colombier 	case 0x8C12:				/* Savage4/IX-MV */
40759cc4ca5SDavid du Colombier 		/*
40859cc4ca5SDavid du Colombier 		 * Experience shows the -1 (according to the manual)
40959cc4ca5SDavid du Colombier 		 * is incorrect.
41059cc4ca5SDavid du Colombier 		 */
4119a747e4fSDavid du Colombier 		x = width/8 /*-1*/;
41259cc4ca5SDavid du Colombier 		vga->crt[0x91] = x;
41359cc4ca5SDavid du Colombier 		vga->crt[0x90] &= ~0x07;
41459cc4ca5SDavid du Colombier 		vga->crt[0x90] |= (x>>8) & 0x07;
4159a747e4fSDavid du Colombier 
4166042bf6dSDavid du Colombier 	case 0x8D04:				/* ProSavage DDR, K.Okamoto */
4176042bf6dSDavid du Colombier 		x = mode->x * ((mode->z + 7) / 8);
4186042bf6dSDavid du Colombier 		x = (x + 7) / 8;
4196042bf6dSDavid du Colombier 		vga->crt[0x91] = x & 0xFF;
4206042bf6dSDavid du Colombier 		vga->crt[0x90] = (x >> 8) | 0x80;
4216042bf6dSDavid du Colombier 
42259cc4ca5SDavid du Colombier 		/*FALLTHROUGH*/
4236042bf6dSDavid du Colombier 
42459cc4ca5SDavid du Colombier 	case 0x8A22:				/* Savage4 */
4250b459c2cSDavid du Colombier 	case 0x8A25:				/* ProSavage PN133 */
4260b459c2cSDavid du Colombier 	case 0x8A26:				/* ProSavage KN133 */
42714414594SDavid du Colombier 		/*
42814414594SDavid du Colombier 		 * The Savage 4 is frustratingly similar to the
42914414594SDavid du Colombier 		 * ViRGE/GX2, but has enough slight differences
43014414594SDavid du Colombier 		 * to warrant special treatment.  Blog.
43114414594SDavid du Colombier 		 */
43214414594SDavid du Colombier 		vga->crt[0x66] = 0x89;
43314414594SDavid du Colombier 		vga->crt[0x67] = 0;
43414414594SDavid du Colombier 		vga->crt[0x85] = 0x02;
43514414594SDavid du Colombier 		vga->crt[0x31] |= 0x08;
43614414594SDavid du Colombier 
43714414594SDavid du Colombier 		vga->crt[0x13] = (width>>3) & 0xFF;
43814414594SDavid du Colombier 		vga->crt[0x51] &= ~0x30;
43914414594SDavid du Colombier 		vga->crt[0x51] |= (width>>7) & 0x30;
44014414594SDavid du Colombier 
44159cc4ca5SDavid du Colombier 		/* pull screen width from GBD for graphics engine. */
4426042bf6dSDavid du Colombier 		vga->crt[0x50] = 0xC1;	/* set color mode */
44359cc4ca5SDavid du Colombier 
44414414594SDavid du Colombier 		/*
44514414594SDavid du Colombier 		 * The high nibble is the mode; or'ing in 0x02 turns
44614414594SDavid du Colombier 		 * on support for gamma correction via the DACs, but I
44714414594SDavid du Colombier 		 * haven't figured out how to turn on the 8-bit DACs,
44814414594SDavid du Colombier 		 * so gamma correction stays off.
44914414594SDavid du Colombier 		 */
45014414594SDavid du Colombier 		switch(vga->mode->z){
45114414594SDavid du Colombier 		default:
45214414594SDavid du Colombier 			error("%d-bit mode not supported on savage 4\n", vga->mode->z);
45314414594SDavid du Colombier 		case 8:
45414414594SDavid du Colombier 			vga->crt[0x67] |= 0x00;
45559cc4ca5SDavid du Colombier 			vga->crt[0x50] |= 0<<4;
45614414594SDavid du Colombier 			break;
45714414594SDavid du Colombier 		case 15:
45814414594SDavid du Colombier 			vga->crt[0x67] |= 0x20;
45959cc4ca5SDavid du Colombier 			vga->crt[0x50] |= 1<<4;
46014414594SDavid du Colombier 			break;
46114414594SDavid du Colombier 		case 16:
46214414594SDavid du Colombier 			vga->crt[0x67] |= 0x40;
46359cc4ca5SDavid du Colombier 			vga->crt[0x50] |= 1<<4;
46459cc4ca5SDavid du Colombier 			/*
4653ff48bf5SDavid du Colombier 			 * Manual says this should be accompanied by setting
46659cc4ca5SDavid du Colombier 			 * the clock-doubled modes but this seems to be the
46759cc4ca5SDavid du Colombier 			 * right answer.
46859cc4ca5SDavid du Colombier 			 * Should check if using doubled modes tidies any of
46959cc4ca5SDavid du Colombier 			 * this up.
47059cc4ca5SDavid du Colombier 			 */
4719a747e4fSDavid du Colombier 			if(id == 0x8C12 || id == 0x8C2E || id == 0x8C10)
47259cc4ca5SDavid du Colombier 				vga->crt[0x67] |= 0x10;
47314414594SDavid du Colombier 			break;
47414414594SDavid du Colombier 		case 32:
47514414594SDavid du Colombier 			vga->crt[0x67] |= 0xD0;
47659cc4ca5SDavid du Colombier 			vga->crt[0x50] |= 3<<4;
47714414594SDavid du Colombier 			break;
47814414594SDavid du Colombier 		}
4799a747e4fSDavid du Colombier 		break;
4807dd7cddfSDavid du Colombier 	}
4817dd7cddfSDavid du Colombier 
4827dd7cddfSDavid du Colombier 	/*
4837dd7cddfSDavid du Colombier 	 * Clock bits. If the desired video clock is
4847dd7cddfSDavid du Colombier 	 * one of the two standard VGA clocks it can just be
4857dd7cddfSDavid du Colombier 	 * set using bits <3:2> of vga->misc, otherwise we
4867dd7cddfSDavid du Colombier 	 * need to programme the DCLK PLL.
4877dd7cddfSDavid du Colombier 	 */
4883ff48bf5SDavid du Colombier 	if(val = dbattr(vga->mode->attr, "noclockset")){
4893ff48bf5SDavid du Colombier 		 if((noclockset = strtol(val, &p, 0)) == 0 && p == val)
4903ff48bf5SDavid du Colombier 			error("%s: invalid 'noclockset' attr\n", ctlr->name);
4913ff48bf5SDavid du Colombier 	}
4927dd7cddfSDavid du Colombier 	if(vga->f[0] == 0)
4937dd7cddfSDavid du Colombier 		vga->f[0] = vga->mode->frequency;
4947dd7cddfSDavid du Colombier 	vga->misc &= ~0x0C;
4959a747e4fSDavid du Colombier 	if(vga->f[0] == VgaFreq0){
4969a747e4fSDavid du Colombier 		/* nothing to do */;
4979a747e4fSDavid du Colombier 	}
4987dd7cddfSDavid du Colombier 	else if(vga->f[0] == VgaFreq1)
4997dd7cddfSDavid du Colombier 		vga->misc |= 0x04;
5003ff48bf5SDavid du Colombier 	else if(noclockset){
50159cc4ca5SDavid du Colombier 		/*
5023ff48bf5SDavid du Colombier 		 * Don't touch the clock on the Aurora64V+
5033ff48bf5SDavid du Colombier 		 * and optionally on some others.
50459cc4ca5SDavid du Colombier 		 */
50559cc4ca5SDavid du Colombier 		vga->misc |= 0x0C;
50659cc4ca5SDavid du Colombier 	}
5077dd7cddfSDavid du Colombier 	else{
5087dd7cddfSDavid du Colombier 		if(vga->f[0] > pclk)
5097dd7cddfSDavid du Colombier 			error("%s: invalid pclk - %lud\n",
5107dd7cddfSDavid du Colombier 				ctlr->name, vga->f[0]);
5117dd7cddfSDavid du Colombier 
5127dd7cddfSDavid du Colombier 		trio64clock(vga, ctlr);
5137dd7cddfSDavid du Colombier 		switch(id){
5147dd7cddfSDavid du Colombier 
51559cc4ca5SDavid du Colombier 		case 0x8A10:			/* ViRGE/GX2 */
5167dd7cddfSDavid du Colombier 			vga->sequencer[0x12] = (vga->r[0]<<6)|vga->n[0];
5177dd7cddfSDavid du Colombier 			if(vga->r[0] & 0x04)
5187dd7cddfSDavid du Colombier 				vga->sequencer[0x29] |= 0x01;
5197dd7cddfSDavid du Colombier 			else
5207dd7cddfSDavid du Colombier 				vga->sequencer[0x29] &= ~0x01;
5217dd7cddfSDavid du Colombier 			break;
5227dd7cddfSDavid du Colombier 
5239a747e4fSDavid du Colombier 		case 0x8C2E:			/* SuperSavage/IXC16 (let's try this -rsc) */
5249a747e4fSDavid du Colombier 		case 0x8C10:			/* Savage MX/MV */
52559cc4ca5SDavid du Colombier 		case 0x8C12:			/* Savage4/IX-MV */
52659cc4ca5SDavid du Colombier 		case 0x8A22:			/* Savage4 */
5270b459c2cSDavid du Colombier 		case 0x8A25:			/* ProSavage PN133 */
5280b459c2cSDavid du Colombier 		case 0x8A26:			/* ProSavage KN133 */
5296042bf6dSDavid du Colombier 		case 0x8D04:			/* ProSavage DDR, K.Okamoto */
53014414594SDavid du Colombier 			vga->sequencer[0x12] = (vga->r[0]<<6)|(vga->n[0] & 0x3F);
53114414594SDavid du Colombier 			vga->sequencer[0x39] &= ~0x01;
53214414594SDavid du Colombier 			vga->sequencer[0x29] &= ~0x1C;
53314414594SDavid du Colombier 			if(vga->r[0] & 0x04)
53414414594SDavid du Colombier 				vga->sequencer[0x29] |= (1<<2);
53514414594SDavid du Colombier 			if(vga->m[0] & 0x100)
53614414594SDavid du Colombier 				vga->sequencer[0x29] |= (1<<3);
53714414594SDavid du Colombier 			if(vga->n[0] & 0x40)
53814414594SDavid du Colombier 				vga->sequencer[0x29] |= (1<<4);
53914414594SDavid du Colombier 			break;
54014414594SDavid du Colombier 
5417dd7cddfSDavid du Colombier 		default:
5427dd7cddfSDavid du Colombier 			vga->sequencer[0x12] = (vga->r[0]<<5)|vga->n[0];
5437dd7cddfSDavid du Colombier 			break;
5447dd7cddfSDavid du Colombier 		}
5457dd7cddfSDavid du Colombier 		vga->sequencer[0x13] = vga->m[0];
5467dd7cddfSDavid du Colombier 		vga->misc |= 0x0C;
5477dd7cddfSDavid du Colombier 	}
5487dd7cddfSDavid du Colombier 
5497dd7cddfSDavid du Colombier 	/*
5507dd7cddfSDavid du Colombier 	 * Internal clock generator.
5517dd7cddfSDavid du Colombier 	 */
5527dd7cddfSDavid du Colombier 	vga->sequencer[0x15] &= ~0x31;
5537dd7cddfSDavid du Colombier 	vga->sequencer[0x15] |= 0x02;
5547dd7cddfSDavid du Colombier 	vga->sequencer[0x18] &= ~0x80;
5557dd7cddfSDavid du Colombier 
5567dd7cddfSDavid du Colombier 	/*
5577dd7cddfSDavid du Colombier 	 * Start display FIFO fetch.
5587dd7cddfSDavid du Colombier 	 */
5597dd7cddfSDavid du Colombier 	x = (vga->crt[0]+vga->crt[4]+1)/2;
5607dd7cddfSDavid du Colombier 	vga->crt[0x3B] = x;
5617dd7cddfSDavid du Colombier 	if(x & 0x100)
5627dd7cddfSDavid du Colombier 		vga->crt[0x5D] |= 0x40;
5637dd7cddfSDavid du Colombier 
5647dd7cddfSDavid du Colombier 	/*
5657dd7cddfSDavid du Colombier 	 * Display memory access control.
5667dd7cddfSDavid du Colombier 	 * Calculation of the M-parameter (Crt54) is
5677dd7cddfSDavid du Colombier 	 * memory-system and dot-clock dependent, the
5687dd7cddfSDavid du Colombier 	 * values below are guesses from dumping
5697dd7cddfSDavid du Colombier 	 * registers.
57014414594SDavid du Colombier 	 * The Savage4 does not document 0x54,
57114414594SDavid du Colombier 	 * but we leave this anyway.
5727dd7cddfSDavid du Colombier 	 */
5737dd7cddfSDavid du Colombier 	if(vga->mode->x <= 800)
5747dd7cddfSDavid du Colombier 		vga->crt[0x54] = 0xE8;
5759a747e4fSDavid du Colombier 	else if(vga->mode->x <= 1024 && id != 0x8C12 && id != 0x8C2E)
5767dd7cddfSDavid du Colombier 		vga->crt[0x54] = 0xA8;
5777dd7cddfSDavid du Colombier 	else
5787dd7cddfSDavid du Colombier 		vga->crt[0x54] = 0x00/*0x48*/;
5797dd7cddfSDavid du Colombier 
5807dd7cddfSDavid du Colombier 	ctlr->flag |= Finit;
5817dd7cddfSDavid du Colombier }
5827dd7cddfSDavid du Colombier 
5837dd7cddfSDavid du Colombier static void
load(Vga * vga,Ctlr * ctlr)5847dd7cddfSDavid du Colombier load(Vga* vga, Ctlr* ctlr)
5857dd7cddfSDavid du Colombier {
5867dd7cddfSDavid du Colombier 	int id;
5877dd7cddfSDavid du Colombier 	ushort advfunc;
5887dd7cddfSDavid du Colombier 
5897dd7cddfSDavid du Colombier 	s3generic.load(vga, ctlr);
5907dd7cddfSDavid du Colombier 
5917dd7cddfSDavid du Colombier 	/*
5927dd7cddfSDavid du Colombier 	 * Load the PLL registers if necessary.
5937dd7cddfSDavid du Colombier 	 * Not sure if the variable-delay method of setting the
5947dd7cddfSDavid du Colombier 	 * PLL will work without a write here to vga->misc,
5957dd7cddfSDavid du Colombier 	 * so use the immediate-load method by toggling bit 5
5967dd7cddfSDavid du Colombier 	 * of Seq15 if necessary.
5977dd7cddfSDavid du Colombier 	 */
5987dd7cddfSDavid du Colombier 	vgaxo(Seqx, 0x12, vga->sequencer[0x12]);
5997dd7cddfSDavid du Colombier 	vgaxo(Seqx, 0x13, vga->sequencer[0x13]);
60059cc4ca5SDavid du Colombier 	id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
6017dd7cddfSDavid du Colombier 	switch(id){
60259cc4ca5SDavid du Colombier 	case 0x883D:				/* ViRGE/VX*/
6037dd7cddfSDavid du Colombier 		vgaxo(Crtx, 0x36, vga->crt[0x36]);
6047dd7cddfSDavid du Colombier 		break;
60559cc4ca5SDavid du Colombier 	case 0x8A10:				/* ViRGE/GX2 */
6067dd7cddfSDavid du Colombier 		vgaxo(Seqx, 0x29, vga->sequencer[0x29]);
6077dd7cddfSDavid du Colombier 		break;
6089a747e4fSDavid du Colombier 	case 0x8C2E:				/* SuperSavage/IXC16 (let's try this -rsc) */
60959cc4ca5SDavid du Colombier 	case 0x8C12:				/* Savage4/IX-MV */
61059cc4ca5SDavid du Colombier 		vgaxo(Crtx, 0x90, vga->crt[0x90]);
61159cc4ca5SDavid du Colombier 		vgaxo(Crtx, 0x91, vga->crt[0x91]);
61259cc4ca5SDavid du Colombier 		/*FALLTHROUGH*/
61359cc4ca5SDavid du Colombier 	case 0x8A22:				/* Savage4 */
6140b459c2cSDavid du Colombier 	case 0x8A25:				/* ProSavage PN133 */
6150b459c2cSDavid du Colombier 	case 0x8A26:				/* ProSavage KN133 */
6166042bf6dSDavid du Colombier 	case 0x8D04:				/* ProSavage DDR, K.Okamoto */
61714414594SDavid du Colombier 		vgaxo(Seqx, 0x29, vga->sequencer[0x29]);
61814414594SDavid du Colombier 		vgaxo(Seqx, 0x39, vga->sequencer[0x39]);
61914414594SDavid du Colombier 		break;
6207dd7cddfSDavid du Colombier 	}
6217dd7cddfSDavid du Colombier 	if((vga->misc & 0x0C) == 0x0C)
6227dd7cddfSDavid du Colombier 		vgaxo(Seqx, 0x15, vga->sequencer[0x15]|0x20);
6237dd7cddfSDavid du Colombier 	vgaxo(Seqx, 0x15, vga->sequencer[0x15]);
6247dd7cddfSDavid du Colombier 	vgaxo(Seqx, 0x18, vga->sequencer[0x18]);
6257dd7cddfSDavid du Colombier 
6267dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x60, vga->crt[0x60]);
6277dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x63, vga->crt[0x63]);
6287dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x65, vga->crt[0x65]);
6297dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x66, vga->crt[0x66]);
6307dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x67, vga->crt[0x67]);
6317dd7cddfSDavid du Colombier 
6327dd7cddfSDavid du Colombier 	switch(id){
6337dd7cddfSDavid du Colombier 
634a4285193SDavid du Colombier 	case 0x8810:				/* Microsoft Virtual PC 2004 */
63559cc4ca5SDavid du Colombier 	case 0x8811:				/* Trio64+ */
6367dd7cddfSDavid du Colombier 		advfunc = 0x0000;
6377dd7cddfSDavid du Colombier 		if(ctlr->flag & Uenhanced)
6387dd7cddfSDavid du Colombier 			advfunc = 0x0001;
6397dd7cddfSDavid du Colombier 		outportw(0x4AE8, advfunc);
6407dd7cddfSDavid du Colombier 		break;
6419a747e4fSDavid du Colombier 	case 0x8901:				/* Trio64V2 */
642fb7f0c93SDavid du Colombier 	case 0x8A01:				/* ViRGE/[DG]X */
6439a747e4fSDavid du Colombier 		vgaxo(Crtx, 0x90, vga->crt[0x90]);
6449a747e4fSDavid du Colombier 		vgaxo(Crtx, 0x91, vga->crt[0x91]);
6459a747e4fSDavid du Colombier 		break;
64659cc4ca5SDavid du Colombier 	case 0x8A10:				/* ViRGE/GX2 */
6477dd7cddfSDavid du Colombier 		vgaxo(Crtx, 0x90, vga->crt[0x90]);
6487dd7cddfSDavid du Colombier 		vgaxo(Crtx, 0x31, vga->crt[0x31]);
6497dd7cddfSDavid du Colombier 		vgaxo(Crtx, 0x13, vga->crt[0x13]);
6507dd7cddfSDavid du Colombier 		vgaxo(Crtx, 0x51, vga->crt[0x51]);
6517dd7cddfSDavid du Colombier 		vgaxo(Crtx, 0x85, vga->crt[0x85]);
6527dd7cddfSDavid du Colombier 		break;
6536042bf6dSDavid du Colombier 	case 0x8D04:				/* ProSavage DDR, K.Okamoto */
6546042bf6dSDavid du Colombier 		vgaxo(Crtx, 0x90, vga->crt[0x90]);		//K.Okamoto
6556042bf6dSDavid du Colombier 		vgaxo(Crtx, 0x91, vga->crt[0x91]);		//K.Okamoto
6569a747e4fSDavid du Colombier 	case 0x8C2E:				/* SuperSavage/IXC16 (let's try this -rsc) */
65759cc4ca5SDavid du Colombier 	case 0x8C12:				/* Savage4/IX-MV */
65859cc4ca5SDavid du Colombier 	case 0x8A22:				/* Savage4 */
6590b459c2cSDavid du Colombier 	case 0x8A25:				/* ProSavage PN133 */
6600b459c2cSDavid du Colombier 	case 0x8A26:				/* ProSavage KN133 */
66114414594SDavid du Colombier 		vgaxo(Crtx, 0x31, vga->crt[0x31]);
66214414594SDavid du Colombier 		vgaxo(Crtx, 0x13, vga->crt[0x13]);
66314414594SDavid du Colombier 		vgaxo(Crtx, 0x51, vga->crt[0x51]);
66414414594SDavid du Colombier 		vgaxo(Crtx, 0x85, vga->crt[0x85]);
66559cc4ca5SDavid du Colombier 		vgaxo(Crtx, 0x50, vga->crt[0x50]);
66614414594SDavid du Colombier 		break;
6677dd7cddfSDavid du Colombier 	}
6687dd7cddfSDavid du Colombier }
6697dd7cddfSDavid du Colombier 
6707dd7cddfSDavid du Colombier static void
dump(Vga * vga,Ctlr * ctlr)6717dd7cddfSDavid du Colombier dump(Vga* vga, Ctlr* ctlr)
6727dd7cddfSDavid du Colombier {
67314414594SDavid du Colombier 	int i, id;
6747dd7cddfSDavid du Colombier 	ulong dclk, m, n, r;
6757dd7cddfSDavid du Colombier 
6767dd7cddfSDavid du Colombier 	s3generic.dump(vga, ctlr);
6777dd7cddfSDavid du Colombier 	printitem(ctlr->name, "Crt70");
6787dd7cddfSDavid du Colombier 	for(i = 0x70; i < 0x99; i++)
6797dd7cddfSDavid du Colombier 		printreg(vga->crt[i]);
6807dd7cddfSDavid du Colombier 
6817dd7cddfSDavid du Colombier 	printitem(ctlr->name, "Seq08");
68259cc4ca5SDavid du Colombier 	for(i = 0x08; i < 0x10; i++)
6837dd7cddfSDavid du Colombier 		printreg(vga->sequencer[i]);
68459cc4ca5SDavid du Colombier 	printitem(ctlr->name, "Seq10");
68559cc4ca5SDavid du Colombier 	for(i = 0x10; i < 0x50; i++)
68659cc4ca5SDavid du Colombier 		printreg(vga->sequencer[i]);
68759cc4ca5SDavid du Colombier 	id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
68859cc4ca5SDavid du Colombier 	switch(id){
68959cc4ca5SDavid du Colombier 	default:
69059cc4ca5SDavid du Colombier 		break;
69159cc4ca5SDavid du Colombier 
69259cc4ca5SDavid du Colombier 	case 0x8812:				/* Aurora64V+ */
6939a747e4fSDavid du Colombier 	case 0x8C2E:				/* SuperSavage/IXC16 (let's try this -rsc) */
69459cc4ca5SDavid du Colombier 	case 0x8C12:				/* Savage4/IX-MV */
69559cc4ca5SDavid du Colombier 		printitem(ctlr->name, "Seq50");
69659cc4ca5SDavid du Colombier 		for(i = 0x50; i < 0x70; i++)
69759cc4ca5SDavid du Colombier 			printreg(vga->sequencer[i]);
69859cc4ca5SDavid du Colombier 		break;
69959cc4ca5SDavid du Colombier 	}
7007dd7cddfSDavid du Colombier 
7017dd7cddfSDavid du Colombier 	printitem(ctlr->name, "Crt2D");
7027dd7cddfSDavid du Colombier 	printreg(vga->crt[0x2D]);
7037dd7cddfSDavid du Colombier 	printreg(vga->crt[0x2E]);
7047dd7cddfSDavid du Colombier 	printreg(vga->crt[0x2F]);
7057dd7cddfSDavid du Colombier 
70659cc4ca5SDavid du Colombier 	m = vga->sequencer[0x13] & vga->m[1];
70759cc4ca5SDavid du Colombier 	n = vga->sequencer[0x12] & vga->n[1];
7087dd7cddfSDavid du Colombier 	r = (vga->sequencer[0x12]>>5) & 0x03;
7097dd7cddfSDavid du Colombier 
71059cc4ca5SDavid du Colombier 	switch(id){
71159cc4ca5SDavid du Colombier 	case 0x8812:				/* Aurora64V+ */
71259cc4ca5SDavid du Colombier 		r = (vga->sequencer[0x12]>>6) & 0x03;
71359cc4ca5SDavid du Colombier 		break;
71459cc4ca5SDavid du Colombier 	case 0x8A01:				/* ViRGE/[DG]X */
7157dd7cddfSDavid du Colombier 		r = (vga->sequencer[0x12]>>5) & 0x07;
7167dd7cddfSDavid du Colombier 		break;
71759cc4ca5SDavid du Colombier 	case 0x8A10:				/* ViRGE/GX2 */
7187dd7cddfSDavid du Colombier 		r = (vga->sequencer[0x12]>>6) & 0x03;
7197dd7cddfSDavid du Colombier 		r |= (vga->sequencer[0x29] & 0x01)<<2;
7207dd7cddfSDavid du Colombier 		break;
7219a747e4fSDavid du Colombier 	case 0x8C2E:				/* SuperSavage/IXC16 (let's try this -rsc) */
72259cc4ca5SDavid du Colombier 	case 0x8C12:				/* Savage4/IX-MV */
72359cc4ca5SDavid du Colombier 	case 0x8A22:				/* Savage4 */
7240b459c2cSDavid du Colombier 	case 0x8A25:				/* ProSavage PN133 */
7250b459c2cSDavid du Colombier 	case 0x8A26:				/* ProSavage KN133 */
7266042bf6dSDavid du Colombier 	case 0x8D04:				/* Prosavage DDR, K.Okamoto */
72759cc4ca5SDavid du Colombier 		m = vga->sequencer[0x13] & 0xFF;
72859cc4ca5SDavid du Colombier 		if(vga->sequencer[0x29] & (1<<3))
72959cc4ca5SDavid du Colombier 			m |= 0x100;
73059cc4ca5SDavid du Colombier 		if(vga->sequencer[0x29] & (1<<4))
73159cc4ca5SDavid du Colombier 			n |= 0x40;
73214414594SDavid du Colombier 		r = (vga->sequencer[0x12]>>6) & 0x03;
73314414594SDavid du Colombier 		r |= (vga->sequencer[0x29] & (1<<2));
73414414594SDavid du Colombier 		break;
7357dd7cddfSDavid du Colombier 	}
73614414594SDavid du Colombier 
7377dd7cddfSDavid du Colombier 	dclk = (m+2)*RefFreq;
7387dd7cddfSDavid du Colombier 	dclk /= (n+2)*(1<<r);
7397dd7cddfSDavid du Colombier 	printitem(ctlr->name, "dclk m n r");
7407dd7cddfSDavid du Colombier 	Bprint(&stdout, "%9ld %8ld       - %8ld %8ld\n", dclk, m, n, r);
7417dd7cddfSDavid du Colombier 
7427dd7cddfSDavid du Colombier 	m = vga->sequencer[0x11] & 0x7F;
7437dd7cddfSDavid du Colombier 	n = vga->sequencer[0x10] & 0x1F;
7447dd7cddfSDavid du Colombier 	r = (vga->sequencer[0x10]>>5) & 0x03;	/* might be GX/2 specific */
7457dd7cddfSDavid du Colombier 	dclk = (m+2)*RefFreq;
7467dd7cddfSDavid du Colombier 	dclk /= (n+2)*(1<<r);
7477dd7cddfSDavid du Colombier 	printitem(ctlr->name, "mclk m n r");
7487dd7cddfSDavid du Colombier 	Bprint(&stdout, "%9ld %8ld       - %8ld %8ld\n", dclk, m, n, r);
7497dd7cddfSDavid du Colombier }
7507dd7cddfSDavid du Colombier 
7517dd7cddfSDavid du Colombier Ctlr virge = {
7527dd7cddfSDavid du Colombier 	"virge",			/* name */
7537dd7cddfSDavid du Colombier 	snarf,				/* snarf */
7547dd7cddfSDavid du Colombier 	options,			/* options */
7557dd7cddfSDavid du Colombier 	init,				/* init */
7567dd7cddfSDavid du Colombier 	load,				/* load */
7577dd7cddfSDavid du Colombier 	dump,				/* dump */
7587dd7cddfSDavid du Colombier };
759