1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #include "pci.h"
6 #include "vga.h"
7
8 /*
9 * Trident Cyber938x.
10 */
11 typedef struct {
12 uchar old[3];
13 int pcr; /* Pixel Command Register */
14
15 int x;
16 int y;
17 } Cyber938x;
18
19 /*
20 * Access to the DAC Pixel Command Register.
21 * The access is similar to that used on the old
22 * SGS-Thompson STG1702 Enhanced True Color Palette-DAC
23 * and Sierra SC1502[56] HiCOLOR-24 Palette.
24 */
25 static void
pcrrw(void)26 pcrrw(void)
27 {
28 int i;
29
30 inportb(PaddrW);
31 for(i = 0; i < 4; i++)
32 inportb(Pixmask);
33 }
34
35 static int
pcrr(void)36 pcrr(void)
37 {
38 int pcr;
39
40 pcrrw();
41 pcr = inportb(Pixmask);
42 inportb(PaddrW);
43
44 return pcr;
45 }
46
47 static void
pcrw(int pcr)48 pcrw(int pcr)
49 {
50 pcrrw();
51 outportb(Pixmask, pcr);
52 inportb(PaddrW);
53 }
54
55 static void
snarf(Vga * vga,Ctlr * ctlr)56 snarf(Vga* vga, Ctlr* ctlr)
57 {
58 int i;
59 Cyber938x *cyber;
60
61 if(vga->private == nil)
62 vga->private = alloc(sizeof(Cyber938x));
63 cyber = vga->private;
64
65 /*
66 * Switch to old mode (write to Seq0B), read the old
67 * mode registers (Seq0[CDE]) then switch to new mode
68 * (read Seq0B).
69 */
70 vgaxo(Seqx, 0x0B, 0);
71 cyber->old[0] = vgaxi(Seqx, 0x0C);
72 cyber->old[1] = vgaxi(Seqx, 0x0D);
73 cyber->old[2] = vgaxi(Seqx, 0x0E);
74 vga->sequencer[0x0B] = vgaxi(Seqx, 0x0B);
75
76 cyber->pcr = pcrr();
77
78 for(i = 0x08; i < 0x20; i++){
79 if(i == 0x0B)
80 continue;
81 vga->sequencer[i] = vgaxi(Seqx, i);
82 }
83 for(i = 0x19; i < 0x60; i++)
84 vga->crt[i] = vgaxi(Crtx, i);
85 vga->crt[0xCF] = vgaxi(Crtx, 0xCF);
86 for(i = 0x09; i < 0x60; i++)
87 vga->graphics[i] = vgaxi(Grx, i);
88
89 vga->vma = 4*1024*1024;
90 switch(vga->crt[0x1F] & 0x07){
91 case 0:
92 case 4:
93 vga->vma = 8*1024*1024;
94 vga->vmz = 8*1024*1024;
95 break;
96 case 1:
97 case 5:
98 vga->vmz = 4*1024*1024;
99 break;
100 case 2:
101 case 6:
102 vga->vmz = 768*1024;
103 break;
104 case 7:
105 vga->vmz = 2*1024*1024;
106 break;
107 case 3:
108 default:
109 vga->vmz = 1024*1024;
110 break;
111 }
112
113 switch((vga->graphics[0x52]>>4) & 0x03){
114 case 0:
115 cyber->x = 1280;
116 cyber->y = 1024;
117 break;
118
119 case 1:
120 cyber->x = 640;
121 cyber->y = 480;
122 break;
123
124 case 2:
125 cyber->x = 1024;
126 cyber->y = 768;
127 break;
128
129 case 3:
130 cyber->x = 800;
131 cyber->y = 600;
132 break;
133 }
134
135 ctlr->flag |= Fsnarf;
136 }
137
138 static void
options(Vga * vga,Ctlr * ctlr)139 options(Vga* vga, Ctlr* ctlr)
140 {
141 USED(vga);
142 ctlr->flag |= Hlinear|Foptions;
143 }
144
145 static void
init(Vga * vga,Ctlr * ctlr)146 init(Vga* vga, Ctlr* ctlr)
147 {
148 Cyber938x *cyber;
149
150 cyber = vga->private;
151
152 vga->crt[0x1E] = 0x80;
153 vga->crt[0x2A] |= 0x40;
154
155 if(vga->linear && (ctlr->flag & Hlinear))
156 ctlr->flag |= Ulinear;
157
158 vga->graphics[0x31] &= 0x8F;
159 if(vga->mode->y > 768)
160 vga->graphics[0x31] |= 0x30;
161 else if(vga->mode->y > 600)
162 vga->graphics[0x31] |= 0x20;
163 else if(vga->mode->y > 480)
164 vga->graphics[0x31] |= 0x10;
165
166 switch(vga->mode->z){
167 case 8:
168 cyber->pcr = 0; /* DAC Pixel Command Register */
169 vga->crt[0x38] = 0x00; /* Pixel Bus Register */
170 break;
171 case 16:
172 cyber->pcr = 0x30;
173 vga->crt[0x38] = 0x05;
174 vga->crt[0x29] |= 0x10; /* RSC: necessary for Versa SX */
175 break;
176 case 24:
177 cyber->pcr = 0xD0;
178 vga->crt[0x38] = 0x29;
179 break;
180 default:
181 error("depth %d not supported\n", vga->mode->z);
182 }
183
184
185 switch(vga->sequencer[0x09]){
186
187 default:
188 error("unknown Cyber revision 0x%uX\n", vga->sequencer[0x09]);
189 break;
190 case 0x21: /* ProVidia 9685 */
191 /*
192 * Incomplete - no clock code so only 640x480x8 works.
193 */
194 vga->attribute[0x11] = 0;
195 vga->graphics[0x0F] |= 0x07;
196 break;
197 case 0x42: /* Cyber9382 */
198 /*
199 * Try a little magic for DSTN displays.
200 * May work on other chips too, who knows.
201 */
202 if(!(vga->graphics[0x42] & 0x80) /* !TFT */
203 && (vga->graphics[0x43] & 0x20)){ /* DSTN */
204 if(vga->mode->x == 640)
205 vga->graphics[0x30] |= 0x81;
206 else
207 vga->graphics[0x30] &= ~0x81;
208 }
209 /*FALLTHROUGH*/
210 case 0x3: /* Cyber9320 */
211 case 0x33: /* Cyber9385 */
212 case 0x34: /* Cyber9385 */
213 case 0x35: /* Cyber9385 */
214 case 0x3A: /* Cyber9385 */
215 vga->graphics[0x0F] |= 0x07;
216 break;
217 case 0x41: /* Cyber9525/DVD */
218 vga->graphics[0x0F] |= 0x17;
219 break;
220 case 0x4A: /* Cyber9388 */
221 case 0x5D: /* CyberBlade */
222 case 0x6A: /* CyberBlade (iTuner) */
223 case 0x7A: /* CyberBlade */
224 vga->crt[0x2F] = 0x3F;
225 vga->graphics[0x0F] |= 0x17;
226 if(vga->mode->x == 1024)
227 vga->graphics[0x30] = 0x18;
228 break;
229 }
230 vga->graphics[0x52] &= ~0x01;
231 vga->graphics[0x53] &= ~0x01;
232
233 ctlr->flag |= Finit;
234 }
235
236 static void
load(Vga * vga,Ctlr * ctlr)237 load(Vga* vga, Ctlr* ctlr)
238 {
239 Cyber938x *cyber;
240
241 cyber = vga->private;
242
243 outportw(0x3C4, 0x000B);
244 outportb(0x3C4, 0x0B);
245 inportb(0x3C5);
246
247 pcrw(cyber->pcr);
248
249 outportw(0x3C4, (0xC2 << 8) | 0x0E);
250 vgaxo(Grx, 0x52, vga->graphics[0x52]);
251 vgaxo(Grx, 0x53, vga->graphics[0x53]);
252 vgaxo(Grx, 0x30, vga->graphics[0x30]);
253 vgaxo(Grx, 0x31, vga->graphics[0x31]);
254
255 vgaxo(Crtx, 0x1E, vga->crt[0x1E]);
256 if(ctlr->flag & Ulinear)
257 vga->crt[0x21] |= 0x20;
258 vgaxo(Crtx, 0x21, vga->crt[0x21]);
259 vgaxo(Crtx, 0x29, vga->crt[0x29]);
260 vgaxo(Crtx, 0x2A, vga->crt[0x2A]);
261 vgaxo(Crtx, 0x2F, vga->crt[0x2F]);
262 vgaxo(Crtx, 0x38, vga->crt[0x38]);
263
264 vgaxo(Grx, 0x0F, vga->graphics[0x0F]);
265
266 ctlr->flag |= Fload;
267 }
268
269 static void
dump(Vga * vga,Ctlr * ctlr)270 dump(Vga* vga, Ctlr* ctlr)
271 {
272 char *name;
273 Cyber938x *cyber;
274 int i, k, m, n, vclka, vclkb;
275
276 name = ctlr->name;
277 cyber = vga->private;
278 printitem(name, "Seq08");
279 for(i = 0x08; i < 0x20; i++)
280 printreg(vga->sequencer[i]);
281 printitem(name, "Old Seq0C");
282 for(i = 0; i < 3; i++)
283 printreg(cyber->old[i]);
284 printitem(name, "pcr");
285 printreg(cyber->pcr);
286 printitem(name, "Crt19");
287 for(i = 0x19; i < 0x20; i++)
288 printreg(vga->crt[i]);
289 printitem(name, "Crt20");
290 for(i = 0x20; i < 0x60; i++)
291 printreg(vga->crt[i]);
292 printitem(name, "CrtCF");
293 printreg(vga->crt[0xCF]);
294 printitem(name, "Gr09");
295 for(i = 0x09; i < 0x10; i++)
296 printreg(vga->graphics[i]);
297 printitem(name, "Gr10");
298 for(i = 0x10; i < 0x60; i++)
299 printreg(vga->graphics[i]);
300
301 if(vga->sequencer[0x09] >= 0x4A){
302 vclka = vga->sequencer[0x18];
303 vclkb = vga->sequencer[0x19];
304 }
305 else{
306 vclka = inportb(0x43C8);
307 vclkb = inportb(0x43C9);
308 printitem(name, "mclk");
309 printreg(inportb(0x43C6));
310 printreg(inportb(0x43C7));
311 }
312 printitem(name, "vclk");
313 printreg(vclka);
314 printreg(vclkb);
315 k = vclkb>>6;
316 m = vclkb & 0x3F;
317 n = vclka;
318 Bprint(&stdout, "%18d\n", (((n+8)*RefFreq)*(1<<k))/(m+2));
319
320 printitem(name, "lcd size");
321 Bprint(&stdout, "%9ud %8ud\n", cyber->x, cyber->y);
322 }
323
324 Ctlr cyber938x = {
325 "cyber938x", /* name */
326 snarf, /* snarf */
327 options, /* options */
328 init, /* init */
329 load, /* load */
330 dump, /* dump */
331 };
332
333 Ctlr cyber938xhwgc = {
334 "cyber938xhwgc", /* name */
335 0, /* snarf */
336 0, /* options */
337 0, /* init */
338 0, /* load */
339 0, /* dump */
340 };
341