xref: /plan9/sys/src/cmd/aux/vga/et4000.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 
5 #include "pci.h"
6 #include "vga.h"
7 
8 /*
9  * Tseng Labs Inc. ET4000 Video Controller.
10  */
11 enum {
12 	Crtcbx		= 0x217A,	/* Secondary CRT controller */
13 
14 	Sprite		= 0xE0,
15 	NSprite		= 0x10,
16 
17 	Ima		= 0xF0,
18 	NIma		= 0x08,
19 };
20 
21 static void
setkey(void)22 setkey(void)
23 {
24 	outportb(0x3BF, 0x03);
25 	outportb(0x3D8, 0xA0);
26 	outportb(0x3CD, 0x00);
27 }
28 
29 static void
snarf(Vga * vga,Ctlr * ctlr)30 snarf(Vga* vga, Ctlr* ctlr)
31 {
32 	int i;
33 
34 	setkey();
35 
36 	vga->sequencer[0x06] = vgaxi(Seqx, 0x06);
37 	vga->sequencer[0x07] = vgaxi(Seqx, 0x07);
38 
39 	for(i = 0x30; i < 0x38; i++)
40 		vga->crt[i] = vgaxi(Crtx, i);
41 	vga->crt[0x3F] = vgaxi(Crtx, 0x3F);
42 
43 	vga->attribute[0x16] = vgaxi(Attrx, 0x16);
44 	vga->attribute[0x17] = vgaxi(Attrx, 0x17);
45 
46 	/*
47 	 * Memory size.
48 	 */
49 	switch(vga->crt[0x37] & 0x03){
50 
51 	case 1:
52 		vga->vmz = 256*1024;
53 		break;
54 
55 	case 2:
56 		vga->vmz = 512*1024;
57 		break;
58 
59 	case 3:
60 		vga->vmz = 1024*1024;
61 		break;
62 	}
63 	if(strncmp(ctlr->name, "et4000-w32", 10) == 0){
64 		if(vga->crt[0x32] & 0x80)
65 			vga->vmz *= 2;
66 	}
67 	else if(vga->crt[0x37] & 0x80)
68 		vga->vmz *= 2;
69 
70 	ctlr->flag |= Fsnarf;
71 }
72 
73 static void
options(Vga * vga,Ctlr * ctlr)74 options(Vga* vga, Ctlr* ctlr)
75 {
76 	/*
77 	 * The ET4000 does not need to have the vertical
78 	 * timing values divided by 2 for interlace mode.
79 	 */
80 	if(vga->mode->interlace == 'v')
81 		vga->mode->interlace = 'V';
82 
83 	if(strncmp(ctlr->name, "et4000-w32", 10) == 0)
84 		ctlr->flag |= Hpclk2x8;
85 
86 	ctlr->flag |= Hclkdiv|Foptions;
87 }
88 
89 static void
init(Vga * vga,Ctlr * ctlr)90 init(Vga* vga, Ctlr* ctlr)
91 {
92 	Mode *mode;
93 	ulong x;
94 
95 	if(vga->mode->z > 8)
96 		error("depth %d not supported\n", vga->mode->z);
97 
98 	if(ctlr->flag & Upclk2x8){
99 		mode = vga->mode;
100 		vga->crt[0x00] = ((mode->ht/2)>>3)-5;
101 		vga->crt[0x01] = ((mode->x/2)>>3)-1;
102 		vga->crt[0x02] = ((mode->shb/2)>>3)-1;
103 
104 		x = (mode->ehb/2)>>3;
105 		vga->crt[0x03] = 0x80|(x & 0x1F);
106 		vga->crt[0x04] = (mode->shs/2)>>3;
107 		vga->crt[0x05] = ((mode->ehs/2)>>3) & 0x1F;
108 		if(x & 0x20)
109 			vga->crt[0x05] |= 0x80;
110 	}
111 	/*
112 	 * Itth a mythtawee.
113 	 */
114 	if(vga->crt[0x14] & 0x20)
115 		vga->crt[0x17] |= 0x08;
116 	vga->crt[0x17] &= ~0x20;
117 
118 	vga->crt[0x30] = 0x00;
119 	vga->crt[0x33] = 0x00;
120 
121 	/*
122 	 * Overflow High.
123 	 */
124 	vga->crt[0x35] = 0x00;
125 	if(vga->crt[0x15] & 0x400)
126 		vga->crt[0x35] |= 0x01;
127 	if(vga->crt[0x06] & 0x400)
128 		vga->crt[0x35] |= 0x02;
129 	if(vga->crt[0x12] & 0x400)
130 		vga->crt[0x35] |= 0x04;
131 	if(vga->crt[0x10] & 0x400)
132 		vga->crt[0x35] |= 0x08;
133 	if(vga->crt[0x18] & 0x400)
134 		vga->crt[0x35] |= 0x10;
135 	if(vga->mode->interlace == 'V')
136 		vga->crt[0x35] |= 0x80;
137 
138 	/*
139 	 * Horizontal Overflow.
140 	 */
141 	vga->crt[0x3F] = 0x00;
142 	if(vga->crt[0x00] & 0x100)
143 		vga->crt[0x3F] |= 0x01;
144 	if(vga->crt[0x02] & 0x100)
145 		vga->crt[0x3F] |= 0x04;
146 	if(vga->crt[0x04] & 0x100)
147 		vga->crt[0x3F] |= 0x10;
148 	if(vga->crt[0x13] & 0x100)
149 		vga->crt[0x3F] |= 0x80;
150 
151 	/*
152 	 * Turn off MMU buffers, linear map
153 	 * and memory-mapped registers.
154 	 */
155 	vga->crt[0x36] &= ~0x38;
156 
157 	if(strncmp(ctlr->name, "et4000-w32", 10) == 0)
158 		vga->crt[0x37] |= 0x80;
159 
160 	vga->sequencer[0x06] = 0x00;
161 
162 	/*
163 	 * Clock select.
164 	 */
165 	if(vga->f[0] > 86000000)
166 		error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
167 	vga->misc &= ~0x0C;
168 	vga->misc |= (vga->i[0] & 0x03)<<2;
169 	if(vga->i[0] & 0x04)
170 		vga->crt[0x34] |= 0x02;
171 	else
172 		vga->crt[0x34] &= ~0x02;
173 	vga->crt[0x31] &= ~0xC0;
174 	vga->crt[0x31] |= (vga->i[0] & 0x18)<<3;
175 
176 	vga->sequencer[0x07] &= ~0x41;
177 	if(vga->d[0] == 4)
178 		vga->sequencer[0x07] |= 0x01;
179 	else if(vga->d[0] == 2)
180 		vga->sequencer[0x07] |= 0x40;
181 
182 	vga->attribute[0x10] &= ~0x40;
183 	vga->attribute[0x11] = Pblack;
184 	vga->attribute[0x16] = 0x80;
185 
186 	if(ctlr->flag & Upclk2x8)
187 		vga->attribute[0x16] |= 0x20;
188 
189 	ctlr->flag |= Finit;
190 }
191 
192 static void
load(Vga * vga,Ctlr * ctlr)193 load(Vga* vga, Ctlr* ctlr)
194 {
195 	vgaxo(Crtx, 0x30, vga->crt[0x30]);
196 	vgaxo(Crtx, 0x31, vga->crt[0x31]);
197 	vgaxo(Crtx, 0x33, vga->crt[0x33]);
198 	vgaxo(Crtx, 0x34, vga->crt[0x34]);
199 	vgaxo(Crtx, 0x35, vga->crt[0x35]);
200 	vgaxo(Crtx, 0x36, vga->crt[0x36]);
201 	vgaxo(Crtx, 0x37, vga->crt[0x37]);
202 	vgaxo(Crtx, 0x3F, vga->crt[0x3F]);
203 
204 	vgaxo(Seqx, 0x06, vga->sequencer[0x06]);
205 	vgaxo(Seqx, 0x07, vga->sequencer[0x07]);
206 
207 	vgaxo(Attrx, 0x16, vga->attribute[0x16]);
208 
209 	ctlr->flag |= Fload;
210 }
211 
212 static void
dump(Vga * vga,Ctlr * ctlr)213 dump(Vga* vga, Ctlr* ctlr)
214 {
215 	int i;
216 	char *name;
217 	ushort shb, vrs, x;
218 
219 	name = ctlr->name;
220 
221 	printitem(name, "Seq06");
222 	printreg(vga->sequencer[0x06]);
223 	printreg(vga->sequencer[0x07]);
224 
225 	printitem(name, "Crt30");
226 	for(i = 0x30; i < 0x38; i++)
227 		printreg(vga->crt[i]);
228 	printitem(name, "Crt3F");
229 	printreg(vga->crt[0x3F]);
230 
231 	printitem(name, "Attr16");
232 	printreg(vga->attribute[0x16]);
233 	printreg(vga->attribute[0x17]);
234 
235 	if(strncmp(name, "et4000-w32", 10) == 0){
236 		printitem(name, "SpriteE0");
237 		for(i = Sprite; i < Sprite+NSprite; i++){
238 			outportb(Crtcbx, i);
239 			printreg(inportb(Crtcbx+1));
240 		}
241 		printitem(name, "ImaF0");
242 		for(i = Ima; i < Ima+NIma; i++){
243 			outportb(Crtcbx, i);
244 			printreg(inportb(Crtcbx+1));
245 		}
246 	}
247 
248 	/*
249 	 * Try to disassemble the snarfed values into
250 	 * understandable numbers.
251 	 * Only do this if we weren't called after Finit.
252 	 */
253 	if(ctlr->flag & Finit)
254 		return;
255 
256 	x = (vga->crt[0x01]+1)<<3;
257 	printitem(name, "hde");
258 	printreg(x);
259 	Bprint(&stdout, "%6ud", x);
260 
261 	shb = ((((vga->crt[0x3F] & 0x04)<<6)|vga->crt[0x02])+1)<<3;
262 	printitem(name, "shb");
263 	printreg(shb);
264 	Bprint(&stdout, "%6ud", shb);
265 
266 	x = (((vga->crt[0x05] & 0x80)>>2)|(vga->crt[0x03] & 0x1F))<<3;
267 	printitem(name, "ehb");
268 	printreg(x);
269 	for(i = 0; x < shb; i++)
270 		x |= 0x200<<i;
271 	Bprint(&stdout, "%6ud", x);
272 
273 	x = ((((vga->crt[0x3F] & 0x01)<<8)|vga->crt[0x00])+5)<<3;
274 	printitem(name, "ht");
275 	printreg(x);
276 	Bprint(&stdout, "%6ud", x);
277 
278 	x = vga->crt[0x12];
279 	if(vga->crt[0x07] & 0x02)
280 		x |= 0x100;
281 	if(vga->crt[0x07] & 0x40)
282 		x |= 0x200;
283 	if(vga->crt[0x35] & 0x04)
284 		x |= 0x400;
285 	x += 1;
286 	printitem(name, "vde");
287 	printreg(x);
288 	Bprint(&stdout, "%6ud", x);
289 
290 	vrs = vga->crt[0x10];
291 	if(vga->crt[0x07] & 0x04)
292 		vrs |= 0x100;
293 	if(vga->crt[0x07] & 0x80)
294 		vrs |= 0x200;
295 	if(vga->crt[0x35] & 0x08)
296 		vrs |= 0x400;
297 	printitem(name, "vrs");
298 	printreg(vrs);
299 	Bprint(&stdout, "%6ud", vrs);
300 
301 	x = (vrs & ~0x0F)|(vga->crt[0x11] & 0x0F);
302 	printitem(name, "vre");
303 	printreg(x);
304 	Bprint(&stdout, "%6ud", x);
305 
306 	x = vga->crt[0x06];
307 	if(vga->crt[0x07] & 0x01)
308 		x |= 0x100;
309 	if(vga->crt[0x07] & 0x20)
310 		x |= 0x200;
311 	if(vga->crt[0x35] & 0x02)
312 		x |= 0x400;
313 	x += 2;
314 	printitem(name, "vt");
315 	printreg(x);
316 	Bprint(&stdout, "%6ud", x);
317 
318 	printitem(name, "d i");
319 	if(vga->sequencer[0x07] & 0x01)
320 		x = 4;
321 	else if(vga->sequencer[0x07] & 0x40)
322 		x = 2;
323 	else
324 		x = 0;
325 	Bprint(&stdout, "%9ud", x);
326 	x = (vga->misc & 0x0C)>>2;
327 	if(vga->crt[0x34] & 0x02)
328 		x |= 0x04;
329 	x |= (vga->crt[0x31] & 0xC0)>>3;
330 	Bprint(&stdout, "%8ud\n", x);
331 }
332 
333 Ctlr et4000 = {
334 	"et4000",			/* name */
335 	snarf,				/* snarf */
336 	options,			/* options */
337 	init,				/* init */
338 	load,				/* load */
339 	dump,				/* dump */
340 };
341