xref: /plan9-contrib/sys/src/9/pc/vga3dfx.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "../port/error.h"
8 
9 #define	Image	IMAGE
10 #include <draw.h>
11 #include <memdraw.h>
12 #include <cursor.h>
13 #include "screen.h"
14 
15 typedef struct Cursor3dfx Cursor3dfx;
16 struct Cursor3dfx {
17 	int	vidProcCfg;
18 	int	hwCurPatAddr;
19 	int	hwCurLoc;
20 	int	hwCurC0;
21 	int	hwCurC1;
22 };
23 
24 enum {
25 	dramInit0	= 0x18,
26 	dramInit1	= 0x1C,
27 
28 	hwCur		= 0x5C,
29 };
30 
31 static void
tdfxenable(VGAscr * scr)32 tdfxenable(VGAscr* scr)
33 {
34 	Pcidev *p;
35 	int i, *mmio;
36 
37 	if(scr->mmio)
38 		return;
39 	if(p = pcimatch(nil, 0x121A, 0)){
40 		switch(p->did){
41 		case 0x0003:		/* Banshee */
42 		case 0x0005:		/* Avenger (a.k.a. Voodoo3) */
43 			break;
44 		default:
45 			return;
46 		}
47 	}
48 	else
49 		return;
50 
51 	scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
52 	if(scr->mmio == nil)
53 		return;
54 	scr->pci = p;
55 
56 	addvgaseg("3dfxmmio", p->mem[0].bar&~0x0F, p->mem[0].size);
57 	vgalinearpci(scr);
58 	if(scr->apsize)
59 		addvgaseg("3dfxscreen", scr->paddr, scr->apsize);
60 
61 	/*
62 	 * Find a place for the cursor data in display memory.
63 	 * If SDRAM then there's 16MB memory else it's SGRAM
64 	 * and can count it based on the power-on straps -
65 	 * chip size can be 8Mb or 16Mb, and there can be 4 or
66 	 * 8 of them.
67 	 * Use the last 1KB of the framebuffer.
68 	 */
69 	mmio = (void*)((uchar*)scr->mmio+dramInit0);
70 	if(*(mmio+1) & 0x40000000)
71 		i = 16*1024*1024;
72 	else{
73 		if(*mmio & 0x08000000)
74 			i = 16*1024*1024/8;
75 		else
76 			i = 8*1024*1024/8;
77 		if(*mmio & 0x04000000)
78 			i *= 8;
79 		else
80 			i *= 4;
81 	}
82 	scr->storage = i - 1024;
83 }
84 
85 static void
tdfxcurdisable(VGAscr * scr)86 tdfxcurdisable(VGAscr* scr)
87 {
88 	Cursor3dfx *cursor3dfx;
89 
90 	if(scr->mmio == 0)
91 		return;
92 	cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
93 	cursor3dfx->vidProcCfg &= ~0x08000000;
94 }
95 
96 static void
tdfxcurload(VGAscr * scr,Cursor * curs)97 tdfxcurload(VGAscr* scr, Cursor* curs)
98 {
99 	int y;
100 	uchar *p;
101 	Cursor3dfx *cursor3dfx;
102 
103 	if(scr->mmio == 0)
104 		return;
105 	cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
106 
107 	/*
108 	 * Disable the cursor then load the new image in
109 	 * the top-left of the 64x64 array.
110 	 * The cursor data is stored in memory as 128-bit
111 	 * words consisting of plane 0 in the least significant 64-bits
112 	 * and plane 1 in the most significant.
113 	 * The X11 cursor truth table is:
114 	 *	p0 p1	colour
115 	 *	 0  0	transparent
116 	 *	 0  1	transparent
117 	 *	 1  0	hwCurC0
118 	 *	 1  1	hwCurC1
119 	 * Unused portions of the image have been initialised to be
120 	 * transparent.
121 	 */
122 	cursor3dfx->vidProcCfg &= ~0x08000000;
123 	p = (uchar*)scr->vaddr + scr->storage;
124 	for(y = 0; y < 16; y++){
125 		*p++ = curs->clr[2*y]|curs->set[2*y];
126 		*p++ = curs->clr[2*y+1]|curs->set[2*y+1];
127 		p += 6;
128 		*p++ = curs->set[2*y];
129 		*p++ = curs->set[2*y+1];
130 		p += 6;
131 	}
132 
133 	/*
134 	 * Save the cursor hotpoint and enable the cursor.
135 	 * The 0,0 cursor point is bottom-right.
136 	 */
137 	scr->offset.x = 63+curs->offset.x;
138 	scr->offset.y = 63+curs->offset.y;
139 	cursor3dfx->vidProcCfg |= 0x08000000;
140 }
141 
142 static int
tdfxcurmove(VGAscr * scr,Point p)143 tdfxcurmove(VGAscr* scr, Point p)
144 {
145 	Cursor3dfx *cursor3dfx;
146 
147 	if(scr->mmio == 0)
148 		return 1;
149 	cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
150 
151 	cursor3dfx->hwCurLoc = ((p.y+scr->offset.y)<<16)|(p.x+scr->offset.x);
152 
153 	return 0;
154 }
155 
156 static void
tdfxcurenable(VGAscr * scr)157 tdfxcurenable(VGAscr* scr)
158 {
159 	Cursor3dfx *cursor3dfx;
160 
161 	tdfxenable(scr);
162 	if(scr->mmio == 0)
163 		return;
164 	cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
165 
166 	/*
167 	 * Cursor colours.
168 	 */
169 	cursor3dfx->hwCurC0 = 0xFFFFFFFF;
170 	cursor3dfx->hwCurC1 = 0x00000000;
171 
172 	/*
173 	 * Initialise the 64x64 cursor to be transparent (X11 mode).
174 	 */
175 	cursor3dfx->hwCurPatAddr = scr->storage;
176 	memset((uchar*)scr->vaddr + scr->storage, 0, 64*16);
177 
178 	/*
179 	 * Load, locate and enable the 64x64 cursor in X11 mode.
180 	 */
181 	tdfxcurload(scr, &arrow);
182 	tdfxcurmove(scr, ZP);
183 	cursor3dfx->vidProcCfg |= 0x08000002;
184 }
185 
186 VGAdev vga3dfxdev = {
187 	"3dfx",
188 
189 	tdfxenable,
190 	nil,
191 	nil,
192 	nil,
193 };
194 
195 VGAcur vga3dfxcur = {
196 	"3dfxhwgc",
197 
198 	tdfxcurenable,
199 	tdfxcurdisable,
200 	tdfxcurload,
201 	tdfxcurmove,
202 };
203