xref: /plan9/sys/src/cmd/aux/vga/3dfx.c (revision 0aa8dc3ce45e27c8119541cf306abb402a5895d8)
159cc4ca5SDavid du Colombier #include <u.h>
259cc4ca5SDavid du Colombier #include <libc.h>
359cc4ca5SDavid du Colombier #include <bio.h>
459cc4ca5SDavid du Colombier 
559cc4ca5SDavid du Colombier #include "pci.h"
69a747e4fSDavid du Colombier #include "vga.h"
759cc4ca5SDavid du Colombier 
859cc4ca5SDavid du Colombier /*
959cc4ca5SDavid du Colombier  * 3Dfx.
1059cc4ca5SDavid du Colombier  */
1159cc4ca5SDavid du Colombier enum {
1259cc4ca5SDavid du Colombier 	dramInit0		= 0x018/4,
1359cc4ca5SDavid du Colombier 	dramInit1		= 0x01C/4,
1459cc4ca5SDavid du Colombier 	vgaInit0		= 0x028/4,
1559cc4ca5SDavid du Colombier 	pllCtrl0		= 0x040/4,
1659cc4ca5SDavid du Colombier 	pllCtrl1		= 0x044/4,
1759cc4ca5SDavid du Colombier 	pllCtrl2		= 0x048/4,
1859cc4ca5SDavid du Colombier 	dacMode			= 0x04C/4,
1959cc4ca5SDavid du Colombier 	vidProcCfg		= 0x05C/4,
2059cc4ca5SDavid du Colombier 	vidScreenSize		= 0x098/4,
2159cc4ca5SDavid du Colombier 	vidDesktopOverlayStride	= 0x0E8/4,
2259cc4ca5SDavid du Colombier 
2359cc4ca5SDavid du Colombier 	Nior			= 0x100/4,
2459cc4ca5SDavid du Colombier };
2559cc4ca5SDavid du Colombier 
2659cc4ca5SDavid du Colombier typedef struct Tdfx {
2759cc4ca5SDavid du Colombier 	ulong	io;
2859cc4ca5SDavid du Colombier 	Pcidev*	pci;
2959cc4ca5SDavid du Colombier 
30b7b24591SDavid du Colombier 	ulong	r[Nior];
3159cc4ca5SDavid du Colombier } Tdfx;
3259cc4ca5SDavid du Colombier 
3359cc4ca5SDavid du Colombier static ulong
io32r(Tdfx * tdfx,int r)3459cc4ca5SDavid du Colombier io32r(Tdfx* tdfx, int r)
3559cc4ca5SDavid du Colombier {
3659cc4ca5SDavid du Colombier 	return inportl(tdfx->io+(r*4));
3759cc4ca5SDavid du Colombier }
3859cc4ca5SDavid du Colombier 
3959cc4ca5SDavid du Colombier static void
io32w(Tdfx * tdfx,int r,ulong l)4059cc4ca5SDavid du Colombier io32w(Tdfx* tdfx, int r, ulong l)
4159cc4ca5SDavid du Colombier {
4259cc4ca5SDavid du Colombier 	outportl(tdfx->io+(r*4), l);
4359cc4ca5SDavid du Colombier }
4459cc4ca5SDavid du Colombier 
4559cc4ca5SDavid du Colombier static void
snarf(Vga * vga,Ctlr * ctlr)4659cc4ca5SDavid du Colombier snarf(Vga* vga, Ctlr* ctlr)
4759cc4ca5SDavid du Colombier {
4859cc4ca5SDavid du Colombier 	int i;
4959cc4ca5SDavid du Colombier 	ulong v;
5059cc4ca5SDavid du Colombier 	Tdfx *tdfx;
5159cc4ca5SDavid du Colombier 
5259cc4ca5SDavid du Colombier 	if(vga->private == nil){
5359cc4ca5SDavid du Colombier 		tdfx = alloc(sizeof(Tdfx));
5459cc4ca5SDavid du Colombier 		tdfx->pci = pcimatch(0, 0x121A, 0);
5559cc4ca5SDavid du Colombier 		if(tdfx->pci == nil)
5659cc4ca5SDavid du Colombier 			error("%s: not found\n", ctlr->name);
5759cc4ca5SDavid du Colombier 		switch(tdfx->pci->did){
5859cc4ca5SDavid du Colombier 		default:
5959cc4ca5SDavid du Colombier 			error("%s: unknown chip - DID %4.4uX\n",
6059cc4ca5SDavid du Colombier 				ctlr->name, tdfx->pci->did);
6159cc4ca5SDavid du Colombier 			break;
6280ee5cbfSDavid du Colombier 		case 0x0003:		/* Banshee */
6380ee5cbfSDavid du Colombier 			vga->f[1] = 270000000;
6480ee5cbfSDavid du Colombier 			break;
6559cc4ca5SDavid du Colombier 		case 0x0005:		/* Avenger (a.k.a. Voodoo3) */
6680ee5cbfSDavid du Colombier 			vga->f[1] = 300000000;
6780ee5cbfSDavid du Colombier 			break;
683ff48bf5SDavid du Colombier 		case 0x0009:		/* Voodoo5 */
693ff48bf5SDavid du Colombier 			vga->f[1] = 350000000;
703ff48bf5SDavid du Colombier 			break;
7180ee5cbfSDavid du Colombier 		}
7259cc4ca5SDavid du Colombier 		/*
7359cc4ca5SDavid du Colombier 		 * Frequency output of PLL's is given by
7459cc4ca5SDavid du Colombier 		 *	fout = RefFreq*(n+2)/((m+2)*2^p)
7559cc4ca5SDavid du Colombier 		 * where there are 6 bits for m, 8 bits for n
7659cc4ca5SDavid du Colombier 		 * and 2 bits for p (k).
7759cc4ca5SDavid du Colombier 		 */
7859cc4ca5SDavid du Colombier 		vga->m[1] = 64;
7959cc4ca5SDavid du Colombier 		vga->n[1] = 256;
8059cc4ca5SDavid du Colombier 		vga->p[1] = 4;
8180ee5cbfSDavid du Colombier 
8259cc4ca5SDavid du Colombier 		if((v = (tdfx->pci->mem[2].bar & ~0x3)) == 0)
8359cc4ca5SDavid du Colombier 			error("%s: I/O not mapped\n", ctlr->name);
8459cc4ca5SDavid du Colombier 		tdfx->io = v;
8559cc4ca5SDavid du Colombier 
8659cc4ca5SDavid du Colombier 		vga->private = tdfx;
8759cc4ca5SDavid du Colombier 	}
8859cc4ca5SDavid du Colombier 	tdfx = vga->private;
8959cc4ca5SDavid du Colombier 
9059cc4ca5SDavid du Colombier 	vga->crt[0x1A] = vgaxi(Crtx, 0x1A);
9159cc4ca5SDavid du Colombier 	vga->crt[0x1B] = vgaxi(Crtx, 0x1B);
9259cc4ca5SDavid du Colombier 	for(i = 0; i < Nior; i++)
9359cc4ca5SDavid du Colombier 		tdfx->r[i] = io32r(tdfx, i);
9459cc4ca5SDavid du Colombier 
9559cc4ca5SDavid du Colombier 	/*
9659cc4ca5SDavid du Colombier 	 * If SDRAM then there's 16MB memory else it's SGRAM
9759cc4ca5SDavid du Colombier 	 * and can count it based on the power-on straps -
9859cc4ca5SDavid du Colombier 	 * chip size can be 8Mb or 16Mb, and there can be 4 or
9959cc4ca5SDavid du Colombier 	 * 8 of them.
10059cc4ca5SDavid du Colombier 	 */
10159cc4ca5SDavid du Colombier 	vga->vma = tdfx->pci->mem[1].size;
10259cc4ca5SDavid du Colombier 	if(tdfx->r[dramInit1] & 0x40000000)
10359cc4ca5SDavid du Colombier 		vga->vmz = 16*1024*1024;
10459cc4ca5SDavid du Colombier 	else{
10559cc4ca5SDavid du Colombier 		if(tdfx->r[dramInit0] & 0x08000000)
10659cc4ca5SDavid du Colombier 			i = 16*1024*1024/8;
10759cc4ca5SDavid du Colombier 		else
10859cc4ca5SDavid du Colombier 			i = 8*1024*1024/8;
10959cc4ca5SDavid du Colombier 		if(tdfx->r[dramInit0] & 0x04000000)
11059cc4ca5SDavid du Colombier 			i *= 8;
11159cc4ca5SDavid du Colombier 		else
11259cc4ca5SDavid du Colombier 			i *= 4;
11359cc4ca5SDavid du Colombier 		vga->vmz = i;
11459cc4ca5SDavid du Colombier 	}
11559cc4ca5SDavid du Colombier 
11659cc4ca5SDavid du Colombier 	ctlr->flag |= Fsnarf;
11759cc4ca5SDavid du Colombier }
11859cc4ca5SDavid du Colombier 
11959cc4ca5SDavid du Colombier static void
options(Vga *,Ctlr * ctlr)12059cc4ca5SDavid du Colombier options(Vga*, Ctlr* ctlr)
12159cc4ca5SDavid du Colombier {
12259cc4ca5SDavid du Colombier 	ctlr->flag |= Hlinear|Hclk2|Foptions;
12359cc4ca5SDavid du Colombier }
12459cc4ca5SDavid du Colombier 
12559cc4ca5SDavid du Colombier static void
tdfxclock(Vga * vga,Ctlr *)12659cc4ca5SDavid du Colombier tdfxclock(Vga* vga, Ctlr*)
12759cc4ca5SDavid du Colombier {
128*0aa8dc3cSDavid du Colombier 	int d, dmin;
129*0aa8dc3cSDavid du Colombier 	uint f, m, n, p;
13059cc4ca5SDavid du Colombier 
13159cc4ca5SDavid du Colombier 	dmin = vga->f[0];
13259cc4ca5SDavid du Colombier 	for(m = 1; m < vga->m[1]; m++){
13359cc4ca5SDavid du Colombier 		for(n = 1; n < vga->n[1]; n++){
13459cc4ca5SDavid du Colombier 			f = (RefFreq*(n+2))/(m+2);
13559cc4ca5SDavid du Colombier 			for(p = 0; p < vga->p[1]; p++){
13659cc4ca5SDavid du Colombier 				d = vga->f[0] - (f/(1<<p));
13759cc4ca5SDavid du Colombier 				if(d < 0)
13859cc4ca5SDavid du Colombier 					d = -d;
13959cc4ca5SDavid du Colombier 				if(d >= dmin)
14059cc4ca5SDavid du Colombier 					continue;
14159cc4ca5SDavid du Colombier 				dmin = d;
14259cc4ca5SDavid du Colombier 				vga->m[0] = m;
14359cc4ca5SDavid du Colombier 				vga->n[0] = n;
14459cc4ca5SDavid du Colombier 				vga->p[0] = p;
14559cc4ca5SDavid du Colombier 			}
14659cc4ca5SDavid du Colombier 		}
14759cc4ca5SDavid du Colombier 	}
14859cc4ca5SDavid du Colombier }
14959cc4ca5SDavid du Colombier 
15059cc4ca5SDavid du Colombier static void
init(Vga * vga,Ctlr * ctlr)15159cc4ca5SDavid du Colombier init(Vga* vga, Ctlr* ctlr)
15259cc4ca5SDavid du Colombier {
15359cc4ca5SDavid du Colombier 	int x;
15459cc4ca5SDavid du Colombier 	Mode *mode;
15559cc4ca5SDavid du Colombier 	Tdfx *tdfx;
15659cc4ca5SDavid du Colombier 
15759cc4ca5SDavid du Colombier 	mode = vga->mode;
15859cc4ca5SDavid du Colombier 	tdfx = vga->private;
15959cc4ca5SDavid du Colombier 
16059cc4ca5SDavid du Colombier 	if(vga->linear && (ctlr->flag & Hlinear))
16159cc4ca5SDavid du Colombier 		ctlr->flag |= Ulinear;
16259cc4ca5SDavid du Colombier 
16359cc4ca5SDavid du Colombier 	/*
16459cc4ca5SDavid du Colombier 	 * Clock bits. If the desired video clock is
16559cc4ca5SDavid du Colombier 	 * one of the two standard VGA clocks or 50MHz it can just be
16659cc4ca5SDavid du Colombier 	 * set using bits <3:2> of vga->misc, otherwise we
16759cc4ca5SDavid du Colombier 	 * need to programme the PLL.
16859cc4ca5SDavid du Colombier 	 */
16959cc4ca5SDavid du Colombier 	if(vga->f[0] == 0)
17059cc4ca5SDavid du Colombier 		vga->f[0] = mode->frequency;
17159cc4ca5SDavid du Colombier 	vga->misc &= ~0x0C;
1729a747e4fSDavid du Colombier 	if(vga->f[0] == VgaFreq0){
1739a747e4fSDavid du Colombier 		/* nothing to do */;
1749a747e4fSDavid du Colombier 	}
17559cc4ca5SDavid du Colombier 	else if(vga->f[0] == VgaFreq1)
17659cc4ca5SDavid du Colombier 		vga->misc |= 0x04;
17759cc4ca5SDavid du Colombier 	else if(vga->f[0] == 50000000)
17859cc4ca5SDavid du Colombier 		vga->misc |= 0x08;
17959cc4ca5SDavid du Colombier 	else{
18059cc4ca5SDavid du Colombier 		if(vga->f[0] > vga->f[1])
18159cc4ca5SDavid du Colombier 			error("%s: invalid pclk - %lud\n",
18259cc4ca5SDavid du Colombier 				ctlr->name, vga->f[0]);
18359cc4ca5SDavid du Colombier 		if(vga->f[0] > 135000000 && (ctlr->flag & Hclk2)){
18459cc4ca5SDavid du Colombier 			if(mode->x%16)
18559cc4ca5SDavid du Colombier 				error("%s: f > 135MHz requires (x%%16) == 0\n",
18659cc4ca5SDavid du Colombier 					ctlr->name);
18759cc4ca5SDavid du Colombier 			ctlr->flag |= Uclk2;
18859cc4ca5SDavid du Colombier 		}
18959cc4ca5SDavid du Colombier 		tdfxclock(vga, ctlr);
19059cc4ca5SDavid du Colombier 
19159cc4ca5SDavid du Colombier 		tdfx->r[pllCtrl0] = (vga->n[0]<<8)|(vga->m[0]<<2)|vga->p[0];
19259cc4ca5SDavid du Colombier 		vga->misc |= 0x0C;
19359cc4ca5SDavid du Colombier 	}
19459cc4ca5SDavid du Colombier 
19559cc4ca5SDavid du Colombier 	/*
19659cc4ca5SDavid du Colombier 	 * Pixel format and memory stride.
19759cc4ca5SDavid du Colombier 	 */
19859cc4ca5SDavid du Colombier 	tdfx->r[vidScreenSize] = (mode->y<<12)|mode->x;
19959cc4ca5SDavid du Colombier 	tdfx->r[vidProcCfg] = 0x00000081;
20059cc4ca5SDavid du Colombier 	switch(mode->z){
20159cc4ca5SDavid du Colombier 	default:
20259cc4ca5SDavid du Colombier 		error("%s: %d-bit mode not supported\n", ctlr->name, mode->z);
20359cc4ca5SDavid du Colombier 		break;
20459cc4ca5SDavid du Colombier 	case 8:
20559cc4ca5SDavid du Colombier 		tdfx->r[vidDesktopOverlayStride] = mode->x;
20659cc4ca5SDavid du Colombier 		break;
20759cc4ca5SDavid du Colombier 	case 16:
20859cc4ca5SDavid du Colombier 		tdfx->r[vidDesktopOverlayStride] = mode->x*2;
20959cc4ca5SDavid du Colombier 		tdfx->r[vidProcCfg] |= 0x00040400;
21059cc4ca5SDavid du Colombier 		break;
21159cc4ca5SDavid du Colombier 	case 32:
21259cc4ca5SDavid du Colombier 		tdfx->r[vidDesktopOverlayStride] = mode->x*4;
21359cc4ca5SDavid du Colombier 		tdfx->r[vidProcCfg] |= 0x000C0400;
21459cc4ca5SDavid du Colombier 		break;
21559cc4ca5SDavid du Colombier 	}
21659cc4ca5SDavid du Colombier 	tdfx->r[vgaInit0] = 0x140;
21759cc4ca5SDavid du Colombier 
21859cc4ca5SDavid du Colombier 	/*
21959cc4ca5SDavid du Colombier 	 * Adjust horizontal timing if doing two screen pixels per clock.
22059cc4ca5SDavid du Colombier 	 */
22159cc4ca5SDavid du Colombier 	tdfx->r[dacMode] = 0;
22259cc4ca5SDavid du Colombier 	if(ctlr->flag & Uclk2){
22359cc4ca5SDavid du Colombier 		vga->crt[0x00] = ((mode->ht/2)>>3)-5;
22459cc4ca5SDavid du Colombier 		vga->crt[0x01] = ((mode->x/2)>>3)-1;
22559cc4ca5SDavid du Colombier 		vga->crt[0x02] = ((mode->shb/2)>>3)-1;
22659cc4ca5SDavid du Colombier 
22759cc4ca5SDavid du Colombier 		x = (mode->ehb/2)>>3;
22859cc4ca5SDavid du Colombier 		vga->crt[0x03] = 0x80|(x & 0x1F);
22959cc4ca5SDavid du Colombier 		vga->crt[0x04] = (mode->shs/2)>>3;
23059cc4ca5SDavid du Colombier 		vga->crt[0x05] = ((mode->ehs/2)>>3) & 0x1F;
23159cc4ca5SDavid du Colombier 		if(x & 0x20)
23259cc4ca5SDavid du Colombier 			vga->crt[0x05] |= 0x80;
23359cc4ca5SDavid du Colombier 
23459cc4ca5SDavid du Colombier 		tdfx->r[dacMode] |= 0x01;
23559cc4ca5SDavid du Colombier 		tdfx->r[vidProcCfg] |= 0x04000000;
23659cc4ca5SDavid du Colombier 	}
23759cc4ca5SDavid du Colombier 
23859cc4ca5SDavid du Colombier 	/*
23959cc4ca5SDavid du Colombier 	 * Overflow.
24059cc4ca5SDavid du Colombier 	 */
24159cc4ca5SDavid du Colombier 	vga->crt[0x1A] = 0x00;
24259cc4ca5SDavid du Colombier 	if(vga->crt[0x00] & 0x100)
24359cc4ca5SDavid du Colombier 		vga->crt[0x1A] |= 0x01;
24459cc4ca5SDavid du Colombier 	if(vga->crt[0x01] & 0x100)
24559cc4ca5SDavid du Colombier 		vga->crt[0x1A] |= 0x04;
24659cc4ca5SDavid du Colombier 	if(vga->crt[0x03] & 0x100)
24759cc4ca5SDavid du Colombier 		vga->crt[0x1A] |= 0x10;
24859cc4ca5SDavid du Colombier 	x = mode->ehb;
24959cc4ca5SDavid du Colombier 	if(ctlr->flag & Uclk2)
25059cc4ca5SDavid du Colombier 		x /= 2;
25159cc4ca5SDavid du Colombier 	if((x>>3) & 0x40)
25259cc4ca5SDavid du Colombier 		vga->crt[0x1A] |= 0x20;
25359cc4ca5SDavid du Colombier 	if(vga->crt[0x04] & 0x100)
25459cc4ca5SDavid du Colombier 		vga->crt[0x1A] |= 0x40;
25559cc4ca5SDavid du Colombier 	x = mode->ehs;
25659cc4ca5SDavid du Colombier 	if(ctlr->flag & Uclk2)
25759cc4ca5SDavid du Colombier 		x /= 2;
25859cc4ca5SDavid du Colombier 	if((x>>3) & 0x20)
25959cc4ca5SDavid du Colombier 		vga->crt[0x1A] |= 0x80;
26059cc4ca5SDavid du Colombier 
26159cc4ca5SDavid du Colombier 	vga->crt[0x1B] = 0x00;
26259cc4ca5SDavid du Colombier 	if(vga->crt[0x06] & 0x400)
26359cc4ca5SDavid du Colombier 		vga->crt[0x1B] |= 0x01;
26459cc4ca5SDavid du Colombier 	if(vga->crt[0x12] & 0x400)
26559cc4ca5SDavid du Colombier 		vga->crt[0x1B] |= 0x04;
26659cc4ca5SDavid du Colombier 	if(vga->crt[0x15] & 0x400)
26759cc4ca5SDavid du Colombier 		vga->crt[0x1B] |= 0x10;
26859cc4ca5SDavid du Colombier 	if(vga->crt[0x10] & 0x400)
26959cc4ca5SDavid du Colombier 		vga->crt[0x1B] |= 0x40;
27059cc4ca5SDavid du Colombier 
27159cc4ca5SDavid du Colombier 	vga->attribute[0x11] = Pblack;
27259cc4ca5SDavid du Colombier 
27359cc4ca5SDavid du Colombier 	ctlr->flag |= Finit;
27459cc4ca5SDavid du Colombier }
27559cc4ca5SDavid du Colombier 
27659cc4ca5SDavid du Colombier static void
load(Vga * vga,Ctlr * ctlr)27759cc4ca5SDavid du Colombier load(Vga* vga, Ctlr* ctlr)
27859cc4ca5SDavid du Colombier {
27959cc4ca5SDavid du Colombier 	Tdfx *tdfx;
28059cc4ca5SDavid du Colombier 
28159cc4ca5SDavid du Colombier 	vgaxo(Crtx, 0x1A, vga->crt[0x1A]);
28259cc4ca5SDavid du Colombier 	vgaxo(Crtx, 0x1B, vga->crt[0x1B]);
28359cc4ca5SDavid du Colombier 
28459cc4ca5SDavid du Colombier 	tdfx = vga->private;
28559cc4ca5SDavid du Colombier 	io32w(tdfx, dacMode, tdfx->r[dacMode]);
28659cc4ca5SDavid du Colombier 	io32w(tdfx, vidScreenSize, tdfx->r[vidScreenSize]);
28759cc4ca5SDavid du Colombier 	io32w(tdfx, vidDesktopOverlayStride, tdfx->r[vidDesktopOverlayStride]);
28859cc4ca5SDavid du Colombier 	io32w(tdfx, vidProcCfg, tdfx->r[vidProcCfg]);
28959cc4ca5SDavid du Colombier 	io32w(tdfx, vgaInit0, tdfx->r[vgaInit0]);
29059cc4ca5SDavid du Colombier 
29159cc4ca5SDavid du Colombier 	if((vga->misc & 0x0C) == 0x0C)
29259cc4ca5SDavid du Colombier 		io32w(tdfx, pllCtrl0, tdfx->r[pllCtrl0]);
29359cc4ca5SDavid du Colombier 
29459cc4ca5SDavid du Colombier 	ctlr->flag |= Fload;
29559cc4ca5SDavid du Colombier }
29659cc4ca5SDavid du Colombier 
29759cc4ca5SDavid du Colombier static uint
pllctrl(Tdfx * tdfx,int pll)29859cc4ca5SDavid du Colombier pllctrl(Tdfx* tdfx, int pll)
29959cc4ca5SDavid du Colombier {
30059cc4ca5SDavid du Colombier 	uint k, m, n, r;
30159cc4ca5SDavid du Colombier 
30259cc4ca5SDavid du Colombier 	r = tdfx->r[pllCtrl0+pll];
30359cc4ca5SDavid du Colombier 	k = r & 0x03;
30459cc4ca5SDavid du Colombier 	m = (r>>2) & 0x3F;
30559cc4ca5SDavid du Colombier 	n = (r>>8) & 0xFF;
30659cc4ca5SDavid du Colombier 
30759cc4ca5SDavid du Colombier 	return (RefFreq*(n+2))/((m+2)*(1<<k));
30859cc4ca5SDavid du Colombier }
30959cc4ca5SDavid du Colombier 
31059cc4ca5SDavid du Colombier static void
dump(Vga * vga,Ctlr * ctlr)31159cc4ca5SDavid du Colombier dump(Vga* vga, Ctlr* ctlr)
31259cc4ca5SDavid du Colombier {
31359cc4ca5SDavid du Colombier 	int i;
31459cc4ca5SDavid du Colombier 	Tdfx *tdfx;
31559cc4ca5SDavid du Colombier 
31659cc4ca5SDavid du Colombier 	if((tdfx = vga->private) == nil)
31759cc4ca5SDavid du Colombier 		return;
31859cc4ca5SDavid du Colombier 
31959cc4ca5SDavid du Colombier 	printitem(ctlr->name, "Crt1A");
32059cc4ca5SDavid du Colombier 	printreg(vga->crt[0x1A]);
32159cc4ca5SDavid du Colombier 	printreg(vga->crt[0x1B]);
32259cc4ca5SDavid du Colombier 
32359cc4ca5SDavid du Colombier 	Bprint(&stdout, "\n");
32459cc4ca5SDavid du Colombier 	for(i = 0; i < Nior; i++)
32559cc4ca5SDavid du Colombier 		Bprint(&stdout, "%s %2.2uX\t%.8luX\n",
32659cc4ca5SDavid du Colombier 			ctlr->name, i*4, tdfx->r[i]);
32759cc4ca5SDavid du Colombier 
32859cc4ca5SDavid du Colombier 	printitem(ctlr->name, "pllCtrl");
32959cc4ca5SDavid du Colombier 	Bprint(&stdout, "%9ud %8ud\n", pllctrl(tdfx, 0), pllctrl(tdfx, 1));
33059cc4ca5SDavid du Colombier }
33159cc4ca5SDavid du Colombier 
33259cc4ca5SDavid du Colombier Ctlr tdfx = {
33359cc4ca5SDavid du Colombier 	"3dfx",				/* name */
33459cc4ca5SDavid du Colombier 	snarf,				/* snarf */
33559cc4ca5SDavid du Colombier 	options,			/* options */
33659cc4ca5SDavid du Colombier 	init,				/* init */
33759cc4ca5SDavid du Colombier 	load,				/* load */
33859cc4ca5SDavid du Colombier 	dump,				/* dump */
33959cc4ca5SDavid du Colombier };
34059cc4ca5SDavid du Colombier 
34159cc4ca5SDavid du Colombier Ctlr tdfxhwgc = {
34259cc4ca5SDavid du Colombier 	"3dfxhwgc",			/* name */
34359cc4ca5SDavid du Colombier 	0,				/* snarf */
34459cc4ca5SDavid du Colombier 	0,				/* options */
34559cc4ca5SDavid du Colombier 	0,				/* init */
34659cc4ca5SDavid du Colombier 	0,				/* load */
34759cc4ca5SDavid du Colombier 	0,				/* dump */
34859cc4ca5SDavid du Colombier };
349