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 = malloc(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 = malloc(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 = malloc(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	DebugF("CRTC[0x%02x] = 0x%02x\n", i, save->CRTC[i]);
1029    }
1030
1031    hwp->enablePalette(hwp);
1032    for (i = 0; i < save->numAttribute; i++) {
1033	save->Attribute[i] = hwp->readAttr(hwp, i);
1034	DebugF("Attribute[0x%02x] = 0x%02x\n", i, save->Attribute[i]);
1035    }
1036    hwp->disablePalette(hwp);
1037
1038    for (i = 0; i < save->numGraphics; i++) {
1039	save->Graphics[i] = hwp->readGr(hwp, i);
1040	DebugF("Graphics[0x%02x] = 0x%02x\n", i, save->Graphics[i]);
1041    }
1042
1043    for (i = 1; i < save->numSequencer; i++) {
1044	save->Sequencer[i] = hwp->readSeq(hwp, i);
1045	DebugF("Sequencer[0x%02x] = 0x%02x\n", i, save->Sequencer[i]);
1046    }
1047}
1048
1049
1050void
1051vgaHWSaveColormap(ScrnInfoPtr scrninfp, vgaRegPtr save)
1052{
1053    vgaHWPtr hwp = VGAHWPTR(scrninfp);
1054    Bool readError = FALSE;
1055    int i;
1056
1057#ifdef NEED_SAVED_CMAP
1058    /*
1059     * Some ET4000 chips from 1991 have a HW bug that prevents the reading
1060     * of the color lookup table.  Mask rev 9042EAI is known to have this bug.
1061     *
1062     * If the colourmap is not readable, we set the saved map to a default
1063     * map (taken from Ferraro's "Programmer's Guide to the EGA and VGA
1064     * Cards" 2nd ed).
1065     */
1066
1067    /* Only save it once */
1068    if (hwp->cmapSaved)
1069	return;
1070
1071#if 0
1072    hwp->enablePalette(hwp);
1073#endif
1074
1075    hwp->writeDacMask(hwp, 0xFF);
1076
1077    /*
1078     * check if we can read the lookup table
1079     */
1080    hwp->writeDacReadAddr(hwp, 0x00);
1081    for (i = 0; i < 6; i++) {
1082	save->DAC[i] = hwp->readDacData(hwp);
1083	switch (i % 3) {
1084	case 0:
1085	    DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
1086	    break;
1087	case 1:
1088	    DebugF("0x%02x, ", save->DAC[i]);
1089	    break;
1090	case 2:
1091	    DebugF("0x%02x\n", save->DAC[i]);
1092	}
1093    }
1094
1095    /*
1096     * Check if we can read the palette -
1097     * use foreground color to prevent flashing.
1098     */
1099    hwp->writeDacWriteAddr(hwp, 0x01);
1100    for (i = 3; i < 6; i++)
1101	hwp->writeDacData(hwp, ~save->DAC[i] & DAC_TEST_MASK);
1102    hwp->writeDacReadAddr(hwp, 0x01);
1103    for (i = 3; i < 6; i++) {
1104	if (hwp->readDacData(hwp) != (~save->DAC[i] & DAC_TEST_MASK))
1105	    readError = TRUE;
1106    }
1107    hwp->writeDacWriteAddr(hwp, 0x01);
1108    for (i = 3; i < 6; i++)
1109	hwp->writeDacData(hwp, save->DAC[i]);
1110
1111    if (readError) {
1112	/*
1113	 * save the default lookup table
1114	 */
1115	memmove(save->DAC, defaultDAC, 768);
1116	xf86DrvMsg(scrninfp->scrnIndex, X_WARNING,
1117	   "Cannot read colourmap from VGA.  Will restore with default\n");
1118    } else {
1119	/* save the colourmap */
1120	hwp->writeDacReadAddr(hwp, 0x02);
1121	for (i = 6; i < 768; i++) {
1122	    save->DAC[i] = hwp->readDacData(hwp);
1123	    DACDelay(hwp);
1124	    switch (i % 3) {
1125	    case 0:
1126		DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
1127		break;
1128	    case 1:
1129		DebugF("0x%02x, ", save->DAC[i]);
1130		break;
1131	    case 2:
1132		DebugF("0x%02x\n", save->DAC[i]);
1133	    }
1134	}
1135    }
1136
1137    hwp->disablePalette(hwp);
1138    hwp->cmapSaved = TRUE;
1139#endif
1140}
1141
1142/*
1143 * vgaHWSave --
1144 *      save the current VGA state
1145 */
1146
1147void
1148vgaHWSave(ScrnInfoPtr scrninfp, vgaRegPtr save, int flags)
1149{
1150    if (save == NULL)
1151	return;
1152
1153   if (flags & VGA_SR_CMAP)
1154	vgaHWSaveColormap(scrninfp, save);
1155
1156   if (flags & VGA_SR_MODE)
1157	vgaHWSaveMode(scrninfp, save);
1158
1159   if (flags & VGA_SR_FONTS)
1160	vgaHWSaveFonts(scrninfp, save);
1161}
1162
1163
1164/*
1165 * vgaHWInit --
1166 *      Handle the initialization, etc. of a screen.
1167 *      Return FALSE on failure.
1168 */
1169
1170Bool
1171vgaHWInit(ScrnInfoPtr scrninfp, DisplayModePtr mode)
1172{
1173    unsigned int       i;
1174    vgaHWPtr hwp;
1175    vgaRegPtr regp;
1176    int depth = scrninfp->depth;
1177
1178    /*
1179     * make sure the vgaHWRec is allocated
1180     */
1181    if (!vgaHWGetHWRec(scrninfp))
1182	return FALSE;
1183    hwp = VGAHWPTR(scrninfp);
1184    regp = &hwp->ModeReg;
1185
1186    /*
1187     * compute correct Hsync & Vsync polarity
1188     */
1189    if ((mode->Flags & (V_PHSYNC | V_NHSYNC))
1190        && (mode->Flags & (V_PVSYNC | V_NVSYNC)))
1191    {
1192        regp->MiscOutReg = 0x23;
1193        if (mode->Flags & V_NHSYNC) regp->MiscOutReg |= 0x40;
1194        if (mode->Flags & V_NVSYNC) regp->MiscOutReg |= 0x80;
1195    }
1196    else
1197    {
1198        int VDisplay = mode->VDisplay;
1199        if (mode->Flags & V_DBLSCAN)
1200            VDisplay *= 2;
1201        if (mode->VScan > 1)
1202            VDisplay *= mode->VScan;
1203        if      (VDisplay < 400)
1204            regp->MiscOutReg = 0xA3;		/* +hsync -vsync */
1205        else if (VDisplay < 480)
1206            regp->MiscOutReg = 0x63;		/* -hsync +vsync */
1207        else if (VDisplay < 768)
1208            regp->MiscOutReg = 0xE3;		/* -hsync -vsync */
1209        else
1210            regp->MiscOutReg = 0x23;		/* +hsync +vsync */
1211    }
1212
1213    regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2;
1214
1215    /*
1216     * Time Sequencer
1217     */
1218    if (depth == 4)
1219        regp->Sequencer[0] = 0x02;
1220    else
1221        regp->Sequencer[0] = 0x00;
1222    if (mode->Flags & V_CLKDIV2)
1223        regp->Sequencer[1] = 0x09;
1224    else
1225        regp->Sequencer[1] = 0x01;
1226    if (depth == 1)
1227        regp->Sequencer[2] = 1 << BIT_PLANE;
1228    else
1229        regp->Sequencer[2] = 0x0F;
1230    regp->Sequencer[3] = 0x00;                             /* Font select */
1231    if (depth < 8)
1232        regp->Sequencer[4] = 0x06;                             /* Misc */
1233    else
1234        regp->Sequencer[4] = 0x0E;                             /* Misc */
1235
1236    /*
1237     * CRTC Controller
1238     */
1239    regp->CRTC[0]  = (mode->CrtcHTotal >> 3) - 5;
1240    regp->CRTC[1]  = (mode->CrtcHDisplay >> 3) - 1;
1241    regp->CRTC[2]  = (mode->CrtcHBlankStart >> 3) - 1;
1242    regp->CRTC[3]  = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
1243    i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F);
1244    if (i < 0x80)
1245	regp->CRTC[3] |= i;
1246    regp->CRTC[4]  = (mode->CrtcHSyncStart >> 3);
1247    regp->CRTC[5]  = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
1248	| (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
1249    regp->CRTC[6]  = (mode->CrtcVTotal - 2) & 0xFF;
1250    regp->CRTC[7]  = (((mode->CrtcVTotal - 2) & 0x100) >> 8)
1251	| (((mode->CrtcVDisplay - 1) & 0x100) >> 7)
1252	| ((mode->CrtcVSyncStart & 0x100) >> 6)
1253	| (((mode->CrtcVBlankStart - 1) & 0x100) >> 5)
1254	| 0x10
1255	| (((mode->CrtcVTotal - 2) & 0x200)   >> 4)
1256	| (((mode->CrtcVDisplay - 1) & 0x200) >> 3)
1257	| ((mode->CrtcVSyncStart & 0x200) >> 2);
1258    regp->CRTC[8]  = 0x00;
1259    regp->CRTC[9]  = (((mode->CrtcVBlankStart - 1) & 0x200) >> 4) | 0x40;
1260    if (mode->Flags & V_DBLSCAN)
1261	regp->CRTC[9] |= 0x80;
1262    if (mode->VScan >= 32)
1263	regp->CRTC[9] |= 0x1F;
1264    else if (mode->VScan > 1)
1265	regp->CRTC[9] |= mode->VScan - 1;
1266    regp->CRTC[10] = 0x00;
1267    regp->CRTC[11] = 0x00;
1268    regp->CRTC[12] = 0x00;
1269    regp->CRTC[13] = 0x00;
1270    regp->CRTC[14] = 0x00;
1271    regp->CRTC[15] = 0x00;
1272    regp->CRTC[16] = mode->CrtcVSyncStart & 0xFF;
1273    regp->CRTC[17] = (mode->CrtcVSyncEnd & 0x0F) | 0x20;
1274    regp->CRTC[18] = (mode->CrtcVDisplay - 1) & 0xFF;
1275    regp->CRTC[19] = scrninfp->displayWidth >> 4;  /* just a guess */
1276    regp->CRTC[20] = 0x00;
1277    regp->CRTC[21] = (mode->CrtcVBlankStart - 1) & 0xFF;
1278    regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1279    if (depth < 8)
1280	regp->CRTC[23] = 0xE3;
1281    else
1282	regp->CRTC[23] = 0xC3;
1283    regp->CRTC[24] = 0xFF;
1284
1285    vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
1286    vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
1287
1288    /*
1289     * Theory resumes here....
1290     */
1291
1292    /*
1293     * Graphics Display Controller
1294     */
1295    regp->Graphics[0] = 0x00;
1296    regp->Graphics[1] = 0x00;
1297    regp->Graphics[2] = 0x00;
1298    regp->Graphics[3] = 0x00;
1299    if (depth == 1) {
1300        regp->Graphics[4] = BIT_PLANE;
1301        regp->Graphics[5] = 0x00;
1302    } else {
1303        regp->Graphics[4] = 0x00;
1304        if (depth == 4)
1305            regp->Graphics[5] = 0x02;
1306        else
1307            regp->Graphics[5] = 0x40;
1308    }
1309    regp->Graphics[6] = 0x05;   /* only map 64k VGA memory !!!! */
1310    regp->Graphics[7] = 0x0F;
1311    regp->Graphics[8] = 0xFF;
1312
1313    if (depth == 1) {
1314        /* Initialise the Mono map according to which bit-plane gets used */
1315
1316	Bool flipPixels = xf86GetFlipPixels();
1317
1318        for (i=0; i<16; i++)
1319            if (((i & (1 << BIT_PLANE)) != 0) != flipPixels)
1320                regp->Attribute[i] = WHITE_VALUE;
1321            else
1322                regp->Attribute[i] = BLACK_VALUE;
1323
1324        regp->Attribute[16] = 0x01;  /* -VGA2- */ /* wrong for the ET4000 */
1325	if (!hwp->ShowOverscan)
1326            regp->Attribute[OVERSCAN] = OVERSCAN_VALUE;  /* -VGA2- */
1327    } else {
1328        regp->Attribute[0]  = 0x00; /* standard colormap translation */
1329        regp->Attribute[1]  = 0x01;
1330        regp->Attribute[2]  = 0x02;
1331        regp->Attribute[3]  = 0x03;
1332        regp->Attribute[4]  = 0x04;
1333        regp->Attribute[5]  = 0x05;
1334        regp->Attribute[6]  = 0x06;
1335        regp->Attribute[7]  = 0x07;
1336        regp->Attribute[8]  = 0x08;
1337        regp->Attribute[9]  = 0x09;
1338        regp->Attribute[10] = 0x0A;
1339        regp->Attribute[11] = 0x0B;
1340        regp->Attribute[12] = 0x0C;
1341        regp->Attribute[13] = 0x0D;
1342        regp->Attribute[14] = 0x0E;
1343        regp->Attribute[15] = 0x0F;
1344        if (depth == 4)
1345            regp->Attribute[16] = 0x81; /* wrong for the ET4000 */
1346        else
1347            regp->Attribute[16] = 0x41; /* wrong for the ET4000 */
1348        /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */
1349    }
1350    regp->Attribute[18] = 0x0F;
1351    regp->Attribute[19] = 0x00;
1352    regp->Attribute[20] = 0x00;
1353
1354    return TRUE;
1355}
1356
1357    /*
1358     * OK, so much for theory.  Now, let's deal with the >real< world...
1359     *
1360     * The above CRTC settings are precise in theory, except that many, if not
1361     * most, VGA clones fail to reset the blanking signal when the character or
1362     * line counter reaches [HV]Total.  In this case, the signal is only
1363     * unblanked when the counter reaches [HV]BlankEnd (mod 64, 128 or 256 as
1364     * the case may be) at the start of the >next< scanline or frame, which
1365     * means only part of the screen shows.  This affects how null overscans
1366     * are to be implemented on such adapters.
1367     *
1368     * Henceforth, VGA cores that implement this broken, but unfortunately
1369     * common, behaviour are to be designated as KGA's, in honour of Koen
1370     * Gadeyne, whose zeal to eliminate overscans (read: fury) set in motion
1371     * a series of events that led to the discovery of this problem.
1372     *
1373     * Some VGA's are KGA's only in the horizontal, or only in the vertical,
1374     * some in both, others in neither.  Don't let anyone tell you there is
1375     * such a thing as a VGA "standard"...  And, thank the Creator for the fact
1376     * that Hilbert spaces are not yet implemented in this industry.
1377     *
1378     * The following implements a trick suggested by David Dawes.  This sets
1379     * [HV]BlankEnd to zero if the blanking interval does not already contain a
1380     * 0-point, and decrements it by one otherwise.  In the latter case, this
1381     * will produce a left and/or top overscan which the colourmap code will
1382     * (still) need to ensure is as close to black as possible.  This will make
1383     * the behaviour consistent across all chipsets, while allowing all
1384     * chipsets to display the entire screen.  Non-KGA drivers can ignore the
1385     * following in their own copy of this code.
1386     *
1387     * --  TSI @ UQV,  1998.08.21
1388     */
1389
1390CARD32
1391vgaHWHBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1392	       unsigned int Flags)
1393{
1394    int nExtBits = (nBits < 6) ? 0 : nBits - 6;
1395    CARD32 ExtBits;
1396    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6;
1397
1398    regp->CRTC[3]  = (regp->CRTC[3] & ~0x1F)
1399                     | (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F);
1400    regp->CRTC[5]  = (regp->CRTC[5] & ~0x80)
1401                     | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2);
1402    ExtBits        = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask;
1403
1404    /* First the horizontal case */
1405    if ((Flags & KGA_FIX_OVERSCAN)
1406	&& ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3)))
1407    {
1408	int i = (regp->CRTC[3] & 0x1F)
1409	    | ((regp->CRTC[5] & 0x80) >> 2)
1410	    | ExtBits;
1411	if (Flags & KGA_ENABLE_ON_ZERO) {
1412	    if ((i-- > (((mode->CrtcHBlankStart >> 3) - 1)
1413		       & (0x3F | ExtBitMask)))
1414	    && (mode->CrtcHBlankEnd == mode->CrtcHTotal))
1415	    i = 0;
1416	} else if (Flags & KGA_BE_TOT_DEC)
1417	    i--;
1418	regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F);
1419	regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80);
1420	ExtBits = i & ExtBitMask;
1421    }
1422    return ExtBits >> 6;
1423}
1424
1425    /*
1426     * The vertical case is a little trickier.  Some VGA's ignore bit 0x80 of
1427     * CRTC[22].  Also, in some cases, a zero CRTC[22] will still blank the
1428     * very first scanline in a double- or multi-scanned mode.  This last case
1429     * needs further investigation.
1430     */
1431CARD32
1432vgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1433	       unsigned int Flags)
1434{
1435    CARD32 ExtBits;
1436    CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8);
1437    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8;
1438    /* If width is not known nBits should be 0. In this
1439     * case BitMask is set to 0 so we can check for it. */
1440    CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1);
1441    int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF;
1442    regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1443    ExtBits        = (mode->CrtcVBlankEnd - 1) & ExtBitMask;
1444
1445    if ((Flags & KGA_FIX_OVERSCAN)
1446	&& (mode->CrtcVBlankEnd == mode->CrtcVTotal))
1447      /* Null top overscan */
1448    {
1449	int i = regp->CRTC[22] | ExtBits;
1450	if (Flags & KGA_ENABLE_ON_ZERO) {
1451	    if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask)))
1452	     || ((i > VBlankStart)  &&  		/* 8-bit case */
1453	    ((i & 0x7F) > (VBlankStart & 0x7F)))) &&	/* 7-bit case */
1454	    !(regp->CRTC[9] & 0x9F))			/* 1 scanline/row */
1455	    i = 0;
1456	else
1457	    i = (i - 1);
1458	} else if (Flags & KGA_BE_TOT_DEC)
1459	    i = (i - 1);
1460
1461	regp->CRTC[22] = i & 0xFF;
1462	ExtBits = i & 0xFF00;
1463    }
1464    return ExtBits >> 8;
1465}
1466
1467/*
1468 * these are some more hardware specific helpers, formerly in vga.c
1469 */
1470static void
1471vgaHWGetHWRecPrivate(void)
1472{
1473    if (vgaHWPrivateIndex < 0)
1474	vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
1475    return;
1476}
1477
1478
1479static void
1480vgaHWFreeRegs(vgaRegPtr regp)
1481{
1482    free(regp->CRTC);
1483
1484    regp->CRTC =
1485    regp->Sequencer =
1486    regp->Graphics =
1487    regp->Attribute = NULL;
1488
1489    regp->numCRTC =
1490    regp->numSequencer =
1491    regp->numGraphics =
1492    regp->numAttribute = 0;
1493}
1494
1495
1496
1497static Bool
1498vgaHWAllocRegs(vgaRegPtr regp)
1499{
1500    unsigned char *buf;
1501
1502    if ((regp->numCRTC + regp->numSequencer + regp->numGraphics +
1503         regp->numAttribute) == 0)
1504        return FALSE;
1505
1506    buf = calloc(regp->numCRTC +
1507    		  regp->numSequencer +
1508		  regp->numGraphics +
1509		  regp->numAttribute, 1);
1510    if (!buf)
1511    	return FALSE;
1512
1513    regp->CRTC = buf;
1514    regp->Sequencer = regp->CRTC + regp->numCRTC;
1515    regp->Graphics = regp->Sequencer + regp->numSequencer;
1516    regp->Attribute = regp->Graphics + regp->numGraphics;
1517
1518    return TRUE;
1519}
1520
1521
1522Bool
1523vgaHWAllocDefaultRegs(vgaRegPtr regp)
1524{
1525    regp->numCRTC = VGA_NUM_CRTC;
1526    regp->numSequencer = VGA_NUM_SEQ;
1527    regp->numGraphics = VGA_NUM_GFX;
1528    regp->numAttribute = VGA_NUM_ATTR;
1529
1530    return vgaHWAllocRegs(regp);
1531}
1532
1533
1534Bool
1535vgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer,
1536		  int numGraphics, int numAttribute)
1537{
1538#define VGAHWMINNUM(regtype) \
1539	((newMode.num##regtype < regp->num##regtype) ? \
1540	 (newMode.num##regtype) : (regp->num##regtype))
1541#define VGAHWCOPYREGSET(regtype) \
1542	memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype))
1543
1544    vgaRegRec newMode, newSaved;
1545    vgaRegPtr regp;
1546
1547    regp = &VGAHWPTR(scrp)->ModeReg;
1548    memcpy (&newMode, regp, sizeof(vgaRegRec));
1549
1550    /* allocate space for new registers */
1551
1552    regp = &newMode;
1553    regp->numCRTC = numCRTC;
1554    regp->numSequencer = numSequencer;
1555    regp->numGraphics = numGraphics;
1556    regp->numAttribute = numAttribute;
1557    if (!vgaHWAllocRegs(regp))
1558    	return FALSE;
1559
1560    regp = &VGAHWPTR(scrp)->SavedReg;
1561    memcpy (&newSaved, regp, sizeof(vgaRegRec));
1562
1563    regp = &newSaved;
1564    regp->numCRTC = numCRTC;
1565    regp->numSequencer = numSequencer;
1566    regp->numGraphics = numGraphics;
1567    regp->numAttribute = numAttribute;
1568    if (!vgaHWAllocRegs(regp)) {
1569        vgaHWFreeRegs(&newMode);
1570    	return FALSE;
1571    }
1572
1573    /* allocations succeeded, copy register data into new space */
1574
1575    regp = &VGAHWPTR(scrp)->ModeReg;
1576    VGAHWCOPYREGSET(CRTC);
1577    VGAHWCOPYREGSET(Sequencer);
1578    VGAHWCOPYREGSET(Graphics);
1579    VGAHWCOPYREGSET(Attribute);
1580
1581    regp = &VGAHWPTR(scrp)->SavedReg;
1582    VGAHWCOPYREGSET(CRTC);
1583    VGAHWCOPYREGSET(Sequencer);
1584    VGAHWCOPYREGSET(Graphics);
1585    VGAHWCOPYREGSET(Attribute);
1586
1587    /* free old register arrays */
1588
1589    regp = &VGAHWPTR(scrp)->ModeReg;
1590    vgaHWFreeRegs(regp);
1591    memcpy(regp, &newMode, sizeof(vgaRegRec));
1592
1593    regp = &VGAHWPTR(scrp)->SavedReg;
1594    vgaHWFreeRegs(regp);
1595    memcpy(regp, &newSaved, sizeof(vgaRegRec));
1596
1597    return TRUE;
1598
1599#undef VGAHWMINNUM
1600#undef VGAHWCOPYREGSET
1601}
1602
1603
1604Bool
1605vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)
1606{
1607    vgaHWFreeRegs(dst);
1608
1609    memcpy(dst, src, sizeof(vgaRegRec));
1610
1611    if (!vgaHWAllocRegs(dst))
1612	return FALSE;
1613
1614    memcpy(dst->CRTC, src->CRTC, src->numCRTC);
1615    memcpy(dst->Sequencer, src->Sequencer, src->numSequencer);
1616    memcpy(dst->Graphics, src->Graphics, src->numGraphics);
1617    memcpy(dst->Attribute, src->Attribute, src->numAttribute);
1618
1619    return TRUE;
1620}
1621
1622
1623Bool
1624vgaHWGetHWRec(ScrnInfoPtr scrp)
1625{
1626    vgaRegPtr regp;
1627    vgaHWPtr hwp;
1628    int i;
1629
1630    /*
1631     * Let's make sure that the private exists and allocate one.
1632     */
1633    vgaHWGetHWRecPrivate();
1634    /*
1635     * New privates are always set to NULL, so we can check if the allocation
1636     * has already been done.
1637     */
1638    if (VGAHWPTR(scrp))
1639	return TRUE;
1640    hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1);
1641    regp = &VGAHWPTR(scrp)->ModeReg;
1642
1643    if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) ||
1644    	(!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) {
1645        free(hwp);
1646	return FALSE;
1647    }
1648
1649    if (scrp->bitsPerPixel == 1) {
1650	rgb blackColour = scrp->display->blackColour,
1651	    whiteColour = scrp->display->whiteColour;
1652
1653	if (blackColour.red   > 0x3F) blackColour.red   = 0x3F;
1654	if (blackColour.green > 0x3F) blackColour.green = 0x3F;
1655	if (blackColour.blue  > 0x3F) blackColour.blue  = 0x3F;
1656
1657	if (whiteColour.red   > 0x3F) whiteColour.red   = 0x3F;
1658	if (whiteColour.green > 0x3F) whiteColour.green = 0x3F;
1659	if (whiteColour.blue  > 0x3F) whiteColour.blue  = 0x3F;
1660
1661	if ((blackColour.red   == whiteColour.red  ) &&
1662	    (blackColour.green == whiteColour.green) &&
1663	    (blackColour.blue  == whiteColour.blue )) {
1664	    blackColour.red   ^= 0x3F;
1665	    blackColour.green ^= 0x3F;
1666	    blackColour.blue  ^= 0x3F;
1667	}
1668
1669        /*
1670         * initialize default colormap for monochrome
1671         */
1672        for (i=0; i<3;   i++) regp->DAC[i] = 0x00;
1673        for (i=3; i<768; i++) regp->DAC[i] = 0x3F;
1674        i = BLACK_VALUE * 3;
1675        regp->DAC[i++] = blackColour.red;
1676        regp->DAC[i++] = blackColour.green;
1677        regp->DAC[i] = blackColour.blue;
1678        i = WHITE_VALUE * 3;
1679        regp->DAC[i++] = whiteColour.red;
1680        regp->DAC[i++] = whiteColour.green;
1681        regp->DAC[i] = whiteColour.blue;
1682        i = OVERSCAN_VALUE * 3;
1683        regp->DAC[i++] = 0x00;
1684        regp->DAC[i++] = 0x00;
1685        regp->DAC[i] = 0x00;
1686    } else {
1687	/* Set all colours to black */
1688        for (i=0; i<768; i++) regp->DAC[i] = 0x00;
1689        /* ... and the overscan */
1690        if (scrp->depth >= 4)
1691            regp->Attribute[OVERSCAN] = 0xFF;
1692    }
1693    if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) {
1694	xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan");
1695	xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n");
1696	regp->DAC[765] = 0x3F;
1697	regp->DAC[766] = 0x00;
1698	regp->DAC[767] = 0x3F;
1699	regp->Attribute[OVERSCAN] = 0xFF;
1700	hwp->ShowOverscan = TRUE;
1701    } else
1702	hwp->ShowOverscan = FALSE;
1703
1704    hwp->paletteEnabled = FALSE;
1705    hwp->cmapSaved = FALSE;
1706    hwp->MapSize = 0;
1707    hwp->pScrn = scrp;
1708
1709    /* Initialise the function pointers with the standard VGA versions */
1710    vgaHWSetStdFuncs(hwp);
1711
1712    hwp->PIOOffset = scrp->domainIOBase;
1713    hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]);
1714
1715    return TRUE;
1716}
1717
1718
1719void
1720vgaHWFreeHWRec(ScrnInfoPtr scrp)
1721{
1722    if (vgaHWPrivateIndex >= 0) {
1723	vgaHWPtr hwp = VGAHWPTR(scrp);
1724
1725	if (!hwp)
1726	    return;
1727
1728	free(hwp->FontInfo1);
1729	free(hwp->FontInfo2);
1730	free(hwp->TextInfo);
1731
1732	vgaHWFreeRegs (&hwp->ModeReg);
1733	vgaHWFreeRegs (&hwp->SavedReg);
1734
1735	free(hwp);
1736	VGAHWPTRLVAL(scrp) = NULL;
1737    }
1738}
1739
1740
1741Bool
1742vgaHWMapMem(ScrnInfoPtr scrp)
1743{
1744    vgaHWPtr hwp = VGAHWPTR(scrp);
1745    int scr_index = scrp->scrnIndex;
1746
1747    if (hwp->Base)
1748	return TRUE;
1749
1750    /* If not set, initialise with the defaults */
1751    if (hwp->MapSize == 0)
1752	hwp->MapSize = VGA_DEFAULT_MEM_SIZE;
1753    if (hwp->MapPhys == 0)
1754	hwp->MapPhys = VGA_DEFAULT_PHYS_ADDR;
1755
1756    /*
1757     * Map as VIDMEM_MMIO_32BIT because WC
1758     * is bad when there is page flipping.
1759     * XXX This is not correct but we do it
1760     * for now.
1761     */
1762    DebugF("Mapping VGAMem\n");
1763    hwp->Base = xf86MapDomainMemory(scr_index, VIDMEM_MMIO_32BIT, hwp->dev,
1764				    hwp->MapPhys, hwp->MapSize);
1765    return hwp->Base != NULL;
1766}
1767
1768
1769void
1770vgaHWUnmapMem(ScrnInfoPtr scrp)
1771{
1772    vgaHWPtr hwp = VGAHWPTR(scrp);
1773    int scr_index = scrp->scrnIndex;
1774
1775    if (hwp->Base == NULL)
1776	return;
1777
1778    DebugF("Unmapping VGAMem\n");
1779    xf86UnMapVidMem(scr_index, hwp->Base, hwp->MapSize);
1780    hwp->Base = NULL;
1781}
1782
1783int
1784vgaHWGetIndex(void)
1785{
1786    return vgaHWPrivateIndex;
1787}
1788
1789
1790void
1791vgaHWGetIOBase(vgaHWPtr hwp)
1792{
1793    hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ?
1794				VGA_IOBASE_COLOR : VGA_IOBASE_MONO;
1795    xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3,
1796	"vgaHWGetIOBase: hwp->IOBase is 0x%04x, hwp->PIOOffset is 0x%04lx\n",
1797	hwp->IOBase, hwp->PIOOffset);
1798}
1799
1800
1801void
1802vgaHWLock(vgaHWPtr hwp)
1803{
1804    /* Protect CRTC[0-7] */
1805    hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80);
1806}
1807
1808void
1809vgaHWUnlock(vgaHWPtr hwp)
1810{
1811    /* Unprotect CRTC[0-7] */
1812     hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80);
1813}
1814
1815
1816void
1817vgaHWEnable(vgaHWPtr hwp)
1818{
1819    hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01);
1820}
1821
1822
1823void
1824vgaHWDisable(vgaHWPtr hwp)
1825{
1826    hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01);
1827}
1828
1829
1830static void
1831vgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
1832		 VisualPtr pVisual)
1833{
1834    vgaHWPtr hwp = VGAHWPTR(pScrn);
1835    int i, index;
1836
1837    for (i = 0; i < numColors; i++) {
1838	index = indices[i];
1839	hwp->writeDacWriteAddr(hwp, index);
1840	DACDelay(hwp);
1841	hwp->writeDacData(hwp, colors[index].red);
1842	DACDelay(hwp);
1843	hwp->writeDacData(hwp, colors[index].green);
1844	DACDelay(hwp);
1845	hwp->writeDacData(hwp, colors[index].blue);
1846	DACDelay(hwp);
1847    }
1848
1849    /* This shouldn't be necessary, but we'll play safe. */
1850    hwp->disablePalette(hwp);
1851}
1852
1853
1854static void
1855vgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan)
1856{
1857    vgaHWPtr hwp = VGAHWPTR(pScrn);
1858
1859    if (overscan < 0 || overscan > 255)
1860	return;
1861
1862    hwp->enablePalette(hwp);
1863    hwp->writeAttr(hwp, OVERSCAN, overscan);
1864
1865#ifdef DEBUGOVERSCAN
1866    {
1867	int ov = hwp->readAttr(hwp, OVERSCAN);
1868	int red, green, blue;
1869
1870	hwp->writeDacReadAddr(hwp, ov);
1871	red = hwp->readDacData(hwp);
1872	green = hwp->readDacData(hwp);
1873	blue = hwp->readDacData(hwp);
1874	ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n",
1875		ov, red, green, blue);
1876    }
1877#endif
1878
1879    hwp->disablePalette(hwp);
1880}
1881
1882
1883Bool
1884vgaHWHandleColormaps(ScreenPtr pScreen)
1885{
1886    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1887
1888    if (pScrn->depth > 1 && pScrn->depth <= 8) {
1889	return xf86HandleColormaps(pScreen, 1 << pScrn->depth,
1890				   pScrn->rgbBits, vgaHWLoadPalette,
1891				   pScrn->depth > 4 ? vgaHWSetOverscan : NULL,
1892				   CMAP_RELOAD_ON_MODE_SWITCH);
1893    }
1894    return TRUE;
1895}
1896
1897/* ----------------------- DDC support ------------------------*/
1898/*
1899 * Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total
1900 * to read out EDID at a faster rate. Allowed maximum is 25kHz with
1901 * 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen
1902 * readback, enable access to cr00-cr07.
1903 */
1904
1905/* vertical timings */
1906#define DISPLAY_END 0x04
1907#define BLANK_START DISPLAY_END
1908#define SYNC_START BLANK_START
1909#define SYNC_END 0x09
1910#define BLANK_END SYNC_END
1911#define V_TOTAL BLANK_END
1912/* this function doesn't have to be reentrant for our purposes */
1913struct _vgaDdcSave {
1914    unsigned char cr03;
1915    unsigned char cr06;
1916    unsigned char cr07;
1917    unsigned char cr09;
1918    unsigned char cr10;
1919    unsigned char cr11;
1920    unsigned char cr12;
1921    unsigned char cr15;
1922    unsigned char cr16;
1923    unsigned char msr;
1924};
1925
1926void
1927vgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed)
1928{
1929    vgaHWPtr hwp = VGAHWPTR(pScrn);
1930    unsigned char tmp;
1931    struct _vgaDdcSave* save;
1932    switch (speed) {
1933    case DDC_FAST:
1934
1935        if (hwp->ddc != NULL) break;
1936        hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave),1);
1937	save = (struct _vgaDdcSave *)hwp->ddc;
1938      /* Lightpen register disable - allow access to cr10 & 11; just in case */
1939	save->cr03 = hwp->readCrtc(hwp, 0x03);
1940	hwp->writeCrtc(hwp,0x03,(save->cr03 |0x80));
1941	save->cr12 = hwp->readCrtc(hwp, 0x12);
1942	hwp->writeCrtc(hwp,0x12,DISPLAY_END);
1943	save->cr15 = hwp->readCrtc(hwp, 0x15);
1944	hwp->writeCrtc(hwp,0x15,BLANK_START);
1945	save->cr10 = hwp->readCrtc(hwp, 0x10);
1946	hwp->writeCrtc(hwp,0x10,SYNC_START);
1947	save->cr11 = hwp->readCrtc(hwp, 0x11);
1948	/* unprotect group 1 registers; just in case ...*/
1949	hwp->writeCrtc(hwp,0x11,((save->cr11 & 0x70) | SYNC_END));
1950	save->cr16 = hwp->readCrtc(hwp, 0x16);
1951	hwp->writeCrtc(hwp,0x16,BLANK_END);
1952	save->cr06 = hwp->readCrtc(hwp, 0x06);
1953	hwp->writeCrtc(hwp,0x06,V_TOTAL);
1954	/* all values have less than 8 bit - mask out 9th and 10th bits */
1955	save->cr09 = hwp->readCrtc(hwp, 0x09);
1956	hwp->writeCrtc(hwp,0x09,(save->cr09 &0xDF));
1957	save->cr07 = hwp->readCrtc(hwp, 0x07);
1958	hwp->writeCrtc(hwp,0x07,(save->cr07 &0x10));
1959	/* vsync polarity negativ & ensure a 25MHz clock */
1960	save->msr = hwp->readMiscOut(hwp);
1961	hwp->writeMiscOut(hwp,((save->msr & 0xF3) | 0x80));
1962	break;
1963    case DDC_SLOW:
1964        if (hwp->ddc == NULL) break;
1965	save = (struct _vgaDdcSave *)hwp->ddc;
1966	hwp->writeMiscOut(hwp,save->msr);
1967	hwp->writeCrtc(hwp,0x07,save->cr07);
1968	tmp = hwp->readCrtc(hwp, 0x09);
1969	hwp->writeCrtc(hwp,0x09,((save->cr09 & 0x20) | (tmp & 0xDF)));
1970	hwp->writeCrtc(hwp,0x06,save->cr06);
1971	hwp->writeCrtc(hwp,0x16,save->cr16);
1972	hwp->writeCrtc(hwp,0x11,save->cr11);
1973	hwp->writeCrtc(hwp,0x10,save->cr10);
1974	hwp->writeCrtc(hwp,0x15,save->cr15);
1975	hwp->writeCrtc(hwp,0x12,save->cr12);
1976	hwp->writeCrtc(hwp,0x03,save->cr03);
1977	free(save);
1978	hwp->ddc = NULL;
1979	break;
1980    default:
1981	break;
1982    }
1983}
1984
1985DDC1SetSpeedProc
1986vgaHWddc1SetSpeedWeak(void)
1987{
1988    return vgaHWddc1SetSpeed;
1989}
1990
1991SaveScreenProcPtr vgaHWSaveScreenWeak(void)
1992{
1993    return vgaHWSaveScreen;
1994}
1995