xref: /plan9-contrib/sys/src/cmd/aux/vga/s3generic.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 
4 #include "vga.h"
5 
6 /*
7  * Generic S3 GUI Accelerator.
8  */
9 static void
10 unlock(void)
11 {
12 	/*
13 	 * 0xA5 ensures Crt36 and Crt37 are also unlocked
14 	 * (0xA0 unlocks everything else).
15 	 */
16 	vgaxo(Crtx, 0x38, 0x48);
17 	vgaxo(Crtx, 0x39, 0xA5);
18 }
19 
20 static void
21 snarf(Vga *vga, Ctlr *ctlr)
22 {
23 	int i;
24 
25 	verbose("%s->snarf->s3generic\n", ctlr->name);
26 
27 	unlock();
28 	/*
29 	 * Not all registers exist on all chips.
30 	 * Crt3[EF] don't exist on any.
31 	 */
32 	for(i = 0x30; i < 0x70; i++)
33 		vga->crt[i] = vgaxi(Crtx, i);
34 
35 	/*
36 	 * Memory size.
37 	 */
38 	switch((vga->crt[0x36]>>5) & 0x07){
39 
40 	case 0x00:
41 		vga->vmb = 4*1024*1024;
42 		break;
43 
44 	case 0x02:
45 		vga->vmb = 3*1024*1024;
46 		break;
47 
48 	case 0x04:
49 		vga->vmb = 2*1024*1024;
50 		break;
51 
52 	case 0x06:
53 		vga->vmb = 1*1024*1024;
54 		break;
55 
56 	case 0x07:
57 		vga->vmb = 512*1024;
58 		break;
59 	}
60 
61 	ctlr->flag |= Fsnarf;
62 }
63 
64 static void
65 init(Vga *vga, Ctlr *ctlr)
66 {
67 	Mode *mode;
68 	ulong x;
69 
70 	verbose("%s->init->s3generic\n", ctlr->name);
71 	mode = vga->mode;
72 
73 	/*
74 	 * Do we need to use enhanced mode?
75 	 */
76 	if((ctlr->flag & (Uenhanced|Henhanced)) == Henhanced){
77 		if(mode->x >= 1024 && mode->z == 8)
78 			resyncinit(vga, ctlr, Uenhanced, 0);
79 		else
80 			resyncinit(vga, ctlr, 0, Uenhanced|Henhanced);
81 	}
82 
83 	vga->crt[0x31] = 0x85;
84 	vga->crt[0x32] &= ~0x40;
85 
86 	vga->crt[0x31] |= 0x08;
87 	vga->crt[0x32] |= 0x40;
88 
89 	vga->crt[0x33] |= 0x20;
90 	if(mode->z == 8)
91 		vga->crt[0x3A] |= 0x10;
92 	else
93 		vga->crt[0x3A] &= ~0x10;
94 
95 	vga->crt[0x34] = 0x10;
96 	vga->crt[0x35] = 0x00;
97 	if(mode->interlace){
98 		vga->crt[0x3C] = vga->crt[0]/2;
99 		vga->crt[0x42] |= 0x20;
100 	}
101 	else{
102 		vga->crt[0x3C] = 0x00;
103 		vga->crt[0x42] &= ~0x20;
104 	}
105 
106 	vga->crt[0x40] = (vga->crt[0x40] & 0xF2);
107 	vga->crt[0x43] = 0x00;
108 
109 	vga->crt[0x50] &= 0x3E;
110 	x = 0x00;
111 	if(mode->x <= 640)
112 		x = 0x40;
113 	else if(mode->x <= 800)
114 		x = 0x80;
115 	else if(mode->x <= 1024)
116 		x = 0x00;
117 	else if(mode->x <= 1152)
118 		x = 0x01;
119 	else if(mode->x <= 1280)
120 		x = 0xC0;
121 	else if(mode->x <= 1600)
122 		x = 0x81;
123 	vga->crt[0x50] |= x;
124 
125 	vga->crt[0x51] = (vga->crt[0x51] & 0xC3)|((vga->crt[0x13]>>4) & 0x30);
126 	vga->crt[0x53] &= ~0x10;
127 
128 	/*
129 	 * Set up linear aperture.
130 	 * For the moment it's 64K at 0xA0000.
131 	 */
132 	vga->crt[0x58] = 0x88;
133 	if(ctlr->flag & Uenhanced)
134 		vga->crt[0x58] |= 0x10;
135 	vga->crt[0x59] = 0x00;
136 	vga->crt[0x5A] = 0x0A;
137 
138 	vga->crt[0x5D] &= 0x80;
139 	if(vga->crt[0x00] & 0x100)
140 		vga->crt[0x5D] |= 0x01;
141 	if(vga->crt[0x01] & 0x100)
142 		vga->crt[0x5D] |= 0x02;
143 	if(vga->crt[0x02] & 0x100)
144 		vga->crt[0x5D] |= 0x04;
145 	if(vga->crt[0x04] & 0x100)
146 		vga->crt[0x5D] |= 0x10;
147 	if(vga->crt[0x3B] & 0x100)
148 		vga->crt[0x5D] |= 0x40;
149 
150 	vga->crt[0x5E] = 0x40;
151 	if(vga->crt[0x06] & 0x400)
152 		vga->crt[0x5E] |= 0x01;
153 	if(vga->crt[0x12] & 0x400)
154 		vga->crt[0x5E] |= 0x02;
155 	if(vga->crt[0x15] & 0x400)
156 		vga->crt[0x5E] |= 0x04;
157 	if(vga->crt[0x10] & 0x400)
158 		vga->crt[0x5E] |= 0x10;
159 
160 	ctlr->type = s3generic.name;
161 
162 	ctlr->flag |= Finit;
163 }
164 
165 static void
166 load(Vga *vga, Ctlr *ctlr)
167 {
168 	verbose("%s->load->s3generic\n", ctlr->name);
169 
170 	vgaxo(Crtx, 0x31, vga->crt[0x31]);
171 	vgaxo(Crtx, 0x32, vga->crt[0x32]);
172 	vgaxo(Crtx, 0x33, vga->crt[0x33]);
173 	vgaxo(Crtx, 0x34, vga->crt[0x34]);
174 	vgaxo(Crtx, 0x35, vga->crt[0x35]);
175 	vgaxo(Crtx, 0x3A, vga->crt[0x3A]);
176 	vgaxo(Crtx, 0x3B, vga->crt[0x3B]);
177 	vgaxo(Crtx, 0x3C, vga->crt[0x3C]);
178 
179 	vgaxo(Crtx, 0x40, vga->crt[0x40]|0x01);
180 	vgaxo(Crtx, 0x42, vga->crt[0x42]);
181 	vgaxo(Crtx, 0x43, vga->crt[0x43]);
182 	vgaxo(Crtx, 0x45, vga->crt[0x45]);
183 
184 	vgaxo(Crtx, 0x50, vga->crt[0x50]);
185 	vgaxo(Crtx, 0x51, vga->crt[0x51]);
186 	vgaxo(Crtx, 0x53, vga->crt[0x53]);
187 	vgaxo(Crtx, 0x54, vga->crt[0x54]);
188 	vgaxo(Crtx, 0x55, vga->crt[0x55]);
189 	vgaxo(Crtx, 0x59, vga->crt[0x59]);
190 	vgaxo(Crtx, 0x5A, vga->crt[0x5A]);
191 	vgaxo(Crtx, 0x58, vga->crt[0x58]);
192 	vgaxo(Crtx, 0x5D, vga->crt[0x5D]);
193 	vgaxo(Crtx, 0x5E, vga->crt[0x5E]);
194 
195 	ctlr->flag |= Fload;
196 }
197 
198 static void
199 dump(Vga *vga, Ctlr *ctlr)
200 {
201 	int i, interlace, mul;
202 	char *name;
203 	ushort shb, vrs, x;
204 
205 	name = ctlr->name;
206 
207 	printitem(name, "Crt30");
208 	for(i = 0x30; i < 0x3E; i++)
209 		printreg(vga->crt[i]);
210 
211 	printitem(name, "Crt40");
212 	for(i = 0x40; i < 0x50; i++)
213 		printreg(vga->crt[i]);
214 
215 	printitem(name, "Crt50");
216 	for(i = 0x50; i < 0x60; i++)
217 		printreg(vga->crt[i]);
218 
219 	printitem(name, "Crt60");
220 	for(i = 0x60; i < 0x70; i++)
221 		printreg(vga->crt[i]);
222 
223 	/*
224 	 * Try to disassemble the snarfed values into
225 	 * understandable numbers.
226 	 * Only do this if we weren't called after Finit.
227 	 */
228 	if(ctlr->flag & Finit)
229 		return;
230 
231 	/*
232 	 * If hde <= 400, assume this is a 928 or Vision964
233 	 * and the horozontal values have been divided by 4.
234 	 */
235 	mul = 1;
236 	x = vga->crt[0x01];
237 	if(vga->crt[0x5D] & 0x02)
238 		x |= 0x100;
239 	x = (x+1)<<3;
240 	if(x <= 400)
241 		mul = 4;
242 	x *= mul;
243 	printitem(name, "hde");
244 	printreg(x);
245 	print("%6hud", x);
246 
247 	shb = vga->crt[0x02];
248 	if(vga->crt[0x5D] & 0x04)
249 		shb |= 0x100;
250 	shb = (shb+1)<<3;
251 	shb *= mul;
252 	printitem(name, "shb");
253 	printreg(shb);
254 	print("%6hud", shb);
255 
256 	x = vga->crt[0x03] & 0x1F;
257 	if(vga->crt[0x05] & 0x80)
258 		x |= 0x20;
259 	x *= mul;
260 	x = shb|x;					/* ???? */
261 	if(vga->crt[0x5D] & 0x08)
262 		x += 64;
263 	printitem(name, "ehb");
264 	printreg(x);
265 	print("%6hud", x);
266 
267 	x = vga->crt[0x00];
268 	if(vga->crt[0x5D] & 0x01)
269 		x |= 0x100;
270 	x = (x+5)<<3;
271 	x *= mul;
272 	printitem(name, "ht");
273 	printreg(x);
274 	print("%6hud", x);
275 
276 	interlace = vga->crt[0x42] & 0x20;
277 	x = vga->crt[0x12];
278 	if(vga->crt[0x07] & 0x02)
279 		x |= 0x100;
280 	if(vga->crt[0x07] & 0x40)
281 		x |= 0x200;
282 	if(vga->crt[0x5E] & 0x02)
283 		x |= 0x400;
284 	x += 1;
285 	if(interlace)
286 		x *= 2;
287 	printitem(name, "vde");
288 	printreg(x);
289 	print("%6hud", x);
290 
291 	vrs = vga->crt[0x10];
292 	if(vga->crt[0x07] & 0x04)
293 		vrs |= 0x100;
294 	if(vga->crt[0x07] & 0x80)
295 		vrs |= 0x200;
296 	if(vga->crt[0x5E] & 0x10)
297 		vrs |= 0x400;
298 	if(interlace)
299 		vrs *= 2;
300 	printitem(name, "vrs");
301 	printreg(vrs);
302 	print("%6hud", vrs);
303 
304 	if(interlace)
305 		vrs /= 2;
306 	x = (vrs & ~0x0F)|(vga->crt[0x11] & 0x0F);
307 	if(interlace)
308 		x *= 2;
309 	printitem(name, "vre");
310 	printreg(x);
311 	print("%6hud", x);
312 
313 	x = vga->crt[0x06];
314 	if(vga->crt[0x07] & 0x01)
315 		x |= 0x100;
316 	if(vga->crt[0x07] & 0x20)
317 		x |= 0x200;
318 	if(vga->crt[0x5E] & 0x01)
319 		x |= 0x400;
320 	x += 2;
321 	if(interlace)
322 		x *= 2;
323 	printitem(name, "vt");
324 	printreg(x);
325 	print("%6hud", x);
326 }
327 
328 Ctlr s3generic = {
329 	"s3",				/* name */
330 	snarf,				/* snarf */
331 	0,				/* options */
332 	init,				/* init */
333 	load,				/* load */
334 	dump,				/* dump */
335 };
336