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