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