1 /* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */
2 /* */
3 /* This library is free software; you can redistribute it and/or */
4 /* modify it without any restrictions. This library is distributed */
5 /* in the hope that it will be useful, but without any warranty. */
6
7 /* Multi-chipset support Copyright (C) 1993 Harm Hanemaayer */
8 /* Modified by Hartmut Schirmer */
9
10 /* TVGA 8900c code taken from tvgalib by Toomas Losin */
11
12 /* TVGA 9440 code added by ARK 29-OCT-97 */
13 /* (root@ark.dyn.ml.org, ark@lhq.com) [nitc?] */
14 /* updated 9-NOV-97 to support more regs */
15 /* this should alllow it to work on 9680's as well */
16
17 /* Thanks to Albert Erdmann (theone@miami.gdi.net) */
18 /* for blindly testing files and mailing me results */
19 /* for the 9680 registers */
20
21
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include "vga.h"
26 #include "libvga.h"
27 #include "driver.h"
28
29 #include "tvga8900.regs"
30 #include "tvga9440.regs"
31 #include "tvga9680.regs"
32
33 /* static int tvga_chiptype; */
34 static int tvga8900_memory; /* amount of video memory in K */
35 static int tvga8900_nonint; /* nonzero if non-interlaced jumper set */
36
37 static int tvga8900_init(int, int, int);
38 static int tvga8900_interlaced(int mode);
39
40 static int reg_0c = 0xad; /* value for 256k cards */
41
42 static int tvga_model = 8900; /* set to 8900, 9440, or 9680 based on model */
43
44 /* Mode table */
45 #define ModeEntry94(res) { G##res, g##res##_regs94 }
46 #define ModeEntry96(res) { G##res, g##res##_regs96 }
47
48 static ModeTable tvga_modes_2048_96[] =
49 { /* 2M modes for the 9680 */
50 ModeEntry96(800x600x16),
51 ModeEntry96(1024x768x16),
52 ModeEntry96(1280x1024x16),
53 ModeEntry96(1600x1200x16),
54 ModeEntry96(640x480x256),
55 ModeEntry96(800x600x256),
56 ModeEntry96(1024x768x256),
57 ModeEntry96(1280x1024x256),
58 ModeEntry96(1600x1200x256),
59 ModeEntry96(320x200x32K),
60 ModeEntry96(640x480x32K),
61 ModeEntry96(800x600x32K),
62 ModeEntry96(1024x768x32K),
63 ModeEntry96(320x200x64K),
64 ModeEntry96(640x480x64K),
65 ModeEntry96(800x600x64K),
66 ModeEntry96(1024x768x64K),
67 ModeEntry96(320x200x16M),
68 ModeEntry96(640x480x16M),
69 ModeEntry96(800x600x16M),
70 END_OF_MODE_TABLE
71 };
72
73 static ModeTable tvga_modes_1024_96[] =
74 { /* 1M modes for the 9680 */
75 ModeEntry96(800x600x16),
76 ModeEntry96(1024x768x16),
77 ModeEntry96(1280x1024x16),
78 ModeEntry96(1600x1200x16),
79 ModeEntry96(640x480x256),
80 ModeEntry96(800x600x256),
81 ModeEntry96(1024x768x256),
82 ModeEntry96(320x200x32K),
83 ModeEntry96(640x480x32K),
84 ModeEntry96(800x600x32K),
85 ModeEntry96(320x200x64K),
86 ModeEntry96(640x480x64K),
87 ModeEntry96(800x600x64K),
88 ModeEntry96(320x200x16M),
89 ModeEntry96(640x480x16M),
90 END_OF_MODE_TABLE
91 };
92
93 static ModeTable tvga_modes_512_96[] =
94 { /* 512K modes for the 9680 */
95 ModeEntry96(800x600x16),
96 ModeEntry96(1024x768x16),
97 ModeEntry96(640x480x256),
98 ModeEntry96(800x600x256),
99 ModeEntry96(320x200x32K),
100 ModeEntry96(320x200x64K),
101 ModeEntry96(320x200x16M),
102 END_OF_MODE_TABLE
103 };
104
105 static ModeTable tvga_modes_1024_94[] =
106 { /* 1M modes for the 9440 */
107 ModeEntry94(800x600x16),
108 ModeEntry94(1024x768x16),
109 ModeEntry94(1280x1024x16),
110 ModeEntry94(1600x1200x16),
111 ModeEntry94(640x480x256),
112 ModeEntry94(800x600x256),
113 ModeEntry94(1024x768x256),
114 ModeEntry94(320x200x32K),
115 ModeEntry94(640x480x32K),
116 ModeEntry94(800x600x32K),
117 ModeEntry94(320x200x64K),
118 ModeEntry94(640x480x64K),
119 ModeEntry94(800x600x64K),
120 ModeEntry94(320x200x16M),
121 ModeEntry94(640x480x16M),
122 END_OF_MODE_TABLE
123 };
124
125 static ModeTable tvga_modes_512_94[] =
126 { /* 512K modes for the 9440 */
127 ModeEntry94(800x600x16),
128 ModeEntry94(1024x768x16),
129 ModeEntry94(640x480x256),
130 ModeEntry94(800x600x256),
131 ModeEntry94(320x200x32K),
132 ModeEntry94(320x200x64K),
133 ModeEntry94(320x200x16M),
134 END_OF_MODE_TABLE
135 };
136
137 static ModeTable tvga_modes_1024[] =
138 { /* 1Mb, non-interlace jumper set */
139 /* *INDENT-OFF* */
140 OneModeEntry(640x480x256),
141 OneModeEntry(800x600x256),
142 OneModeEntry(1024x768x256),
143 END_OF_MODE_TABLE
144 /* *INDENT-ON* */
145 };
146
147 #define INTERL(res,i) { G##res, g##res##i##_regs }
148
149 static ModeTable tvga_modes_1024i[] =
150 { /* 1Mb, jumper set to interlaced */
151 /* *INDENT-OFF* */
152 INTERL(640x480x256, i),
153 INTERL(800x600x256, i),
154 INTERL(1024x768x256, i),
155 END_OF_MODE_TABLE
156 /* *INDENT-ON* */
157 };
158
159 static ModeTable tvga_modes_512[] =
160 { /* 512K */
161 /* *INDENT-OFF* */
162 INTERL(640x480x256, i),
163 INTERL(800x600x256, i1),
164 END_OF_MODE_TABLE
165 /* *INDENT-ON* */
166 };
167
168 static ModeTable *tvga_modes = NULL;
169
nothing(void)170 static void nothing(void)
171 {
172 }
173
174 /* Fill in chipset specific mode information */
175
tvga8900_getmodeinfo(int mode,vga_modeinfo * modeinfo)176 static void tvga8900_getmodeinfo(int mode, vga_modeinfo * modeinfo)
177 {
178 if (modeinfo->bytesperpixel > 0)
179 modeinfo->maxpixels = tvga8900_memory * 1024 /
180 modeinfo->bytesperpixel;
181 else
182 modeinfo->maxpixels = tvga8900_memory * 1024;
183 modeinfo->maxlogicalwidth = 2040;
184 modeinfo->startaddressrange = 0xfffff;
185 if (mode == G320x200x256) {
186 /* Special case: bank boundary may not fall within display. */
187 modeinfo->startaddressrange = 0xf0000;
188 /* Hack: disable page flipping capability for the moment. */
189 modeinfo->startaddressrange = 0xffff;
190 modeinfo->maxpixels = 65536;
191 }
192 modeinfo->haveblit = 0;
193
194 if (tvga8900_interlaced(mode))
195 modeinfo->flags |= IS_INTERLACED;
196 modeinfo->flags &= ~HAVE_RWPAGE;
197 }
198
199
200 /* select the correct register table */
setup_registers(void)201 static void setup_registers(void)
202 {
203 if (tvga_modes == NULL) {
204 if (tvga_model == 9440) {
205 if (tvga8900_memory < 1024)
206 tvga_modes = tvga_modes_512_94;
207 else
208 tvga_modes = tvga_modes_1024_94;
209 }
210 else if (tvga_model == 9680) {
211 if (tvga8900_memory < 1024)
212 tvga_modes = tvga_modes_512_96;
213 else if (tvga8900_memory < 2048)
214 tvga_modes = tvga_modes_1024_96;
215 else
216 tvga_modes = tvga_modes_2048_96;
217 }
218 else {
219 if (tvga8900_memory < 1024)
220 tvga_modes = tvga_modes_512;
221 if (tvga8900_nonint)
222 tvga_modes = tvga_modes_1024;
223 else
224 tvga_modes = tvga_modes_1024i;
225 }
226 }
227 }
228
229
230 /* Read and store chipset-specific registers */
231
tvga8900_saveregs(unsigned char regs[])232 static int tvga8900_saveregs(unsigned char regs[])
233 {
234 int i;
235
236 /* I know goto is bad, but i didnt want to indent all the old code.. */
237 /* the 9680 uses the same regs, just completely different values */
238 if (tvga_model == 9440 || tvga_model == 9680) goto tvga9440_saveregs;
239
240 /* save extended CRT registers */
241 for (i = 0; i < 7; i++) {
242 port_out(0x18 + i, __svgalib_CRT_I);
243 regs[EXT + i] = port_in(__svgalib_CRT_D);
244 }
245
246 /* now do the sequencer mode regs */
247 port_out(0x0b, SEQ_I); /* force old mode regs */
248 port_out(port_in(SEQ_D), SEQ_D); /* by writing */
249
250 /* outw(SEQ_I, 0x820E); */ /* unlock conf. reg */
251 /* port_out(0x0c, SEQ_I); */ /* save conf. reg */
252 /* regs[EXT + 11] = port_in(SEQ_D); */
253
254 port_out(0x0d, SEQ_I); /* old reg 13 */
255 regs[EXT + 7] = port_in(SEQ_D);
256 port_out(0x0e, SEQ_I); /* old reg 14 */
257 regs[EXT + 8] = port_in(SEQ_D);
258
259 port_out(0x0b, SEQ_I); /* now use new regs */
260 port_in(SEQ_D);
261 port_out(0x0d, SEQ_I); /* new reg 13 */
262 regs[EXT + 9] = port_in(SEQ_D);
263 port_out(0x0e, SEQ_I); /* new reg 14 */
264 regs[EXT + 10] = port_in(SEQ_D) ^ 0x02;
265
266 /* we do the ^ 0x02 so that when the regs are restored */
267 /* later we don't have a special case; see trident.doc */
268
269 return 12; /* tridents requires 12 additional registers */
270
271
272 /* 9440 code added by ARK */
273 tvga9440_saveregs:
274
275 /* unprotect some trident regs */
276 port_out(0x0E, SEQ_I);
277 port_out(port_in(SEQ_D) | 0x80, SEQ_D);
278
279 /* save sequencer regs */
280 port_out(0x0B, SEQ_I);
281 regs[EXT + 0] = port_in(SEQ_D);
282 port_out(0x0D, SEQ_I);
283 regs[EXT + 1] = port_in(SEQ_D);
284 port_out(0x0E, SEQ_I);
285 regs[EXT + 2] = port_in(SEQ_D);
286 port_out(0x0F, SEQ_I);
287 regs[EXT + 3] = port_in(SEQ_D);
288
289 /* save extended CRT registers */
290 port_out(0x19, __svgalib_CRT_I);
291 regs[EXT + 4] = port_in(__svgalib_CRT_D);
292 port_out(0x1E, __svgalib_CRT_I);
293 regs[EXT + 5] = port_in(__svgalib_CRT_D);
294 port_out(0x1F, __svgalib_CRT_I);
295 regs[EXT + 6] = port_in(__svgalib_CRT_D);
296 port_out(0x21, __svgalib_CRT_I);
297 regs[EXT + 7] = port_in(__svgalib_CRT_D);
298 port_out(0x25, __svgalib_CRT_I);
299 regs[EXT + 8] = port_in(__svgalib_CRT_D);
300 port_out(0x27, __svgalib_CRT_I);
301 regs[EXT + 9] = port_in(__svgalib_CRT_D);
302 port_out(0x29, __svgalib_CRT_I);
303 regs[EXT + 10] = port_in(__svgalib_CRT_D);
304 /* Extended regs 11/12 are clobbered by vga.c */
305 port_out(0x2A, __svgalib_CRT_I);
306 regs[EXT + 13] = port_in(__svgalib_CRT_D);
307 port_out(0x2F, __svgalib_CRT_I);
308 regs[EXT + 14] = port_in(__svgalib_CRT_D);
309 port_out(0x30, __svgalib_CRT_I);
310 regs[EXT + 15] = port_in(__svgalib_CRT_D);
311 port_out(0x36, __svgalib_CRT_I);
312 regs[EXT + 16] = port_in(__svgalib_CRT_D);
313 port_out(0x38, __svgalib_CRT_I);
314 regs[EXT + 17] = port_in(__svgalib_CRT_D);
315 port_out(0x50, __svgalib_CRT_I);
316 regs[EXT + 18] = port_in(__svgalib_CRT_D);
317
318 /* grfx controller */
319 port_out(0x0F, GRA_I);
320 regs[EXT + 19] = port_in(GRA_D);
321 port_out(0x2F, GRA_I);
322 regs[EXT + 20] = port_in(GRA_D);
323
324 /* trident specific ports */
325 regs[EXT + 21] = port_in(0x43C8);
326 regs[EXT + 22] = port_in(0x43C9);
327 regs[EXT + 23] = port_in(0x83C6);
328 regs[EXT + 24] = port_in(0x83C8);
329 for(i=0;i<5;i++)
330 port_in(PEL_MSK);
331 regs[EXT + 25] = port_in(PEL_MSK);
332
333 /* reprotect the regs to avoid conflicts */
334 port_out(0x0E, SEQ_I);
335 port_out(port_in(SEQ_D) & 0x7F, SEQ_D);
336
337 return 26; /* The 9440 requires 26 additional registers */
338 }
339
340
341 /* Set chipset-specific registers */
342
tvga8900_setregs(const unsigned char regs[],int mode)343 static void tvga8900_setregs(const unsigned char regs[], int mode)
344 {
345 int i;
346 int crtc31 = 0;
347
348 /* 7 extended CRT registers */
349 /* 4 extended Sequencer registers (old and new) */
350 /* CRTC reg 0x1f is apparently dependent */
351 /* on the amount of memory installed. */
352
353 switch (tvga8900_memory >> 8) {
354 case 1:
355 crtc31 = 0x94;
356 reg_0c = 0xad;
357 break; /* 256K */
358 case 2:
359 case 3:
360 crtc31 = 0x98;
361 reg_0c = 0xcd;
362 break; /* 512/768K */
363 case 4: /* 1024K */
364 crtc31 = 0x18;
365 reg_0c = 0xcd;
366 if (mode == G1024x768x256) {
367 reg_0c = 0xed;
368 crtc31 = 0x98;
369 } else if (mode == G640x480x256 || mode == G800x600x256)
370 reg_0c = 0xed;
371 break;
372 }
373
374 if (tvga_model == 9440 || tvga_model == 9680) goto tvga9440_setregs;
375
376 if (mode == TEXT) {
377 reg_0c = regs[EXT + 11];
378 crtc31 = regs[EXT + 12];
379 }
380 #ifdef REG_DEBUG
381 printf("Setting extended registers\n");
382 #endif
383
384 /* write extended CRT registers */
385 for (i = 0; i < 7; i++) {
386 port_out(0x18 + i, __svgalib_CRT_I);
387 port_out(regs[EXT + i], __svgalib_CRT_D);
388 }
389
390 /* update sequencer mode regs */
391 port_out(0x0b, SEQ_I); /* select old regs */
392 port_out(port_in(SEQ_D), SEQ_D);
393 port_out(0x0d, SEQ_I); /* old reg 13 */
394 port_out(regs[EXT + 7], SEQ_D);
395 port_out(0x0e, SEQ_I); /* old reg 14 */
396 #if 0
397 port_out(regs[EXT + 8], SEQ_D);
398 #endif
399 port_out(((port_in(SEQ_D) & 0x08) | (regs[EXT + 8] & 0xf7)), SEQ_D);
400
401
402 port_out(0x0b, SEQ_I);
403 port_in(SEQ_D); /* select new regs */
404
405 if (tvga8900_memory > 512) {
406 port_out(0x0e, SEQ_I); /* set bit 7 of reg 14 */
407 port_out(0x80, SEQ_D); /* to enable writing to */
408 port_out(0x0c, SEQ_I); /* reg 12 */
409 port_out(reg_0c, SEQ_D);
410 }
411 /* outw(SEQ_I, 0x820e); */ /* unlock conf. reg */
412 /* port_out(0x0c, SEQ_I); */ /* reg 12 */
413
414 port_out(0x0d, SEQ_I); /* new reg 13 */
415 port_out(regs[EXT + 9], SEQ_D);
416 port_out(0x0e, SEQ_I); /* new reg 14 */
417 port_out(regs[EXT + 10], SEQ_D);
418
419 #ifdef REG_DEBUG
420 printf("Now setting last two extended registers.\n");
421 #endif
422
423 /* update CRTC reg 1f */
424 port_out(0x1f, __svgalib_CRT_I);
425 port_out((port_in(__svgalib_CRT_D) & 0x03) | crtc31, __svgalib_CRT_D);
426
427 return;
428
429
430 tvga9440_setregs:
431
432 /* update sequencer mode regs */
433 port_out(0x0D, SEQ_I);
434 port_out(regs[EXT + 1], SEQ_D);
435 port_out(0x0E, SEQ_I);
436 port_out(regs[EXT + 2], SEQ_D);
437 port_out(0x0F, SEQ_I);
438 port_out(regs[EXT + 3], SEQ_D);
439 /* you cant write to this anyways... it messes things up...
440 port_out(0x0B, SEQ_I);
441 port_out(regs[EXT + 0], SEQ_D);
442 */
443 /* write extended CRT registers */
444 port_out(0x19, __svgalib_CRT_I);
445 port_out(regs[EXT + 4], __svgalib_CRT_D);
446 port_out(0x1E, __svgalib_CRT_I);
447 port_out(regs[EXT + 5], __svgalib_CRT_D);
448 port_out(0x1F, __svgalib_CRT_I);
449 port_out(regs[EXT + 6], __svgalib_CRT_D);
450 port_out(0x21, __svgalib_CRT_I);
451 port_out(regs[EXT + 7], __svgalib_CRT_D);
452 port_out(0x25, __svgalib_CRT_I);
453 port_out(regs[EXT + 8], __svgalib_CRT_D);
454 port_out(0x27, __svgalib_CRT_I);
455 port_out(regs[EXT + 9], __svgalib_CRT_D);
456 port_out(0x29, __svgalib_CRT_I);
457 port_out(regs[EXT + 10], __svgalib_CRT_D);
458 /* Extended regs 11/12 are clobbered by vga.c */
459 port_out(0x2A, __svgalib_CRT_I);
460 port_out(regs[EXT + 13], __svgalib_CRT_D);
461 port_out(0x2F, __svgalib_CRT_I);
462 port_out(regs[EXT + 14], __svgalib_CRT_D);
463 port_out(0x30, __svgalib_CRT_I);
464 port_out(regs[EXT + 15], __svgalib_CRT_D);
465 port_out(0x36, __svgalib_CRT_I);
466 port_out(regs[EXT + 16], __svgalib_CRT_D);
467 port_out(0x38, __svgalib_CRT_I);
468 port_out(regs[EXT + 17], __svgalib_CRT_D);
469 port_out(0x50, __svgalib_CRT_I);
470 port_out(regs[EXT + 18], __svgalib_CRT_D);
471
472 /* grfx controller */
473 port_out(0x0F, GRA_I);
474 port_out(regs[EXT + 19], GRA_D);
475 port_out(0x2F, GRA_I);
476 port_out(regs[EXT + 20], GRA_D);
477
478 /* unprotect 3DB */
479 port_out(0x0F, GRA_I);
480 port_out(port_in(GRA_D) | 0x04, GRA_D);
481 /* allow user-defined clock rates */
482 port_out((port_in(0x3DB) & 0xFC) | 0x02, 0x3DB);
483
484 /* trident specific ports */
485 port_out(regs[EXT + 21], 0x43C8);
486 port_out(regs[EXT + 22], 0x43C9);
487 port_out(regs[EXT + 23], 0x83C6);
488 port_out(regs[EXT + 24], 0x83C8);
489 for(i=0;i<5;i++)
490 port_in(PEL_MSK);
491 port_out(regs[EXT + 25], PEL_MSK);
492 port_out(0xFF, PEL_MSK);
493 }
494
495
496 /* Return nonzero if mode is available */
497
tvga8900_modeavailable(int mode)498 static int tvga8900_modeavailable(int mode)
499 {
500 const unsigned char *regs;
501 struct info *info;
502
503 regs = LOOKUPMODE(tvga_modes, mode);
504 if (regs == NULL || mode == GPLANE16)
505 return __svgalib_vga_driverspecs.modeavailable(mode);
506 if (regs == DISABLE_MODE || mode <= TEXT || mode > GLASTMODE)
507 return 0;
508
509 info = &__svgalib_infotable[mode];
510 if (tvga8900_memory * 1024 < info->ydim * info->xbytes)
511 return 0;
512
513 return SVGADRV;
514 }
515
516
517 /* Check if mode is interlaced */
518
tvga8900_interlaced(int mode)519 static int tvga8900_interlaced(int mode)
520 {
521 const unsigned char *regs;
522
523 setup_registers();
524 regs = LOOKUPMODE(tvga_modes, mode);
525 if (regs == NULL || regs == DISABLE_MODE)
526 return 0;
527 return tvga8900_nonint == 0;
528 }
529
530
531 /* Set a mode */
532
tvga8900_setmode(int mode,int prv_mode)533 static int tvga8900_setmode(int mode, int prv_mode)
534 {
535 const unsigned char *regs;
536
537 regs = LOOKUPMODE(tvga_modes, mode);
538 if (regs == NULL)
539 return (int) (__svgalib_vga_driverspecs.setmode(mode, prv_mode));
540 if (!tvga8900_modeavailable(mode))
541 return 1;
542 __svgalib_setregs(regs);
543 tvga8900_setregs(regs, mode);
544 return 0;
545 }
546
547
548 /* Indentify chipset; return non-zero if detected */
549
tvga8900_test(void)550 static int tvga8900_test(void)
551 {
552 int origVal, newVal;
553 int save0b;
554 /*
555 * Check first that we have a Trident card.
556 */
557 outb(SEQ_I, 0x0b);
558 save0b = inb(SEQ_D);
559 outw(SEQ_I, 0x000B); /* Switch to Old Mode */
560 inb(SEQ_D); /* Now to New Mode */
561 outb(SEQ_I, 0x0E);
562 origVal = inb(SEQ_D);
563 outb(SEQ_D, 0x00);
564 newVal = inb(SEQ_D) & 0x0F;
565 outb(SEQ_D, (origVal ^ 0x02));
566
567 if (newVal != 2) {
568 outb(SEQ_D, origVal);
569 outb(SEQ_I, 0x0b);
570 outb(SEQ_D, save0b);
571 return 0;
572 }
573
574 /* The version check that was here was moved to the init function by ARK */
575 /* in order to tell the 8900 from the 9440 model.. */
576
577 tvga8900_init(0, 0, 0);
578 return 1;
579 }
580
581
582 /* Bank switching function - set 64K bank number */
583
tvga8900_setpage(int page)584 static void tvga8900_setpage(int page)
585 {
586 port_out(0x0b, SEQ_I);
587 port_out(port_in(SEQ_D), SEQ_D);
588 port_in(SEQ_D); /* select new mode regs */
589
590 port_out(0x0e, SEQ_I);
591 port_out(page ^ 0x02, SEQ_D); /* select the page */
592 }
593
594
595 /* Set display start address (not for 16 color modes) */
596 /* Trident supports any address in video memory (up to 1Mb) */
597
tvga8900_setdisplaystart(int address)598 static void tvga8900_setdisplaystart(int address)
599 {
600 if (__svgalib_cur_mode == G320x200x256) {
601 outw(CRT_IC, 0x0d + (address & 0x00ff) * 256);
602 outw(CRT_IC, 0x0c + (address & 0xff00));
603 address <<= 2; /* Adjust address so that extended bits */
604 /* are correctly set later (too allow for */
605 /* multi-page flipping in 320x200). */
606 goto setextendedbits;
607 }
608 if (tvga8900_memory == 1024) {
609 outw(CRT_IC, 0x0d + ((address >> 3) & 0x00ff) * 256); /* sa2-sa9 */
610 outw(CRT_IC, 0x0c + ((address >> 3) & 0xff00)); /* sa10-sa17 */
611 } else {
612 outw(CRT_IC, 0x0d + ((address >> 2) & 0x00ff) * 256); /* sa2-sa9 */
613 outw(CRT_IC, 0x0c + ((address >> 2) & 0xff00)); /* sa10-sa17 */
614 }
615 if (__svgalib_cur_mode != G320x200x256) {
616 inb(0x3da); /* set ATC to addressing mode */
617 outb(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */
618 if (tvga8900_memory == 1024) {
619 outb(ATT_IW, (inb(ATT_R) & 0xf0) | (address & 7));
620 /* write sa0-2 to bits 0-2 */
621 address >>= 1;
622 } else
623 outb(ATT_IW, (inb(ATT_R) & 0xf0) | ((address & 3) << 1));
624 /* write sa0-1 to bits 1-2 */
625 }
626 setextendedbits:
627 outb(CRT_IC, 0x1e);
628 outb(CRT_DC, (inb(CRT_DC) & 0x5f) | 0x80 /* set bit 7 */
629 | ((address & 0x40000) >> 13)); /* sa18: write to bit 5 */
630 outb(SEQ_I, 0x0b);
631 outb(SEQ_D, 0); /* select 'old mode' */
632 outb(SEQ_I, 0x0e);
633 outb(SEQ_D, (inb(SEQ_D) & 0xfe)
634 | ((address & 0x80000) >> 19)); /* sa19: write to bit 0 */
635 outb(SEQ_I, 0x0b);
636 inb(SEQ_D); /* return to 'new mode' */
637 }
638
639
640 /* Set logical scanline length (usually multiple of 8) */
641 /* Trident supports multiples of 8 to 2040 */
642
tvga8900_setlogicalwidth(int width)643 static void tvga8900_setlogicalwidth(int width)
644 {
645 outw(CRT_IC, 0x13 + (width >> 3) * 256); /* lw3-lw11 */
646 }
647
648
649 /* Function table */
650
651 DriverSpecs __svgalib_tvga8900_driverspecs =
652 {
653 tvga8900_saveregs,
654 tvga8900_setregs,
655 nothing, /* unlock */
656 nothing, /* lock */
657 tvga8900_test,
658 tvga8900_init,
659 tvga8900_setpage,
660 (void (*)(int)) nothing, /* __svgalib_setrdpage */
661 (void (*)(int)) nothing, /* __svgalib_setwrpage */
662 tvga8900_setmode,
663 tvga8900_modeavailable,
664 tvga8900_setdisplaystart,
665 tvga8900_setlogicalwidth,
666 tvga8900_getmodeinfo,
667 0, /* bitblt */
668 0, /* imageblt */
669 0, /* fillblt */
670 0, /* hlinelistblt */
671 0, /* bltwait */
672 0, /* extset */
673 0,
674 0, /* linear */
675 NULL, /* Accelspecs */
676 NULL, /* Emulation */
677 };
678
679
680 /* Initialize chipset (called after detection) */
681
tvga8900_init(int force,int par1,int par2)682 static int tvga8900_init(int force, int par1, int par2)
683 {
684 if (force) {
685 #ifdef DEBUG
686 printf("Forcing memory to %dK\n", par1);
687 #endif
688 tvga8900_memory = par1;
689 tvga8900_nonint = par2 & 1;
690 /*
691 par2 specs
692 bit 31-3: reserved
693 bit 2-1: 00 - force 8900
694 01 - force 9440
695 10 - force 9680
696 11 - reserved
697 bit 0: force noninterlaced if set
698 only affects the 8900
699 */
700 switch (par2 & 6)
701 {
702 case 0: tvga_model=8900;
703 break;
704 case 2: tvga_model=9440;
705 break;
706 case 4: tvga_model=9680;
707 break;
708 case 6: tvga_model=0;
709 break;
710 }
711 } else {
712 port_out(0x1f, __svgalib_CRT_I);
713 /* this should detect up to 2M memory now */
714 tvga8900_memory = (port_in(__svgalib_CRT_D) & 0x07) * 256 + 256;
715
716 /* Now is the card running in interlace mode? */
717 port_out(0x0f, SEQ_I);
718 tvga8900_nonint = port_in(SEQ_D) & 0x04;
719
720 /* check version */
721 outw(SEQ_I, 0x000b);
722 switch (inb(SEQ_D)) {
723 case 0x02: /* 8800cs */
724 case 0x03: /* 8900b */
725 case 0x04: /* 8900c */
726 case 0x13:
727 case 0x33: /* 8900cl */
728 case 0x23: /* 9000 */
729 tvga_model = 8900;
730 break;
731 case 0xD3:
732 /* I know 0xD3 is a 9680, but if your 9680 is detected as a */
733 /* 9440, EMAIL ME! (ark) and I will change this... */
734 tvga_model = 9680;
735 break;
736 default:
737 /* Whatever the original 8900 driver thought was */
738 /* an invalid version, we will use as a 9440. */
739 tvga_model = 9440;
740 }
741 }
742
743 /* The 9440 uses ports 43C8 and 43C9... we need more privileges */
744 if (tvga_model == 9440 || tvga_model == 9680)
745 if (getenv("IOPERM") == NULL)
746 if (iopl(3) < 0) {
747 printf("tvga%d: Cannot get I/O permissions\n",tvga_model);
748 }
749
750
751 if (__svgalib_driver_report) {
752 if(tvga_model == 9440)
753 printf("Using Trident 9440 driver (%dK)\n",
754 tvga8900_memory);
755 else if(tvga_model == 9680)
756 printf("Using Trident 9680 driver (%dK)\n",
757 tvga8900_memory);
758 else
759 printf("Using Trident 8900/9000 driver (%dK, %sinterlaced).\n",
760 tvga8900_memory, (tvga8900_nonint) ? "non-" : "");
761 }
762 __svgalib_driverspecs = &__svgalib_tvga8900_driverspecs;
763 setup_registers();
764 __svgalib_banked_mem_base=0xa0000;
765 __svgalib_banked_mem_size=0x10000;
766 return 0;
767 }
768