1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #include "pci.h"
6 #include "vga.h"
7
8 /*
9 * Tseng Labs Inc. ET4000 Video Controller.
10 */
11 enum {
12 Crtcbx = 0x217A, /* Secondary CRT controller */
13
14 Sprite = 0xE0,
15 NSprite = 0x10,
16
17 Ima = 0xF0,
18 NIma = 0x08,
19 };
20
21 static void
setkey(void)22 setkey(void)
23 {
24 outportb(0x3BF, 0x03);
25 outportb(0x3D8, 0xA0);
26 outportb(0x3CD, 0x00);
27 }
28
29 static void
snarf(Vga * vga,Ctlr * ctlr)30 snarf(Vga* vga, Ctlr* ctlr)
31 {
32 int i;
33
34 setkey();
35
36 vga->sequencer[0x06] = vgaxi(Seqx, 0x06);
37 vga->sequencer[0x07] = vgaxi(Seqx, 0x07);
38
39 for(i = 0x30; i < 0x38; i++)
40 vga->crt[i] = vgaxi(Crtx, i);
41 vga->crt[0x3F] = vgaxi(Crtx, 0x3F);
42
43 vga->attribute[0x16] = vgaxi(Attrx, 0x16);
44 vga->attribute[0x17] = vgaxi(Attrx, 0x17);
45
46 /*
47 * Memory size.
48 */
49 switch(vga->crt[0x37] & 0x03){
50
51 case 1:
52 vga->vmz = 256*1024;
53 break;
54
55 case 2:
56 vga->vmz = 512*1024;
57 break;
58
59 case 3:
60 vga->vmz = 1024*1024;
61 break;
62 }
63 if(strncmp(ctlr->name, "et4000-w32", 10) == 0){
64 if(vga->crt[0x32] & 0x80)
65 vga->vmz *= 2;
66 }
67 else if(vga->crt[0x37] & 0x80)
68 vga->vmz *= 2;
69
70 ctlr->flag |= Fsnarf;
71 }
72
73 static void
options(Vga * vga,Ctlr * ctlr)74 options(Vga* vga, Ctlr* ctlr)
75 {
76 /*
77 * The ET4000 does not need to have the vertical
78 * timing values divided by 2 for interlace mode.
79 */
80 if(vga->mode->interlace == 'v')
81 vga->mode->interlace = 'V';
82
83 if(strncmp(ctlr->name, "et4000-w32", 10) == 0)
84 ctlr->flag |= Hpclk2x8;
85
86 ctlr->flag |= Hclkdiv|Foptions;
87 }
88
89 static void
init(Vga * vga,Ctlr * ctlr)90 init(Vga* vga, Ctlr* ctlr)
91 {
92 Mode *mode;
93 ulong x;
94
95 if(vga->mode->z > 8)
96 error("depth %d not supported\n", vga->mode->z);
97
98 if(ctlr->flag & Upclk2x8){
99 mode = vga->mode;
100 vga->crt[0x00] = ((mode->ht/2)>>3)-5;
101 vga->crt[0x01] = ((mode->x/2)>>3)-1;
102 vga->crt[0x02] = ((mode->shb/2)>>3)-1;
103
104 x = (mode->ehb/2)>>3;
105 vga->crt[0x03] = 0x80|(x & 0x1F);
106 vga->crt[0x04] = (mode->shs/2)>>3;
107 vga->crt[0x05] = ((mode->ehs/2)>>3) & 0x1F;
108 if(x & 0x20)
109 vga->crt[0x05] |= 0x80;
110 }
111 /*
112 * Itth a mythtawee.
113 */
114 if(vga->crt[0x14] & 0x20)
115 vga->crt[0x17] |= 0x08;
116 vga->crt[0x17] &= ~0x20;
117
118 vga->crt[0x30] = 0x00;
119 vga->crt[0x33] = 0x00;
120
121 /*
122 * Overflow High.
123 */
124 vga->crt[0x35] = 0x00;
125 if(vga->crt[0x15] & 0x400)
126 vga->crt[0x35] |= 0x01;
127 if(vga->crt[0x06] & 0x400)
128 vga->crt[0x35] |= 0x02;
129 if(vga->crt[0x12] & 0x400)
130 vga->crt[0x35] |= 0x04;
131 if(vga->crt[0x10] & 0x400)
132 vga->crt[0x35] |= 0x08;
133 if(vga->crt[0x18] & 0x400)
134 vga->crt[0x35] |= 0x10;
135 if(vga->mode->interlace == 'V')
136 vga->crt[0x35] |= 0x80;
137
138 /*
139 * Horizontal Overflow.
140 */
141 vga->crt[0x3F] = 0x00;
142 if(vga->crt[0x00] & 0x100)
143 vga->crt[0x3F] |= 0x01;
144 if(vga->crt[0x02] & 0x100)
145 vga->crt[0x3F] |= 0x04;
146 if(vga->crt[0x04] & 0x100)
147 vga->crt[0x3F] |= 0x10;
148 if(vga->crt[0x13] & 0x100)
149 vga->crt[0x3F] |= 0x80;
150
151 /*
152 * Turn off MMU buffers, linear map
153 * and memory-mapped registers.
154 */
155 vga->crt[0x36] &= ~0x38;
156
157 if(strncmp(ctlr->name, "et4000-w32", 10) == 0)
158 vga->crt[0x37] |= 0x80;
159
160 vga->sequencer[0x06] = 0x00;
161
162 /*
163 * Clock select.
164 */
165 if(vga->f[0] > 86000000)
166 error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
167 vga->misc &= ~0x0C;
168 vga->misc |= (vga->i[0] & 0x03)<<2;
169 if(vga->i[0] & 0x04)
170 vga->crt[0x34] |= 0x02;
171 else
172 vga->crt[0x34] &= ~0x02;
173 vga->crt[0x31] &= ~0xC0;
174 vga->crt[0x31] |= (vga->i[0] & 0x18)<<3;
175
176 vga->sequencer[0x07] &= ~0x41;
177 if(vga->d[0] == 4)
178 vga->sequencer[0x07] |= 0x01;
179 else if(vga->d[0] == 2)
180 vga->sequencer[0x07] |= 0x40;
181
182 vga->attribute[0x10] &= ~0x40;
183 vga->attribute[0x11] = Pblack;
184 vga->attribute[0x16] = 0x80;
185
186 if(ctlr->flag & Upclk2x8)
187 vga->attribute[0x16] |= 0x20;
188
189 ctlr->flag |= Finit;
190 }
191
192 static void
load(Vga * vga,Ctlr * ctlr)193 load(Vga* vga, Ctlr* ctlr)
194 {
195 vgaxo(Crtx, 0x30, vga->crt[0x30]);
196 vgaxo(Crtx, 0x31, vga->crt[0x31]);
197 vgaxo(Crtx, 0x33, vga->crt[0x33]);
198 vgaxo(Crtx, 0x34, vga->crt[0x34]);
199 vgaxo(Crtx, 0x35, vga->crt[0x35]);
200 vgaxo(Crtx, 0x36, vga->crt[0x36]);
201 vgaxo(Crtx, 0x37, vga->crt[0x37]);
202 vgaxo(Crtx, 0x3F, vga->crt[0x3F]);
203
204 vgaxo(Seqx, 0x06, vga->sequencer[0x06]);
205 vgaxo(Seqx, 0x07, vga->sequencer[0x07]);
206
207 vgaxo(Attrx, 0x16, vga->attribute[0x16]);
208
209 ctlr->flag |= Fload;
210 }
211
212 static void
dump(Vga * vga,Ctlr * ctlr)213 dump(Vga* vga, Ctlr* ctlr)
214 {
215 int i;
216 char *name;
217 ushort shb, vrs, x;
218
219 name = ctlr->name;
220
221 printitem(name, "Seq06");
222 printreg(vga->sequencer[0x06]);
223 printreg(vga->sequencer[0x07]);
224
225 printitem(name, "Crt30");
226 for(i = 0x30; i < 0x38; i++)
227 printreg(vga->crt[i]);
228 printitem(name, "Crt3F");
229 printreg(vga->crt[0x3F]);
230
231 printitem(name, "Attr16");
232 printreg(vga->attribute[0x16]);
233 printreg(vga->attribute[0x17]);
234
235 if(strncmp(name, "et4000-w32", 10) == 0){
236 printitem(name, "SpriteE0");
237 for(i = Sprite; i < Sprite+NSprite; i++){
238 outportb(Crtcbx, i);
239 printreg(inportb(Crtcbx+1));
240 }
241 printitem(name, "ImaF0");
242 for(i = Ima; i < Ima+NIma; i++){
243 outportb(Crtcbx, i);
244 printreg(inportb(Crtcbx+1));
245 }
246 }
247
248 /*
249 * Try to disassemble the snarfed values into
250 * understandable numbers.
251 * Only do this if we weren't called after Finit.
252 */
253 if(ctlr->flag & Finit)
254 return;
255
256 x = (vga->crt[0x01]+1)<<3;
257 printitem(name, "hde");
258 printreg(x);
259 Bprint(&stdout, "%6ud", x);
260
261 shb = ((((vga->crt[0x3F] & 0x04)<<6)|vga->crt[0x02])+1)<<3;
262 printitem(name, "shb");
263 printreg(shb);
264 Bprint(&stdout, "%6ud", shb);
265
266 x = (((vga->crt[0x05] & 0x80)>>2)|(vga->crt[0x03] & 0x1F))<<3;
267 printitem(name, "ehb");
268 printreg(x);
269 for(i = 0; x < shb; i++)
270 x |= 0x200<<i;
271 Bprint(&stdout, "%6ud", x);
272
273 x = ((((vga->crt[0x3F] & 0x01)<<8)|vga->crt[0x00])+5)<<3;
274 printitem(name, "ht");
275 printreg(x);
276 Bprint(&stdout, "%6ud", x);
277
278 x = vga->crt[0x12];
279 if(vga->crt[0x07] & 0x02)
280 x |= 0x100;
281 if(vga->crt[0x07] & 0x40)
282 x |= 0x200;
283 if(vga->crt[0x35] & 0x04)
284 x |= 0x400;
285 x += 1;
286 printitem(name, "vde");
287 printreg(x);
288 Bprint(&stdout, "%6ud", x);
289
290 vrs = vga->crt[0x10];
291 if(vga->crt[0x07] & 0x04)
292 vrs |= 0x100;
293 if(vga->crt[0x07] & 0x80)
294 vrs |= 0x200;
295 if(vga->crt[0x35] & 0x08)
296 vrs |= 0x400;
297 printitem(name, "vrs");
298 printreg(vrs);
299 Bprint(&stdout, "%6ud", vrs);
300
301 x = (vrs & ~0x0F)|(vga->crt[0x11] & 0x0F);
302 printitem(name, "vre");
303 printreg(x);
304 Bprint(&stdout, "%6ud", x);
305
306 x = vga->crt[0x06];
307 if(vga->crt[0x07] & 0x01)
308 x |= 0x100;
309 if(vga->crt[0x07] & 0x20)
310 x |= 0x200;
311 if(vga->crt[0x35] & 0x02)
312 x |= 0x400;
313 x += 2;
314 printitem(name, "vt");
315 printreg(x);
316 Bprint(&stdout, "%6ud", x);
317
318 printitem(name, "d i");
319 if(vga->sequencer[0x07] & 0x01)
320 x = 4;
321 else if(vga->sequencer[0x07] & 0x40)
322 x = 2;
323 else
324 x = 0;
325 Bprint(&stdout, "%9ud", x);
326 x = (vga->misc & 0x0C)>>2;
327 if(vga->crt[0x34] & 0x02)
328 x |= 0x04;
329 x |= (vga->crt[0x31] & 0xC0)>>3;
330 Bprint(&stdout, "%8ud\n", x);
331 }
332
333 Ctlr et4000 = {
334 "et4000", /* name */
335 snarf, /* snarf */
336 options, /* options */
337 init, /* init */
338 load, /* load */
339 dump, /* dump */
340 };
341