vgaHW.c revision 4642e01f
1
2/*
3 *
4 * Copyright 1991-1999 by The XFree86 Project, Inc.
5 *
6 * Loosely based on code bearing the following copyright:
7 *
8 *   Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
9 *
10 */
11
12#define _NEED_SYSI86
13
14#ifdef HAVE_XORG_CONFIG_H
15#include <xorg-config.h>
16#endif
17
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21
22#include <X11/X.h>
23#include "misc.h"
24
25#include "xf86.h"
26#include "xf86_OSproc.h"
27#include "vgaHW.h"
28
29#include "compiler.h"
30
31#include "xf86cmap.h"
32
33#include "Pci.h"
34
35#ifndef SAVE_FONT1
36#define SAVE_FONT1 1
37#endif
38
39/*
40 * These used to be OS-specific, which made this module have an undesirable
41 * OS dependency.  Define them by default for all platforms.
42 */
43#ifndef NEED_SAVED_CMAP
44#define NEED_SAVED_CMAP
45#endif
46#ifndef SAVE_TEXT
47#define SAVE_TEXT 1
48#endif
49#ifndef SAVE_FONT2
50#define SAVE_FONT2 1
51#endif
52
53/* bytes per plane to save for text */
54#define TEXT_AMOUNT 16384
55
56/* bytes per plane to save for font data */
57#define FONT_AMOUNT (8*8192)
58
59#if 0
60/* Override all of these for now */
61#undef SAVE_FONT1
62#define SAVE_FONT1 1
63#undef SAVE_FONT2
64#define SAVE_FONT2 1
65#undef SAVE_TEST
66#define SAVE_TEST 1
67#undef FONT_AMOUNT
68#define FONT_AMOUNT 65536
69#undef TEXT_AMOUNT
70#define TEXT_AMOUNT 65536
71#endif
72
73/* DAC indices for white and black */
74#define WHITE_VALUE 0x3F
75#define BLACK_VALUE 0x00
76#define OVERSCAN_VALUE 0x01
77
78
79/* Use a private definition of this here */
80#undef VGAHWPTR
81#define VGAHWPTRLVAL(p) (p)->privates[vgaHWPrivateIndex].ptr
82#define VGAHWPTR(p) ((vgaHWPtr)(VGAHWPTRLVAL(p)))
83
84static int vgaHWPrivateIndex = -1;
85
86#define DAC_TEST_MASK 0x3F
87
88#ifdef NEED_SAVED_CMAP
89/* This default colourmap is used only when it can't be read from the VGA */
90
91static CARD8 defaultDAC[768] =
92{
93     0,  0,  0,    0,  0, 42,    0, 42,  0,    0, 42, 42,
94    42,  0,  0,   42,  0, 42,   42, 21,  0,   42, 42, 42,
95    21, 21, 21,   21, 21, 63,   21, 63, 21,   21, 63, 63,
96    63, 21, 21,   63, 21, 63,   63, 63, 21,   63, 63, 63,
97     0,  0,  0,    5,  5,  5,    8,  8,  8,   11, 11, 11,
98    14, 14, 14,   17, 17, 17,   20, 20, 20,   24, 24, 24,
99    28, 28, 28,   32, 32, 32,   36, 36, 36,   40, 40, 40,
100    45, 45, 45,   50, 50, 50,   56, 56, 56,   63, 63, 63,
101     0,  0, 63,   16,  0, 63,   31,  0, 63,   47,  0, 63,
102    63,  0, 63,   63,  0, 47,   63,  0, 31,   63,  0, 16,
103    63,  0,  0,   63, 16,  0,   63, 31,  0,   63, 47,  0,
104    63, 63,  0,   47, 63,  0,   31, 63,  0,   16, 63,  0,
105     0, 63,  0,    0, 63, 16,    0, 63, 31,    0, 63, 47,
106     0, 63, 63,    0, 47, 63,    0, 31, 63,    0, 16, 63,
107    31, 31, 63,   39, 31, 63,   47, 31, 63,   55, 31, 63,
108    63, 31, 63,   63, 31, 55,   63, 31, 47,   63, 31, 39,
109    63, 31, 31,   63, 39, 31,   63, 47, 31,   63, 55, 31,
110    63, 63, 31,   55, 63, 31,   47, 63, 31,   39, 63, 31,
111    31, 63, 31,   31, 63, 39,   31, 63, 47,   31, 63, 55,
112    31, 63, 63,   31, 55, 63,   31, 47, 63,   31, 39, 63,
113    45, 45, 63,   49, 45, 63,   54, 45, 63,   58, 45, 63,
114    63, 45, 63,   63, 45, 58,   63, 45, 54,   63, 45, 49,
115    63, 45, 45,   63, 49, 45,   63, 54, 45,   63, 58, 45,
116    63, 63, 45,   58, 63, 45,   54, 63, 45,   49, 63, 45,
117    45, 63, 45,   45, 63, 49,   45, 63, 54,   45, 63, 58,
118    45, 63, 63,   45, 58, 63,   45, 54, 63,   45, 49, 63,
119     0,  0, 28,    7,  0, 28,   14,  0, 28,   21,  0, 28,
120    28,  0, 28,   28,  0, 21,   28,  0, 14,   28,  0,  7,
121    28,  0,  0,   28,  7,  0,   28, 14,  0,   28, 21,  0,
122    28, 28,  0,   21, 28,  0,   14, 28,  0,    7, 28,  0,
123     0, 28,  0,    0, 28,  7,    0, 28, 14,    0, 28, 21,
124     0, 28, 28,    0, 21, 28,    0, 14, 28,    0,  7, 28,
125    14, 14, 28,   17, 14, 28,   21, 14, 28,   24, 14, 28,
126    28, 14, 28,   28, 14, 24,   28, 14, 21,   28, 14, 17,
127    28, 14, 14,   28, 17, 14,   28, 21, 14,   28, 24, 14,
128    28, 28, 14,   24, 28, 14,   21, 28, 14,   17, 28, 14,
129    14, 28, 14,   14, 28, 17,   14, 28, 21,   14, 28, 24,
130    14, 28, 28,   14, 24, 28,   14, 21, 28,   14, 17, 28,
131    20, 20, 28,   22, 20, 28,   24, 20, 28,   26, 20, 28,
132    28, 20, 28,   28, 20, 26,   28, 20, 24,   28, 20, 22,
133    28, 20, 20,   28, 22, 20,   28, 24, 20,   28, 26, 20,
134    28, 28, 20,   26, 28, 20,   24, 28, 20,   22, 28, 20,
135    20, 28, 20,   20, 28, 22,   20, 28, 24,   20, 28, 26,
136    20, 28, 28,   20, 26, 28,   20, 24, 28,   20, 22, 28,
137     0,  0, 16,    4,  0, 16,    8,  0, 16,   12,  0, 16,
138    16,  0, 16,   16,  0, 12,   16,  0,  8,   16,  0,  4,
139    16,  0,  0,   16,  4,  0,   16,  8,  0,   16, 12,  0,
140    16, 16,  0,   12, 16,  0,    8, 16,  0,    4, 16,  0,
141     0, 16,  0,    0, 16,  4,    0, 16,  8,    0, 16, 12,
142     0, 16, 16,    0, 12, 16,    0,  8, 16,    0,  4, 16,
143     8,  8, 16,   10,  8, 16,   12,  8, 16,   14,  8, 16,
144    16,  8, 16,   16,  8, 14,   16,  8, 12,   16,  8, 10,
145    16,  8,  8,   16, 10,  8,   16, 12,  8,   16, 14,  8,
146    16, 16,  8,   14, 16,  8,   12, 16,  8,   10, 16,  8,
147     8, 16,  8,    8, 16, 10,    8, 16, 12,    8, 16, 14,
148     8, 16, 16,    8, 14, 16,    8, 12, 16,    8, 10, 16,
149    11, 11, 16,   12, 11, 16,   13, 11, 16,   15, 11, 16,
150    16, 11, 16,   16, 11, 15,   16, 11, 13,   16, 11, 12,
151    16, 11, 11,   16, 12, 11,   16, 13, 11,   16, 15, 11,
152    16, 16, 11,   15, 16, 11,   13, 16, 11,   12, 16, 11,
153    11, 16, 11,   11, 16, 12,   11, 16, 13,   11, 16, 15,
154    11, 16, 16,   11, 15, 16,   11, 13, 16,   11, 12, 16,
155     0,  0,  0,    0,  0,  0,    0,  0,  0,    0,  0,  0,
156     0,  0,  0,    0,  0,  0,    0,  0,  0,    0,  0,  0,
157};
158#endif /* NEED_SAVED_CMAP */
159
160/*
161 * Standard VGA versions of the register access functions.
162 */
163static void
164stdWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
165{
166    outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_INDEX_OFFSET, index);
167    outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_DATA_OFFSET, value);
168}
169
170static CARD8
171stdReadCrtc(vgaHWPtr hwp, CARD8 index)
172{
173    outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_INDEX_OFFSET, index);
174    return inb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_DATA_OFFSET);
175}
176
177static void
178stdWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
179{
180    outb(hwp->PIOOffset + VGA_GRAPH_INDEX, index);
181    outb(hwp->PIOOffset + VGA_GRAPH_DATA, value);
182}
183
184static CARD8
185stdReadGr(vgaHWPtr hwp, CARD8 index)
186{
187    outb(hwp->PIOOffset + VGA_GRAPH_INDEX, index);
188    return inb(hwp->PIOOffset + VGA_GRAPH_DATA);
189}
190
191static void
192stdWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
193{
194    outb(hwp->PIOOffset + VGA_SEQ_INDEX, index);
195    outb(hwp->PIOOffset + VGA_SEQ_DATA, value);
196}
197
198static CARD8
199stdReadSeq(vgaHWPtr hwp, CARD8 index)
200{
201    outb(hwp->PIOOffset + VGA_SEQ_INDEX, index);
202    return inb(hwp->PIOOffset + VGA_SEQ_DATA);
203}
204
205static CARD8
206stdReadST00(vgaHWPtr hwp)
207{
208    return inb(hwp->PIOOffset + VGA_IN_STAT_0);
209}
210
211static CARD8
212stdReadST01(vgaHWPtr hwp)
213{
214    return inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET);
215}
216
217static CARD8
218stdReadFCR(vgaHWPtr hwp)
219{
220    return inb(hwp->PIOOffset + VGA_FEATURE_R);
221}
222
223static void
224stdWriteFCR(vgaHWPtr hwp, CARD8 value)
225{
226    outb(hwp->IOBase + hwp->PIOOffset + VGA_FEATURE_W_OFFSET,value);
227}
228
229static void
230stdWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
231{
232    if (hwp->paletteEnabled)
233	index &= ~0x20;
234    else
235	index |= 0x20;
236
237    (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET);
238    outb(hwp->PIOOffset + VGA_ATTR_INDEX, index);
239    outb(hwp->PIOOffset + VGA_ATTR_DATA_W, value);
240}
241
242static CARD8
243stdReadAttr(vgaHWPtr hwp, CARD8 index)
244{
245    if (hwp->paletteEnabled)
246	index &= ~0x20;
247    else
248	index |= 0x20;
249
250    (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET);
251    outb(hwp->PIOOffset + VGA_ATTR_INDEX, index);
252    return inb(hwp->PIOOffset + VGA_ATTR_DATA_R);
253}
254
255static void
256stdWriteMiscOut(vgaHWPtr hwp, CARD8 value)
257{
258    outb(hwp->PIOOffset + VGA_MISC_OUT_W, value);
259}
260
261static CARD8
262stdReadMiscOut(vgaHWPtr hwp)
263{
264    return inb(hwp->PIOOffset + VGA_MISC_OUT_R);
265}
266
267static void
268stdEnablePalette(vgaHWPtr hwp)
269{
270    (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET);
271    outb(hwp->PIOOffset + VGA_ATTR_INDEX, 0x00);
272    hwp->paletteEnabled = TRUE;
273}
274
275static void
276stdDisablePalette(vgaHWPtr hwp)
277{
278    (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET);
279    outb(hwp->PIOOffset + VGA_ATTR_INDEX, 0x20);
280    hwp->paletteEnabled = FALSE;
281}
282
283static void
284stdWriteDacMask(vgaHWPtr hwp, CARD8 value)
285{
286    outb(hwp->PIOOffset + VGA_DAC_MASK, value);
287}
288
289static CARD8
290stdReadDacMask(vgaHWPtr hwp)
291{
292    return inb(hwp->PIOOffset + VGA_DAC_MASK);
293}
294
295static void
296stdWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
297{
298    outb(hwp->PIOOffset + VGA_DAC_READ_ADDR, value);
299}
300
301static void
302stdWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
303{
304    outb(hwp->PIOOffset + VGA_DAC_WRITE_ADDR, value);
305}
306
307static void
308stdWriteDacData(vgaHWPtr hwp, CARD8 value)
309{
310    outb(hwp->PIOOffset + VGA_DAC_DATA, value);
311}
312
313static CARD8
314stdReadDacData(vgaHWPtr hwp)
315{
316    return inb(hwp->PIOOffset + VGA_DAC_DATA);
317}
318
319static CARD8
320stdReadEnable(vgaHWPtr hwp)
321{
322    return inb(hwp->PIOOffset + VGA_ENABLE);
323}
324
325static void
326stdWriteEnable(vgaHWPtr hwp, CARD8 value)
327{
328    outb(hwp->PIOOffset + VGA_ENABLE, value);
329}
330
331void
332vgaHWSetStdFuncs(vgaHWPtr hwp)
333{
334    hwp->writeCrtc		= stdWriteCrtc;
335    hwp->readCrtc		= stdReadCrtc;
336    hwp->writeGr		= stdWriteGr;
337    hwp->readGr			= stdReadGr;
338    hwp->readST00               = stdReadST00;
339    hwp->readST01               = stdReadST01;
340    hwp->readFCR                = stdReadFCR;
341    hwp->writeFCR               = stdWriteFCR;
342    hwp->writeAttr		= stdWriteAttr;
343    hwp->readAttr		= stdReadAttr;
344    hwp->writeSeq		= stdWriteSeq;
345    hwp->readSeq		= stdReadSeq;
346    hwp->writeMiscOut		= stdWriteMiscOut;
347    hwp->readMiscOut		= stdReadMiscOut;
348    hwp->enablePalette		= stdEnablePalette;
349    hwp->disablePalette		= stdDisablePalette;
350    hwp->writeDacMask		= stdWriteDacMask;
351    hwp->readDacMask		= stdReadDacMask;
352    hwp->writeDacWriteAddr	= stdWriteDacWriteAddr;
353    hwp->writeDacReadAddr	= stdWriteDacReadAddr;
354    hwp->writeDacData		= stdWriteDacData;
355    hwp->readDacData		= stdReadDacData;
356    hwp->PIOOffset		= 0;
357    hwp->readEnable		= stdReadEnable;
358    hwp->writeEnable		= stdWriteEnable;
359}
360
361/*
362 * MMIO versions of the register access functions.  These require
363 * hwp->MemBase to be set in such a way that when the standard VGA port
364 * adderss is added the correct memory address results.
365 */
366
367#define minb(p) MMIO_IN8(hwp->MMIOBase, (hwp->MMIOOffset + (p)))
368#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (hwp->MMIOOffset + (p)),(v))
369
370static void
371mmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
372{
373    moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
374    moutb(hwp->IOBase + VGA_CRTC_DATA_OFFSET, value);
375}
376
377static CARD8
378mmioReadCrtc(vgaHWPtr hwp, CARD8 index)
379{
380    moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
381    return minb(hwp->IOBase + VGA_CRTC_DATA_OFFSET);
382}
383
384static void
385mmioWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
386{
387    moutb(VGA_GRAPH_INDEX, index);
388    moutb(VGA_GRAPH_DATA, value);
389}
390
391static CARD8
392mmioReadGr(vgaHWPtr hwp, CARD8 index)
393{
394    moutb(VGA_GRAPH_INDEX, index);
395    return minb(VGA_GRAPH_DATA);
396}
397
398static void
399mmioWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
400{
401    moutb(VGA_SEQ_INDEX, index);
402    moutb(VGA_SEQ_DATA, value);
403}
404
405static CARD8
406mmioReadSeq(vgaHWPtr hwp, CARD8 index)
407{
408    moutb(VGA_SEQ_INDEX, index);
409    return minb(VGA_SEQ_DATA);
410}
411
412static CARD8
413mmioReadST00(vgaHWPtr hwp)
414{
415    return minb(VGA_IN_STAT_0);
416}
417
418static CARD8
419mmioReadST01(vgaHWPtr hwp)
420{
421    return minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
422}
423
424static CARD8
425mmioReadFCR(vgaHWPtr hwp)
426{
427    return minb(VGA_FEATURE_R);
428}
429
430static void
431mmioWriteFCR(vgaHWPtr hwp, CARD8 value)
432{
433    moutb(hwp->IOBase + VGA_FEATURE_W_OFFSET,value);
434}
435
436static void
437mmioWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
438{
439    if (hwp->paletteEnabled)
440	index &= ~0x20;
441    else
442	index |= 0x20;
443
444    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
445    moutb(VGA_ATTR_INDEX, index);
446    moutb(VGA_ATTR_DATA_W, value);
447}
448
449static CARD8
450mmioReadAttr(vgaHWPtr hwp, CARD8 index)
451{
452    if (hwp->paletteEnabled)
453	index &= ~0x20;
454    else
455	index |= 0x20;
456
457    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
458    moutb(VGA_ATTR_INDEX, index);
459    return minb(VGA_ATTR_DATA_R);
460}
461
462static void
463mmioWriteMiscOut(vgaHWPtr hwp, CARD8 value)
464{
465    moutb(VGA_MISC_OUT_W, value);
466}
467
468static CARD8
469mmioReadMiscOut(vgaHWPtr hwp)
470{
471    return minb(VGA_MISC_OUT_R);
472}
473
474static void
475mmioEnablePalette(vgaHWPtr hwp)
476{
477    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
478    moutb(VGA_ATTR_INDEX, 0x00);
479    hwp->paletteEnabled = TRUE;
480}
481
482static void
483mmioDisablePalette(vgaHWPtr hwp)
484{
485    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
486    moutb(VGA_ATTR_INDEX, 0x20);
487    hwp->paletteEnabled = FALSE;
488}
489
490static void
491mmioWriteDacMask(vgaHWPtr hwp, CARD8 value)
492{
493    moutb(VGA_DAC_MASK, value);
494}
495
496static CARD8
497mmioReadDacMask(vgaHWPtr hwp)
498{
499    return minb(VGA_DAC_MASK);
500}
501
502static void
503mmioWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
504{
505    moutb(VGA_DAC_READ_ADDR, value);
506}
507
508static void
509mmioWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
510{
511    moutb(VGA_DAC_WRITE_ADDR, value);
512}
513
514static void
515mmioWriteDacData(vgaHWPtr hwp, CARD8 value)
516{
517    moutb(VGA_DAC_DATA, value);
518}
519
520static CARD8
521mmioReadDacData(vgaHWPtr hwp)
522{
523    return minb(VGA_DAC_DATA);
524}
525
526static CARD8
527mmioReadEnable(vgaHWPtr hwp)
528{
529    return minb(VGA_ENABLE);
530}
531
532static void
533mmioWriteEnable(vgaHWPtr hwp, CARD8 value)
534{
535    moutb(VGA_ENABLE, value);
536}
537
538void
539vgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset)
540{
541    hwp->writeCrtc		= mmioWriteCrtc;
542    hwp->readCrtc		= mmioReadCrtc;
543    hwp->writeGr		= mmioWriteGr;
544    hwp->readGr			= mmioReadGr;
545    hwp->readST00               = mmioReadST00;
546    hwp->readST01               = mmioReadST01;
547    hwp->readFCR                = mmioReadFCR;
548    hwp->writeFCR               = mmioWriteFCR;
549    hwp->writeAttr		= mmioWriteAttr;
550    hwp->readAttr		= mmioReadAttr;
551    hwp->writeSeq		= mmioWriteSeq;
552    hwp->readSeq		= mmioReadSeq;
553    hwp->writeMiscOut		= mmioWriteMiscOut;
554    hwp->readMiscOut		= mmioReadMiscOut;
555    hwp->enablePalette		= mmioEnablePalette;
556    hwp->disablePalette		= mmioDisablePalette;
557    hwp->writeDacMask		= mmioWriteDacMask;
558    hwp->readDacMask		= mmioReadDacMask;
559    hwp->writeDacWriteAddr	= mmioWriteDacWriteAddr;
560    hwp->writeDacReadAddr	= mmioWriteDacReadAddr;
561    hwp->writeDacData		= mmioWriteDacData;
562    hwp->readDacData		= mmioReadDacData;
563    hwp->MMIOBase		= base;
564    hwp->MMIOOffset		= offset;
565    hwp->readEnable		= mmioReadEnable;
566    hwp->writeEnable		= mmioWriteEnable;
567}
568
569/*
570 * vgaHWProtect --
571 *	Protect VGA registers and memory from corruption during loads.
572 */
573
574void
575vgaHWProtect(ScrnInfoPtr pScrn, Bool on)
576{
577  vgaHWPtr hwp = VGAHWPTR(pScrn);
578
579  unsigned char tmp;
580
581  if (pScrn->vtSema) {
582    if (on) {
583      /*
584       * Turn off screen and disable sequencer.
585       */
586      tmp = hwp->readSeq(hwp, 0x01);
587
588      vgaHWSeqReset(hwp, TRUE);			/* start synchronous reset */
589      hwp->writeSeq(hwp, 0x01, tmp | 0x20);	/* disable the display */
590
591      hwp->enablePalette(hwp);
592    } else {
593      /*
594       * Reenable sequencer, then turn on screen.
595       */
596
597      tmp = hwp->readSeq(hwp, 0x01);
598
599      hwp->writeSeq(hwp, 0x01, tmp & ~0x20);	/* reenable display */
600      vgaHWSeqReset(hwp, FALSE);		/* clear synchronousreset */
601
602      hwp->disablePalette(hwp);
603    }
604  }
605}
606
607vgaHWProtectProc *vgaHWProtectWeak(void) {
608  return vgaHWProtect;
609}
610
611/*
612 * vgaHWBlankScreen -- blank the screen.
613 */
614
615void
616vgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on)
617{
618  vgaHWPtr hwp = VGAHWPTR(pScrn);
619  unsigned char scrn;
620
621  scrn = hwp->readSeq(hwp, 0x01);
622
623  if (on) {
624    scrn &= ~0x20;			/* enable screen */
625  } else {
626    scrn |= 0x20;			/* blank screen */
627  }
628
629  vgaHWSeqReset(hwp, TRUE);
630  hwp->writeSeq(hwp, 0x01, scrn);	/* change mode */
631  vgaHWSeqReset(hwp, FALSE);
632}
633
634vgaHWBlankScreenProc *vgaHWBlankScreenWeak(void) {
635  return vgaHWBlankScreen;
636}
637
638/*
639 * vgaHWSaveScreen -- blank the screen.
640 */
641
642Bool
643vgaHWSaveScreen(ScreenPtr pScreen, int mode)
644{
645   ScrnInfoPtr pScrn = NULL;
646   Bool on;
647
648   if (pScreen != NULL)
649      pScrn = xf86Screens[pScreen->myNum];
650
651   on = xf86IsUnblank(mode);
652
653#if 0
654   if (on)
655      SetTimeSinceLastInputEvent();
656#endif
657
658   if ((pScrn != NULL) && pScrn->vtSema) {
659     vgaHWBlankScreen(pScrn, on);
660   }
661   return (TRUE);
662}
663
664
665/*
666 * vgaHWDPMSSet -- Sets VESA Display Power Management Signaling (DPMS) Mode
667 *
668 * This generic VGA function can only set the Off and On modes.  If the
669 * Standby and Suspend modes are to be supported, a chip specific replacement
670 * for this function must be written.
671 */
672
673void
674vgaHWDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
675{
676  unsigned char seq1 = 0, crtc17 = 0;
677  vgaHWPtr hwp = VGAHWPTR(pScrn);
678
679  if (!pScrn->vtSema) return;
680
681  switch (PowerManagementMode) {
682  case DPMSModeOn:
683    /* Screen: On; HSync: On, VSync: On */
684    seq1 = 0x00;
685    crtc17 = 0x80;
686    break;
687  case DPMSModeStandby:
688    /* Screen: Off; HSync: Off, VSync: On -- Not Supported */
689    seq1 = 0x20;
690    crtc17 = 0x80;
691    break;
692  case DPMSModeSuspend:
693    /* Screen: Off; HSync: On, VSync: Off -- Not Supported */
694    seq1 = 0x20;
695    crtc17 = 0x80;
696    break;
697  case DPMSModeOff:
698    /* Screen: Off; HSync: Off, VSync: Off */
699    seq1 = 0x20;
700    crtc17 = 0x00;
701    break;
702  }
703  hwp->writeSeq(hwp, 0x00, 0x01);		/* Synchronous Reset */
704  seq1 |= hwp->readSeq(hwp, 0x01) & ~0x20;
705  hwp->writeSeq(hwp, 0x01, seq1);
706  crtc17 |= hwp->readCrtc(hwp, 0x17) & ~0x80;
707  usleep(10000);
708  hwp->writeCrtc(hwp, 0x17, crtc17);
709  hwp->writeSeq(hwp, 0x00, 0x03);		/* End Reset */
710}
711
712
713/*
714 * vgaHWSeqReset
715 *      perform a sequencer reset.
716 */
717
718void
719vgaHWSeqReset(vgaHWPtr hwp, Bool start)
720{
721  if (start)
722    hwp->writeSeq(hwp, 0x00, 0x01);		/* Synchronous Reset */
723  else
724    hwp->writeSeq(hwp, 0x00, 0x03);		/* End Reset */
725}
726
727
728void
729vgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
730{
731#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
732    vgaHWPtr hwp = VGAHWPTR(scrninfp);
733    int savedIOBase;
734    unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4;
735    Bool doMap = FALSE;
736
737    /* If nothing to do, return now */
738    if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo)
739	return;
740
741    if (hwp->Base == NULL) {
742	doMap = TRUE;
743	if (!vgaHWMapMem(scrninfp)) {
744	    xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
745		       "vgaHWRestoreFonts: vgaHWMapMem() failed\n");
746	    return;
747	}
748    }
749
750    /* save the registers that are needed here */
751    miscOut = hwp->readMiscOut(hwp);
752    attr10 = hwp->readAttr(hwp, 0x10);
753    gr1 = hwp->readGr(hwp, 0x01);
754    gr3 = hwp->readGr(hwp, 0x03);
755    gr4 = hwp->readGr(hwp, 0x04);
756    gr5 = hwp->readGr(hwp, 0x05);
757    gr6 = hwp->readGr(hwp, 0x06);
758    gr8 = hwp->readGr(hwp, 0x08);
759    seq2 = hwp->readSeq(hwp, 0x02);
760    seq4 = hwp->readSeq(hwp, 0x04);
761
762    /* save hwp->IOBase and temporarily set it for colour mode */
763    savedIOBase = hwp->IOBase;
764    hwp->IOBase = VGA_IOBASE_COLOR;
765
766    /* Force into colour mode */
767    hwp->writeMiscOut(hwp, miscOut | 0x01);
768
769    vgaHWBlankScreen(scrninfp, FALSE);
770
771    /*
772     * here we temporarily switch to 16 colour planar mode, to simply
773     * copy the font-info and saved text.
774     *
775     * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
776     */
777#if 0
778    hwp->writeAttr(hwp, 0x10, 0x01);	/* graphics mode */
779#endif
780
781    hwp->writeSeq(hwp, 0x04, 0x06);	/* enable plane graphics */
782    hwp->writeGr(hwp, 0x05, 0x00);	/* write mode 0, read mode 0 */
783    hwp->writeGr(hwp, 0x06, 0x05);	/* set graphics */
784
785    if (scrninfp->depth == 4) {
786	/* GJA */
787	hwp->writeGr(hwp, 0x03, 0x00);	/* don't rotate, write unmodified */
788	hwp->writeGr(hwp, 0x08, 0xFF);	/* write all bits in a byte */
789	hwp->writeGr(hwp, 0x01, 0x00);	/* all planes come from CPU */
790    }
791
792#if SAVE_FONT1
793    if (hwp->FontInfo1) {
794	hwp->writeSeq(hwp, 0x02, 0x04);	/* write to plane 2 */
795	hwp->writeGr(hwp, 0x04, 0x02);	/* read plane 2 */
796	slowbcopy_tobus(hwp->FontInfo1, hwp->Base, FONT_AMOUNT);
797    }
798#endif
799
800#if SAVE_FONT2
801    if (hwp->FontInfo2) {
802	hwp->writeSeq(hwp, 0x02, 0x08);	/* write to plane 3 */
803	hwp->writeGr(hwp, 0x04, 0x03);	/* read plane 3 */
804	slowbcopy_tobus(hwp->FontInfo2, hwp->Base, FONT_AMOUNT);
805    }
806#endif
807
808#if SAVE_TEXT
809    if (hwp->TextInfo) {
810	hwp->writeSeq(hwp, 0x02, 0x01);	/* write to plane 0 */
811	hwp->writeGr(hwp, 0x04, 0x00);	/* read plane 0 */
812	slowbcopy_tobus(hwp->TextInfo, hwp->Base, TEXT_AMOUNT);
813	hwp->writeSeq(hwp, 0x02, 0x02);	/* write to plane 1 */
814	hwp->writeGr(hwp, 0x04, 0x01);	/* read plane 1 */
815	slowbcopy_tobus((unsigned char *)hwp->TextInfo + TEXT_AMOUNT,
816			hwp->Base, TEXT_AMOUNT);
817    }
818#endif
819
820    vgaHWBlankScreen(scrninfp, TRUE);
821
822    /* restore the registers that were changed */
823    hwp->writeMiscOut(hwp, miscOut);
824    hwp->writeAttr(hwp, 0x10, attr10);
825    hwp->writeGr(hwp, 0x01, gr1);
826    hwp->writeGr(hwp, 0x03, gr3);
827    hwp->writeGr(hwp, 0x04, gr4);
828    hwp->writeGr(hwp, 0x05, gr5);
829    hwp->writeGr(hwp, 0x06, gr6);
830    hwp->writeGr(hwp, 0x08, gr8);
831    hwp->writeSeq(hwp, 0x02, seq2);
832    hwp->writeSeq(hwp, 0x04, seq4);
833    hwp->IOBase = savedIOBase;
834
835    if (doMap)
836	vgaHWUnmapMem(scrninfp);
837
838#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
839}
840
841
842void
843vgaHWRestoreMode(ScrnInfoPtr scrninfp, vgaRegPtr restore)
844{
845    vgaHWPtr hwp = VGAHWPTR(scrninfp);
846    int i;
847
848    if (restore->MiscOutReg & 0x01)
849	hwp->IOBase = VGA_IOBASE_COLOR;
850    else
851	hwp->IOBase = VGA_IOBASE_MONO;
852
853    hwp->writeMiscOut(hwp, restore->MiscOutReg);
854
855    for (i = 1; i < restore->numSequencer; i++)
856	hwp->writeSeq(hwp, i, restore->Sequencer[i]);
857
858    /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
859    hwp->writeCrtc(hwp, 17, restore->CRTC[17] & ~0x80);
860
861    for (i = 0; i < restore->numCRTC; i++)
862	hwp->writeCrtc(hwp, i, restore->CRTC[i]);
863
864    for (i = 0; i < restore->numGraphics; i++)
865	hwp->writeGr(hwp, i, restore->Graphics[i]);
866
867    hwp->enablePalette(hwp);
868    for (i = 0; i < restore->numAttribute; i++)
869	hwp->writeAttr(hwp, i, restore->Attribute[i]);
870    hwp->disablePalette(hwp);
871}
872
873
874void
875vgaHWRestoreColormap(ScrnInfoPtr scrninfp, vgaRegPtr restore)
876{
877    vgaHWPtr hwp = VGAHWPTR(scrninfp);
878    int i;
879
880#if 0
881    hwp->enablePalette(hwp);
882#endif
883
884    hwp->writeDacMask(hwp, 0xFF);
885    hwp->writeDacWriteAddr(hwp, 0x00);
886    for (i = 0; i < 768; i++) {
887	hwp->writeDacData(hwp, restore->DAC[i]);
888	DACDelay(hwp);
889    }
890
891    hwp->disablePalette(hwp);
892}
893
894
895/*
896 * vgaHWRestore --
897 *      restore the VGA state
898 */
899
900void
901vgaHWRestore(ScrnInfoPtr scrninfp, vgaRegPtr restore, int flags)
902{
903    if (flags & VGA_SR_MODE)
904	vgaHWRestoreMode(scrninfp, restore);
905
906    if (flags & VGA_SR_FONTS)
907	vgaHWRestoreFonts(scrninfp, restore);
908
909    if (flags & VGA_SR_CMAP)
910	vgaHWRestoreColormap(scrninfp, restore);
911}
912
913void
914vgaHWSaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save)
915{
916#if  SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
917    vgaHWPtr hwp = VGAHWPTR(scrninfp);
918    int savedIOBase;
919    unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4;
920    Bool doMap = FALSE;
921
922    if (hwp->Base == NULL) {
923	doMap = TRUE;
924	if (!vgaHWMapMem(scrninfp)) {
925	    xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
926		       "vgaHWSaveFonts: vgaHWMapMem() failed\n");
927	    return;
928	}
929    }
930
931    /* If in graphics mode, don't save anything */
932    attr10 = hwp->readAttr(hwp, 0x10);
933    if (attr10 & 0x01)
934	return;
935
936    /* save the registers that are needed here */
937    miscOut = hwp->readMiscOut(hwp);
938    gr4 = hwp->readGr(hwp, 0x04);
939    gr5 = hwp->readGr(hwp, 0x05);
940    gr6 = hwp->readGr(hwp, 0x06);
941    seq2 = hwp->readSeq(hwp, 0x02);
942    seq4 = hwp->readSeq(hwp, 0x04);
943
944    /* save hwp->IOBase and temporarily set it for colour mode */
945    savedIOBase = hwp->IOBase;
946    hwp->IOBase = VGA_IOBASE_COLOR;
947
948    /* Force into colour mode */
949    hwp->writeMiscOut(hwp, miscOut | 0x01);
950
951    vgaHWBlankScreen(scrninfp, FALSE);
952
953    /*
954     * get the character sets, and text screen if required
955     */
956    /*
957     * Here we temporarily switch to 16 colour planar mode, to simply
958     * copy the font-info
959     *
960     * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
961     */
962#if 0
963    hwp->writeAttr(hwp, 0x10, 0x01);	/* graphics mode */
964#endif
965
966    hwp->writeSeq(hwp, 0x04, 0x06);	/* enable plane graphics */
967    hwp->writeGr(hwp, 0x05, 0x00);	/* write mode 0, read mode 0 */
968    hwp->writeGr(hwp, 0x06, 0x05);	/* set graphics */
969
970#if SAVE_FONT1
971    if (hwp->FontInfo1 || (hwp->FontInfo1 = xalloc(FONT_AMOUNT))) {
972	hwp->writeSeq(hwp, 0x02, 0x04);	/* write to plane 2 */
973	hwp->writeGr(hwp, 0x04, 0x02);	/* read plane 2 */
974	slowbcopy_frombus(hwp->Base, hwp->FontInfo1, FONT_AMOUNT);
975    }
976#endif /* SAVE_FONT1 */
977#if SAVE_FONT2
978    if (hwp->FontInfo2 || (hwp->FontInfo2 = xalloc(FONT_AMOUNT))) {
979	hwp->writeSeq(hwp, 0x02, 0x08);	/* write to plane 3 */
980	hwp->writeGr(hwp, 0x04, 0x03);	/* read plane 3 */
981	slowbcopy_frombus(hwp->Base, hwp->FontInfo2, FONT_AMOUNT);
982    }
983#endif /* SAVE_FONT2 */
984#if SAVE_TEXT
985    if (hwp->TextInfo || (hwp->TextInfo = xalloc(2 * TEXT_AMOUNT))) {
986	hwp->writeSeq(hwp, 0x02, 0x01);	/* write to plane 0 */
987	hwp->writeGr(hwp, 0x04, 0x00);	/* read plane 0 */
988	slowbcopy_frombus(hwp->Base, hwp->TextInfo, TEXT_AMOUNT);
989	hwp->writeSeq(hwp, 0x02, 0x02);	/* write to plane 1 */
990	hwp->writeGr(hwp, 0x04, 0x01);	/* read plane 1 */
991	slowbcopy_frombus(hwp->Base,
992		(unsigned char *)hwp->TextInfo + TEXT_AMOUNT, TEXT_AMOUNT);
993    }
994#endif /* SAVE_TEXT */
995
996    /* Restore clobbered registers */
997    hwp->writeAttr(hwp, 0x10, attr10);
998    hwp->writeSeq(hwp, 0x02, seq2);
999    hwp->writeSeq(hwp, 0x04, seq4);
1000    hwp->writeGr(hwp, 0x04, gr4);
1001    hwp->writeGr(hwp, 0x05, gr5);
1002    hwp->writeGr(hwp, 0x06, gr6);
1003    hwp->writeMiscOut(hwp, miscOut);
1004    hwp->IOBase = savedIOBase;
1005
1006    vgaHWBlankScreen(scrninfp, TRUE);
1007
1008    if (doMap)
1009	vgaHWUnmapMem(scrninfp);
1010
1011#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
1012}
1013
1014void
1015vgaHWSaveMode(ScrnInfoPtr scrninfp, vgaRegPtr save)
1016{
1017    vgaHWPtr hwp = VGAHWPTR(scrninfp);
1018    int i;
1019
1020    save->MiscOutReg = hwp->readMiscOut(hwp);
1021    if (save->MiscOutReg & 0x01)
1022	hwp->IOBase = VGA_IOBASE_COLOR;
1023    else
1024	hwp->IOBase = VGA_IOBASE_MONO;
1025
1026    for (i = 0; i < save->numCRTC; i++) {
1027	save->CRTC[i] = hwp->readCrtc(hwp, i);
1028#ifdef DEBUG
1029	ErrorF("CRTC[0x%02x] = 0x%02x\n", i, save->CRTC[i]);
1030#endif
1031    }
1032
1033    hwp->enablePalette(hwp);
1034    for (i = 0; i < save->numAttribute; i++) {
1035	save->Attribute[i] = hwp->readAttr(hwp, i);
1036#ifdef DEBUG
1037	ErrorF("Attribute[0x%02x] = 0x%02x\n", i, save->Attribute[i]);
1038#endif
1039    }
1040    hwp->disablePalette(hwp);
1041
1042    for (i = 0; i < save->numGraphics; i++) {
1043	save->Graphics[i] = hwp->readGr(hwp, i);
1044#ifdef DEBUG
1045	ErrorF("Graphics[0x%02x] = 0x%02x\n", i, save->Graphics[i]);
1046#endif
1047    }
1048
1049    for (i = 1; i < save->numSequencer; i++) {
1050	save->Sequencer[i] = hwp->readSeq(hwp, i);
1051#ifdef DEBUG
1052	ErrorF("Sequencer[0x%02x] = 0x%02x\n", i, save->Sequencer[i]);
1053#endif
1054    }
1055}
1056
1057
1058void
1059vgaHWSaveColormap(ScrnInfoPtr scrninfp, vgaRegPtr save)
1060{
1061    vgaHWPtr hwp = VGAHWPTR(scrninfp);
1062    Bool readError = FALSE;
1063    int i;
1064
1065#ifdef NEED_SAVED_CMAP
1066    /*
1067     * Some ET4000 chips from 1991 have a HW bug that prevents the reading
1068     * of the color lookup table.  Mask rev 9042EAI is known to have this bug.
1069     *
1070     * If the colourmap is not readable, we set the saved map to a default
1071     * map (taken from Ferraro's "Programmer's Guide to the EGA and VGA
1072     * Cards" 2nd ed).
1073     */
1074
1075    /* Only save it once */
1076    if (hwp->cmapSaved)
1077	return;
1078
1079#if 0
1080    hwp->enablePalette(hwp);
1081#endif
1082
1083    hwp->writeDacMask(hwp, 0xFF);
1084
1085    /*
1086     * check if we can read the lookup table
1087     */
1088    hwp->writeDacReadAddr(hwp, 0x00);
1089    for (i = 0; i < 6; i++) {
1090	save->DAC[i] = hwp->readDacData(hwp);
1091#ifdef DEBUG
1092	switch (i % 3) {
1093	case 0:
1094	    ErrorF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
1095	    break;
1096	case 1:
1097	    ErrorF("0x%02x, ", save->DAC[i]);
1098	    break;
1099	case 2:
1100	    ErrorF("0x%02x\n", save->DAC[i]);
1101	}
1102#endif
1103    }
1104
1105    /*
1106     * Check if we can read the palette -
1107     * use foreground color to prevent flashing.
1108     */
1109    hwp->writeDacWriteAddr(hwp, 0x01);
1110    for (i = 3; i < 6; i++)
1111	hwp->writeDacData(hwp, ~save->DAC[i] & DAC_TEST_MASK);
1112    hwp->writeDacReadAddr(hwp, 0x01);
1113    for (i = 3; i < 6; i++) {
1114	if (hwp->readDacData(hwp) != (~save->DAC[i] & DAC_TEST_MASK))
1115	    readError = TRUE;
1116    }
1117    hwp->writeDacWriteAddr(hwp, 0x01);
1118    for (i = 3; i < 6; i++)
1119	hwp->writeDacData(hwp, save->DAC[i]);
1120
1121    if (readError) {
1122	/*
1123	 * save the default lookup table
1124	 */
1125	memmove(save->DAC, defaultDAC, 768);
1126	xf86DrvMsg(scrninfp->scrnIndex, X_WARNING,
1127	   "Cannot read colourmap from VGA.  Will restore with default\n");
1128    } else {
1129	/* save the colourmap */
1130	hwp->writeDacReadAddr(hwp, 0x02);
1131	for (i = 6; i < 768; i++) {
1132	    save->DAC[i] = hwp->readDacData(hwp);
1133	    DACDelay(hwp);
1134#ifdef DEBUG
1135	    switch (i % 3) {
1136	    case 0:
1137		ErrorF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
1138		break;
1139	    case 1:
1140		ErrorF("0x%02x, ", save->DAC[i]);
1141		break;
1142	    case 2:
1143		ErrorF("0x%02x\n", save->DAC[i]);
1144	    }
1145#endif
1146	}
1147    }
1148
1149    hwp->disablePalette(hwp);
1150    hwp->cmapSaved = TRUE;
1151#endif
1152}
1153
1154/*
1155 * vgaHWSave --
1156 *      save the current VGA state
1157 */
1158
1159void
1160vgaHWSave(ScrnInfoPtr scrninfp, vgaRegPtr save, int flags)
1161{
1162    if (save == NULL)
1163	return;
1164
1165   if (flags & VGA_SR_CMAP)
1166	vgaHWSaveColormap(scrninfp, save);
1167
1168   if (flags & VGA_SR_MODE)
1169	vgaHWSaveMode(scrninfp, save);
1170
1171   if (flags & VGA_SR_FONTS)
1172	vgaHWSaveFonts(scrninfp, save);
1173}
1174
1175
1176/*
1177 * vgaHWInit --
1178 *      Handle the initialization, etc. of a screen.
1179 *      Return FALSE on failure.
1180 */
1181
1182Bool
1183vgaHWInit(ScrnInfoPtr scrninfp, DisplayModePtr mode)
1184{
1185    unsigned int       i;
1186    vgaHWPtr hwp;
1187    vgaRegPtr regp;
1188    int depth = scrninfp->depth;
1189
1190    /*
1191     * make sure the vgaHWRec is allocated
1192     */
1193    if (!vgaHWGetHWRec(scrninfp))
1194	return FALSE;
1195    hwp = VGAHWPTR(scrninfp);
1196    regp = &hwp->ModeReg;
1197
1198    /*
1199     * compute correct Hsync & Vsync polarity
1200     */
1201    if ((mode->Flags & (V_PHSYNC | V_NHSYNC))
1202        && (mode->Flags & (V_PVSYNC | V_NVSYNC)))
1203    {
1204        regp->MiscOutReg = 0x23;
1205        if (mode->Flags & V_NHSYNC) regp->MiscOutReg |= 0x40;
1206        if (mode->Flags & V_NVSYNC) regp->MiscOutReg |= 0x80;
1207    }
1208    else
1209    {
1210        int VDisplay = mode->VDisplay;
1211        if (mode->Flags & V_DBLSCAN)
1212            VDisplay *= 2;
1213        if (mode->VScan > 1)
1214            VDisplay *= mode->VScan;
1215        if      (VDisplay < 400)
1216            regp->MiscOutReg = 0xA3;		/* +hsync -vsync */
1217        else if (VDisplay < 480)
1218            regp->MiscOutReg = 0x63;		/* -hsync +vsync */
1219        else if (VDisplay < 768)
1220            regp->MiscOutReg = 0xE3;		/* -hsync -vsync */
1221        else
1222            regp->MiscOutReg = 0x23;		/* +hsync +vsync */
1223    }
1224
1225    regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2;
1226
1227    /*
1228     * Time Sequencer
1229     */
1230    if (depth == 4)
1231        regp->Sequencer[0] = 0x02;
1232    else
1233        regp->Sequencer[0] = 0x00;
1234    if (mode->Flags & V_CLKDIV2)
1235        regp->Sequencer[1] = 0x09;
1236    else
1237        regp->Sequencer[1] = 0x01;
1238    if (depth == 1)
1239        regp->Sequencer[2] = 1 << BIT_PLANE;
1240    else
1241        regp->Sequencer[2] = 0x0F;
1242    regp->Sequencer[3] = 0x00;                             /* Font select */
1243    if (depth < 8)
1244        regp->Sequencer[4] = 0x06;                             /* Misc */
1245    else
1246        regp->Sequencer[4] = 0x0E;                             /* Misc */
1247
1248    /*
1249     * CRTC Controller
1250     */
1251    regp->CRTC[0]  = (mode->CrtcHTotal >> 3) - 5;
1252    regp->CRTC[1]  = (mode->CrtcHDisplay >> 3) - 1;
1253    regp->CRTC[2]  = (mode->CrtcHBlankStart >> 3) - 1;
1254    regp->CRTC[3]  = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
1255    i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F);
1256    if (i < 0x80)
1257	regp->CRTC[3] |= i;
1258    regp->CRTC[4]  = (mode->CrtcHSyncStart >> 3);
1259    regp->CRTC[5]  = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
1260	| (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
1261    regp->CRTC[6]  = (mode->CrtcVTotal - 2) & 0xFF;
1262    regp->CRTC[7]  = (((mode->CrtcVTotal - 2) & 0x100) >> 8)
1263	| (((mode->CrtcVDisplay - 1) & 0x100) >> 7)
1264	| ((mode->CrtcVSyncStart & 0x100) >> 6)
1265	| (((mode->CrtcVBlankStart - 1) & 0x100) >> 5)
1266	| 0x10
1267	| (((mode->CrtcVTotal - 2) & 0x200)   >> 4)
1268	| (((mode->CrtcVDisplay - 1) & 0x200) >> 3)
1269	| ((mode->CrtcVSyncStart & 0x200) >> 2);
1270    regp->CRTC[8]  = 0x00;
1271    regp->CRTC[9]  = (((mode->CrtcVBlankStart - 1) & 0x200) >> 4) | 0x40;
1272    if (mode->Flags & V_DBLSCAN)
1273	regp->CRTC[9] |= 0x80;
1274    if (mode->VScan >= 32)
1275	regp->CRTC[9] |= 0x1F;
1276    else if (mode->VScan > 1)
1277	regp->CRTC[9] |= mode->VScan - 1;
1278    regp->CRTC[10] = 0x00;
1279    regp->CRTC[11] = 0x00;
1280    regp->CRTC[12] = 0x00;
1281    regp->CRTC[13] = 0x00;
1282    regp->CRTC[14] = 0x00;
1283    regp->CRTC[15] = 0x00;
1284    regp->CRTC[16] = mode->CrtcVSyncStart & 0xFF;
1285    regp->CRTC[17] = (mode->CrtcVSyncEnd & 0x0F) | 0x20;
1286    regp->CRTC[18] = (mode->CrtcVDisplay - 1) & 0xFF;
1287    regp->CRTC[19] = scrninfp->displayWidth >> 4;  /* just a guess */
1288    regp->CRTC[20] = 0x00;
1289    regp->CRTC[21] = (mode->CrtcVBlankStart - 1) & 0xFF;
1290    regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1291    if (depth < 8)
1292	regp->CRTC[23] = 0xE3;
1293    else
1294	regp->CRTC[23] = 0xC3;
1295    regp->CRTC[24] = 0xFF;
1296
1297    vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
1298    vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
1299
1300    /*
1301     * Theory resumes here....
1302     */
1303
1304    /*
1305     * Graphics Display Controller
1306     */
1307    regp->Graphics[0] = 0x00;
1308    regp->Graphics[1] = 0x00;
1309    regp->Graphics[2] = 0x00;
1310    regp->Graphics[3] = 0x00;
1311    if (depth == 1) {
1312        regp->Graphics[4] = BIT_PLANE;
1313        regp->Graphics[5] = 0x00;
1314    } else {
1315        regp->Graphics[4] = 0x00;
1316        if (depth == 4)
1317            regp->Graphics[5] = 0x02;
1318        else
1319            regp->Graphics[5] = 0x40;
1320    }
1321    regp->Graphics[6] = 0x05;   /* only map 64k VGA memory !!!! */
1322    regp->Graphics[7] = 0x0F;
1323    regp->Graphics[8] = 0xFF;
1324
1325    if (depth == 1) {
1326        /* Initialise the Mono map according to which bit-plane gets used */
1327
1328	Bool flipPixels = xf86GetFlipPixels();
1329
1330        for (i=0; i<16; i++)
1331            if (((i & (1 << BIT_PLANE)) != 0) != flipPixels)
1332                regp->Attribute[i] = WHITE_VALUE;
1333            else
1334                regp->Attribute[i] = BLACK_VALUE;
1335
1336        regp->Attribute[16] = 0x01;  /* -VGA2- */ /* wrong for the ET4000 */
1337	if (!hwp->ShowOverscan)
1338            regp->Attribute[OVERSCAN] = OVERSCAN_VALUE;  /* -VGA2- */
1339    } else {
1340        regp->Attribute[0]  = 0x00; /* standard colormap translation */
1341        regp->Attribute[1]  = 0x01;
1342        regp->Attribute[2]  = 0x02;
1343        regp->Attribute[3]  = 0x03;
1344        regp->Attribute[4]  = 0x04;
1345        regp->Attribute[5]  = 0x05;
1346        regp->Attribute[6]  = 0x06;
1347        regp->Attribute[7]  = 0x07;
1348        regp->Attribute[8]  = 0x08;
1349        regp->Attribute[9]  = 0x09;
1350        regp->Attribute[10] = 0x0A;
1351        regp->Attribute[11] = 0x0B;
1352        regp->Attribute[12] = 0x0C;
1353        regp->Attribute[13] = 0x0D;
1354        regp->Attribute[14] = 0x0E;
1355        regp->Attribute[15] = 0x0F;
1356        if (depth == 4)
1357            regp->Attribute[16] = 0x81; /* wrong for the ET4000 */
1358        else
1359            regp->Attribute[16] = 0x41; /* wrong for the ET4000 */
1360        /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */
1361    }
1362    regp->Attribute[18] = 0x0F;
1363    regp->Attribute[19] = 0x00;
1364    regp->Attribute[20] = 0x00;
1365
1366    return(TRUE);
1367}
1368
1369    /*
1370     * OK, so much for theory.  Now, let's deal with the >real< world...
1371     *
1372     * The above CRTC settings are precise in theory, except that many, if not
1373     * most, VGA clones fail to reset the blanking signal when the character or
1374     * line counter reaches [HV]Total.  In this case, the signal is only
1375     * unblanked when the counter reaches [HV]BlankEnd (mod 64, 128 or 256 as
1376     * the case may be) at the start of the >next< scanline or frame, which
1377     * means only part of the screen shows.  This affects how null overscans
1378     * are to be implemented on such adapters.
1379     *
1380     * Henceforth, VGA cores that implement this broken, but unfortunately
1381     * common, behaviour are to be designated as KGA's, in honour of Koen
1382     * Gadeyne, whose zeal to eliminate overscans (read: fury) set in motion
1383     * a series of events that led to the discovery of this problem.
1384     *
1385     * Some VGA's are KGA's only in the horizontal, or only in the vertical,
1386     * some in both, others in neither.  Don't let anyone tell you there is
1387     * such a thing as a VGA "standard"...  And, thank the Creator for the fact
1388     * that Hilbert spaces are not yet implemented in this industry.
1389     *
1390     * The following implements a trick suggested by David Dawes.  This sets
1391     * [HV]BlankEnd to zero if the blanking interval does not already contain a
1392     * 0-point, and decrements it by one otherwise.  In the latter case, this
1393     * will produce a left and/or top overscan which the colourmap code will
1394     * (still) need to ensure is as close to black as possible.  This will make
1395     * the behaviour consistent across all chipsets, while allowing all
1396     * chipsets to display the entire screen.  Non-KGA drivers can ignore the
1397     * following in their own copy of this code.
1398     *
1399     * --  TSI @ UQV,  1998.08.21
1400     */
1401
1402CARD32
1403vgaHWHBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1404	       unsigned int Flags)
1405{
1406    int nExtBits = (nBits < 6) ? 0 : nBits - 6;
1407    CARD32 ExtBits;
1408    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6;
1409
1410    regp->CRTC[3]  = (regp->CRTC[3] & ~0x1F)
1411                     | (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F);
1412    regp->CRTC[5]  = (regp->CRTC[5] & ~0x80)
1413                     | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2);
1414    ExtBits        = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask;
1415
1416    /* First the horizontal case */
1417    if ((Flags & KGA_FIX_OVERSCAN)
1418	&& ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3)))
1419    {
1420	int i = (regp->CRTC[3] & 0x1F)
1421	    | ((regp->CRTC[5] & 0x80) >> 2)
1422	    | ExtBits;
1423	if (Flags & KGA_ENABLE_ON_ZERO) {
1424	    if ((i-- > (((mode->CrtcHBlankStart >> 3) - 1)
1425		       & (0x3F | ExtBitMask)))
1426	    && (mode->CrtcHBlankEnd == mode->CrtcHTotal))
1427	    i = 0;
1428	} else if (Flags & KGA_BE_TOT_DEC)
1429	    i--;
1430	regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F);
1431	regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80);
1432	ExtBits = i & ExtBitMask;
1433    }
1434    return ExtBits >> 6;
1435}
1436
1437    /*
1438     * The vertical case is a little trickier.  Some VGA's ignore bit 0x80 of
1439     * CRTC[22].  Also, in some cases, a zero CRTC[22] will still blank the
1440     * very first scanline in a double- or multi-scanned mode.  This last case
1441     * needs further investigation.
1442     */
1443CARD32
1444vgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1445	       unsigned int Flags)
1446{
1447    CARD32 ExtBits;
1448    CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8);
1449    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8;
1450    /* If width is not known nBits should be 0. In this
1451     * case BitMask is set to 0 so we can check for it. */
1452    CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1);
1453    int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF;
1454    regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1455    ExtBits        = (mode->CrtcVBlankEnd - 1) & ExtBitMask;
1456
1457    if ((Flags & KGA_FIX_OVERSCAN)
1458	&& (mode->CrtcVBlankEnd == mode->CrtcVTotal))
1459      /* Null top overscan */
1460    {
1461	int i = regp->CRTC[22] | ExtBits;
1462	if (Flags & KGA_ENABLE_ON_ZERO) {
1463	    if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask)))
1464	     || ((i > VBlankStart)  &&  		/* 8-bit case */
1465	    ((i & 0x7F) > (VBlankStart & 0x7F)))) &&	/* 7-bit case */
1466	    !(regp->CRTC[9] & 0x9F))			/* 1 scanline/row */
1467	    i = 0;
1468	else
1469	    i = (i - 1);
1470	} else if (Flags & KGA_BE_TOT_DEC)
1471	    i = (i - 1);
1472
1473	regp->CRTC[22] = i & 0xFF;
1474	ExtBits = i & 0xFF00;
1475    }
1476    return ExtBits >> 8;
1477}
1478
1479/*
1480 * these are some more hardware specific helpers, formerly in vga.c
1481 */
1482static void
1483vgaHWGetHWRecPrivate(void)
1484{
1485    if (vgaHWPrivateIndex < 0)
1486	vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
1487    return;
1488}
1489
1490
1491static void
1492vgaHWFreeRegs(vgaRegPtr regp)
1493{
1494    if (regp->CRTC)
1495    	xfree (regp->CRTC);
1496
1497    regp->CRTC =
1498    regp->Sequencer =
1499    regp->Graphics =
1500    regp->Attribute = NULL;
1501
1502    regp->numCRTC =
1503    regp->numSequencer =
1504    regp->numGraphics =
1505    regp->numAttribute = 0;
1506}
1507
1508
1509
1510static Bool
1511vgaHWAllocRegs(vgaRegPtr regp)
1512{
1513    unsigned char *buf;
1514
1515    if ((regp->numCRTC + regp->numSequencer + regp->numGraphics +
1516         regp->numAttribute) == 0)
1517        return FALSE;
1518
1519    buf = xcalloc(regp->numCRTC +
1520    		  regp->numSequencer +
1521		  regp->numGraphics +
1522		  regp->numAttribute, 1);
1523    if (!buf)
1524    	return FALSE;
1525
1526    regp->CRTC = buf;
1527    regp->Sequencer = regp->CRTC + regp->numCRTC;
1528    regp->Graphics = regp->Sequencer + regp->numSequencer;
1529    regp->Attribute = regp->Graphics + regp->numGraphics;
1530
1531    return TRUE;
1532}
1533
1534
1535Bool
1536vgaHWAllocDefaultRegs(vgaRegPtr regp)
1537{
1538    regp->numCRTC = VGA_NUM_CRTC;
1539    regp->numSequencer = VGA_NUM_SEQ;
1540    regp->numGraphics = VGA_NUM_GFX;
1541    regp->numAttribute = VGA_NUM_ATTR;
1542
1543    return vgaHWAllocRegs(regp);
1544}
1545
1546
1547Bool
1548vgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer,
1549		  int numGraphics, int numAttribute)
1550{
1551#define VGAHWMINNUM(regtype) \
1552	((newMode.num##regtype < regp->num##regtype) ? \
1553	 (newMode.num##regtype) : (regp->num##regtype))
1554#define VGAHWCOPYREGSET(regtype) \
1555	memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype))
1556
1557    vgaRegRec newMode, newSaved;
1558    vgaRegPtr regp;
1559
1560    regp = &VGAHWPTR(scrp)->ModeReg;
1561    memcpy (&newMode, regp, sizeof(vgaRegRec));
1562
1563    /* allocate space for new registers */
1564
1565    regp = &newMode;
1566    regp->numCRTC = numCRTC;
1567    regp->numSequencer = numSequencer;
1568    regp->numGraphics = numGraphics;
1569    regp->numAttribute = numAttribute;
1570    if (!vgaHWAllocRegs(regp))
1571    	return FALSE;
1572
1573    regp = &VGAHWPTR(scrp)->SavedReg;
1574    memcpy (&newSaved, regp, sizeof(vgaRegRec));
1575
1576    regp = &newSaved;
1577    regp->numCRTC = numCRTC;
1578    regp->numSequencer = numSequencer;
1579    regp->numGraphics = numGraphics;
1580    regp->numAttribute = numAttribute;
1581    if (!vgaHWAllocRegs(regp)) {
1582        vgaHWFreeRegs(&newMode);
1583    	return FALSE;
1584    }
1585
1586    /* allocations succeeded, copy register data into new space */
1587
1588    regp = &VGAHWPTR(scrp)->ModeReg;
1589    VGAHWCOPYREGSET(CRTC);
1590    VGAHWCOPYREGSET(Sequencer);
1591    VGAHWCOPYREGSET(Graphics);
1592    VGAHWCOPYREGSET(Attribute);
1593
1594    regp = &VGAHWPTR(scrp)->SavedReg;
1595    VGAHWCOPYREGSET(CRTC);
1596    VGAHWCOPYREGSET(Sequencer);
1597    VGAHWCOPYREGSET(Graphics);
1598    VGAHWCOPYREGSET(Attribute);
1599
1600    /* free old register arrays */
1601
1602    regp = &VGAHWPTR(scrp)->ModeReg;
1603    vgaHWFreeRegs(regp);
1604    memcpy(regp, &newMode, sizeof(vgaRegRec));
1605
1606    regp = &VGAHWPTR(scrp)->SavedReg;
1607    vgaHWFreeRegs(regp);
1608    memcpy(regp, &newSaved, sizeof(vgaRegRec));
1609
1610    return TRUE;
1611
1612#undef VGAHWMINNUM
1613#undef VGAHWCOPYREGSET
1614}
1615
1616
1617Bool
1618vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)
1619{
1620    vgaHWFreeRegs(dst);
1621
1622    memcpy(dst, src, sizeof(vgaRegRec));
1623
1624    if (!vgaHWAllocRegs(dst))
1625	return FALSE;
1626
1627    memcpy(dst->CRTC, src->CRTC, src->numCRTC);
1628    memcpy(dst->Sequencer, src->Sequencer, src->numSequencer);
1629    memcpy(dst->Graphics, src->Graphics, src->numGraphics);
1630    memcpy(dst->Attribute, src->Attribute, src->numAttribute);
1631
1632    return TRUE;
1633}
1634
1635
1636Bool
1637vgaHWGetHWRec(ScrnInfoPtr scrp)
1638{
1639    vgaRegPtr regp;
1640    vgaHWPtr hwp;
1641    int i;
1642
1643    /*
1644     * Let's make sure that the private exists and allocate one.
1645     */
1646    vgaHWGetHWRecPrivate();
1647    /*
1648     * New privates are always set to NULL, so we can check if the allocation
1649     * has already been done.
1650     */
1651    if (VGAHWPTR(scrp))
1652	return TRUE;
1653    hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1);
1654    regp = &VGAHWPTR(scrp)->ModeReg;
1655
1656    if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) ||
1657    	(!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) {
1658        xfree(hwp);
1659	return FALSE;
1660    }
1661
1662    if (scrp->bitsPerPixel == 1) {
1663	rgb blackColour = scrp->display->blackColour,
1664	    whiteColour = scrp->display->whiteColour;
1665
1666	if (blackColour.red   > 0x3F) blackColour.red   = 0x3F;
1667	if (blackColour.green > 0x3F) blackColour.green = 0x3F;
1668	if (blackColour.blue  > 0x3F) blackColour.blue  = 0x3F;
1669
1670	if (whiteColour.red   > 0x3F) whiteColour.red   = 0x3F;
1671	if (whiteColour.green > 0x3F) whiteColour.green = 0x3F;
1672	if (whiteColour.blue  > 0x3F) whiteColour.blue  = 0x3F;
1673
1674	if ((blackColour.red   == whiteColour.red  ) &&
1675	    (blackColour.green == whiteColour.green) &&
1676	    (blackColour.blue  == whiteColour.blue )) {
1677	    blackColour.red   ^= 0x3F;
1678	    blackColour.green ^= 0x3F;
1679	    blackColour.blue  ^= 0x3F;
1680	}
1681
1682        /*
1683         * initialize default colormap for monochrome
1684         */
1685        for (i=0; i<3;   i++) regp->DAC[i] = 0x00;
1686        for (i=3; i<768; i++) regp->DAC[i] = 0x3F;
1687        i = BLACK_VALUE * 3;
1688        regp->DAC[i++] = blackColour.red;
1689        regp->DAC[i++] = blackColour.green;
1690        regp->DAC[i] = blackColour.blue;
1691        i = WHITE_VALUE * 3;
1692        regp->DAC[i++] = whiteColour.red;
1693        regp->DAC[i++] = whiteColour.green;
1694        regp->DAC[i] = whiteColour.blue;
1695        i = OVERSCAN_VALUE * 3;
1696        regp->DAC[i++] = 0x00;
1697        regp->DAC[i++] = 0x00;
1698        regp->DAC[i] = 0x00;
1699    } else {
1700	/* Set all colours to black */
1701        for (i=0; i<768; i++) regp->DAC[i] = 0x00;
1702        /* ... and the overscan */
1703        if (scrp->depth >= 4)
1704            regp->Attribute[OVERSCAN] = 0xFF;
1705    }
1706    if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) {
1707	xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan");
1708	xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n");
1709	regp->DAC[765] = 0x3F;
1710	regp->DAC[766] = 0x00;
1711	regp->DAC[767] = 0x3F;
1712	regp->Attribute[OVERSCAN] = 0xFF;
1713	hwp->ShowOverscan = TRUE;
1714    } else
1715	hwp->ShowOverscan = FALSE;
1716
1717    hwp->paletteEnabled = FALSE;
1718    hwp->cmapSaved = FALSE;
1719    hwp->MapSize = 0;
1720    hwp->pScrn = scrp;
1721
1722    /* Initialise the function pointers with the standard VGA versions */
1723    vgaHWSetStdFuncs(hwp);
1724
1725    hwp->PIOOffset = scrp->domainIOBase;
1726    hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]);
1727
1728    return TRUE;
1729}
1730
1731
1732void
1733vgaHWFreeHWRec(ScrnInfoPtr scrp)
1734{
1735    if (vgaHWPrivateIndex >= 0) {
1736	vgaHWPtr hwp = VGAHWPTR(scrp);
1737
1738	if (!hwp)
1739	    return;
1740
1741	xfree(hwp->FontInfo1);
1742	xfree(hwp->FontInfo2);
1743	xfree(hwp->TextInfo);
1744
1745	vgaHWFreeRegs (&hwp->ModeReg);
1746	vgaHWFreeRegs (&hwp->SavedReg);
1747
1748	xfree(hwp);
1749	VGAHWPTRLVAL(scrp) = NULL;
1750    }
1751}
1752
1753
1754Bool
1755vgaHWMapMem(ScrnInfoPtr scrp)
1756{
1757    vgaHWPtr hwp = VGAHWPTR(scrp);
1758    int scr_index = scrp->scrnIndex;
1759
1760    if (hwp->Base)
1761	return TRUE;
1762
1763    /* If not set, initialise with the defaults */
1764    if (hwp->MapSize == 0)
1765	hwp->MapSize = VGA_DEFAULT_MEM_SIZE;
1766    if (hwp->MapPhys == 0)
1767	hwp->MapPhys = VGA_DEFAULT_PHYS_ADDR;
1768
1769    /*
1770     * Map as VIDMEM_MMIO_32BIT because WC
1771     * is bad when there is page flipping.
1772     * XXX This is not correct but we do it
1773     * for now.
1774     */
1775#ifdef DEBUG
1776    ErrorF("Mapping VGAMem\n");
1777#endif
1778    hwp->Base = xf86MapDomainMemory(scr_index, VIDMEM_MMIO_32BIT, hwp->dev,
1779				    hwp->MapPhys, hwp->MapSize);
1780    return hwp->Base != NULL;
1781}
1782
1783
1784void
1785vgaHWUnmapMem(ScrnInfoPtr scrp)
1786{
1787    vgaHWPtr hwp = VGAHWPTR(scrp);
1788    int scr_index = scrp->scrnIndex;
1789
1790    if (hwp->Base == NULL)
1791	return;
1792
1793#ifdef DEBUG
1794    ErrorF("Unmapping VGAMem\n");
1795#endif
1796    xf86UnMapVidMem(scr_index, hwp->Base, hwp->MapSize);
1797    hwp->Base = NULL;
1798}
1799
1800int
1801vgaHWGetIndex()
1802{
1803    return vgaHWPrivateIndex;
1804}
1805
1806
1807void
1808vgaHWGetIOBase(vgaHWPtr hwp)
1809{
1810    hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ?
1811				VGA_IOBASE_COLOR : VGA_IOBASE_MONO;
1812    xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3,
1813	"vgaHWGetIOBase: hwp->IOBase is 0x%04x, hwp->PIOOffset is 0x%04lx\n",
1814	hwp->IOBase, hwp->PIOOffset);
1815}
1816
1817
1818void
1819vgaHWLock(vgaHWPtr hwp)
1820{
1821    /* Protect CRTC[0-7] */
1822    hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80);
1823}
1824
1825void
1826vgaHWUnlock(vgaHWPtr hwp)
1827{
1828    /* Unprotect CRTC[0-7] */
1829     hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80);
1830}
1831
1832
1833void
1834vgaHWEnable(vgaHWPtr hwp)
1835{
1836    hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01);
1837}
1838
1839
1840void
1841vgaHWDisable(vgaHWPtr hwp)
1842{
1843    hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01);
1844}
1845
1846
1847static void
1848vgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
1849		 VisualPtr pVisual)
1850{
1851    vgaHWPtr hwp = VGAHWPTR(pScrn);
1852    int i, index;
1853
1854    for (i = 0; i < numColors; i++) {
1855	index = indices[i];
1856	hwp->writeDacWriteAddr(hwp, index);
1857	DACDelay(hwp);
1858	hwp->writeDacData(hwp, colors[index].red);
1859	DACDelay(hwp);
1860	hwp->writeDacData(hwp, colors[index].green);
1861	DACDelay(hwp);
1862	hwp->writeDacData(hwp, colors[index].blue);
1863	DACDelay(hwp);
1864    }
1865
1866    /* This shouldn't be necessary, but we'll play safe. */
1867    hwp->disablePalette(hwp);
1868}
1869
1870
1871static void
1872vgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan)
1873{
1874    vgaHWPtr hwp = VGAHWPTR(pScrn);
1875
1876    if (overscan < 0 || overscan > 255)
1877	return;
1878
1879    hwp->enablePalette(hwp);
1880    hwp->writeAttr(hwp, OVERSCAN, overscan);
1881
1882#ifdef DEBUGOVERSCAN
1883    {
1884	int ov = hwp->readAttr(hwp, OVERSCAN);
1885	int red, green, blue;
1886
1887	hwp->writeDacReadAddr(hwp, ov);
1888	red = hwp->readDacData(hwp);
1889	green = hwp->readDacData(hwp);
1890	blue = hwp->readDacData(hwp);
1891	ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n",
1892		ov, red, green, blue);
1893    }
1894#endif
1895
1896    hwp->disablePalette(hwp);
1897}
1898
1899
1900Bool
1901vgaHWHandleColormaps(ScreenPtr pScreen)
1902{
1903    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1904
1905    if (pScrn->depth > 1 && pScrn->depth <= 8) {
1906	return xf86HandleColormaps(pScreen, 1 << pScrn->depth,
1907				   pScrn->rgbBits, vgaHWLoadPalette,
1908				   pScrn->depth > 4 ? vgaHWSetOverscan : NULL,
1909				   CMAP_RELOAD_ON_MODE_SWITCH);
1910    }
1911    return TRUE;
1912}
1913
1914/* ----------------------- DDC support ------------------------*/
1915/*
1916 * Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total
1917 * to read out EDID at a faster rate. Allowed maximum is 25kHz with
1918 * 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen
1919 * readback, enable access to cr00-cr07.
1920 */
1921
1922/* vertical timings */
1923#define DISPLAY_END 0x04
1924#define BLANK_START DISPLAY_END
1925#define SYNC_START BLANK_START
1926#define SYNC_END 0x09
1927#define BLANK_END SYNC_END
1928#define V_TOTAL BLANK_END
1929/* this function doesn't have to be reentrant for our purposes */
1930struct _vgaDdcSave {
1931    unsigned char cr03;
1932    unsigned char cr06;
1933    unsigned char cr07;
1934    unsigned char cr09;
1935    unsigned char cr10;
1936    unsigned char cr11;
1937    unsigned char cr12;
1938    unsigned char cr15;
1939    unsigned char cr16;
1940    unsigned char msr;
1941};
1942
1943void
1944vgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed)
1945{
1946    vgaHWPtr hwp = VGAHWPTR(pScrn);
1947    unsigned char tmp;
1948    struct _vgaDdcSave* save;
1949    switch (speed) {
1950    case DDC_FAST:
1951
1952        if (hwp->ddc != NULL) break;
1953        hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave),1);
1954	save = (struct _vgaDdcSave *)hwp->ddc;
1955      /* Lightpen register disable - allow access to cr10 & 11; just in case */
1956	save->cr03 = hwp->readCrtc(hwp, 0x03);
1957	hwp->writeCrtc(hwp,0x03,(save->cr03 |0x80));
1958	save->cr12 = hwp->readCrtc(hwp, 0x12);
1959	hwp->writeCrtc(hwp,0x12,DISPLAY_END);
1960	save->cr15 = hwp->readCrtc(hwp, 0x15);
1961	hwp->writeCrtc(hwp,0x15,BLANK_START);
1962	save->cr10 = hwp->readCrtc(hwp, 0x10);
1963	hwp->writeCrtc(hwp,0x10,SYNC_START);
1964	save->cr11 = hwp->readCrtc(hwp, 0x11);
1965	/* unprotect group 1 registers; just in case ...*/
1966	hwp->writeCrtc(hwp,0x11,((save->cr11 & 0x70) | SYNC_END));
1967	save->cr16 = hwp->readCrtc(hwp, 0x16);
1968	hwp->writeCrtc(hwp,0x16,BLANK_END);
1969	save->cr06 = hwp->readCrtc(hwp, 0x06);
1970	hwp->writeCrtc(hwp,0x06,V_TOTAL);
1971	/* all values have less than 8 bit - mask out 9th and 10th bits */
1972	save->cr09 = hwp->readCrtc(hwp, 0x09);
1973	hwp->writeCrtc(hwp,0x09,(save->cr09 &0xDF));
1974	save->cr07 = hwp->readCrtc(hwp, 0x07);
1975	hwp->writeCrtc(hwp,0x07,(save->cr07 &0x10));
1976	/* vsync polarity negativ & ensure a 25MHz clock */
1977	save->msr = hwp->readMiscOut(hwp);
1978	hwp->writeMiscOut(hwp,((save->msr & 0xF3) | 0x80));
1979	break;
1980    case DDC_SLOW:
1981        if (hwp->ddc == NULL) break;
1982	save = (struct _vgaDdcSave *)hwp->ddc;
1983	hwp->writeMiscOut(hwp,save->msr);
1984	hwp->writeCrtc(hwp,0x07,save->cr07);
1985	tmp = hwp->readCrtc(hwp, 0x09);
1986	hwp->writeCrtc(hwp,0x09,((save->cr09 & 0x20) | (tmp & 0xDF)));
1987	hwp->writeCrtc(hwp,0x06,save->cr06);
1988	hwp->writeCrtc(hwp,0x16,save->cr16);
1989	hwp->writeCrtc(hwp,0x11,save->cr11);
1990	hwp->writeCrtc(hwp,0x10,save->cr10);
1991	hwp->writeCrtc(hwp,0x15,save->cr15);
1992	hwp->writeCrtc(hwp,0x12,save->cr12);
1993	hwp->writeCrtc(hwp,0x03,save->cr03);
1994	xfree(save);
1995	hwp->ddc = NULL;
1996	break;
1997    default:
1998	break;
1999    }
2000}
2001
2002DDC1SetSpeedProc  vgaHWddc1SetSpeedWeak(void) { return vgaHWddc1SetSpeed; }
2003
2004SaveScreenProcPtr vgaHWSaveScreenWeak(void) { return vgaHWSaveScreen; }
2005