]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/vga/s3generic.c
exec(2): fix prototypes
[plan9front.git] / sys / src / cmd / aux / vga / s3generic.c
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, 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 };