1 /*
2 * Copyright 1993 by David Wexelblat <dwex@goblin.org>
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of David Wexelblat not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. David Wexelblat makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
13 *
14 * DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL DAVID WEXELBLAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23 /*************************************************************************/
24
25 /*
26 * This is a oak SVGA driver for XFree86.
27 *
28 * Built from Xfree86 1.3 stub file.
29 * 9/1/93 Initial version Steve Goldman sgoldman@encore.com
30 *
31 * This one file can be used for both the color and monochrome servers.
32 * Remember that the monochrome server is actually using a 16-color mode,
33 * with only one bitplane active. To distinguish between the two at
34 * compile-time, use '#ifdef MONOVGA', etc.
35 */
36
37 /*************************************************************************/
38
39 /* $XFree86: mit/server/ddx/x386/vga256/drivers/oak/oak_driver.c,v 2.1 1993/10/02 07:16:14 dawes Exp $ */
40
41 /*
42 * These are X and server generic header files.
43 */
44 #include "X.h"
45 #include "input.h"
46 #include "screenint.h"
47
48 /*
49 * These are XFree86-specific header files
50 */
51 #include "compiler.h"
52 #include "x386.h"
53 #include "x386Priv.h"
54 #include "xf86_OSlib.h"
55 #include "xf86_HWlib.h"
56 #include "vga.h"
57
58 /*
59 * Driver data structures.
60 */
61 typedef struct {
62 /*
63 * This structure defines all of the register-level information
64 * that must be stored to define a video mode for this chipset.
65 * The 'vgaHWRec' member must be first, and contains all of the
66 * standard VGA register information, as well as saved text and
67 * font data.
68 */
69 vgaHWRec std; /* good old IBM VGA */
70 /*
71 * Any other registers or other data that the new chipset needs
72 * to be saved should be defined here. The Init/Save/Restore
73 * functions will manipulate theses fields. Examples of things
74 * that would go here are registers that contain bank select
75 * registers, or extended clock select bits, or extensions to
76 * the timing registers. Use 'unsigned char' as the type for
77 * these registers.
78 */
79 unsigned char oakMisc; /* Misc register */
80 unsigned char oakOverflow; /* overflow register */
81 unsigned char oakHsync2; /* Hsync/2 start register */
82 unsigned char oakOverflow2; /* overflow2 register */
83 unsigned char oakConfig; /* config 67 vs. 77 */
84 unsigned char oakBCompat; /* backward compatibility */
85 unsigned char oakBank; /* initial bank, debug only */
86 } vgaOAKRec, *vgaOAKPtr;
87
88 /*
89 * Forward definitions for the functions that make up the driver. See
90 * the definitions of these functions for the real scoop.
91 */
92 static Bool OAKProbe();
93 static char * OAKIdent();
94 static void OAKClockSelect();
95 static void OAKEnterLeave();
96 static Bool OAKInit();
97 extern void * OAKSave();
98 extern void OAKRestore();
99 static void OAKAdjust();
100 static void OAKSaveScreen();
101 static void OAKGetMode();
102 /*
103 * These are the bank select functions. There are defined in oak_bank.s
104 */
105 extern void OAKSetRead();
106 extern void OAKSetWrite();
107 extern void OAKSetReadWrite();
108
109 /*
110 * This data structure defines the driver itself. The data structure is
111 * initialized with the functions that make up the driver and some data
112 * that defines how the driver operates.
113 */
114 vgaVideoChipRec OAK = {
115 /*
116 * Function pointers
117 */
118 OAKProbe,
119 OAKIdent,
120 OAKEnterLeave,
121 OAKInit,
122 OAKSave,
123 OAKRestore,
124 OAKAdjust,
125 NoopDDA,
126 NoopDDA,
127 NoopDDA,
128 OAKSetRead,
129 OAKSetWrite,
130 OAKSetReadWrite,
131 /*
132 * This is the size of the mapped memory window, usually 64k.
133 */
134 0x10000,
135 /*
136 * This is the size of a video memory bank for this chipset.
137 */
138 0x10000,
139 /*
140 * This is the number of bits by which an address is shifted
141 * right to determine the bank number for that address.
142 */
143 16,
144 /*
145 * This is the bitmask used to determine the address within a
146 * specific bank.
147 */
148 0xFFFF,
149 /*
150 * These are the bottom and top addresses for reads inside a
151 * given bank.
152 */
153 0x00000, 0x10000,
154 /*
155 * And corresponding limits for writes.
156 */
157 0x00000, 0x10000,
158 /*
159 * Whether this chipset supports a single bank register or
160 * separate read and write bank registers. Almost all chipsets
161 * support two banks, and two banks are almost always faster
162 * (Trident 8900C and 9000 are odd exceptions).
163 */
164 TRUE, /* two banks */
165 /*
166 * If the chipset requires vertical timing numbers to be divided
167 * by two for interlaced modes, set this to VGA_DIVIDE_VERT.
168 */
169 VGA_NO_DIVIDE_VERT,
170 /*
171 * This is a dummy initialization for the set of vendor/option flags
172 * that this driver supports. It gets filled in properly in the
173 * probe function, if the probe succeeds (assuming the driver
174 * supports any such flags).
175 */
176 {0,},
177 /*
178 * This specifies how the virtual width is to be rounded. The
179 * virtual width will be rounded down the nearest multiple of
180 * this value
181 */
182 16,
183 };
184
185 /*
186 * This is a convenience macro, so that entries in the driver structure
187 * can simply be dereferenced with 'new->xxx'.
188 */
189 #define new ((vgaOAKPtr)vgaNewVideoState)
190
191 /*
192 A bunch of defines that match Oak's register names
193 so we don't use a bunch of hardcoded constants in the code.
194 */
195 #define OTI_INDEX 0x3DE /* Oak extended index register */
196 #define OTI_R_W 0x3DF /* Oak extended r/w register */
197 #define OTI_CRT_CNTL 0xC /* Oak CRT COntrol Register */
198 #define OTI_MISC 0xD /* Oak Misc register */
199 #define OTI_BCOMPAT 0xE /* Oak Back compat register */
200 #define OTI_SEGMENT 0x11 /* Oak segment register */
201 #define OTI_CONFIG 0x12 /* Oak config register */
202 #define OTI_OVERFLOW 0x14 /* Oak overflow register */
203 #define OTI_HSYNC2 0x15 /* Oak hsync/2 start register */
204 #define OTI_OVERFLOW2 0x16 /* Oak overflow2 register */
205
206
207 #define OTI67 0 /* same index as ident function */
208 #define OTI77 1 /* same index as ident function */
209
210 static int OTI_chipset;
211
212 static unsigned OAK_ExtPorts[] = { OTI_INDEX, OTI_R_W };
213 static int Num_OAK_ExtPorts = (sizeof(OAK_ExtPorts)/sizeof(OAK_ExtPorts[0]));
214
215 /*
216 * OAKIdent --
217 *
218 * Returns the string name for supported chipset 'n'. Most drivers only
219 * support one chipset, but multiple version may require that the driver
220 * identify them individually (e.g. the Trident driver). The Ident function
221 * should return a string if 'n' is valid, or NULL otherwise. The
222 * server will call this function when listing supported chipsets, with 'n'
223 * incrementing from 0, until the function returns NULL. The 'Probe'
224 * function should call this function to get the string name for a chipset
225 * and when comparing against an Xconfig-supplied chipset value. This
226 * cuts down on the number of places errors can creep in.
227 */
228 static char *
OAKIdent(n)229 OAKIdent(n)
230 int n;
231 {
232 static char *chipsets[] = {"oti067","oti077"};
233
234 if (n + 1 > sizeof(chipsets) / sizeof(char *))
235 return(NULL);
236 else
237 return(chipsets[n]);
238 }
239
240 /*
241 * OAKClockSelect --
242 *
243 * This function selects the dot-clock with index 'no'. In most cases
244 * this is done my setting the correct bits in various registers (generic
245 * VGA uses two bits in the Miscellaneous Output Register to select from
246 * 4 clocks). Care must be taken to protect any other bits in these
247 * registers by fetching their values and masking off the other bits.
248 */
249 static void
OAKClockSelect(no)250 OAKClockSelect(no)
251 int no;
252 {
253 static unsigned char save1,save2;
254 unsigned char temp;
255
256 switch(no)
257 {
258 case CLK_REG_SAVE:
259 /*
260 * Here all of the registers that can be affected by
261 * clock setting should be saved into static variables.
262 */
263 save1 = inb(0x3CC);
264 /* Any extended registers would go here */
265 outb(OTI_INDEX, OTI_MISC);
266 save2 = inb(OTI_R_W);
267 break;
268 case CLK_REG_RESTORE:
269 /*
270 * Here all the previously saved registers are restored.
271 */
272 outb(0x3C2, save1);
273 /* Any extended registers would go here */
274 /* all the examples seem to just blast the old data
275 in what about any other bit changes?? */
276 outw(OTI_INDEX, OTI_MISC | (save2 << 8));
277 break;
278 default:
279 /*
280 * These are the generic two low-order bits of the clock select
281 */
282 temp = inb(0x3CC);
283 outb(0x3C2, ( temp & 0xF3) | ((no << 2) & 0x0C));
284 /*
285 * Here is where the high order bit(s) supported by the chipset
286 * are set. This is done by fetching the appropriate register,
287 * masking off bits that will be changing, then shifting and
288 * masking 'no' to set the bits as appropriate.
289 */
290 outb(OTI_INDEX, OTI_MISC);
291 temp = inb(OTI_R_W);
292 outw(OTI_INDEX, OTI_MISC |
293 ((( temp & 0xDF ) | (( no & 4) << 3)) << 8));
294
295 }
296 }
297
298
299 /*
300 * OAKProbe --
301 *
302 * This is the function that makes a yes/no decision about whether or not
303 * a chipset supported by this driver is present or not. The server will
304 * call each driver's probe function in sequence, until one returns TRUE
305 * or they all fail.
306 *
307 * Pretty much any mechanism can be used to determine the presence of the
308 * chipset. If there is a BIOS signature (e.g. ATI, GVGA), it can be read
309 * via /dev/mem on most OSs, but some OSs (e.g. Mach) require special
310 * handling, and others (e.g. Amoeba) don't allow reading the BIOS at
311 * all. Hence, this mechanism is discouraged, if other mechanisms can be
312 * found. If the BIOS-reading mechanism must be used, examine the ATI and
313 * GVGA drivers for the special code that is needed. Note that the BIOS
314 * base should not be assumed to be at 0xC0000 (although most are). Use
315 * 'vga256InfoRec.BIOSbase', which will pick up any changes the user may
316 * have specified in the Xconfig file.
317 *
318 * The preferred mechanism for doing this is via register identification.
319 * It is important not only the chipset is detected, but also to
320 * ensure that other chipsets will not be falsely detected by the probe
321 * (this is difficult, but something that the developer should strive for).
322 * For testing registers, there are a set of utility functions in the
323 * "compiler.h" header file. A good place to find example probing code is
324 * in the SuperProbe program, which uses algorithms from the "vgadoc2.zip"
325 * package (available on most PC/vga FTP mirror sites, like ftp.uu.net and
326 * wuarchive.wustl.edu).
327 *
328 * Once the chipset has been successfully detected, then the developer needs
329 * to do some other work to find memory, and clocks, etc, and do any other
330 * driver-level data-structure initialization may need to be done.
331 */
332 static Bool
OAKProbe()333 OAKProbe()
334 {
335 unsigned char save, temp1;
336
337 xf86ClearIOPortList(vga256InfoRec.scrnIndex);
338 xf86AddIOPorts(vga256InfoRec.scrnIndex, Num_VGA_IOPorts, VGA_IOPorts);
339 xf86AddIOPorts(vga256InfoRec.scrnIndex, Num_OAK_ExtPorts, OAK_ExtPorts);
340
341 /*
342 * First we attempt to figure out if one of the supported chipsets
343 * is present.
344 */
345 if (vga256InfoRec.chipset)
346 {
347 /*
348 * This is the easy case. The user has specified the
349 * chipset in the Xconfig file. All we need to do here
350 * is a string comparison against each of the supported
351 * names available from the Ident() function. If this
352 * driver supports more than one chipset, there would be
353 * nested conditionals here (see the Trident and WD drivers
354 * for examples).
355 */
356 if (!StrCaseCmp(vga256InfoRec.chipset, OAKIdent(0))) {
357 OTI_chipset = OTI67;
358 } else if (!StrCaseCmp(vga256InfoRec.chipset, OAKIdent(1))) {
359 OTI_chipset = OTI77;
360 } else
361 return (FALSE);
362 OAKEnterLeave(ENTER);
363 }
364 else
365 {
366 /*
367 * OK. We have to actually test the hardware. The
368 * EnterLeave() function (described below) unlocks access
369 * to registers that may be locked, and for OSs that require
370 * it, enables I/O access. So we do this before we probe,
371 * even though we don't know for sure that this chipset
372 * is present.
373 */
374 OAKEnterLeave(ENTER);
375
376 /*
377 * Here is where all of the probing code should be placed.
378 * The best advice is to look at what the other drivers are
379 * doing. If you are lucky, the chipset reference will tell
380 * how to do this. Other resources include SuperProbe/vgadoc2,
381 * and the Ferraro book.
382 */
383
384 /* First we see if the segment register is present */
385 outb(OTI_INDEX, OTI_SEGMENT);
386 save = inb(OTI_R_W);
387 /* I assume that one I set the index I can r/w/r/w to
388 my hearts content */
389 outb(OTI_R_W, save ^ 0x11);
390 temp1 = inb(OTI_R_W);
391 outb(OTI_R_W, save);
392 if (temp1 != ( save ^ 0x11 )) {
393 /*
394 * Turn things back off if the probe is going to fail.
395 * Returning FALSE implies failure, and the server
396 * will go on to the next driver.
397 */
398 OAKEnterLeave(LEAVE);
399 return(FALSE);
400 }
401 /* figure out which chipset */
402 temp1 = inb(OTI_INDEX);
403 temp1 &= 0xE0;
404 switch (temp1) {
405 case 0xE0 : /* oti 57 don't know it */
406 ErrorF("OAK driver: OTI-57 unsupported\n");
407 OAKEnterLeave(LEAVE);
408 return(FALSE);
409 case 0x40 : /* oti 67 */
410 OTI_chipset = OTI67;
411 break;
412 case 0xA0 : /* oti 77 */
413 OTI_chipset = OTI77;
414 break;
415 default : /* don't know it */
416 ErrorF("OAK driver: unknown chipset\n");
417 OAKEnterLeave(LEAVE);
418 return(FALSE);
419 }
420 }
421
422 /*
423 * If the user has specified the amount of memory in the Xconfig
424 * file, we respect that setting.
425 */
426 if (!vga256InfoRec.videoRam) {
427 /*
428 * Otherwise, do whatever chipset-specific things are
429 * necessary to figure out how much memory (in kBytes) is
430 * available.
431 */
432 outb(OTI_INDEX, OTI_MISC);
433 temp1 = inb(OTI_R_W);
434 temp1 &= 0xC0;
435 if (temp1 == 0xC0 )
436 vga256InfoRec.videoRam = 1024;
437 else if (temp1 == 0x80 )
438 vga256InfoRec.videoRam = 512;
439 else if (temp1 == 0x00 )
440 vga256InfoRec.videoRam = 256;
441 else {
442 ErrorF("OAK driver: unknown video memory\n");
443 OAKEnterLeave(LEAVE);
444 return(FALSE);
445 }
446 }
447
448 /*
449 * Again, if the user has specified the clock values in the Xconfig
450 * file, we respect those choices.
451 */
452 if (!vga256InfoRec.clocks)
453 {
454 /*
455 * This utility function will probe for the clock values.
456 * It is passed the number of supported clocks, and a
457 * pointer to the clock-select function.
458 */
459 vgaGetClocks(8, OAKClockSelect);
460 }
461
462 /*
463 * Last we fill in the remaining data structures. We specify
464 * the chipset name, using the Ident() function and an appropriate
465 * index. We set a boolean for whether or not this driver supports
466 * banking for the Monochrome server. And we set up a list of all
467 * the vendor flags that this driver can make use of.
468 */
469 vga256InfoRec.chipset = OAKIdent(OTI_chipset);
470 vga256InfoRec.bankedMono = TRUE;
471 return(TRUE);
472 }
473
474 /*
475 * OAKEnterLeave --
476 *
477 * This function is called when the virtual terminal on which the server
478 * is running is entered or left, as well as when the server starts up
479 * and is shut down. Its function is to obtain and relinquish I/O
480 * permissions for the SVGA device. This includes unlocking access to
481 * any registers that may be protected on the chipset, and locking those
482 * registers again on exit.
483 */
484 static void
OAKEnterLeave(enter)485 OAKEnterLeave(enter)
486 Bool enter;
487 {
488 static unsigned char save;
489 unsigned char temp;
490
491 if (enter)
492 {
493 xf86EnableIOPorts(vga256InfoRec.scrnIndex);
494
495 /*
496 * This is a global. The CRTC base address depends on
497 * whether the VGA is functioning in color or mono mode.
498 * This is just a convenient place to initialize this
499 * variable.
500 */
501 vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
502
503 /*
504 * Here we deal with register-level access locks. This
505 * is a generic VGA protection; most SVGA chipsets have
506 * similar register locks for their extended registers
507 * as well.
508 */
509
510 /* Unprotect CRTC[0-7] */
511 outb(vgaIOBase + 4, 0x11); temp = inb(vgaIOBase + 5);
512 outb(vgaIOBase + 5, temp & 0x7F);
513 outb(OTI_INDEX, OTI_CRT_CNTL);
514 temp = inb(OTI_R_W);
515 outb(OTI_R_W, temp & 0xF0);
516 save = temp;
517 }
518 else
519 {
520 /*
521 * Here undo what was done above.
522 */
523 outb(OTI_INDEX, OTI_CRT_CNTL);
524 /* don't set the i/o write test bit even though
525 we cleared it on entry */
526 outb(OTI_R_W, (save & 0xF7) );
527
528 /* Protect CRTC[0-7] */
529 outb(vgaIOBase + 4, 0x11); temp = inb(vgaIOBase + 5);
530 outb(vgaIOBase + 5, (temp & 0x7F) | 0x80);
531
532 xf86DisableIOPorts(vga256InfoRec.scrnIndex);
533 }
534 }
535
536 /*
537 * OAKRestore --
538 *
539 * This function restores a video mode. It basically writes out all of
540 * the registers that have previously been saved in the vgaOAKRec data
541 * structure.
542 *
543 * Note that "Restore" is a little bit incorrect. This function is also
544 * used when the server enters/changes video modes. The mode definitions
545 * have previously been initialized by the Init() function, below.
546 */
547 extern void
548 OAKRestore(restore)
549 vgaOAKPtr restore;
550 {
551 unsigned char temp;
552
553 /*
554 * Whatever code is needed to get things back to bank zero should be
555 * placed here. Things should be in the same state as when the
556 * Save/Init was done.
557 */
558 /* put the segment regs back to zero */
559 outw(OTI_INDEX, OTI_SEGMENT);
560
561 /*
562 Set the OTI-Misc register. We must be sure that we
563 aren't in one of the extended graphics modes when
564 we are leaving X and about to call vgaHWRestore for
565 the last time. If we don't text mode is completely
566 fouled up.
567 */
568 outb(OTI_INDEX, OTI_MISC);
569 temp = inb(OTI_R_W) & 0x20; /* get the clock bit */
570 temp |= (restore->oakMisc & 0xDF);
571 outb(OTI_R_W, temp);
572
573 /*
574 * This function handles restoring the generic VGA registers.
575 */
576 vgaHWRestore(restore);
577
578 /*
579 * Code to restore any SVGA registers that have been saved/modified
580 * goes here. Note that it is allowable, and often correct, to
581 * only modify certain bits in a register by a read/modify/write cycle.
582 *
583 * A special case - when using an external clock-setting program,
584 * this function must not change bits associated with the clock
585 * selection. This condition can be checked by the condition:
586 *
587 * if (restore->std.NoClock >= 0)
588 * restore clock-select bits.
589 */
590
591 outb(OTI_INDEX, OTI_SEGMENT);
592 outb(OTI_R_W, restore->oakBank);
593
594 if (restore->std.NoClock >= 0) {
595 /* restore clock-select bits. */
596 outw(OTI_INDEX, OTI_MISC + (restore->oakMisc << 8));
597 } else {
598 /* don't restore clock-select bits. */
599 outb(OTI_INDEX, OTI_MISC);
600 temp = inb(OTI_R_W) & 0x20; /* get the clock bit */
601 temp |= (restore->oakMisc & 0xDF);
602 outb(OTI_R_W, temp);
603 }
604
605 outb(OTI_INDEX, OTI_BCOMPAT);
606 temp = inb(OTI_R_W);
607 temp &= 0xF9;
608 temp |= (restore->oakBCompat & 0x6);
609 outb(OTI_INDEX, OTI_CONFIG);
610 temp = inb(OTI_R_W);
611 temp &= 0xF7;
612 temp |= (restore->oakConfig & 0x8);
613 outb(OTI_R_W, temp);
614 outw(OTI_INDEX, OTI_OVERFLOW + (restore->oakOverflow << 8));
615 outw(OTI_INDEX, OTI_HSYNC2 + (restore->oakHsync2 << 8));
616
617 if ( OTI_chipset == OTI77)
618 outw(OTI_INDEX, OTI_OVERFLOW2 + (restore->oakOverflow2 << 8));
619
620 outw(0x3C4, 0x0300); /* now reenable the timing sequencer */
621
622 }
623
624 /*
625 * OAKSave --
626 *
627 * This function saves the video state. It reads all of the SVGA registers
628 * into the vgaOAKRec data structure. There is in general no need to
629 * mask out bits here - just read the registers.
630 */
631 extern void *
632 OAKSave(save)
633 vgaOAKPtr save;
634 {
635 unsigned char temp;
636 /*
637 * Whatever code is needed to get back to bank zero goes here.
638 */
639 outb(OTI_INDEX, OTI_SEGMENT);
640 temp = inb(OTI_R_W);
641 /* put segment register to zero */
642 outb(OTI_R_W, 0);
643
644 /*
645 * This function will handle creating the data structure and filling
646 * in the generic VGA portion.
647 */
648 save = (vgaOAKPtr)vgaHWSave(save, sizeof(vgaOAKRec));
649
650 /*
651 * The port I/O code necessary to read in the extended registers
652 * into the fields of the vgaOAKRec structure goes here.
653 */
654
655 save->oakBank = temp; /* this seems silly, leftover from textmode
656 problems */
657
658 outb(OTI_INDEX, OTI_MISC);
659 save->oakMisc = inb(OTI_R_W);
660 outb(OTI_INDEX, OTI_CONFIG);
661 save->oakConfig = inb(OTI_R_W);
662 outb(OTI_INDEX, OTI_BCOMPAT);
663 save->oakBCompat = inb(OTI_R_W);
664 outb(OTI_INDEX, OTI_OVERFLOW);
665 save->oakOverflow = inb(OTI_R_W);
666 outb(OTI_INDEX, OTI_HSYNC2);
667 save->oakHsync2 = inb(OTI_R_W);
668 if ( OTI_chipset == OTI77) {
669 outb(OTI_INDEX, OTI_OVERFLOW2);
670 save->oakOverflow2 = inb(OTI_R_W);
671 }
672
673 return ((void *) save);
674 }
675
676 /*
677 * OAKInit --
678 *
679 * This is the most important function (after the Probe) function. This
680 * function fills in the vgaOAKRec with all of the register values needed
681 * to enable either a 256-color mode (for the color server) or a 16-color
682 * mode (for the monochrome server).
683 *
684 * The 'mode' parameter describes the video mode. The 'mode' structure
685 * as well as the 'vga256InfoRec' structure can be dereferenced for
686 * information that is needed to initialize the mode. The 'new' macro
687 * (see definition above) is used to simply fill in the structure.
688 */
689 static Bool
OAKInit(mode)690 OAKInit(mode)
691 DisplayModePtr mode;
692 {
693 if (mode->Flags & V_INTERLACE ) {
694 /*
695 When in interlace mode cut the vertical numbers in half.
696 (Try and find that in the manual!)
697 Could just set VGA_DIVIDE_VERT but we'd have to
698 test it and do the divides here anyway.
699 */
700 mode->VTotal >>= 1;
701 mode->VDisplay >>= 1;
702 mode->VSyncStart >>= 1;
703 mode->VSyncEnd >>= 1;
704 }
705 /*
706 * This will allocate the datastructure and initialize all of the
707 * generic VGA registers.
708 */
709 if (!vgaHWInit(mode,sizeof(vgaOAKRec)))
710 return(FALSE);
711
712 /*
713 * Here all of the other fields of 'new' get filled in, to
714 * handle the SVGA extended registers. It is also allowable
715 * to override generic registers whenever necessary.
716 *
717 * A special case - when using an external clock-setting program,
718 * this function must not change bits associated with the clock
719 * selection. This condition can be checked by the condition:
720 *
721 * if (new->std.NoClock >= 0)
722 * initialize clock-select bits.
723 */
724 #ifndef MONOVGA
725 /* new->std.CRTC[19] = vga256InfoRec.virtualX >> 3; /* 3 in byte mode */
726 /* much clearer as 0x01 than 0x41, seems odd though... */
727 new->std.Attribute[16] = 0x01;
728
729 /*
730 We set the fifo depth to maximum since it seems to
731 remove screen interference at high resolution. This
732 could probably be set to some other value for better
733 performance.
734 */
735 if ( new->std.NoClock >= 0 ) {
736 new->oakMisc = 0x0F | ((new->std.NoClock & 0x04) << 3);
737 } else
738 new->oakMisc = 0x0F; /* high res mode, deep fifo */
739 #else
740 if ( new->std.NoClock >= 0 ) {
741 new->oakMisc = 0x18 | ((new->std.NoClock & 0x04) << 3);
742 } else
743 new->oakMisc = 0x18; /* 16 color high res mode */
744 #endif
745 new->oakBank = 0;
746 new->oakBCompat = 0x80; /* vga mode */
747 new->oakConfig = (OTI_chipset == OTI77 ? 0x8 : 0 );
748 /* set number of ram chips! */ /* 40 */
749 new->oakMisc |= (vga256InfoRec.videoRam == 1024 ? 0x40 : 0x00 );
750 new->oakMisc |= (vga256InfoRec.videoRam >= 512 ? 0x80 : 0x00 );
751 if (mode->Flags & V_INTERLACE ) {
752 new->oakOverflow = 0x80 |
753 /* V-retrace-start */ (((mode->VSyncStart ) & 0x400) >> 8 ) |
754 /* V-blank-start */ ((((mode->VDisplay-1) ) & 0x400) >> 9 ) |
755 /* V-total */ ((((mode->VTotal-2) ) & 0x400) >> 10 ) ;
756 /* can set overflow2 no matter what here since restore will
757 do the right thing */
758 new->oakOverflow2 = 0;
759 /* Doc. says this is when vertical retrace will start in
760 every odd frame in interlaced mode in characters. Hmm??? */
761 new->oakHsync2 = (mode->VTotal-2) >> 3;
762 } else {
763 new->oakOverflow = (mode->Flags & V_INTERLACE ? 0x80 : 0x00) |
764 /* V-retrace-start */ ((mode->VSyncStart & 0x400) >> 8 ) |
765 /* V-blank-start */ (((mode->VDisplay-1) & 0x400) >> 9 ) |
766 /* V-total */ (((mode->VTotal-2) & 0x400) >> 10 ) ;
767 /* can set overflow2 no matter what here since restore will
768 do the right thing */
769 new->oakOverflow2 = 0;
770 new->oakHsync2 = 0;
771 }
772
773 /*
774 Put vertical numbers back so virtual screen doesn't
775 get fooled.
776 */
777 if (mode->Flags & V_INTERLACE ) {
778 mode->VTotal <<= 1;
779 mode->VDisplay <<= 1;
780 mode->VSyncStart <<= 1;
781 mode->VSyncEnd <<= 1;
782 }
783
784
785 return(TRUE);
786 }
787
788 /*
789 * OAKAdjust --
790 *
791 * This function is used to initialize the SVGA Start Address - the first
792 * displayed location in the video memory. This is used to implement the
793 * virtual window.
794 */
795 static void
OAKAdjust(x,y)796 OAKAdjust(x, y)
797 int x, y;
798 {
799 int temp;
800 /*
801 * The calculation for Base works as follows:
802 *
803 * (y * virtX) + x ==> the linear starting pixel
804 *
805 * This number is divided by 8 for the monochrome server, because
806 * there are 8 pixels per byte.
807 *
808 * For the color server, it's a bit more complex. There is 1 pixel
809 * per byte. In general, the 256-color modes are in word-mode
810 * (16-bit words). Word-mode vs byte-mode is will vary based on
811 * the chipset - refer to the chipset databook. So the pixel address
812 * must be divided by 2 to get a word address. In 256-color modes,
813 * the 4 planes are interleaved (i.e. pixels 0,3,7, etc are adjacent
814 * on plane 0). The starting address needs to be as an offset into
815 * plane 0, so the Base address is divided by 4.
816 *
817 * So:
818 * Monochrome: Base is divided by 8
819 * Color:
820 * if in word mode, Base is divided by 8
821 * if in byte mode, Base is divided by 4
822 *
823 * The generic VGA only supports 16 bits for the Starting Address.
824 * But this is not enough for the extended memory. SVGA chipsets
825 * will have additional bits in their extended registers, which
826 * must also be set.
827 */
828 int Base = (y * vga256InfoRec.virtualX + x + 3) >> 3;
829
830 /*
831 * These are the generic starting address registers.
832 */
833 outw(vgaIOBase + 4, (Base & 0x00FF00) | 0x0C);
834 outw(vgaIOBase + 4, ((Base & 0x00FF) << 8) | 0x0D);
835
836 /*
837 * Here the high-order bits are masked and shifted, and put into
838 * the appropriate extended registers.
839 */
840 outb(OTI_INDEX, OTI_OVERFLOW);
841 temp = inb(OTI_R_W);
842 temp &= 0xF7;
843 temp |= ((Base & 0x10000) >> (5+8));
844 outb(OTI_R_W, temp);
845 if ( OTI_chipset == OTI77) {
846 outb(OTI_INDEX, OTI_OVERFLOW2);
847 temp = inb(OTI_R_W);
848 temp &= 0xF7;
849 temp |= ((Base & 0x20000) >> (6 + 8));
850 outb(OTI_R_W, temp);
851 }
852 }
853