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