xref: /plan9/sys/src/cmd/aux/vga/hiqvideo.c (revision fb7f0c934c48abaed6040d054ef636408c3c522d)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier 
57dd7cddfSDavid du Colombier #include "pci.h"
69a747e4fSDavid du Colombier #include "vga.h"
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier /*
97dd7cddfSDavid du Colombier  * Chips and Technologies HiQVideo.
107dd7cddfSDavid du Colombier  * Extensions in the 69000 over the 65550 are not fully taken into account.
117dd7cddfSDavid du Colombier  * Depths other than 8 are too slow.
127dd7cddfSDavid du Colombier  */
137dd7cddfSDavid du Colombier enum {
147dd7cddfSDavid du Colombier 	Frx		= 0x3D0,	/* Flat Panel Extensions Index */
157dd7cddfSDavid du Colombier 	Mrx		= 0x3D2,	/* Multimedia Extensions Index */
167dd7cddfSDavid du Colombier 	Xrx		= 0x3D6,	/* Configuration Extensions Index */
177dd7cddfSDavid du Colombier };
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier typedef struct {
207dd7cddfSDavid du Colombier 	Pcidev* pci;
217dd7cddfSDavid du Colombier 
227dd7cddfSDavid du Colombier 	uchar	fr[256];
237dd7cddfSDavid du Colombier 	uchar	mr[256];
247dd7cddfSDavid du Colombier 	uchar	xr[256];
257dd7cddfSDavid du Colombier } HiQVideo;
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier static uchar
hiqvideoxi(long port,uchar index)287dd7cddfSDavid du Colombier hiqvideoxi(long port, uchar index)
297dd7cddfSDavid du Colombier {
307dd7cddfSDavid du Colombier 	uchar data;
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier 	outportb(port, index);
337dd7cddfSDavid du Colombier 	data = inportb(port+1);
347dd7cddfSDavid du Colombier 
357dd7cddfSDavid du Colombier 	return data;
367dd7cddfSDavid du Colombier }
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier static void
hiqvideoxo(long port,uchar index,uchar data)397dd7cddfSDavid du Colombier hiqvideoxo(long port, uchar index, uchar data)
407dd7cddfSDavid du Colombier {
417dd7cddfSDavid du Colombier 	outportb(port, index);
427dd7cddfSDavid du Colombier 	outportb(port+1, data);
437dd7cddfSDavid du Colombier }
447dd7cddfSDavid du Colombier 
457dd7cddfSDavid du Colombier static void
snarf(Vga * vga,Ctlr * ctlr)467dd7cddfSDavid du Colombier snarf(Vga* vga, Ctlr* ctlr)
477dd7cddfSDavid du Colombier {
487dd7cddfSDavid du Colombier 	int i;
497dd7cddfSDavid du Colombier 	Pcidev *p;
507dd7cddfSDavid du Colombier 	HiQVideo *hqv;
517dd7cddfSDavid du Colombier 
527dd7cddfSDavid du Colombier 	if(vga->private == nil){
537dd7cddfSDavid du Colombier 		vga->private = alloc(sizeof(HiQVideo));
547dd7cddfSDavid du Colombier 		hqv = vga->private;
557dd7cddfSDavid du Colombier 		if((p = pcimatch(nil, 0x102C, 0)) == nil)
567dd7cddfSDavid du Colombier 			error("%s: not found\n", ctlr->name);
577dd7cddfSDavid du Colombier 		switch(p->did){
587dd7cddfSDavid du Colombier 		case 0x00C0:		/* 69000 HiQVideo */
597dd7cddfSDavid du Colombier 			vga->f[1] = 135000000;
607dd7cddfSDavid du Colombier 			vga->vmz = 2048*1024;
617dd7cddfSDavid du Colombier 			break;
627dd7cddfSDavid du Colombier 		case 0x00E0:		/* 65550 HiQV32 */
6359cc4ca5SDavid du Colombier 		case 0x00E4:		/* 65554 HiQV32 */
64*fb7f0c93SDavid du Colombier 		case 0x00E5:		/* 65555 HiQV32 */
657dd7cddfSDavid du Colombier 			vga->f[1] = 90000000;
667dd7cddfSDavid du Colombier 			vga->vmz = 2048*1024;
677dd7cddfSDavid du Colombier 			break;
687dd7cddfSDavid du Colombier 		default:
697dd7cddfSDavid du Colombier 			error("%s: DID %4.4uX unsupported\n",
707dd7cddfSDavid du Colombier 				ctlr->name, p->did);
717dd7cddfSDavid du Colombier 		}
727dd7cddfSDavid du Colombier 		hqv->pci = p;
737dd7cddfSDavid du Colombier 	}
747dd7cddfSDavid du Colombier 	hqv = vga->private;
757dd7cddfSDavid du Colombier 
767dd7cddfSDavid du Colombier 	for(i = 0; i < 0x50; i++)
777dd7cddfSDavid du Colombier 		hqv->fr[i] = hiqvideoxi(Frx, i);
787dd7cddfSDavid du Colombier 	for(i = 0; i < 0x60; i++)
797dd7cddfSDavid du Colombier 		hqv->mr[i] = hiqvideoxi(Mrx, i);
807dd7cddfSDavid du Colombier 	for(i = 0x30; i < 0x80; i++)
817dd7cddfSDavid du Colombier 		vga->crt[i] = vgaxi(Crtx, i);
827dd7cddfSDavid du Colombier 	for(i = 0; i < 0x100; i++)
837dd7cddfSDavid du Colombier 		hqv->xr[i] = hiqvideoxi(Xrx, i);
847dd7cddfSDavid du Colombier 
857dd7cddfSDavid du Colombier 	switch(hqv->pci->did){
867dd7cddfSDavid du Colombier 	case 0x00C0:			/* 69000 HiQVideo */
877dd7cddfSDavid du Colombier 		vga->f[1] = 135000000;
887dd7cddfSDavid du Colombier 		vga->vmz = 2048*1024;
897dd7cddfSDavid du Colombier 		break;
907dd7cddfSDavid du Colombier 	case 0x00E0:			/* 65550 HiQV32 */
9159cc4ca5SDavid du Colombier 	case 0x00E4:			/* 65554 HiQV32 */
92*fb7f0c93SDavid du Colombier 	case 0x00E5:			/* 65555 HiQV32 */
937dd7cddfSDavid du Colombier 		/*
947dd7cddfSDavid du Colombier 		 * Check VCC to determine max clock.
957dd7cddfSDavid du Colombier 		 * 5V allows a higher rate.
967dd7cddfSDavid du Colombier 		 */
977dd7cddfSDavid du Colombier 		if(hqv->fr[0x0A] & 0x02)
987dd7cddfSDavid du Colombier 			vga->f[1] = 110000000;
997dd7cddfSDavid du Colombier 		else
1007dd7cddfSDavid du Colombier 			vga->f[1] = 80000000;
1017dd7cddfSDavid du Colombier 		switch((hqv->xr[0x43]>>1) & 0x03){
1027dd7cddfSDavid du Colombier 		case 0:
1037dd7cddfSDavid du Colombier 			vga->vmz = 1*1024*1024;
1047dd7cddfSDavid du Colombier 			break;
1057dd7cddfSDavid du Colombier 		case 1:
1067dd7cddfSDavid du Colombier 			vga->vmz = 2*1024*1024;
1077dd7cddfSDavid du Colombier 			break;
1087dd7cddfSDavid du Colombier 		default:
1097dd7cddfSDavid du Colombier 			vga->vmz = 16*1024*1024;
1107dd7cddfSDavid du Colombier 			break;
1117dd7cddfSDavid du Colombier 		}
1127dd7cddfSDavid du Colombier 		break;
1137dd7cddfSDavid du Colombier 	}
1147dd7cddfSDavid du Colombier 
1157dd7cddfSDavid du Colombier 	ctlr->flag |= Fsnarf;
1167dd7cddfSDavid du Colombier }
1177dd7cddfSDavid du Colombier 
1187dd7cddfSDavid du Colombier static void
options(Vga *,Ctlr * ctlr)1197dd7cddfSDavid du Colombier options(Vga*, Ctlr* ctlr)
1207dd7cddfSDavid du Colombier {
1217dd7cddfSDavid du Colombier 	ctlr->flag |= Hlinear|Foptions;
1227dd7cddfSDavid du Colombier }
1237dd7cddfSDavid du Colombier 
1247dd7cddfSDavid du Colombier static void
clock(Vga * vga,Ctlr * ctlr)1257dd7cddfSDavid du Colombier clock(Vga* vga, Ctlr* ctlr)
1267dd7cddfSDavid du Colombier {
1277dd7cddfSDavid du Colombier 	double f, fmin, fvco, m;
1287dd7cddfSDavid du Colombier 	ulong n, nmin, nmax, pd, rd;
1297dd7cddfSDavid du Colombier 
1307dd7cddfSDavid du Colombier 	/*
1317dd7cddfSDavid du Colombier 	 * Constraints:
1327dd7cddfSDavid du Colombier 	 *  1.	1MHz <= Fref <= 60MHz
1337dd7cddfSDavid du Colombier 	 *  2.	150KHz <= Fref/(RD*N) <= 2MHz
1347dd7cddfSDavid du Colombier 	 *  3.	48MHz < Fvco <= 220MHz
1357dd7cddfSDavid du Colombier 	 *  4.	3 <= M <= 1023
1367dd7cddfSDavid du Colombier 	 *  5.	3 <= N <= 1023
1377dd7cddfSDavid du Colombier 	 */
1387dd7cddfSDavid du Colombier 	f = vga->f[0];
1397dd7cddfSDavid du Colombier 
1407dd7cddfSDavid du Colombier 	/*
1417dd7cddfSDavid du Colombier 	 * Although pd = 0 is valid, things seems more stable
1427dd7cddfSDavid du Colombier 	 * starting at 1.
1437dd7cddfSDavid du Colombier 	 */
1447dd7cddfSDavid du Colombier 	for(pd = 1; pd < 6; pd++){
1457dd7cddfSDavid du Colombier 		f = vga->f[0]*(1<<pd);
1467dd7cddfSDavid du Colombier 		if(f > 48000000 && f <= 220000000)
1477dd7cddfSDavid du Colombier 			break;
1487dd7cddfSDavid du Colombier 	}
1497dd7cddfSDavid du Colombier 	if(pd >= 6)
1507dd7cddfSDavid du Colombier 		error("%s: dclk %lud out of range\n", ctlr->name, vga->f[0]);
1517dd7cddfSDavid du Colombier 	vga->p[0] = pd;
1527dd7cddfSDavid du Colombier 
1537dd7cddfSDavid du Colombier 	/*
1547dd7cddfSDavid du Colombier 	 * The reference divisor has only two possible values, 1 and 4.
1557dd7cddfSDavid du Colombier 	 */
1567dd7cddfSDavid du Colombier 	fmin = f;
1577dd7cddfSDavid du Colombier 	for(rd = 1; rd <= 4; rd += 3){
1587dd7cddfSDavid du Colombier 		/*
1597dd7cddfSDavid du Colombier 		 * Find the range for n (constraint 2).
1607dd7cddfSDavid du Colombier 		 */
1617dd7cddfSDavid du Colombier 		for(nmin = 3; nmin <= 1023; nmin++){
1627dd7cddfSDavid du Colombier 			if(RefFreq/(rd*nmin) <= 2000000)
1637dd7cddfSDavid du Colombier 				break;
1647dd7cddfSDavid du Colombier 		}
1657dd7cddfSDavid du Colombier 		for(nmax = 1023; nmax >= 3; nmax--){
1667dd7cddfSDavid du Colombier 			if(RefFreq/(rd*nmax) >= 150000)
1677dd7cddfSDavid du Colombier 				break;
1687dd7cddfSDavid du Colombier 		}
1697dd7cddfSDavid du Colombier 
1707dd7cddfSDavid du Colombier 		/*
1717dd7cddfSDavid du Colombier 		 * Now find the closest match for M and N.
1727dd7cddfSDavid du Colombier 		 */
1737dd7cddfSDavid du Colombier 		for(n = nmin; n < nmax; n++){
1747dd7cddfSDavid du Colombier 			for(m = 3; m <= vga->m[1]; m++){
1757dd7cddfSDavid du Colombier 				fvco = (RefFreq*4*m)/(rd*n);
1767dd7cddfSDavid du Colombier 				if(fvco < 48000000 || fvco > 220000000)
1777dd7cddfSDavid du Colombier 					continue;
1787dd7cddfSDavid du Colombier 				fvco -= f;
1797dd7cddfSDavid du Colombier 				if(fvco < 0)
1807dd7cddfSDavid du Colombier 					fvco = -fvco;
1817dd7cddfSDavid du Colombier 				if(fvco < fmin){
1827dd7cddfSDavid du Colombier 					fmin = fvco;
1837dd7cddfSDavid du Colombier 					vga->m[0] = m;
1847dd7cddfSDavid du Colombier 					vga->n[0] = n;
1857dd7cddfSDavid du Colombier 					vga->p[0] = pd;
1867dd7cddfSDavid du Colombier 					vga->r[0] = rd;
1877dd7cddfSDavid du Colombier 				}
1887dd7cddfSDavid du Colombier 			}
1897dd7cddfSDavid du Colombier 		}
1907dd7cddfSDavid du Colombier 	}
1917dd7cddfSDavid du Colombier 
1927dd7cddfSDavid du Colombier }
1937dd7cddfSDavid du Colombier 
1947dd7cddfSDavid du Colombier static void
init(Vga * vga,Ctlr * ctlr)1957dd7cddfSDavid du Colombier init(Vga* vga, Ctlr* ctlr)
1967dd7cddfSDavid du Colombier {
1977dd7cddfSDavid du Colombier 	HiQVideo *hqv;
1987dd7cddfSDavid du Colombier 
1997dd7cddfSDavid du Colombier 	hqv = vga->private;
2007dd7cddfSDavid du Colombier 
2017dd7cddfSDavid du Colombier 	if(vga->f[0] == 0)
2027dd7cddfSDavid du Colombier 		vga->f[0] = vga->mode->frequency;
2037dd7cddfSDavid du Colombier 	vga->misc &= ~0x0C;
2047dd7cddfSDavid du Colombier 	hqv->fr[0x03] &= ~0x0C;
2057dd7cddfSDavid du Colombier 
2067dd7cddfSDavid du Colombier 	switch(vga->mode->z){
2077dd7cddfSDavid du Colombier 	case 8:
2087dd7cddfSDavid du Colombier 	case 16:
2097dd7cddfSDavid du Colombier 	case 32:
2107dd7cddfSDavid du Colombier 		break;
2117dd7cddfSDavid du Colombier 	default:
2127dd7cddfSDavid du Colombier 		error("depth %d not supported\n", vga->mode->z);
2137dd7cddfSDavid du Colombier 	}
2147dd7cddfSDavid du Colombier 
2157dd7cddfSDavid du Colombier 	/*
2167dd7cddfSDavid du Colombier 	 * FR[0x01] == 1 for CRT, 2 for LCD.
2177dd7cddfSDavid du Colombier 	 * Don't programme the clock if it's an LCD.
2187dd7cddfSDavid du Colombier 	 */
2197dd7cddfSDavid du Colombier 	if((hqv->fr[0x01] & 0x03) == 0x02){
2207dd7cddfSDavid du Colombier 		vga->misc |= 0x08;
2217dd7cddfSDavid du Colombier 		hqv->fr[0x03] |= 0x08;
2227dd7cddfSDavid du Colombier 	}
2237dd7cddfSDavid du Colombier 	else{
2247dd7cddfSDavid du Colombier 		/*
2257dd7cddfSDavid du Colombier 		 * Clock bits. If the desired video clock is
2267dd7cddfSDavid du Colombier 		 * one of the two standard VGA clocks it can just be
2277dd7cddfSDavid du Colombier 		 * set using bits <3:2> of vga->misc or Fr03,
2287dd7cddfSDavid du Colombier 		 * otherwise the DCLK PLL needs to be programmed.
2297dd7cddfSDavid du Colombier 		 */
2309a747e4fSDavid du Colombier 		if(vga->f[0] == VgaFreq0){
2319a747e4fSDavid du Colombier 			/* nothing to do */;
2329a747e4fSDavid du Colombier 		}
2337dd7cddfSDavid du Colombier 		else if(vga->f[0] == VgaFreq1){
2347dd7cddfSDavid du Colombier 			vga->misc |= 0x04;
2357dd7cddfSDavid du Colombier 			hqv->fr[0x03] |= 0x04;
2367dd7cddfSDavid du Colombier 		}
2377dd7cddfSDavid du Colombier 		else{
2387dd7cddfSDavid du Colombier 			if(vga->f[0] > vga->f[1])
2397dd7cddfSDavid du Colombier 				error("%s: invalid dclk - %lud\n",
2407dd7cddfSDavid du Colombier 					ctlr->name, vga->f[0]);
2417dd7cddfSDavid du Colombier 
2427dd7cddfSDavid du Colombier 			if((hqv->fr[0x01] & 0x03) != 0x02){
2437dd7cddfSDavid du Colombier 				vga->m[1] = 1023;
2447dd7cddfSDavid du Colombier 				clock(vga, ctlr);
2457dd7cddfSDavid du Colombier 				hqv->xr[0xC8] = (vga->m[0]-2) & 0xFF;
2467dd7cddfSDavid du Colombier 				hqv->xr[0xCA] = ((vga->m[0]-2) & 0x300)>>8;
2477dd7cddfSDavid du Colombier 				hqv->xr[0xC9] = (vga->n[0]-2) & 0xFF;
2487dd7cddfSDavid du Colombier 				hqv->xr[0xCA] |= ((vga->n[0]-2) & 0x300)>>4;
2497dd7cddfSDavid du Colombier 				hqv->xr[0xCB] = (vga->p[0]<<4)|(vga->r[0] == 1);
2507dd7cddfSDavid du Colombier 			}
2517dd7cddfSDavid du Colombier 			vga->misc |= 0x08;
2527dd7cddfSDavid du Colombier 			hqv->fr[0x03] |= 0x08;
2537dd7cddfSDavid du Colombier 		}
2547dd7cddfSDavid du Colombier 	}
2557dd7cddfSDavid du Colombier 
2567dd7cddfSDavid du Colombier 	if(vga->mode->y >= 480)
2577dd7cddfSDavid du Colombier 		vga->misc &= ~0xC0;
2587dd7cddfSDavid du Colombier 
2597dd7cddfSDavid du Colombier 	/*
2607dd7cddfSDavid du Colombier 	 * 10 bits should be enough, but set the extended mode anyway.
2617dd7cddfSDavid du Colombier 	 */
2627dd7cddfSDavid du Colombier 	hqv->xr[0x09] |= 0x01;
2637dd7cddfSDavid du Colombier 	vga->crt[0x30] = ((vga->mode->vt-2)>>8) & 0x0F;
2647dd7cddfSDavid du Colombier 	vga->crt[0x31] = ((vga->mode->y-1)>>8) & 0x0F;
2657dd7cddfSDavid du Colombier 	vga->crt[0x32] = (vga->mode->vrs>>8) & 0x0F;
2667dd7cddfSDavid du Colombier 	vga->crt[0x33] = (vga->mode->vrs>>8) & 0x0F;
2677dd7cddfSDavid du Colombier 	vga->crt[0x38] = (((vga->mode->ht>>3)-5)>>8) & 0x01;
2687dd7cddfSDavid du Colombier 	vga->crt[0x3C] = (vga->mode->ehb>>3) & 0xC0;
2697dd7cddfSDavid du Colombier 	vga->crt[0x41] = (vga->crt[0x13]>>8) & 0x0F;
2707dd7cddfSDavid du Colombier 	vga->crt[0x40] = 0x80;
2717dd7cddfSDavid du Colombier 
2727dd7cddfSDavid du Colombier 	hqv->xr[0x40] |= 0x03;
2737dd7cddfSDavid du Colombier 	hqv->xr[0x80] |= 0x10;
2747dd7cddfSDavid du Colombier 	hqv->xr[0x81] &= ~0x0F;
2757dd7cddfSDavid du Colombier 	switch(vga->mode->z){
2767dd7cddfSDavid du Colombier 	case 8:
2777dd7cddfSDavid du Colombier 		hqv->xr[0x81] |= 0x12;
2787dd7cddfSDavid du Colombier 		break;
2797dd7cddfSDavid du Colombier 	case 16:
2807dd7cddfSDavid du Colombier 		hqv->xr[0x81] |= 0x15;
2817dd7cddfSDavid du Colombier 		break;
2827dd7cddfSDavid du Colombier 	case 32:
2837dd7cddfSDavid du Colombier 		hqv->xr[0x81] |= 0x16;
2847dd7cddfSDavid du Colombier 		break;
2857dd7cddfSDavid du Colombier 	}
2867dd7cddfSDavid du Colombier 
2877dd7cddfSDavid du Colombier 	hqv->xr[0x0A] = 0x01;
2887dd7cddfSDavid du Colombier 	if(vga->linear && (ctlr->flag & Hlinear))
2897dd7cddfSDavid du Colombier 		ctlr->flag |= Ulinear;
2907dd7cddfSDavid du Colombier 
2917dd7cddfSDavid du Colombier 	vga->attribute[0x11] = 0;
2927dd7cddfSDavid du Colombier 
2937dd7cddfSDavid du Colombier 	ctlr->flag |= Finit;
2947dd7cddfSDavid du Colombier }
2957dd7cddfSDavid du Colombier 
2967dd7cddfSDavid du Colombier static void
load(Vga * vga,Ctlr * ctlr)2977dd7cddfSDavid du Colombier load(Vga* vga, Ctlr* ctlr)
2987dd7cddfSDavid du Colombier {
2997dd7cddfSDavid du Colombier 	HiQVideo *hqv;
3007dd7cddfSDavid du Colombier 
3017dd7cddfSDavid du Colombier 	hqv = vga->private;
3027dd7cddfSDavid du Colombier 
3037dd7cddfSDavid du Colombier 	hiqvideoxo(Xrx, 0x0E, 0x00);
3047dd7cddfSDavid du Colombier 	while((vgai(Status1) & 0x08) == 0x08)
3057dd7cddfSDavid du Colombier 		;
3067dd7cddfSDavid du Colombier 	while((vgai(Status1) & 0x08) == 0)
3077dd7cddfSDavid du Colombier 		;
3087dd7cddfSDavid du Colombier 	vgaxo(Seqx, 0x07, 0x00);
3097dd7cddfSDavid du Colombier 
3107dd7cddfSDavid du Colombier 	/*
3117dd7cddfSDavid du Colombier 	 * Set the clock if necessary.
3127dd7cddfSDavid du Colombier 	 */
3137dd7cddfSDavid du Colombier 	if((vga->misc & 0x0C) == 0x08 && (hqv->fr[0x01] & 0x03) != 0x02){
3147dd7cddfSDavid du Colombier 		vgao(MiscW, vga->misc & ~0x0C);
3157dd7cddfSDavid du Colombier 		hiqvideoxo(Frx, 0x03, hqv->fr[0x03] & ~0x0C);
3167dd7cddfSDavid du Colombier 
3177dd7cddfSDavid du Colombier 		hiqvideoxo(Xrx, 0xC8, hqv->xr[0xC8]);
3187dd7cddfSDavid du Colombier 		hiqvideoxo(Xrx, 0xC9, hqv->xr[0xC9]);
3197dd7cddfSDavid du Colombier 		hiqvideoxo(Xrx, 0xCA, hqv->xr[0xCA]);
3207dd7cddfSDavid du Colombier 		hiqvideoxo(Xrx, 0xCB, hqv->xr[0xCB]);
3217dd7cddfSDavid du Colombier 	}
3227dd7cddfSDavid du Colombier 	hiqvideoxo(Frx, 0x03, hqv->fr[0x03]);
3237dd7cddfSDavid du Colombier 	vgao(MiscW, vga->misc);
3247dd7cddfSDavid du Colombier 
3257dd7cddfSDavid du Colombier 	hiqvideoxo(Xrx, 0x09, hqv->xr[0x09]);
3267dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x30, vga->crt[0x30]);
3277dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x31, vga->crt[0x31]);
3287dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x32, vga->crt[0x32]);
3297dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x33, vga->crt[0x33]);
3307dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x38, vga->crt[0x38]);
3317dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x3C, vga->crt[0x3C]);
3327dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x41, vga->crt[0x41]);
3337dd7cddfSDavid du Colombier 	vgaxo(Crtx, 0x40, vga->crt[0x40]);
3347dd7cddfSDavid du Colombier 
3357dd7cddfSDavid du Colombier 	hiqvideoxo(Xrx, 0x40, hqv->xr[0x40]);
3367dd7cddfSDavid du Colombier 	hiqvideoxo(Xrx, 0x80, hqv->xr[0x80]);
3377dd7cddfSDavid du Colombier 	hiqvideoxo(Xrx, 0x81, hqv->xr[0x81]);
3387dd7cddfSDavid du Colombier 	if(ctlr->flag & Ulinear){
3397dd7cddfSDavid du Colombier 		hqv->xr[0x05] = vga->vmb>>16;
3407dd7cddfSDavid du Colombier 		hqv->xr[0x06] = vga->vmb>>24;
3417dd7cddfSDavid du Colombier 		hiqvideoxo(Xrx, 0x05, hqv->xr[0x05]);
3427dd7cddfSDavid du Colombier 		hiqvideoxo(Xrx, 0x06, hqv->xr[0x06]);
3437dd7cddfSDavid du Colombier 		hqv->xr[0x0A] = 0x02;
3447dd7cddfSDavid du Colombier 	}
3457dd7cddfSDavid du Colombier 	hiqvideoxo(Xrx, 0x0A, hqv->xr[0x0A]);
3467dd7cddfSDavid du Colombier 
3477dd7cddfSDavid du Colombier 	ctlr->flag |= Fload;
3487dd7cddfSDavid du Colombier }
3497dd7cddfSDavid du Colombier 
3507dd7cddfSDavid du Colombier static ulong
dumpmclk(uchar data[4])3517dd7cddfSDavid du Colombier dumpmclk(uchar data[4])
3527dd7cddfSDavid du Colombier {
3537dd7cddfSDavid du Colombier 	double f, m, n;
3547dd7cddfSDavid du Colombier 	int pds, rds;
3557dd7cddfSDavid du Colombier 
3567dd7cddfSDavid du Colombier 	m = data[0] & 0x7F;
3577dd7cddfSDavid du Colombier 	n = data[1] & 0x7F;
3587dd7cddfSDavid du Colombier 	pds = 1<<((data[2] & 0x70)>>4);
3597dd7cddfSDavid du Colombier 	if(data[2] & 0x01)
3607dd7cddfSDavid du Colombier 		rds = 1;
3617dd7cddfSDavid du Colombier 	else
3627dd7cddfSDavid du Colombier 		rds = 4;
3637dd7cddfSDavid du Colombier 	f = (RefFreq*4*(m+2))/(rds*(n+2));
3647dd7cddfSDavid du Colombier 	f /= pds;
3657dd7cddfSDavid du Colombier 
3667dd7cddfSDavid du Colombier 	return f;
3677dd7cddfSDavid du Colombier }
3687dd7cddfSDavid du Colombier 
3697dd7cddfSDavid du Colombier static ulong
dumpvclk(uchar data[4])3707dd7cddfSDavid du Colombier dumpvclk(uchar data[4])
3717dd7cddfSDavid du Colombier {
3727dd7cddfSDavid du Colombier 	double f, m, n;
3737dd7cddfSDavid du Colombier 	int pds, rds;
3747dd7cddfSDavid du Colombier 
3757dd7cddfSDavid du Colombier 	m = ((data[2] & 0x03)<<8)|data[0];
3767dd7cddfSDavid du Colombier 	n = (((data[2] & 0x30)>>4)<<8)|data[1];
3777dd7cddfSDavid du Colombier 	pds = 1<<((data[3] & 0x70)>>4);
3787dd7cddfSDavid du Colombier 	if(data[3] & 0x01)
3797dd7cddfSDavid du Colombier 		rds = 1;
3807dd7cddfSDavid du Colombier 	else
3817dd7cddfSDavid du Colombier 		rds = 4;
3827dd7cddfSDavid du Colombier 	f = (RefFreq*4*(m+2))/(rds*(n+2));
3837dd7cddfSDavid du Colombier 	f /= pds;
3847dd7cddfSDavid du Colombier 
3857dd7cddfSDavid du Colombier 	return f;
3867dd7cddfSDavid du Colombier }
3877dd7cddfSDavid du Colombier 
3887dd7cddfSDavid du Colombier static void
dump(Vga * vga,Ctlr * ctlr)3897dd7cddfSDavid du Colombier dump(Vga* vga, Ctlr* ctlr)
3907dd7cddfSDavid du Colombier {
3917dd7cddfSDavid du Colombier 	int i;
3927dd7cddfSDavid du Colombier 	char *name;
3937dd7cddfSDavid du Colombier 	HiQVideo *hqv;
3947dd7cddfSDavid du Colombier 
3957dd7cddfSDavid du Colombier 	name = ctlr->name;
3967dd7cddfSDavid du Colombier 	hqv = vga->private;
3977dd7cddfSDavid du Colombier 
3987dd7cddfSDavid du Colombier 	printitem(name, "Fr00");
3997dd7cddfSDavid du Colombier 	for(i = 0; i < 0x50; i++)
4007dd7cddfSDavid du Colombier 		printreg(hqv->fr[i]);
4017dd7cddfSDavid du Colombier 	printitem(name, "Mr00");
4027dd7cddfSDavid du Colombier 	for(i = 0; i < 0x60; i++)
4037dd7cddfSDavid du Colombier 		printreg(hqv->mr[i]);
4047dd7cddfSDavid du Colombier 	printitem(name, "Crt30");
4057dd7cddfSDavid du Colombier 	for(i = 0x30; i < 0x80; i++)
4067dd7cddfSDavid du Colombier 		printreg(vga->crt[i]);
4077dd7cddfSDavid du Colombier 	printitem(name, "Xr00");
4087dd7cddfSDavid du Colombier 	for(i = 0; i < 0x100; i++)
4097dd7cddfSDavid du Colombier 		printreg(hqv->xr[i]);
4107dd7cddfSDavid du Colombier 
4117dd7cddfSDavid du Colombier 	printitem(ctlr->name, "CLK0");
4127dd7cddfSDavid du Colombier 	for(i = 0; i < 4; i++)
4137dd7cddfSDavid du Colombier 		printreg(hqv->xr[0xC0+i]);
4147dd7cddfSDavid du Colombier 	Bprint(&stdout, "%23ld", dumpvclk(&hqv->xr[0xC0]));
4157dd7cddfSDavid du Colombier 	printitem(ctlr->name, "CLK1");
4167dd7cddfSDavid du Colombier 	for(i = 0; i < 4; i++)
4177dd7cddfSDavid du Colombier 		printreg(hqv->xr[0xC4+i]);
4187dd7cddfSDavid du Colombier 	Bprint(&stdout, "%23ld", dumpvclk(&hqv->xr[0xC4]));
4197dd7cddfSDavid du Colombier 	printitem(ctlr->name, "CLK2");
4207dd7cddfSDavid du Colombier 	for(i = 0; i < 4; i++)
4217dd7cddfSDavid du Colombier 		printreg(hqv->xr[0xC8+i]);
4227dd7cddfSDavid du Colombier 	Bprint(&stdout, "%23ld", dumpvclk(&hqv->xr[0xC8]));
4237dd7cddfSDavid du Colombier 	printitem(ctlr->name, "MCLK");
4247dd7cddfSDavid du Colombier 	for(i = 0; i < 4; i++)
4257dd7cddfSDavid du Colombier 		printreg(hqv->xr[0xCC+i]);
4267dd7cddfSDavid du Colombier 	Bprint(&stdout, "%23ld", dumpmclk(&hqv->xr[0xCC]));
4277dd7cddfSDavid du Colombier 
4287dd7cddfSDavid du Colombier 	printitem(ctlr->name, "m n pd rd");
4297dd7cddfSDavid du Colombier 	Bprint(&stdout, "%9ld %8ld       - %8ld %8ld\n",
4307dd7cddfSDavid du Colombier 		vga->m[0], vga->n[0], vga->p[0], vga->r[0]);
4317dd7cddfSDavid du Colombier }
4327dd7cddfSDavid du Colombier 
4337dd7cddfSDavid du Colombier Ctlr hiqvideo = {
4347dd7cddfSDavid du Colombier 	"hiqvideo",			/* name */
4357dd7cddfSDavid du Colombier 	snarf,				/* snarf */
4367dd7cddfSDavid du Colombier 	options,			/* options */
4377dd7cddfSDavid du Colombier 	init,				/* init */
4387dd7cddfSDavid du Colombier 	load,				/* load */
4397dd7cddfSDavid du Colombier 	dump,				/* dump */
4407dd7cddfSDavid du Colombier };
4417dd7cddfSDavid du Colombier 
4427dd7cddfSDavid du Colombier Ctlr hiqvideohwgc = {
4437dd7cddfSDavid du Colombier 	"hiqvideohwgc",			/* name */
4447dd7cddfSDavid du Colombier 	0,				/* snarf */
4457dd7cddfSDavid du Colombier 	0,				/* options */
4467dd7cddfSDavid du Colombier 	0,				/* init */
4477dd7cddfSDavid du Colombier 	0,				/* load */
4487dd7cddfSDavid du Colombier 	0,				/* dump */
4497dd7cddfSDavid du Colombier };
450