xref: /plan9/sys/src/9/pc/vga3dfx.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
159cc4ca5SDavid du Colombier #include "u.h"
259cc4ca5SDavid du Colombier #include "../port/lib.h"
359cc4ca5SDavid du Colombier #include "mem.h"
459cc4ca5SDavid du Colombier #include "dat.h"
559cc4ca5SDavid du Colombier #include "fns.h"
659cc4ca5SDavid du Colombier #include "io.h"
759cc4ca5SDavid du Colombier #include "../port/error.h"
859cc4ca5SDavid du Colombier 
959cc4ca5SDavid du Colombier #define	Image	IMAGE
1059cc4ca5SDavid du Colombier #include <draw.h>
1159cc4ca5SDavid du Colombier #include <memdraw.h>
1259cc4ca5SDavid du Colombier #include <cursor.h>
1359cc4ca5SDavid du Colombier #include "screen.h"
1459cc4ca5SDavid du Colombier 
1559c21d95SDavid du Colombier typedef struct Cursor3dfx Cursor3dfx;
1659c21d95SDavid du Colombier struct Cursor3dfx {
1759cc4ca5SDavid du Colombier 	int	vidProcCfg;
1859cc4ca5SDavid du Colombier 	int	hwCurPatAddr;
1959cc4ca5SDavid du Colombier 	int	hwCurLoc;
2059cc4ca5SDavid du Colombier 	int	hwCurC0;
2159cc4ca5SDavid du Colombier 	int	hwCurC1;
2259c21d95SDavid du Colombier };
2359cc4ca5SDavid du Colombier 
2459cc4ca5SDavid du Colombier enum {
2559cc4ca5SDavid du Colombier 	dramInit0	= 0x18,
2659cc4ca5SDavid du Colombier 	dramInit1	= 0x1C,
2759cc4ca5SDavid du Colombier 
2859cc4ca5SDavid du Colombier 	hwCur		= 0x5C,
2959cc4ca5SDavid du Colombier };
3059cc4ca5SDavid du Colombier 
3159cc4ca5SDavid du Colombier static void
tdfxenable(VGAscr * scr)3259cc4ca5SDavid du Colombier tdfxenable(VGAscr* scr)
3359cc4ca5SDavid du Colombier {
3459cc4ca5SDavid du Colombier 	Pcidev *p;
35*4de34a7eSDavid du Colombier 	int i, *mmio;
3659cc4ca5SDavid du Colombier 
37*4de34a7eSDavid du Colombier 	if(scr->mmio)
3859cc4ca5SDavid du Colombier 		return;
3959cc4ca5SDavid du Colombier 	if(p = pcimatch(nil, 0x121A, 0)){
4059cc4ca5SDavid du Colombier 		switch(p->did){
4180ee5cbfSDavid du Colombier 		case 0x0003:		/* Banshee */
4259cc4ca5SDavid du Colombier 		case 0x0005:		/* Avenger (a.k.a. Voodoo3) */
4359cc4ca5SDavid du Colombier 			break;
4459cc4ca5SDavid du Colombier 		default:
4559cc4ca5SDavid du Colombier 			return;
4659cc4ca5SDavid du Colombier 		}
4759cc4ca5SDavid du Colombier 	}
4859cc4ca5SDavid du Colombier 	else
4959cc4ca5SDavid du Colombier 		return;
50*4de34a7eSDavid du Colombier 
51*4de34a7eSDavid du Colombier 	scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
52*4de34a7eSDavid du Colombier 	if(scr->mmio == nil)
5359cc4ca5SDavid du Colombier 		return;
54*4de34a7eSDavid du Colombier 	scr->pci = p;
5559cc4ca5SDavid du Colombier 
56*4de34a7eSDavid du Colombier 	addvgaseg("3dfxmmio", p->mem[0].bar&~0x0F, p->mem[0].size);
57*4de34a7eSDavid du Colombier 	vgalinearpci(scr);
58*4de34a7eSDavid du Colombier 	if(scr->apsize)
59*4de34a7eSDavid du Colombier 		addvgaseg("3dfxscreen", scr->paddr, scr->apsize);
6059cc4ca5SDavid du Colombier 
6159cc4ca5SDavid du Colombier 	/*
6259cc4ca5SDavid du Colombier 	 * Find a place for the cursor data in display memory.
6359cc4ca5SDavid du Colombier 	 * If SDRAM then there's 16MB memory else it's SGRAM
6459cc4ca5SDavid du Colombier 	 * and can count it based on the power-on straps -
6559cc4ca5SDavid du Colombier 	 * chip size can be 8Mb or 16Mb, and there can be 4 or
6659cc4ca5SDavid du Colombier 	 * 8 of them.
6759cc4ca5SDavid du Colombier 	 * Use the last 1KB of the framebuffer.
6859cc4ca5SDavid du Colombier 	 */
69*4de34a7eSDavid du Colombier 	mmio = (void*)((uchar*)scr->mmio+dramInit0);
7059cc4ca5SDavid du Colombier 	if(*(mmio+1) & 0x40000000)
7159cc4ca5SDavid du Colombier 		i = 16*1024*1024;
7259cc4ca5SDavid du Colombier 	else{
7359cc4ca5SDavid du Colombier 		if(*mmio & 0x08000000)
7459cc4ca5SDavid du Colombier 			i = 16*1024*1024/8;
7559cc4ca5SDavid du Colombier 		else
7659cc4ca5SDavid du Colombier 			i = 8*1024*1024/8;
7759cc4ca5SDavid du Colombier 		if(*mmio & 0x04000000)
7859cc4ca5SDavid du Colombier 			i *= 8;
7959cc4ca5SDavid du Colombier 		else
8059cc4ca5SDavid du Colombier 			i *= 4;
8159cc4ca5SDavid du Colombier 	}
8259cc4ca5SDavid du Colombier 	scr->storage = i - 1024;
8359cc4ca5SDavid du Colombier }
8459cc4ca5SDavid du Colombier 
8559cc4ca5SDavid du Colombier static void
tdfxcurdisable(VGAscr * scr)8659cc4ca5SDavid du Colombier tdfxcurdisable(VGAscr* scr)
8759cc4ca5SDavid du Colombier {
8859cc4ca5SDavid du Colombier 	Cursor3dfx *cursor3dfx;
8959cc4ca5SDavid du Colombier 
90*4de34a7eSDavid du Colombier 	if(scr->mmio == 0)
9159cc4ca5SDavid du Colombier 		return;
92*4de34a7eSDavid du Colombier 	cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
9359cc4ca5SDavid du Colombier 	cursor3dfx->vidProcCfg &= ~0x08000000;
9459cc4ca5SDavid du Colombier }
9559cc4ca5SDavid du Colombier 
9659cc4ca5SDavid du Colombier static void
tdfxcurload(VGAscr * scr,Cursor * curs)9759cc4ca5SDavid du Colombier tdfxcurload(VGAscr* scr, Cursor* curs)
9859cc4ca5SDavid du Colombier {
9959cc4ca5SDavid du Colombier 	int y;
10059cc4ca5SDavid du Colombier 	uchar *p;
10159cc4ca5SDavid du Colombier 	Cursor3dfx *cursor3dfx;
10259cc4ca5SDavid du Colombier 
103*4de34a7eSDavid du Colombier 	if(scr->mmio == 0)
10459cc4ca5SDavid du Colombier 		return;
105*4de34a7eSDavid du Colombier 	cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
10659cc4ca5SDavid du Colombier 
10759cc4ca5SDavid du Colombier 	/*
10859cc4ca5SDavid du Colombier 	 * Disable the cursor then load the new image in
10959cc4ca5SDavid du Colombier 	 * the top-left of the 64x64 array.
11059cc4ca5SDavid du Colombier 	 * The cursor data is stored in memory as 128-bit
11159cc4ca5SDavid du Colombier 	 * words consisting of plane 0 in the least significant 64-bits
11259cc4ca5SDavid du Colombier 	 * and plane 1 in the most significant.
11359cc4ca5SDavid du Colombier 	 * The X11 cursor truth table is:
11459cc4ca5SDavid du Colombier 	 *	p0 p1	colour
11559cc4ca5SDavid du Colombier 	 *	 0  0	transparent
11659cc4ca5SDavid du Colombier 	 *	 0  1	transparent
11759cc4ca5SDavid du Colombier 	 *	 1  0	hwCurC0
11859cc4ca5SDavid du Colombier 	 *	 1  1	hwCurC1
11959cc4ca5SDavid du Colombier 	 * Unused portions of the image have been initialised to be
12059cc4ca5SDavid du Colombier 	 * transparent.
12159cc4ca5SDavid du Colombier 	 */
12259cc4ca5SDavid du Colombier 	cursor3dfx->vidProcCfg &= ~0x08000000;
123*4de34a7eSDavid du Colombier 	p = (uchar*)scr->vaddr + scr->storage;
12459cc4ca5SDavid du Colombier 	for(y = 0; y < 16; y++){
12559cc4ca5SDavid du Colombier 		*p++ = curs->clr[2*y]|curs->set[2*y];
12659cc4ca5SDavid du Colombier 		*p++ = curs->clr[2*y+1]|curs->set[2*y+1];
12759cc4ca5SDavid du Colombier 		p += 6;
12859cc4ca5SDavid du Colombier 		*p++ = curs->set[2*y];
12959cc4ca5SDavid du Colombier 		*p++ = curs->set[2*y+1];
13059cc4ca5SDavid du Colombier 		p += 6;
13159cc4ca5SDavid du Colombier 	}
13259cc4ca5SDavid du Colombier 
13359cc4ca5SDavid du Colombier 	/*
13459cc4ca5SDavid du Colombier 	 * Save the cursor hotpoint and enable the cursor.
13559cc4ca5SDavid du Colombier 	 * The 0,0 cursor point is bottom-right.
13659cc4ca5SDavid du Colombier 	 */
13759cc4ca5SDavid du Colombier 	scr->offset.x = 63+curs->offset.x;
13859cc4ca5SDavid du Colombier 	scr->offset.y = 63+curs->offset.y;
13959cc4ca5SDavid du Colombier 	cursor3dfx->vidProcCfg |= 0x08000000;
14059cc4ca5SDavid du Colombier }
14159cc4ca5SDavid du Colombier 
14259cc4ca5SDavid du Colombier static int
tdfxcurmove(VGAscr * scr,Point p)14359cc4ca5SDavid du Colombier tdfxcurmove(VGAscr* scr, Point p)
14459cc4ca5SDavid du Colombier {
14559cc4ca5SDavid du Colombier 	Cursor3dfx *cursor3dfx;
14659cc4ca5SDavid du Colombier 
147*4de34a7eSDavid du Colombier 	if(scr->mmio == 0)
14859cc4ca5SDavid du Colombier 		return 1;
149*4de34a7eSDavid du Colombier 	cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
15059cc4ca5SDavid du Colombier 
15159cc4ca5SDavid du Colombier 	cursor3dfx->hwCurLoc = ((p.y+scr->offset.y)<<16)|(p.x+scr->offset.x);
15259cc4ca5SDavid du Colombier 
15359cc4ca5SDavid du Colombier 	return 0;
15459cc4ca5SDavid du Colombier }
15559cc4ca5SDavid du Colombier 
15659cc4ca5SDavid du Colombier static void
tdfxcurenable(VGAscr * scr)15759cc4ca5SDavid du Colombier tdfxcurenable(VGAscr* scr)
15859cc4ca5SDavid du Colombier {
15959cc4ca5SDavid du Colombier 	Cursor3dfx *cursor3dfx;
16059cc4ca5SDavid du Colombier 
16159cc4ca5SDavid du Colombier 	tdfxenable(scr);
162*4de34a7eSDavid du Colombier 	if(scr->mmio == 0)
16359cc4ca5SDavid du Colombier 		return;
164*4de34a7eSDavid du Colombier 	cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
16559cc4ca5SDavid du Colombier 
16659cc4ca5SDavid du Colombier 	/*
16759cc4ca5SDavid du Colombier 	 * Cursor colours.
16859cc4ca5SDavid du Colombier 	 */
16959cc4ca5SDavid du Colombier 	cursor3dfx->hwCurC0 = 0xFFFFFFFF;
17059cc4ca5SDavid du Colombier 	cursor3dfx->hwCurC1 = 0x00000000;
17159cc4ca5SDavid du Colombier 
17259cc4ca5SDavid du Colombier 	/*
17359cc4ca5SDavid du Colombier 	 * Initialise the 64x64 cursor to be transparent (X11 mode).
17459cc4ca5SDavid du Colombier 	 */
17559cc4ca5SDavid du Colombier 	cursor3dfx->hwCurPatAddr = scr->storage;
176*4de34a7eSDavid du Colombier 	memset((uchar*)scr->vaddr + scr->storage, 0, 64*16);
17759cc4ca5SDavid du Colombier 
17859cc4ca5SDavid du Colombier 	/*
17959cc4ca5SDavid du Colombier 	 * Load, locate and enable the 64x64 cursor in X11 mode.
18059cc4ca5SDavid du Colombier 	 */
18159cc4ca5SDavid du Colombier 	tdfxcurload(scr, &arrow);
18259cc4ca5SDavid du Colombier 	tdfxcurmove(scr, ZP);
18359cc4ca5SDavid du Colombier 	cursor3dfx->vidProcCfg |= 0x08000002;
18459cc4ca5SDavid du Colombier }
18559cc4ca5SDavid du Colombier 
18659cc4ca5SDavid du Colombier VGAdev vga3dfxdev = {
18759cc4ca5SDavid du Colombier 	"3dfx",
18859cc4ca5SDavid du Colombier 
18959cc4ca5SDavid du Colombier 	tdfxenable,
19059cc4ca5SDavid du Colombier 	nil,
19159cc4ca5SDavid du Colombier 	nil,
192*4de34a7eSDavid du Colombier 	nil,
19359cc4ca5SDavid du Colombier };
19459cc4ca5SDavid du Colombier 
19559cc4ca5SDavid du Colombier VGAcur vga3dfxcur = {
19659cc4ca5SDavid du Colombier 	"3dfxhwgc",
19759cc4ca5SDavid du Colombier 
19859cc4ca5SDavid du Colombier 	tdfxcurenable,
19959cc4ca5SDavid du Colombier 	tdfxcurdisable,
20059cc4ca5SDavid du Colombier 	tdfxcurload,
20159cc4ca5SDavid du Colombier 	tdfxcurmove,
20259cc4ca5SDavid du Colombier };
203