1 /*
2 * VGAlib version 1.2 - (c) 1993 Tommy Frandsen
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it without any restrictions. This library is distributed
6 * in the hope that it will be useful, but without any warranty.
7 *
8 * Multi-chipset support Copyright (C) 1993 Harm Hanemaayer
9 * S3 805,868 support Copyright (C) 1995 Stephen Lee
10 */
11
12 /*
13 * Mar 1999 (Eduardo ...)
14 * Recognizes Trio3D as Trio64
15 *
16 * Sep 1997 (Greg Alexander):
17 * Recognizes S3Trio64V2/DX cards as Trio64's.
18 *
19 * Feb 1996 (Stephen Lee):
20 * 968/IBMRGB support. Only 256 colors for now.
21 * can now save more than 10 DAC registers (IBMRGB has 256!)
22 * Trio64 patch from Moto Kawamura <kawamura@mmp.cl.nec.co.jp>.
23 * Changed handling of CR34 for VGA modes at Andreas' suggestion.
24 * Changes to s3_saveregs() and s3_setregs() to make them more safe against
25 * lockups.
26 * 16 color mode should work on the 868/SDAC.
27 * SDAC 4/8bpp doesn't seem to do pixel multiplexing.
28 *
29 * Dec 1995 (Stephen Lee):
30 * Fixed color problem with 868 (CR43 again!). Could somebody find the
31 * value that works with Trio64?
32 *
33 * Nov 1995 (Stephen Lee):
34 * Linear addressing mode partially works (but is very alpha).
35 * Merged in Andreas Arens' <ari@av.rwth-aachen.de> patch for the 928.
36 *
37 * Sep 1995 (Stephen Lee):
38 * 16 Colors works on my 805, should work on other cards too.
39 *
40 * Alternate banking scheme for 864+. If you have problems, try undefining
41 * S3_LINEAR_MODE_BANKING_864.
42 *
43 * 8 bit color *really* works. Took me 3 months to bag this sucker.
44 *
45 * SVGA 8 bit color modes works. 320x200x256 is not really 'packed-pixel',
46 * it occupies 256K per page. There is no SVGA 320x200x256 mode; I cannot
47 * get the display (timing?) right.
48 *
49 * Aug 1995 (Stephen Lee):
50 * Added "Dacspeed" parsing.
51 * Added support for CLUT8_8 on ATT20C490/498.
52 * Improved support for S3-801/805.
53 * 15/16/24 bit colors works on the 805 + ATT20C490 I tested.
54 * Newer chipsets are recognized (but no support coded in yet).
55 * Should recognize memory size correctly on S3-924.
56 *
57 * Dec 1994 (Harm Hanemaayer):
58 * Partially rewritten using new SVGA-abstracted interface.
59 * Based on XFree86 code (accel/s3/s3.c and s3init.c).
60 * Goal is to have support for the S3-864 + S3-SDAC (which I can test).
61 * 80x with GENDAC might also be supported.
62 * Also, 640x480x256 should work on cards that have standard 25 and 28 MHz
63 * clocks.
64 *
65 * XFree86-equivalent clock select is now supported plus some
66 * industry-standard RAMDACs.
67 *
68 * Remaining problems:
69 * * Okay, okay, so 256 color still isn't fully working on the 805. I'm
70 * trying to get a fix for it.
71 *
72 * * The DCLK limit for 864/868 is a bit too relaxed. If you see noise at
73 * the highest resolutions when the screen is drawing it is possibly due
74 * to this. (How about changing MCLK?)
75 *
76 * * Horizontal Total is limited to 4088 which makes some modes unavailable
77 * (e.g. 800x600x16M with HTotal > 1022). Should experiment with
78 * CR43.7?
79 *
80 * * Some 864 problems are now fixed -- XF86_S3 seems to program the
81 * linewidth in bytes doubled for the S3-864 with > 1024K, which
82 * caused problems for this driver. There's still interference
83 * though when writing to video memory in the higher resolutions.
84 *
85 * * XXXX results of malloc() are not checked: should fix sometime.
86 */
87
88 #include <stdlib.h>
89 #include <stdarg.h>
90 #include <stdio.h>
91 #include <string.h>
92 #include <unistd.h> /* iopl() */
93 #include "vga.h"
94 #include "libvga.h"
95 #include "driver.h"
96 #include "timing.h"
97 #include "ramdac/ramdac.h"
98 #include "clockchip/clockchip.h"
99 #include "vgaregs.h"
100 #include "interface.h"
101 #include "8514a.h"
102 #include "vgapci.h"
103
104 /* no acceleration as of now. */
105 #undef S3_USE_GRAPHIC_ENGINE
106
107 /* kludge packed pixel for 320x200x256 */
108 /* XXXX doesn't really work */
109 #undef S3_KLUDGE_PAGE_MODE
110
111 /* use alternate 'linear' banking method for 864+ */
112 #undef S3_LINEAR_MODE_BANKING_864
113
114 #ifdef __alpha__ /* no good for alpha's */
115 #undef S3_LINEAR_MODE_BANKING_864
116 #endif
117
118 /*
119 * supports linear buffer.
120 *
121 * XXXX does not work with console switching and might be incompatible with
122 * S3_LINEAR_MODE_BANKING_864.
123 */
124 #define S3_LINEAR_SUPPORT
125
126 /* supports 16 colors */
127 #define S3_16_COLORS
128
129 /*
130 * zero wait state + (ramdac?) FIFO for 864 & 805,
131 * twice as fast but might not work on some cards.
132 */
133 #undef S3_0_WAIT_805_864
134
135 enum {
136 S3_911, S3_924, S3_801, S3_805, S3_928, S3_864, S3_964, S3_TRIO32,
137 S3_TRIO64, S3_866, S3_868, S3_968, S3_765
138 };
139
140 static const char *s3_chipname[] =
141 {"911", "924", "801", "805", "928",
142 "864", "964", "Trio32", "Trio64", "866", "868", "968", "Trio64V+"};
143
144 #define S3_CR(n) (EXT + (0x##n) - 0x30)
145
146 #define S3_CR30 S3_CR(30)
147 #define S3_CR31 S3_CR(31)
148 #define S3_CR32 S3_CR(32)
149 #define S3_CR33 S3_CR(33)
150 #define S3_CR34 S3_CR(34)
151 #define S3_CR35 S3_CR(35)
152 #define S3_CR3A S3_CR(3A)
153 #define S3_CR3B S3_CR(3B)
154 #define S3_CR3C S3_CR(3C)
155 #define S3_CR40 S3_CR(40)
156 #define S3_CR42 S3_CR(42)
157 #define S3_CR43 S3_CR(43)
158 #define S3_CR44 S3_CR(44)
159 #define S3_CR50 S3_CR(50) /* 801+ */
160 #define S3_CR51 S3_CR(51)
161 #define S3_CR53 S3_CR(53)
162 #define S3_CR54 S3_CR(54)
163 #define S3_CR55 S3_CR(55)
164 #define S3_CR58 S3_CR(58)
165 #define S3_CR59 S3_CR(59)
166 #define S3_CR5A S3_CR(5A)
167 #define S3_CR5D S3_CR(5D)
168 #define S3_CR5E S3_CR(5E)
169 #define S3_CR60 S3_CR(60)
170 #define S3_CR61 S3_CR(61)
171 #define S3_CR62 S3_CR(62)
172 #define S3_CR67 S3_CR(67)
173 #define S3_CR6A S3_CR(6A)
174 #define S3_CR6D S3_CR(6D)
175
176 /* For debugging, these (non-)registers are read also (but never written). */
177
178 #define S3_CR36 S3_CR(36)
179 #define S3_CR37 S3_CR(37)
180 #define S3_CR38 S3_CR(38)
181 #define S3_CR39 S3_CR(39)
182 #define S3_CR3D S3_CR(3D)
183 #define S3_CR3E S3_CR(3E)
184 #define S3_CR3F S3_CR(3F)
185 #define S3_CR45 S3_CR(45)
186 #define S3_CR46 S3_CR(46)
187 #define S3_CR47 S3_CR(47)
188 #define S3_CR48 S3_CR(48)
189 #define S3_CR49 S3_CR(49)
190 #define S3_CR4A S3_CR(4A)
191 #define S3_CR4B S3_CR(4B)
192 #define S3_CR4C S3_CR(4C)
193 #define S3_CR4D S3_CR(4D)
194 #define S3_CR4E S3_CR(4E)
195 #define S3_CR4F S3_CR(4F)
196 #define S3_CR52 S3_CR(52)
197 #define S3_CR56 S3_CR(56)
198 #define S3_CR57 S3_CR(57)
199 #define S3_CR5B S3_CR(5B)
200 #define S3_CR5C S3_CR(5C)
201 #define S3_CR5F S3_CR(5F)
202 #define S3_CR63 S3_CR(63)
203 #define S3_CR64 S3_CR(64)
204 #define S3_CR65 S3_CR(65)
205 #define S3_CR66 S3_CR(66)
206 #define S3_CR6E S3_CR(6E)
207 #define S3_CR6F S3_CR(6F)
208
209 /* Trio extended SR registers */
210
211 #define S3_SR(n) (S3_CR6F + 1 + (0x##n) - 0x08)
212
213 #define S3_SR08 S3_SR(08)
214 #define S3_SR09 S3_SR(09)
215 #define S3_SR0A S3_SR(0A)
216 #define S3_SR0D S3_SR(0D)
217 #define S3_SR10 S3_SR(10)
218 #define S3_SR11 S3_SR(11)
219 #define S3_SR12 S3_SR(12)
220 #define S3_SR13 S3_SR(13)
221 #define S3_SR15 S3_SR(15)
222 #define S3_SR18 S3_SR(18)
223 #define S3_SR1D S3_SR(1D)
224
225 #define S3_8514_OFFSET (S3_SR1D + 1)
226
227 #define S3_8514_COUNT (1) /* number of 2-byte words */
228
229 #define S3_DAC_OFFSET (S3_8514_OFFSET + (S3_8514_COUNT * 2))
230
231 #define S3_TOTAL_REGS (S3_DAC_OFFSET + MAX_DAC_STATE)
232
233 /* 8514 regs */
234 #define S3_ADVFUNC_CNTL 0
235
236 static unsigned short s3_8514regs[S3_8514_COUNT] =
237 {
238 /* default assuming text mode */
239 0x0000U
240 };
241
242 /* flags used by this driver */
243 #define S3_LOCALBUS 0x01
244 #define S3_CLUT8_8 0x02
245 #define S3_OLD_STEPPING 0x04
246
247 static int s3_flags = 0;
248
249 static int s3_chiptype;
250 static int s3_memory;
251 static CardSpecs *cardspecs;
252 static DacMethods *dac_used;
253 static ClockChipMethods *clk_used;
254 static int dac_speed = 0;
255
256 int s3Mclk = 0;
257
258 /* forward declaration. */
259 extern DriverSpecs __svgalib_s3_driverspecs;
260
261 static int s3_init(int, int, int);
262 static void s3_setpage(int page);
263 #ifdef S3_LINEAR_MODE_BANKING_864
264 static void s3_setpage864(int page);
265 #endif
266
267 #ifdef S3_LINEAR_SUPPORT
268 static int s3_cr40;
269 static int s3_cr54;
270 static int s3_cr58;
271 static int s3_cr59;
272 static int s3_cr5A;
273 static int s3_linear_opt = 0;
274 static int s3_linear_addr = 0;
275 static int s3_linear_base = 0;
276 static void s3_linear_enable(void);
277 static void s3_linear_disable(void);
278 #endif
279
nothing(void)280 static void nothing(void)
281 {
282 }
283
284 /*
285 * Lock S3's registers.
286 * There are more locks, but this should suffice.
287 *
288 * ARI: More complete Extended VGA Register Lock Documentation, as of Ferraro:
289 *
290 * Register Bit Controls Access To: Function
291 * CR33 1 CR7 bits 1 and 6 1=disable write protect
292 * setting of CR11 bit 7
293 * CR33 4 Ramdac Register 1=disable writes
294 * CR33 6 Palette/Overscan Registers 1=lock
295 * CR34 5 Memory Configuration bit 5 1=lock
296 * CR34 7 Misc Register bit 3-2 (Clock) 1=lock
297 * CR35 4 Vertical Timing Registers 1=lock
298 * CR35 5 Horizontal Timing Registers 1=lock
299 *
300 * XXXX mostly, need to lock the enhanced command regs on the 805 (and
301 * probably below) to avoid display corruption.
302 */
s3_lock(void)303 static void s3_lock(void)
304 {
305 __svgalib_outCR(0x39, 0x00); /* Lock system control regs. */
306 __svgalib_outCR(0x38, 0x00); /* Lock special regs. */
307 }
308
s3_lock_enh(void)309 static void s3_lock_enh(void)
310 {
311 if (s3_chiptype > S3_911)
312 __svgalib_outCR(0x40, __svgalib_inCR(0x40) & ~0x01); /* Lock enhanced command regs. */
313 s3_lock();
314 }
315
316 /*
317 * Unlock S3's registers.
318 * There are more locks, but this should suffice.
319 */
s3_unlock(void)320 static void s3_unlock(void)
321 {
322 __svgalib_outCR(0x38, 0x48); /* Unlock special regs. */
323 __svgalib_outCR(0x39, 0xA5); /* Unlock system control regs. */
324 }
325
s3_unlock_enh(void)326 static void s3_unlock_enh(void)
327 {
328 s3_unlock();
329 if (s3_chiptype > S3_911)
330 __svgalib_outCR(0x40, __svgalib_inCR(0x40) | 0x01); /* Unlock enhanced command regs. */
331 }
332
333 /*
334 * Adjust the display width. This is necessary for the graphics
335 * engine if acceleration is used. However it will require more
336 * memory making some modes unavailable.
337 */
s3_adjlinewidth(int oldwidth)338 static int s3_adjlinewidth(int oldwidth)
339 {
340 if (s3_chiptype < S3_801)
341 return 1024;
342 #ifdef S3_USE_GRAPHIC_ENGINE
343 if (oldwidth <= 640)
344 return 640;
345 if (oldwidth <= 800)
346 return 800;
347 if (oldwidth <= 1024)
348 return 1024;
349 if (!(s3_flags & S3_OLD_STEPPING))
350 if (oldwidth <= 1152)
351 return 1152;
352 if (oldwidth <= 1280)
353 return 1280;
354 if (oldwidth <= 1600 && s3_chiptype >= S3_864)
355 return 1600;
356
357 return 2048;
358 #else
359 return oldwidth;
360 #endif
361 }
362
363 /* Fill in chipset specific mode information */
364
s3_getmodeinfo(int mode,vga_modeinfo * modeinfo)365 static void s3_getmodeinfo(int mode, vga_modeinfo * modeinfo)
366 {
367 switch (modeinfo->colors) {
368 case 16: /* 4-plane 16 color mode */
369 modeinfo->maxpixels = s3_memory * 1024 * 2;
370 break;
371 default:
372 modeinfo->maxpixels = s3_memory * 1024 /
373 modeinfo->bytesperpixel;
374 }
375
376 /* Adjust line width (only for SVGA modes) */
377 if (!(mode < G640x480x256 || mode == G720x348x2))
378 modeinfo->linewidth = s3_adjlinewidth(modeinfo->linewidth);
379
380 modeinfo->maxlogicalwidth = 8184;
381 if (s3_chiptype >= S3_801)
382 modeinfo->startaddressrange = 0x3fffff;
383 else
384 modeinfo->startaddressrange = 0xfffff;
385
386 #ifdef S3_KLUDGE_PAGE_MODE
387 if (mode == G320x200x256) {
388 /* set page size to 256k. */
389 modeinfo->startaddressrange /= 4;
390 modeinfo->maxpixels /= 4;
391 }
392 #else
393 if (mode == G320x200x256) {
394 /* disable page flipping. */
395 /* modeinfo->startaddressrange = 0xffff; */
396 modeinfo->startaddressrange = 0;
397 modeinfo->maxpixels = 65536;
398 }
399 #endif
400
401 modeinfo->haveblit = 0;
402 modeinfo->flags &= ~HAVE_RWPAGE;
403 modeinfo->flags |= HAVE_EXT_SET;
404 #ifdef S3_LINEAR_SUPPORT
405 if (modeinfo->bytesperpixel >= 1) {
406 modeinfo->flags |= CAPABLE_LINEAR;
407 if (s3_linear_addr)
408 modeinfo->flags |= IS_LINEAR;
409 }
410 #endif
411
412 modeinfo->memory = s3_memory;
413 modeinfo->chiptype = s3_chiptype;
414 }
415
416 /*
417 * XXX Part of this function should be implemented in ramdac.c,
418 * but we just kludge it here for now.
419 */
s3_ext_set(unsigned what,va_list params)420 static int s3_ext_set(unsigned what, va_list params)
421 {
422 int param2, old_values;
423 unsigned char regs[10];
424
425 /* only know this, for now */
426 if (dac_used->id != ATT20C490 && dac_used->id != ATT20C498 &&
427 dac_used->id != SIERRA_15025)
428 return 0;
429
430 param2 = va_arg(params, int);
431 old_values = (s3_flags & S3_CLUT8_8) ? VGA_CLUT8 : 0;
432
433 switch (what) {
434 case VGA_EXT_AVAILABLE:
435 switch (param2) {
436 case VGA_AVAIL_SET:
437 return VGA_EXT_AVAILABLE | VGA_EXT_SET | VGA_EXT_CLEAR | VGA_EXT_RESET;
438 case VGA_AVAIL_ACCEL:
439 return 0;
440 case VGA_AVAIL_FLAGS:
441 return VGA_CLUT8;
442 }
443 break;
444
445 case VGA_EXT_SET:
446 if (param2 & VGA_CLUT8)
447 goto setclut8;
448
449 case VGA_EXT_CLEAR:
450 if (param2 & VGA_CLUT8)
451 goto clearclut8;
452
453 case VGA_EXT_RESET:
454 if (param2 & VGA_CLUT8) {
455 setclut8:
456 dac_used->saveState(regs);
457 if (regs[0] == 0x00) { /* 8bpp, 6 bits/color */
458 s3_flags |= S3_CLUT8_8;
459 if (dac_used->id == SIERRA_15025)
460 regs[1] = 1;
461 regs[0] = 0x02;
462 }
463 dac_used->restoreState(regs);
464 return old_values;
465 } else {
466 clearclut8:
467 dac_used->saveState(regs);
468 if (regs[0] == 0x02) { /* 8bpp, 8 bits/color */
469 s3_flags &= ~S3_CLUT8_8;
470 if (dac_used->id == SIERRA_15025)
471 regs[1] = 0;
472 regs[0] = 0x00;
473 }
474 dac_used->restoreState(regs);
475 return old_values;
476 }
477 }
478 return 0;
479 }
480
481 /* Return non-zero if mode is available */
482
s3_modeavailable(int mode)483 static int s3_modeavailable(int mode)
484 {
485 struct info *info;
486 ModeInfo *modeinfo;
487 ModeTiming *modetiming;
488
489 if (mode < G640x480x256 || mode == G720x348x2)
490 return __svgalib_vga_driverspecs.modeavailable(mode);
491
492 /* Enough memory? */
493 info = &__svgalib_infotable[mode];
494 if (s3_memory * 1024 < info->ydim * s3_adjlinewidth(info->xbytes))
495 return 0;
496
497 modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
498
499 modetiming = malloc(sizeof(ModeTiming));
500 if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
501 free(modetiming);
502 free(modeinfo);
503 return 0;
504 }
505 free(modetiming);
506 free(modeinfo);
507
508 return SVGADRV;
509 }
510
511 /*
512 * save S3 registers. Lock registers receive special treatment
513 * so dumpreg will work under X.
514 */
s3_saveregs(unsigned char regs[])515 static int s3_saveregs(unsigned char regs[])
516 {
517 unsigned char b, bmax;
518 unsigned char cr38, cr39, cr40;
519
520 cr38 = __svgalib_inCR(0x38);
521 __svgalib_outCR(0x38, 0x48); /* unlock S3 VGA regs (CR30-CR3B) */
522
523 cr39 = __svgalib_inCR(0x39);
524 __svgalib_outCR(0x39, 0xA5); /* unlock S3 system control (CR40-CR4F) */
525 /* and extended regs (CR50-CR6D) */
526
527 cr40 = __svgalib_inCR(0x40); /* unlock enhanced regs */
528 __svgalib_outCR(0x40, cr40 | 0x01);
529
530 /* retrieve values from private copy */
531 memcpy(regs + S3_8514_OFFSET, s3_8514regs, S3_8514_COUNT * 2);
532
533 /* get S3 VGA/Ext registers */
534 bmax = 0x4F;
535 if (s3_chiptype >= S3_801)
536 bmax = 0x66;
537 if (s3_chiptype >= S3_864)
538 bmax = 0x6D;
539 for (b = 0x30; b <= bmax; b++)
540 regs[EXT + b - 0x30] = __svgalib_inCR(b);
541
542 /* get S3 ext. SR registers */
543 /* if (s3_chiptype >= S3_864) { */
544 if (s3_chiptype == S3_TRIO32 || s3_chiptype == S3_TRIO64
545 || s3_chiptype == S3_765) {/* SL: actually Trio32/64/V+ */
546 regs[S3_SR08] = __svgalib_inSR(0x08);
547 __svgalib_outSR(0x08, 0x06); /* unlock extended seq regs */
548 regs[S3_SR09] = __svgalib_inSR(0x09);
549 regs[S3_SR0A] = __svgalib_inSR(0x0A);
550 regs[S3_SR0D] = __svgalib_inSR(0x0D);
551 regs[S3_SR10] = __svgalib_inSR(0x10);
552 regs[S3_SR11] = __svgalib_inSR(0x11);
553 regs[S3_SR12] = __svgalib_inSR(0x12);
554 regs[S3_SR13] = __svgalib_inSR(0x13);
555 regs[S3_SR15] = __svgalib_inSR(0x15);
556 regs[S3_SR18] = __svgalib_inSR(0x18);
557 __svgalib_outSR(0x08, regs[S3_SR08]);
558 }
559
560 dac_used->saveState(regs + S3_DAC_OFFSET);
561
562 /* leave the locks the way we found it */
563 __svgalib_outCR(0x40, regs[EXT + 0x40 - 0x30] = cr40);
564 __svgalib_outCR(0x39, regs[EXT + 0x39 - 0x30] = cr39);
565 __svgalib_outCR(0x38, regs[EXT + 0x38 - 0x30] = cr38);
566 #if 0
567 #include "ramdac/IBMRGB52x.h"
568
569 do {
570 unsigned char m, n, df;
571
572 printf("pix_fmt = 0x%02X, 8bpp = 0x%02X, 16bpp = 0x%02X, 24bpp = 0x%02X, 32bpp = 0x%02X,\n"
573 "CR58 = 0x%02X, CR66 = 0x%02X, CR67 = 0x%02X, CR6D = 0x%02X\n",
574 regs[S3_DAC_OFFSET + IBMRGB_pix_fmt],
575 regs[S3_DAC_OFFSET + IBMRGB_8bpp],
576 regs[S3_DAC_OFFSET + IBMRGB_16bpp],
577 regs[S3_DAC_OFFSET + IBMRGB_24bpp],
578 regs[S3_DAC_OFFSET + IBMRGB_32bpp],
579 regs[S3_CR58],
580 regs[S3_CR66],
581 regs[S3_CR67],
582 regs[S3_CR6D]);
583
584 m = regs[S3_DAC_OFFSET + IBMRGB_m0 + 4];
585 n = regs[S3_DAC_OFFSET + IBMRGB_n0 + 4];
586 df = m >> 6;
587 m &= ~0xC0;
588
589 printf("m = 0x%02X %d, n = 0x%02X %d, df = 0x%02X %d, freq = %.3f\n",
590 m, m, n, n, df, df, ((m + 65.0) / n) / (8 >> df) * 16.0);
591 } while (0);
592 #endif
593 return S3_DAC_OFFSET - VGA_TOTAL_REGS + dac_used->stateSize;
594 }
595
596 /* Set chipset-specific registers */
s3_setregs(const unsigned char regs[],int mode)597 static void s3_setregs(const unsigned char regs[], int mode)
598 {
599 unsigned char b, bmax;
600 /*
601 * Right now, anything != 0x00 gets written in s3_setregs.
602 * May change this into a bitmask later.
603 */
604 static unsigned char s3_regmask[] =
605 {
606 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x00, 0x00, /* CR30-CR37 */
607 0x00, 0x00, 0x3A, 0x3B, 0x3C, 0x00, 0x00, 0x00, /* CR38-CR3F */
608 0x00, 0x00, 0x42, 0x43, 0x44, 0x00, 0x00, 0x00, /* CR40-CR47 */
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* CR48-CR4F */
610 0x50, 0x51, 0x00, 0x00, 0x54, 0x55, 0x00, 0x00, /* CR50-CR57 */
611 0x58, 0x59, 0x5A, 0x00, 0x00, 0x5D, 0x5E, 0x00, /* CR58-CR5F */
612 0x60, 0x61, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, /* CR60-CR67 */
613 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00 /* CR68-CR6D */
614 };
615
616 s3_unlock_enh();
617
618 /* save a private copy */
619 memcpy(s3_8514regs, regs + S3_8514_OFFSET, S3_8514_COUNT * 2);
620 /*
621 * set this first, so if we segfault on this (e.g. we didn't do a iopl(3))
622 * we don't get a screwed up display
623 */
624 outw(ADVFUNC_CNTL, s3_8514regs[S3_ADVFUNC_CNTL]);
625
626 /* get S3 VGA/Ext registers */
627 bmax = 0x4F;
628 if (s3_chiptype >= S3_801)
629 bmax = 0x66;
630 if (s3_chiptype >= S3_864)
631 bmax = 0x6D;
632 for (b = 0x30; b <= bmax; b++) {
633 if (s3_regmask[b - 0x30])
634 __svgalib_outCR(b, regs[EXT + b - 0x30]);
635 }
636
637 if (dac_used->id != NORMAL_DAC) {
638 unsigned char CR1;
639 /* Blank the screen. */
640 CR1 = __svgalib_inCR(0x01);
641 __svgalib_outCR(0x01, CR1 | 0x20);
642
643 __svgalib_outbCR(0x55, __svgalib_inCR(0x55) | 1);
644 __svgalib_outCR(0x66, regs[S3_CR66]);
645 __svgalib_outCR(0x67, regs[S3_CR67]); /* S3 pixmux. */
646
647 dac_used->restoreState(regs + S3_DAC_OFFSET);
648
649 __svgalib_outCR(0x6D, regs[S3_CR6D]);
650 __svgalib_outbCR(0x55, __svgalib_inCR(0x55) & ~1);
651
652 __svgalib_outCR(0x01, CR1); /* Unblank screen. */
653 }
654 #ifdef S3_LINEAR_SUPPORT
655 if (mode == TEXT && s3_linear_addr)
656 s3_linear_disable(); /* make sure linear is off */
657 #endif
658
659 /* restore CR38/39 (may lock other regs) */
660 if (mode == TEXT) {
661 /* restore lock registers as well */
662 __svgalib_outCR(0x40, regs[S3_CR40]);
663 __svgalib_outCR(0x39, regs[S3_CR39]);
664 __svgalib_outCR(0x38, regs[S3_CR38]);
665 } else
666 s3_lock_enh();
667 }
668
669 /*
670 * Initialize register state for a mode.
671 */
672
s3_initializemode(unsigned char * moderegs,ModeTiming * modetiming,ModeInfo * modeinfo)673 static void s3_initializemode(unsigned char *moderegs,
674 ModeTiming * modetiming, ModeInfo * modeinfo)
675 {
676 /* Get current values. */
677 s3_saveregs(moderegs);
678
679 /* Set up the standard VGA registers for a generic SVGA. */
680 __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo);
681
682 /* Set up the extended register values, including modifications */
683 /* of standard VGA registers. */
684
685 moderegs[VGA_SR0] = 0x03;
686 moderegs[VGA_CR13] = modeinfo->lineWidth >> 3;
687 moderegs[VGA_CR17] = 0xE3;
688
689 if (modeinfo->lineWidth / modeinfo->bytesPerPixel == 2048)
690 moderegs[S3_CR31] = 0x8F;
691 else
692 moderegs[S3_CR31] = 0x8D;
693 #ifdef S3_LINEAR_MODE_BANKING_864
694 if (s3_chiptype >= S3_864) {
695 /* moderegs[S3_ENHANCEDMODE] |= 0x01; */
696 /* Enable enhanced memory mode. */
697 moderegs[S3_CR31] |= 0x04;
698 /* Enable banking via CR6A in linear mode. */
699 moderegs[S3_CR31] |= 0x01;
700 }
701 #endif
702 moderegs[S3_CR32] = 0;
703 moderegs[S3_CR33] = 0x20;
704 moderegs[S3_CR34] = 0x10; /* 1024 */
705 moderegs[S3_CR35] = 0;
706 /* Call cebank() here when setting registers. */
707 if (modeinfo->bitsPerPixel >= 8) {
708 moderegs[S3_CR3A] = 0xB5;
709 if (s3_chiptype == S3_928)
710 /* ARI: Turn on CHAIN4 for 928, since __svgalib_setup_VGA_registers
711 initializes ModeX */
712 moderegs[VGA_CR14] = 0x60;
713 } else {
714 /* 16 color mode */
715 moderegs[VGA_CR13] = modeinfo->lineWidth >> 1;
716 moderegs[VGA_GR0] = 0x0F;
717 moderegs[VGA_GR1] = 0x0F;
718 moderegs[VGA_GR5] = 0x00; /* write mode 0 */
719 moderegs[VGA_AR11] = 0x00;
720 moderegs[S3_CR3A] = 0x85;
721 }
722
723 moderegs[S3_CR3B] = (moderegs[VGA_CR0] + moderegs[VGA_CR4] + 1) / 2;
724 moderegs[S3_CR3C] = moderegs[VGA_CR0] / 2;
725 if (s3_chiptype == S3_911) {
726 moderegs[S3_CR40] &= 0xF2;
727 moderegs[S3_CR40] |= 0x09;
728 } else if (s3_flags & S3_LOCALBUS) {
729 moderegs[S3_CR40] &= 0xF2;
730 /* Pegasus wants 0x01 for zero wait states. */
731 #ifdef S3_0_WAIT_805_864
732 moderegs[S3_CR40] |= 0x09; /* use fifo + 0 wait state */
733 #else
734 moderegs[S3_CR40] |= 0x05;
735 #endif
736 } else {
737 moderegs[S3_CR40] &= 0xF6;
738 moderegs[S3_CR40] |= 0x01;
739 }
740
741 if (modeinfo->bitsPerPixel >= 24) {
742 /* 24/32 bit color */
743 if (s3_chiptype == S3_864 || s3_chiptype == S3_964)
744 moderegs[S3_CR43] = 0x08;
745 else if (s3_chiptype == S3_928 && dac_used->id == SIERRA_15025)
746 moderegs[S3_CR43] = 0x01; /* ELSA Winner 1000 */
747 } else if (modeinfo->bitsPerPixel >= 15) {
748 /* 15/16 bit color */
749 if (s3_chiptype <= S3_864 || s3_chiptype >= S3_866) { /* XXXX Trio? */
750 moderegs[S3_CR43] = 0x08;
751 if (dac_used->id == IBMRGB52x)
752 moderegs[S3_CR43] = 0x10;
753 else if (s3_chiptype == S3_928 && dac_used->id == SIERRA_15025)
754 moderegs[S3_CR43] = 0x01;
755 if (s3_chiptype <= S3_924 && dac_used->id != NORMAL_DAC)
756 moderegs[S3_CR43] = 0x01;
757
758 } else
759 /* XXXX some DAC might need this; XF86 source says... */
760 moderegs[S3_CR43] = 0x09;
761 } else {
762 /* 4/8 bit color */
763 moderegs[S3_CR43] = 0x00;
764 }
765
766 if (s3_chiptype >= S3_924 && s3_chiptype <= S3_928) { /* different for 864+ */
767 s3_8514regs[S3_ADVFUNC_CNTL] = 0x0002;
768 if ((s3_chiptype == S3_928 && modeinfo->bitsPerPixel != 4) || !(s3_flags & S3_OLD_STEPPING))
769 s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0001;
770 if (modeinfo->bitsPerPixel == 4)
771 s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0004;
772 #if 0
773 /* 864 databook says it is for enhanced 4bpp */
774 if (modeinfo->lineWidth > 640)
775 s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0004;
776 #endif
777 } else if (s3_chiptype == S3_968) {
778 s3_8514regs[S3_ADVFUNC_CNTL] = 0x0002;
779 if (modeinfo->bitsPerPixel == 4)
780 s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0004;
781 #ifdef PIXEL_MULTIPLEXING
782 else
783 s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0001;
784 #endif
785 } else if (modeinfo->lineWidth / modeinfo->bytesPerPixel == 1024)
786 s3_8514regs[S3_ADVFUNC_CNTL] = 0x0007;
787 else
788 s3_8514regs[S3_ADVFUNC_CNTL] = 0x0003;
789
790 moderegs[S3_CR44] = 0;
791 /* Skip CR45, 'hi/truecolor cursor color enable'. */
792
793 if (s3_chiptype >= S3_801) {
794 int m, n; /* for FIFO balancing */
795
796 /* XXXX Not all chips support all widths. */
797 moderegs[S3_CR50] &= ~0xF1;
798 switch (modeinfo->bitsPerPixel) {
799 case 16:
800 moderegs[S3_CR50] |= 0x10;
801 break;
802 case 24: /* XXXX 868/968 only */
803 if (s3_chiptype >= S3_868)
804 moderegs[S3_CR50] |= 0x20;
805 break;
806 case 32:
807 moderegs[S3_CR50] |= 0x30;
808 break;
809 }
810
811 switch (modeinfo->lineWidth / modeinfo->bytesPerPixel) {
812 case 640:
813 moderegs[S3_CR50] |= 0x40;
814 break;
815 case 800:
816 moderegs[S3_CR50] |= 0x80;
817 break;
818 case 1152:
819 if (!(s3_flags & S3_OLD_STEPPING)) {
820 moderegs[S3_CR50] |= 0x01;
821 break;
822 } /* else fall through */
823 case 1280:
824 moderegs[S3_CR50] |= 0xC0;
825 break;
826 case 1600:
827 moderegs[S3_CR50] |= 0x81;
828 break;
829 /* 1024/2048 no change. */
830 }
831
832 moderegs[S3_CR51] &= 0xC0;
833 moderegs[S3_CR51] |= (modeinfo->lineWidth >> 7) & 0x30;
834
835 /* moderegs[S3_CR53] |= 0x10; *//* Enable MMIO. */
836 /* moderegs[S3_CR53] |= 0x20; *//* DRAM interleaving for S3_805i with 2MB */
837
838 n = 0xFF;
839 if (s3_chiptype >= S3_864 ||
840 s3_chiptype == S3_801 || s3_chiptype == S3_805) {
841 /*
842 * CRT FIFO balancing for DRAM cards and 964/968
843 * in VGA mode.
844 */
845 int clock, mclk;
846 if (modeinfo->bitsPerPixel < 8) {
847 clock = modetiming->pixelClock;
848 } else {
849 clock = modetiming->pixelClock *
850 modeinfo->bytesPerPixel;
851 }
852 if (s3_memory < 2048 || s3_chiptype == S3_TRIO32)
853 clock *= 2;
854 if (s3Mclk > 0)
855 mclk = s3Mclk;
856 else if (s3_chiptype == S3_801 || s3_chiptype == S3_805)
857 mclk = 50000; /* Assumption. */
858 else
859 mclk = 60000; /* Assumption. */
860 m = (int) ((mclk / 1000.0 * .72 + 16.867) * 89.736 / (clock / 1000.0 + 39) - 21.1543);
861 if (s3_memory < 2048 || s3_chiptype == S3_TRIO32)
862 m /= 2;
863 if (m > 31)
864 m = 31;
865 else if (m < 0) {
866 m = 0;
867 n = 16;
868 }
869 } else if (s3_memory == 512 || modetiming->HDisplay > 1200)
870 m = 0;
871 else if (s3_memory == 1024)
872 m = 2;
873 else
874 m = 20;
875
876 moderegs[S3_CR54] = m << 3;
877 moderegs[S3_CR60] = n;
878
879 moderegs[S3_CR55] &= 0x08;
880 moderegs[S3_CR55] |= 0x40;
881
882 #ifdef S3_LINEAR_MODE_BANKING_864
883 if (s3_chiptype >= S3_864) {
884 if (modeinfo->bitsPerPixel >= 8) {
885 /* Enable linear addressing. */
886 moderegs[S3_CR58] |= 0x10;
887 /* Set window size to 64K. */
888 moderegs[S3_CR58] &= ~0x03;
889 /* Assume CR59/5A are correctly set up for 0xA0000. */
890 /* Set CR6A linear bank to zero. */
891 moderegs[S3_CR6A] &= ~0x3F;
892 /* use alternate __svgalib_setpage() function */
893 __svgalib_s3_driverspecs.__svgalib_setpage = s3_setpage864;
894 } else {
895 /* doesn't work for 4bpp. */
896 __svgalib_s3_driverspecs.__svgalib_setpage = s3_setpage;
897 }
898 }
899 #endif
900 #ifdef S3_LINEAR_SUPPORT
901 moderegs[S3_CR59] = s3_cr59;
902 moderegs[S3_CR5A] = s3_cr5A;
903 #endif
904
905 /* Extended CRTC timing. */
906 moderegs[S3_CR5E] =
907 (((modetiming->CrtcVTotal - 2) & 0x400) >> 10) |
908 (((modetiming->CrtcVDisplay - 1) & 0x400) >> 9) |
909 (((modetiming->CrtcVSyncStart) & 0x400) >> 8) |
910 (((modetiming->CrtcVSyncStart) & 0x400) >> 6) | 0x40;
911
912 {
913 int i, j;
914 i = ((((modetiming->CrtcHTotal >> 3) - 5) & 0x100) >> 8) |
915 ((((modetiming->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) |
916 ((((modetiming->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) |
917 ((modetiming->CrtcHSyncStart & 0x800) >> 7);
918 if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 64)
919 i |= 0x08;
920 if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 32)
921 i |= 0x20;
922 j = ((moderegs[VGA_CR0] + ((i & 0x01) << 8) +
923 moderegs[VGA_CR4] + ((i & 0x10) << 4) + 1) / 2);
924 if (j - (moderegs[VGA_CR4] + ((i & 0x10) << 4)) < 4) {
925 if (moderegs[VGA_CR4] + ((i & 0x10) << 4) + 4 <= moderegs[VGA_CR0] + ((i & 0x01) << 8))
926 j = moderegs[VGA_CR4] + ((i & 0x10) << 4) + 4;
927 else
928 j = moderegs[VGA_CR0] + ((i & 0x01) << 8) + 1;
929 }
930
931 moderegs[S3_CR3B] = j & 0xFF;
932 i |= (j & 0x100) >> 2;
933 /* Interlace mode frame offset. */
934 moderegs[S3_CR3C] = (moderegs[VGA_CR0] + ((i & 0x01) << 8)) / 2;
935 moderegs[S3_CR5D] = (moderegs[S3_CR5D] & 0x80) | i;
936 }
937
938 {
939 int i;
940
941 if (modeinfo->bitsPerPixel < 8)
942 i = modetiming->HDisplay / 4 + 1;
943 else
944 i = modetiming->HDisplay *
945 modeinfo->bytesPerPixel / 4 + 1;
946
947 moderegs[S3_CR61] = (i >> 8) | 0x80;
948 moderegs[S3_CR62] = i & 0xFF;
949 }
950 } /* 801+ */
951 if (modetiming->flags & INTERLACED)
952 moderegs[S3_CR42] |= 0x20;
953
954 /*
955 * Clock select works as follows:
956 * Clocks 0 and 1 (VGA 25 and 28 MHz) can be selected via the
957 * two VGA MiscOutput clock select bits.
958 * If 0x3 is written to these bits, the selected clock index
959 * is taken from the S3 clock select register at CR42. Clock
960 * indices 0 and 1 should correspond to the VGA ones above,
961 * and 3 is often 0 MHz, followed by extended clocks for a
962 * total of mostly 16.
963 */
964
965 if (modetiming->flags & USEPROGRCLOCK)
966 moderegs[VGA_MISCOUTPUT] |= 0x0C; /* External clock select. */
967 else if (modetiming->selectedClockNo < 2) {
968 /* Program clock select bits 0 and 1. */
969 moderegs[VGA_MISCOUTPUT] &= ~0x0C;
970 moderegs[VGA_MISCOUTPUT] |=
971 (modetiming->selectedClockNo & 3) << 2;
972 } else if (modetiming->selectedClockNo >= 2) {
973 moderegs[VGA_MISCOUTPUT] |= 0x0C;
974 /* Program S3 clock select bits. */
975 moderegs[S3_CR42] &= ~0x1F;
976 moderegs[S3_CR42] |=
977 modetiming->selectedClockNo;
978 }
979 if (s3_chiptype == S3_TRIO64 || s3_chiptype == S3_765) {
980 moderegs[S3_CR33] &= ~0x08;
981 if (modeinfo->bitsPerPixel == 16)
982 moderegs[S3_CR33] |= 0x08;
983 /*
984 * The rest of the DAC/clocking is setup by the
985 * Trio64 code in the RAMDAC interface (ramdac.c).
986 */
987 }
988 if (dac_used->id != NORMAL_DAC) {
989 int colormode;
990 colormode = __svgalib_colorbits_to_colormode(modeinfo->bitsPerPixel,
991 modeinfo->colorBits);
992 dac_used->initializeState(&moderegs[S3_DAC_OFFSET],
993 modeinfo->bitsPerPixel, colormode,
994 modetiming->pixelClock);
995
996 if (dac_used->id == ATT20C490) {
997 int pixmux, invert_vclk, blank_delay;
998 pixmux = 0;
999 invert_vclk = 0;
1000 blank_delay = 2;
1001 if (colormode == CLUT8_6
1002 && modetiming->pixelClock >= 67500) {
1003 pixmux = 0x00;
1004 invert_vclk = 1;
1005 } else if (colormode == CLUT8_8)
1006 pixmux = 0x02;
1007 else if (colormode == RGB16_555)
1008 pixmux = 0xa0;
1009 else if (colormode == RGB16_565)
1010 pixmux = 0xc0;
1011 else if (colormode == RGB24_888_B)
1012 pixmux = 0xe0;
1013 moderegs[S3_CR67] = pixmux | invert_vclk;
1014 moderegs[S3_CR6D] = blank_delay;
1015 }
1016 if (dac_used->id == S3_SDAC) {
1017 int pixmux, invert_vclk, blank_delay;
1018 pixmux = 0;
1019 invert_vclk = 0;
1020 blank_delay = 0;
1021 if (colormode == CLUT8_6
1022 && modetiming->pixelClock >= 67500) {
1023 #ifdef SDAC_8BPP_PIXMUX
1024 /* x64 8bpp pixel multiplexing? */
1025 pixmux = 0x10;
1026 if (s3_chiptype != S3_866 && s3_chiptype != S3_868)
1027 invert_vclk = 1;
1028 blank_delay = 2;
1029 #endif
1030 } else if (colormode == RGB16_555) {
1031 pixmux = 0x30;
1032 blank_delay = 2;
1033 } else if (colormode == RGB16_565) {
1034 pixmux = 0x50;
1035 blank_delay = 2;
1036 } else if (colormode == RGB24_888_B) { /* XXXX 868/968 only */
1037 pixmux = 0x90;
1038 blank_delay = 2;
1039 } else if (colormode == RGB32_888_B) {
1040 pixmux = 0x70;
1041 blank_delay = 2;
1042 }
1043 moderegs[S3_CR67] = pixmux | invert_vclk;
1044 moderegs[S3_CR6D] = blank_delay;
1045 /* Clock select. */
1046 moderegs[S3_CR42] &= ~0x0F;
1047 moderegs[S3_CR42] |= 0x02;
1048 }
1049 if (dac_used->id == IBMRGB52x) {
1050 unsigned char pixmux, blank_delay, tmp;
1051 tmp = 0;
1052 pixmux = 0x11;
1053 blank_delay = 0;
1054 if (modeinfo->bitsPerPixel < 8 || colormode == RGB32_888_B)
1055 pixmux = 0x00;
1056 moderegs[S3_CR58] |= 0x40;
1057 moderegs[S3_CR65] = 0;
1058 moderegs[S3_CR66] &= 0xf8;
1059 moderegs[S3_CR66] |= tmp;
1060 #ifdef PIXEL_MULTIPLEXING
1061 moderegs[S3_CR67] = pixmux;
1062 #endif
1063 moderegs[S3_CR6D] = blank_delay;
1064 /* Clock select. */
1065 moderegs[S3_CR42] &= ~0x0F;
1066 moderegs[S3_CR42] |= 0x02;
1067 }
1068 }
1069 #ifdef S3_LINEAR_SUPPORT
1070 s3_cr58 = moderegs[S3_CR58];
1071 s3_cr40 = moderegs[S3_CR40];
1072 s3_cr54 = moderegs[S3_CR54];
1073 #endif
1074 if (clk_used == &__svgalib_I2061A_clockchip_methods &&
1075 (modetiming->flags & USEPROGRCLOCK)) {
1076 /* Clock select. */
1077 moderegs[S3_CR42] &= ~0x0F;
1078 moderegs[S3_CR42] |= 0x02;
1079 }
1080 /* update the 8514 regs */
1081 memcpy(moderegs + S3_8514_OFFSET, s3_8514regs, S3_8514_COUNT * 2);
1082 }
1083
1084
1085 /* Set a mode */
1086
s3_setmode(int mode,int prv_mode)1087 static int s3_setmode(int mode, int prv_mode)
1088 {
1089 ModeInfo *modeinfo;
1090 ModeTiming *modetiming;
1091 unsigned char moderegs[S3_TOTAL_REGS];
1092 int res;
1093
1094 if (mode < G640x480x256 || mode == G720x348x2) {
1095 /* Let the standard VGA driver set standard VGA modes. */
1096 res = __svgalib_vga_driverspecs.setmode(mode, prv_mode);
1097 if (res == 0) {
1098 /*
1099 * ARI: Turn off virtual size of 1024 - this fixes all problems
1100 * with standard modes, including 320x200x256.
1101 *
1102 * SL: Is this for 928 only? Doesn't matter for 805.
1103 *
1104 * MZ: Affects 765 as well, so I assume it is good for all chipsets.
1105 */
1106 s3_unlock();
1107 __svgalib_outCR(0x34, __svgalib_inCR(0x34) & ~0x10);
1108 s3_lock();
1109 }
1110 return res;
1111 }
1112 if (!s3_modeavailable(mode))
1113 return 1;
1114
1115 modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);
1116
1117 modetiming = malloc(sizeof(ModeTiming));
1118 if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
1119 free(modetiming);
1120 free(modeinfo);
1121 return 1;
1122 }
1123 /* Adjust the display width. */
1124 modeinfo->lineWidth = s3_adjlinewidth(modeinfo->lineWidth);
1125 CI.xbytes = modeinfo->lineWidth;
1126
1127 s3_initializemode(moderegs, modetiming, modeinfo);
1128 free(modeinfo);
1129 free(modetiming);
1130
1131 __svgalib_setregs(moderegs); /* Set standard regs. */
1132 s3_setregs(moderegs, mode); /* Set extended regs. */
1133 return 0;
1134 }
1135
1136
1137 /* Indentify chipset; return non-zero if detected */
1138
1139 /* Some port I/O functions: */
rdinx(int port,unsigned char index)1140 static unsigned char rdinx(int port, unsigned char index)
1141 {
1142 outb(port, index);
1143 return inb(port + 1);
1144 }
1145
wrinx(int port,unsigned char index,unsigned char val)1146 static void wrinx(int port, unsigned char index, unsigned char val)
1147 {
1148 outb(port, index);
1149 outb(port + 1, val);
1150 }
1151
1152 /*
1153 * Returns true iff the bits in 'mask' of register 'port', index 'index'
1154 * are read/write.
1155 */
testinx2(int port,unsigned char index,unsigned char mask)1156 static int testinx2(int port, unsigned char index, unsigned char mask)
1157 {
1158 unsigned char old, new1, new2;
1159
1160 old = rdinx(port, index);
1161 wrinx(port, index, (old & ~mask));
1162 new1 = rdinx(port, index) & mask;
1163 wrinx(port, index, (old | mask));
1164 new2 = rdinx(port, index) & mask;
1165 wrinx(port, index, old);
1166 return (new1 == 0) && (new2 == mask);
1167 }
1168
s3_test(void)1169 static int s3_test(void)
1170 {
1171 int vgaIOBase, vgaCRIndex, vgaCRReg;
1172
1173 vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
1174 vgaCRIndex = vgaIOBase + 4;
1175 vgaCRReg = vgaIOBase + 5;
1176
1177 outb(vgaCRIndex, 0x11); /* for register CR11, (Vertical Retrace End) */
1178 outb(vgaCRReg, 0x00); /* set to 0 */
1179
1180 outb(vgaCRIndex, 0x38); /* check if we have an S3 */
1181 outb(vgaCRReg, 0x00);
1182
1183 /* Make sure we can't write when locked */
1184
1185 if (testinx2(vgaCRIndex, 0x35, 0x0f))
1186 return 0;
1187
1188 outb(vgaCRIndex, 0x38); /* for register CR38, (REG_LOCK1) */
1189 outb(vgaCRReg, 0x48); /* unlock S3 register set for read/write */
1190
1191 /* Make sure we can write when unlocked */
1192
1193 if (!testinx2(vgaCRIndex, 0x35, 0x0f))
1194 return 0;
1195
1196 if (s3_init(0, 0, 0)) /* type not OK */
1197 return 0;
1198 return 1;
1199 }
1200
1201 /*
1202 * Bank switching function - set 64K bank number
1203 *
1204 * XXXX locking and unlocking might hurt performance but is safer.
1205 */
s3_setpage(int page)1206 static void s3_setpage(int page)
1207 {
1208 #ifdef S3_16_COLORS
1209 /*
1210 * XXXX adjust the parameter for 4bpp (1bpp is ignored). Shouldn't
1211 * need this, but either me or the drawing functions are making bad
1212 * assumptions about 4bpp.
1213 */
1214 if (infotable[CM].bytesperpixel == 0)
1215 page *= 4;
1216 #endif
1217 #ifdef S3_KLUDGE_PAGE_MODE
1218 /* adjust to use 256K pages */
1219 if (CM == G320x200x256)
1220 page *= 4;
1221 #endif
1222 s3_unlock();
1223 outb(CRT_IC, 0x35);
1224 outb(CRT_DC, (inb(CRT_DC) & 0xF0) | (page & 0x0F));
1225 if (s3_chiptype >= S3_801) {
1226 outb(CRT_IC, 0x51);
1227 outb(CRT_DC, (inb(CRT_DC) & ~0x0C) | ((page & 0x30) >> 2));
1228 }
1229 inb(CRT_DC); /* ARI: Ferraro says: required for first generation 911 only */
1230 s3_lock();
1231 }
1232
1233 /*
1234 * Bank switching function - set 64K bank number for 864+
1235 * (not for 4bpp)
1236 *
1237 * XXXX locking and unlocking might hurt performance
1238 * (864 shouldn't need it).
1239 */
1240 #ifdef S3_LINEAR_MODE_BANKING_864
s3_setpage864(int page)1241 static void s3_setpage864(int page)
1242 {
1243 s3_unlock();
1244 /* "Linear" mode banking. */
1245 outb(CRT_IC, 0x6A);
1246 outb(CRT_DC, (inb(CRT_DC) & ~0x3F) | page);
1247 s3_lock();
1248 }
1249
1250 #endif
1251
1252 /*
1253 * Set display start address (not for 16 color modes).
1254 *
1255 * This works up to 4Mb (should be able to go higher).
1256 *
1257 * XXXX locking and unlocking might hurt performance but is safer.
1258 */
s3_setdisplaystart(int address)1259 static void s3_setdisplaystart(int address)
1260 {
1261 #ifdef S3_KLUDGE_PAGE_MODE
1262 /* adjust to use 256K pages */
1263 if (CM == G320x200x256)
1264 address *= 4;
1265 #endif
1266 s3_unlock();
1267 outw(CRT_IC, 0x0d | ((address << 6) & 0xff00)); /* sa2-sa9 */
1268 outw(CRT_IC, 0x0c | ((address >> 2) & 0xff00)); /* sa10-sa17 */
1269 inb(0x3da); /* set ATC to addressing mode */
1270 outb(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */
1271 outb(ATT_IW, (inb(ATT_R) & 0xf0) | ((address & 3) << 1));
1272 /* write sa0-1 to bits 1-2 */
1273
1274 outb(CRT_IC, 0x31);
1275 outb(CRT_DC, (inb(CRT_DC) & ~0x30) | ((address & 0xc0000) >> 14));
1276 if (s3_chiptype >= S3_801) {
1277 outb(CRT_IC, 0x51);
1278 outb(CRT_DC, (inb(CRT_DC) & ~0x03) | ((address & 0x300000) >> 20));
1279 }
1280 s3_lock();
1281 }
1282
1283 /*
1284 * Set logical scanline length (Multiples of 8 to 8184).
1285 * CR43.2 should be 0 for this.
1286 */
s3_setlogicalwidth(int width)1287 static void s3_setlogicalwidth(int width)
1288 {
1289 __svgalib_outCR(0x13, (width >> 3)); /* lw3-lw11 */
1290 __svgalib_outCR(0x51, (width & 0x300) >> 4); /* lw12-lw13 */
1291 }
1292
1293 #ifdef S3_LINEAR_SUPPORT
s3_linear_enable(void)1294 static void s3_linear_enable(void)
1295 {
1296 s3_unlock();
1297
1298 if (s3_chiptype > S3_924) {
1299 int i;
1300 outb (CRT_IC, 0x40);
1301 i = (s3_cr40 & 0xf6) | 0x0a;
1302 outb (CRT_DC, (unsigned char) i);
1303 outb (CRT_IC, 0x58);
1304 outb (CRT_DC, s3_linear_opt | s3_cr58);
1305 if (s3_chiptype > S3_928) {
1306 outb (CRT_IC, 0x54);
1307 outb (CRT_DC, (s3_cr54 + 0x07));
1308 }
1309 }
1310
1311 s3_lock();
1312 }
1313
s3_linear_disable(void)1314 static void s3_linear_disable(void)
1315 {
1316 s3_unlock();
1317
1318 if (s3_chiptype > S3_924) {
1319 if (s3_chiptype > S3_928) {
1320 outb (CRT_IC, 0x54);
1321 outb (CRT_DC, s3_cr54);
1322 }
1323 outb (CRT_IC, 0x58);
1324 outb (CRT_DC, s3_cr58);
1325 outb (CRT_IC, 0x40);
1326 outb (CRT_DC, s3_cr40);
1327 }
1328
1329 s3_lock();
1330 }
1331
1332 /* Set linear addressing mode */
1333
s3_linear(int op,int param)1334 static int s3_linear(int op, int param)
1335 {
1336 if (op == LINEAR_QUERY_BASE)
1337 return s3_linear_base;
1338 if (op == LINEAR_QUERY_GRANULARITY) {
1339 switch (s3_memory) {
1340 case 4096:
1341 case 2048:
1342 case 1024:
1343 return s3_memory * 1024;
1344 default:
1345 return 1024 * 1024;
1346 }
1347 } else if (op == LINEAR_QUERY_RANGE)
1348 return 256;
1349 else if (op == LINEAR_ENABLE) {
1350 s3_setpage(0);
1351 s3_linear_enable();
1352 s3_linear_addr = param;
1353 return 0;
1354 } else if (op == LINEAR_DISABLE) {
1355 s3_setpage(0);
1356 s3_linear_disable();
1357 s3_linear_addr = 0;
1358 return 0;
1359 } else
1360 return -1;
1361 }
1362
1363 #define S3_LINEAR_FUNC s3_linear
1364 #else
1365 #define S3_LINEAR_FUNC 0
1366 #endif /* S3_LINEAR_SUPPORT */
1367
1368 /* Function table (exported) */
1369
1370 DriverSpecs __svgalib_s3_driverspecs =
1371 {
1372 s3_saveregs, /* saveregs */
1373 s3_setregs, /* setregs */
1374 (void (*)(void)) nothing, /* unlock */
1375 (void (*)(void)) nothing, /* lock */
1376 s3_test,
1377 s3_init,
1378 s3_setpage,
1379 (void (*)(int)) nothing,
1380 (void (*)(int)) nothing,
1381 s3_setmode,
1382 s3_modeavailable,
1383 s3_setdisplaystart,
1384 s3_setlogicalwidth,
1385 s3_getmodeinfo,
1386 0, /* bitblt */
1387 0, /* imageblt */
1388 0, /* fillblt */
1389 0, /* hlinelistblt */
1390 0, /* bltwait */
1391 s3_ext_set, /* extset */
1392 0, /* accel */
1393 S3_LINEAR_FUNC, /* linear */
1394 NULL, /* Accelspecs */
1395 NULL, /* Emulation */
1396 };
1397
1398
1399 /* S3-specific config file options. */
1400
1401 /*
1402 * Currently this only handles Clocks. It would a good idea to have
1403 * higher-level code process options like Clocks that are valid for
1404 * more than one driver driver (with better error detection etc.).
1405 */
1406
1407 static char *s3_config_options[] =
1408 {
1409 "clocks", "ramdac", "dacspeed", "clockchip", NULL
1410 };
1411
s3_process_option(int option,int mode)1412 static char *s3_process_option(int option, int mode)
1413 {
1414 /*
1415 * option is the number of the option string in s3_config_options,
1416 * mode seems to be a 'hardness' indicator for security.
1417 */
1418 if (option == 0) { /* "Clocks" */
1419 /* Process at most 16 specified clocks. */
1420 cardspecs->clocks = malloc(sizeof(int) * 16);
1421 /* cardspecs->nClocks should be already be 0. */
1422 for (;;) {
1423 char *ptr;
1424 int freq;
1425 ptr = strtok(NULL, " ");
1426 if (ptr == NULL)
1427 break;
1428 /*
1429 * This doesn't protect against bad characters
1430 * (atof() doesn't detect errors).
1431 */
1432 freq = atof(ptr) * 1000;
1433 cardspecs->clocks[cardspecs->nClocks] = freq;
1434 cardspecs->nClocks++;
1435 if (cardspecs->nClocks == 16)
1436 break;
1437 }
1438 }
1439 if (option == 1) { /* "Ramdac" */
1440 char *ptr;
1441 ptr = strtok(NULL, " ");
1442 #ifdef INCLUDE_IBMRGB52x_DAC
1443 if (strcasecmp(ptr, "IBMRGB52x") == 0)
1444 dac_used = &__svgalib_IBMRGB52x_methods;
1445 #endif
1446 #ifdef INCLUDE_SIERRA_DAC
1447 if (strcasecmp(ptr, "Sierra32K") == 0)
1448 dac_used = &__svgalib_Sierra_32K_methods;
1449 #endif
1450 #ifdef INCLUDE_SC15025_DAC
1451 if (strcasecmp(ptr, "SC15025") == 0)
1452 dac_used = &__svgalib_SC15025_methods;
1453 #endif
1454 #ifdef INCLUDE_S3_SDAC_DAC
1455 if (strcasecmp(ptr, "SDAC") == 0)
1456 dac_used = &__svgalib_S3_SDAC_methods;
1457 #endif
1458 #ifdef INCLUDE_S3_GENDAC_DAC
1459 if (strcasecmp(ptr, "GenDAC") == 0)
1460 dac_used = &__svgalib_S3_GENDAC_methods;
1461 #endif
1462 #ifdef INCLUDE_ATT20C490_DAC
1463 if (strcasecmp(ptr, "ATT20C490") == 0)
1464 dac_used = &__svgalib_ATT20C490_methods;
1465 #endif
1466 #ifdef INCLUDE_ATT20C498_DAC
1467 if (strcasecmp(ptr, "ATT20C498") == 0)
1468 dac_used = &__svgalib_ATT20C498_methods;
1469 #endif
1470 #ifdef INCLUDE_NORMAL_DAC
1471 if (strcasecmp(ptr, "Normal") == 0) /* force normal VGA dac */
1472 dac_used = &__svgalib_normal_dac_methods;
1473 #endif
1474
1475 if (clk_used)
1476 clk_used->initialize(cardspecs, dac_used);
1477 }
1478 if (option == 2) { /* "Dacspeed" */
1479 char *ptr;
1480 ptr = strtok(NULL, " ");
1481 /*
1482 * This doesn't protect against bad characters
1483 * (atoi() doesn't detect errors).
1484 */
1485 dac_speed = atoi(ptr) * 1000;
1486 }
1487 if (option == 3) { /* "ClockChip" */
1488 char *ptr;
1489 long freq;
1490 ptr = strtok(NULL, " \t");
1491 if (strcasecmp(ptr, "ICD2061A") == 0 ||
1492 strcasecmp(ptr, "DCS2824") == 0) /* Diamond, compatible to icd2061a */
1493 clk_used = &__svgalib_I2061A_clockchip_methods;
1494 clk_used->initialize(cardspecs, dac_used);
1495 ptr = strtok(NULL, " \t");
1496 if (ptr != NULL) {
1497 freq = atof(ptr) * 1000L;
1498 if (freq) {
1499 clk_used->TextFrequency = freq;
1500 ptr = strtok(NULL, " \t");
1501 }
1502 }
1503 return ptr;
1504 }
1505 return strtok(NULL, " ");
1506 }
1507
1508
1509 /* Initialize driver (called after detection) */
1510 /* Derived from XFree86 SuperProbe and s3 driver. */
1511
1512 static DacMethods *dacs_to_probe[] =
1513 {
1514 #ifdef INCLUDE_S3_SDAC_DAC_TEST
1515 &__svgalib_S3_SDAC_methods,
1516 #endif
1517 #ifdef INCLUDE_S3_GENDAC_DAC_TEST
1518 &__svgalib_S3_GENDAC_methods,
1519 #endif
1520 #ifdef INCLUDE_ATT20C490_DAC_TEST
1521 &__svgalib_ATT20C490_methods,
1522 #endif
1523 #ifdef INCLUDE_SC15025_DAC_TEST
1524 &__svgalib_SC15025_methods,
1525 #endif
1526 #ifdef INCLUDE_SC1148X_DAC_TEST
1527 &__svgalib_SC1148X_methods,
1528 #endif
1529 #ifdef INCLUDE_IBMRGB52x_DAC_TEST
1530 &__svgalib_IBMRGB52x_methods,
1531 #endif
1532 NULL};
1533
s3_init(int force,int par1,int par2)1534 static int s3_init(int force, int par1, int par2)
1535 {
1536 int id, rev, config;
1537
1538 s3_unlock();
1539
1540 s3_flags = 0; /* initialize */
1541 id = __svgalib_inCR(0x30); /* Get chip id. */
1542 rev = id & 0x0F;
1543 if (id >= 0xE0) {
1544 id |= __svgalib_inCR(0x2E) << 8;
1545 rev |= __svgalib_inCR(0x2F) << 4;
1546 }
1547 if (force) {
1548 s3_chiptype = par1; /* we already know the type */
1549 s3_memory = par2;
1550 /* ARI: can we really trust the user's specification, or should we ignore
1551 it and probe ourselves ? */
1552 if (s3_chiptype == S3_801 || s3_chiptype == S3_805) {
1553 if ((rev & 0x0F) < 2)
1554 s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */
1555 } else if (s3_chiptype == S3_928) {
1556 if ((rev & 0x0F) < 4) /* ARI: Stepping D or below */
1557 s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */
1558 }
1559 } else {
1560 s3_chiptype = -1;
1561 config = __svgalib_inCR(0x36); /* get configuration info */
1562 switch (id & 0xf0) {
1563 case 0x80:
1564 if (rev == 1) {
1565 s3_chiptype = S3_911;
1566 break;
1567 }
1568 if (rev == 2) {
1569 s3_chiptype = S3_924;
1570 break;
1571 }
1572 break;
1573 case 0xa0:
1574 switch (config & 0x03) {
1575 case 0x00:
1576 case 0x01:
1577 /* EISA or VLB - 805 */
1578 s3_chiptype = S3_805;
1579 /* ARI: Test stepping: 0:B, 1:unknown, 2,3,4:C, 8:I, >=5:D */
1580 if ((rev & 0x0F) < 2)
1581 s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */
1582 break;
1583 case 0x03:
1584 /* ISA - 801 */
1585 s3_chiptype = S3_801;
1586 /* Stepping same as 805, just ISA */
1587 if ((rev & 0x0F) < 2)
1588 s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */
1589 break;
1590 }
1591 break;
1592 case 0x90:
1593 s3_chiptype = S3_928;
1594 if ((rev & 0x0F) < 4) /* ARI: Stepping D or below */
1595 s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */
1596 break;
1597 case 0xB0:
1598 /* 928P */
1599 s3_chiptype = S3_928;
1600 break;
1601 case 0xC0:
1602 s3_chiptype = S3_864;
1603 break;
1604 case 0xD0:
1605 s3_chiptype = S3_964;
1606 break;
1607 case 0xE0:
1608 switch (id & 0xFFF0) {
1609 case 0x10E0:
1610 s3_chiptype = S3_TRIO32;
1611 break;
1612 case 0x3DE0: /* ViRGE/VX ID */
1613 case 0x31E0: /* ViRGE ID */
1614 case 0x01E0: /* S3Trio64V2/DX ... any others? */
1615 case 0x04E0:
1616 case 0x11E0:
1617 if (rev & 0x0400)
1618 s3_chiptype = S3_765;
1619 else
1620 s3_chiptype = S3_TRIO64;
1621 break;
1622 case 0x80E0:
1623 s3_chiptype = S3_866;
1624 break;
1625 case 0x90E0:
1626 s3_chiptype = S3_868;
1627 break;
1628 case 0xF0E0: /* XXXX From data book; XF86 says 0xB0E0? */
1629 s3_chiptype = S3_968;
1630 break;
1631 }
1632 }
1633 if (s3_chiptype == -1) {
1634 printf("svgalib: S3: Unknown chip id %02x\n",
1635 id);
1636 return -1;
1637 }
1638 if (s3_chiptype <= S3_924) {
1639 if ((config & 0x20) != 0)
1640 s3_memory = 512;
1641 else
1642 s3_memory = 1024;
1643 } else {
1644 /* look at bits 5, 6 and 7 */
1645 switch ((config & 0xE0) >> 5) {
1646 case 0:
1647 s3_memory = 4096;
1648 break;
1649 case 2:
1650 s3_memory = 3072;
1651 break;
1652 case 3:
1653 s3_memory = 8192;
1654 break;
1655 case 4:
1656 s3_memory = 2048;
1657 break;
1658 case 5:
1659 s3_memory = 6144;
1660 break;
1661 case 6:
1662 s3_memory = 1024;
1663 break;
1664 case 7:
1665 s3_memory = 512;
1666 break; /* Trio32 */
1667 }
1668 }
1669
1670 if ((config & 0x03) < 3) /* XXXX 928P is ignored */
1671 s3_flags |= S3_LOCALBUS;
1672 }
1673
1674 if (__svgalib_driver_report) {
1675 printf("svgalib: Using S3 driver (%s, %dK).\n", s3_chipname[s3_chiptype],
1676 s3_memory);
1677 if (s3_flags & S3_OLD_STEPPING)
1678 printf("svgalib: Chip revision cannot handle modes with width 1152.\n");
1679 if (s3_chiptype > S3_TRIO64) {
1680 printf("svgalib: s3: chipsets newer than S3 Trio64 is not supported well yet.\n");
1681 }
1682 }
1683 /* begin: Initialize cardspecs. */
1684 /* If IOPERM is set, assume permissions have already been set by Olaf Titz' */
1685 /* ioperm(1). */
1686 if (getenv("IOPERM") == NULL) {
1687 if (0 > iopl(3))
1688 printf("svgalib: s3: cannot get I/O permissions for 8514.");
1689 }
1690 #ifdef S3_LINEAR_SUPPORT
1691 if (s3_chiptype > S3_805) {
1692 int found_pciconfig;
1693 unsigned long pci_conf[64];
1694
1695 found_pciconfig = __svgalib_pci_find_vendor_vga(0x5333, pci_conf, 0);
1696 if (!found_pciconfig)
1697 s3_linear_base = pci_conf[4] & 0xFF800000;
1698 }
1699
1700 s3_cr59 = s3_linear_base >> 24;
1701 s3_cr5A = (s3_linear_base >> 16);
1702 if (! (s3_cr59 | s3_cr5A)) {
1703 s3_cr59 = __svgalib_inCR(0x59);
1704 s3_cr5A = __svgalib_inCR(0x5A);
1705 if (!s3_cr59) {
1706 s3_cr59 = 0xF3000000 >> 24;
1707 s3_cr5A = (0xF3000000 >> 16);
1708 }
1709 s3_linear_base = (s3_cr59 << 24) | (s3_cr5A << 16);
1710 }
1711 s3_linear_opt |= 0x10;
1712 switch (s3_memory) {
1713 case 512 :
1714 case 1024 :
1715 s3_linear_opt |= 0x01;
1716 break;
1717 case 2048 :
1718 s3_linear_opt |= 0x02;
1719 break;
1720 case 3072 :
1721 case 4096 :
1722 case 6144 :
1723 case 8192 :
1724 s3_linear_opt |= 0x03;
1725 break;
1726 default :
1727 s3_linear_opt = 0x14; /* like XFree */
1728 }
1729 #endif
1730
1731 cardspecs = malloc(sizeof(CardSpecs));
1732 cardspecs->videoMemory = s3_memory;
1733 cardspecs->nClocks = 0;
1734 /* cardspecs->maxHorizontalCrtc = 2040; SL: kills 800x600x32k and above */
1735 cardspecs->maxHorizontalCrtc = 4088;
1736 cardspecs->flags = INTERLACE_DIVIDE_VERT;
1737
1738 /* Process S3-specific config file options. */
1739 __svgalib_read_options(s3_config_options, s3_process_option);
1740
1741 #ifdef INCLUDE_S3_TRIO64_DAC
1742 if ((s3_chiptype == S3_TRIO64 || s3_chiptype == S3_765) && dac_used == NULL)
1743 dac_used = &__svgalib_Trio64_methods;
1744 #endif
1745
1746 if (dac_used == NULL)
1747 dac_used = __svgalib_probeDacs(dacs_to_probe);
1748 else
1749 dac_used->initialize();
1750
1751
1752 if (dac_used == NULL) {
1753 /* Not supported. */
1754 printf("svgalib: s3: Assuming normal VGA DAC.\n");
1755 #ifdef INCLUDE_NORMAL_DAC
1756 dac_used = &__svgalib_normal_dac_methods;
1757 dac_used->initialize();
1758 #else
1759 printf("svgalib: Alas, normal VGA DAC support is not compiled in, goodbye.\n");
1760 return 1;
1761 #endif
1762 }
1763 if (clk_used)
1764 clk_used->initialize(cardspecs, dac_used);
1765
1766 dac_used->qualifyCardSpecs(cardspecs, dac_speed);
1767
1768 /* Initialize standard clocks for unknown DAC. */
1769 if ((!(cardspecs->flags & CLOCK_PROGRAMMABLE))
1770 && cardspecs->nClocks == 0) {
1771 /*
1772 * Almost all cards have 25 and 28 MHz on VGA clocks 0 and 1,
1773 * so use these for an unknown DAC, yielding 640x480x256.
1774 */
1775 cardspecs->nClocks = 2;
1776 cardspecs->clocks = malloc(sizeof(int) * 2);
1777 cardspecs->clocks[0] = 25175;
1778 cardspecs->clocks[1] = 28322;
1779 }
1780 /* Limit pixel clocks according to chip specifications. */
1781 if (s3_chiptype == S3_864 || s3_chiptype == S3_868) {
1782 /* Limit max clocks according to 95 MHz DCLK spec. */
1783 /* SL: might just be 95000 for 4/8bpp since no pixmux'ing */
1784 LIMIT(cardspecs->maxPixelClock4bpp, 95000 * 2);
1785 LIMIT(cardspecs->maxPixelClock8bpp, 95000 * 2);
1786 LIMIT(cardspecs->maxPixelClock16bpp, 95000);
1787 /* see explanation below */
1788 LIMIT(cardspecs->maxPixelClock24bpp, 36000);
1789 /*
1790 * The official 32bpp limit is 47500, but we allow
1791 * 50 MHz for VESA 800x600 timing (actually the
1792 * S3-864 doesn't have the horizontal timing range
1793 * to run unmodified VESA 800x600 72 Hz timings).
1794 */
1795 LIMIT(cardspecs->maxPixelClock32bpp, 50000);
1796 }
1797 #ifndef S3_16_COLORS
1798 cardspecs->maxPixelClock4bpp = 0; /* 16-color doesn't work. */
1799 #endif
1800
1801 /* end: Initialize cardspecs. */
1802
1803 __svgalib_driverspecs = &__svgalib_s3_driverspecs;
1804
1805 __svgalib_banked_mem_base=0xa0000;
1806 __svgalib_banked_mem_size=0x10000;
1807 #ifdef S3_LINEAR_SUPPORT
1808 __svgalib_linear_mem_base=s3_linear_base;
1809 __svgalib_linear_mem_size=s3_memory*0x400;
1810 #endif
1811
1812 return 0;
1813 }
1814