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
snarf(Vga * vga,Ctlr * ctlr)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
init(Vga * vga,Ctlr * ctlr)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
load(Vga * vga,Ctlr * ctlr)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
dump(Vga * vga,Ctlr * ctlr)226 dump(Vga* vga, Ctlr* ctlr)
227 {
228 int i, id, interlace, mul, div;
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 /*
260 * If hde <= 400, assume this is a 928 or Vision964
261 * and the horizontal values have been divided by 4.
262 *
263 * if ViRGE/[DG]X and 15 or 16bpp, horizontal values have
264 * been multiplied by 2.
265 */
266 mul = 1;
267 div = 1;
268
269 if(strcmp(name, "virge") == 0){
270 id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
271 /* S3 ViRGE/[DG]X */
272 if(id==0x8A01 && ((vga->crt[0x67] & 0x30) || (vga->crt[0x67] & 0x50))){
273 mul = 1;
274 div = 2;
275 }
276 }
277
278 x = vga->crt[0x01];
279 if(vga->crt[0x5D] & 0x02)
280 x |= 0x100;
281 x = (x+1)<<3;
282
283 if(x <= 400){
284 mul = 4;
285 div = 1;
286 }
287
288 x = (x * mul) / div;
289 printitem(name, "hde");
290 printreg(x);
291 Bprint(&stdout, "%6ud", x);
292
293 shb = vga->crt[0x02];
294 if(vga->crt[0x5D] & 0x04)
295 shb |= 0x100;
296 shb = (shb+1)<<3;
297 shb = (shb * mul) / div;
298 printitem(name, "shb");
299 printreg(shb);
300 Bprint(&stdout, "%6ud", shb);
301
302 x = vga->crt[0x03] & 0x1F;
303 if(vga->crt[0x05] & 0x80)
304 x |= 0x20;
305 x = (x * mul) / div;
306 x = shb|x; /* ???? */
307 if(vga->crt[0x5D] & 0x08)
308 x += 64;
309 printitem(name, "ehb");
310 printreg(x);
311 Bprint(&stdout, "%6ud", x);
312
313 x = vga->crt[0x00];
314 if(vga->crt[0x5D] & 0x01)
315 x |= 0x100;
316 x = (x+5)<<3;
317 x = (x * mul) / div;
318 printitem(name, "ht");
319 printreg(x);
320 Bprint(&stdout, "%6ud", x);
321
322 interlace = vga->crt[0x42] & 0x20;
323 x = vga->crt[0x12];
324 if(vga->crt[0x07] & 0x02)
325 x |= 0x100;
326 if(vga->crt[0x07] & 0x40)
327 x |= 0x200;
328 if(vga->crt[0x5E] & 0x02)
329 x |= 0x400;
330 x += 1;
331 if(interlace)
332 x *= 2;
333 printitem(name, "vde");
334 printreg(x);
335 Bprint(&stdout, "%6ud", x);
336
337 vrs = vga->crt[0x10];
338 if(vga->crt[0x07] & 0x04)
339 vrs |= 0x100;
340 if(vga->crt[0x07] & 0x80)
341 vrs |= 0x200;
342 if(vga->crt[0x5E] & 0x10)
343 vrs |= 0x400;
344 if(interlace)
345 vrs *= 2;
346 printitem(name, "vrs");
347 printreg(vrs);
348 Bprint(&stdout, "%6ud", vrs);
349
350 if(interlace)
351 vrs /= 2;
352 x = (vrs & ~0x0F)|(vga->crt[0x11] & 0x0F);
353 if(interlace)
354 x *= 2;
355 printitem(name, "vre");
356 printreg(x);
357 Bprint(&stdout, "%6ud", x);
358
359 x = vga->crt[0x06];
360 if(vga->crt[0x07] & 0x01)
361 x |= 0x100;
362 if(vga->crt[0x07] & 0x20)
363 x |= 0x200;
364 if(vga->crt[0x5E] & 0x01)
365 x |= 0x400;
366 x += 2;
367 if(interlace)
368 x *= 2;
369 printitem(name, "vt");
370 printreg(x);
371 Bprint(&stdout, "%6ud", x);
372 }
373
374 Ctlr s3generic = {
375 "s3", /* name */
376 snarf, /* snarf */
377 0, /* options */
378 init, /* init */
379 load, /* load */
380 dump, /* dump */
381 };
382