vgaHW.c revision 9b06bd19
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/* Use a private definition of this here */
79#undef VGAHWPTR
80#define VGAHWPTRLVAL(p) (p)->privates[vgaHWPrivateIndex].ptr
81#define VGAHWPTR(p) ((vgaHWPtr)(VGAHWPTRLVAL(p)))
82
83static int vgaHWPrivateIndex = -1;
84
85#define DAC_TEST_MASK 0x3F
86
87#ifdef NEED_SAVED_CMAP
88/* This default colourmap is used only when it can't be read from the VGA */
89
90static CARD8 defaultDAC[768] = {
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    pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
165    pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_DATA_OFFSET, value);
166}
167
168static CARD8
169stdReadCrtc(vgaHWPtr hwp, CARD8 index)
170{
171    pci_io_write8(hwp->io, hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
172    return pci_io_read8(hwp->io, hwp->IOBase + VGA_CRTC_DATA_OFFSET);
173}
174
175static void
176stdWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
177{
178    pci_io_write8(hwp->io, VGA_GRAPH_INDEX, index);
179    pci_io_write8(hwp->io, VGA_GRAPH_DATA, value);
180}
181
182static CARD8
183stdReadGr(vgaHWPtr hwp, CARD8 index)
184{
185    pci_io_write8(hwp->io, VGA_GRAPH_INDEX, index);
186    return pci_io_read8(hwp->io, VGA_GRAPH_DATA);
187}
188
189static void
190stdWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
191{
192    pci_io_write8(hwp->io, VGA_SEQ_INDEX, index);
193    pci_io_write8(hwp->io, VGA_SEQ_DATA, value);
194}
195
196static CARD8
197stdReadSeq(vgaHWPtr hwp, CARD8 index)
198{
199    pci_io_write8(hwp->io, VGA_SEQ_INDEX, index);
200    return pci_io_read8(hwp->io, VGA_SEQ_DATA);
201}
202
203static CARD8
204stdReadST00(vgaHWPtr hwp)
205{
206    return pci_io_read8(hwp->io, VGA_IN_STAT_0);
207}
208
209static CARD8
210stdReadST01(vgaHWPtr hwp)
211{
212    return pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
213}
214
215static CARD8
216stdReadFCR(vgaHWPtr hwp)
217{
218    return pci_io_read8(hwp->io, VGA_FEATURE_R);
219}
220
221static void
222stdWriteFCR(vgaHWPtr hwp, CARD8 value)
223{
224    pci_io_write8(hwp->io, hwp->IOBase + 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) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
236    pci_io_write8(hwp->io, VGA_ATTR_INDEX, index);
237    pci_io_write8(hwp->io, 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) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
249    pci_io_write8(hwp->io, VGA_ATTR_INDEX, index);
250    return pci_io_read8(hwp->io, VGA_ATTR_DATA_R);
251}
252
253static void
254stdWriteMiscOut(vgaHWPtr hwp, CARD8 value)
255{
256    pci_io_write8(hwp->io, VGA_MISC_OUT_W, value);
257}
258
259static CARD8
260stdReadMiscOut(vgaHWPtr hwp)
261{
262    return pci_io_read8(hwp->io, VGA_MISC_OUT_R);
263}
264
265static void
266stdEnablePalette(vgaHWPtr hwp)
267{
268    (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
269    pci_io_write8(hwp->io, VGA_ATTR_INDEX, 0x00);
270    hwp->paletteEnabled = TRUE;
271}
272
273static void
274stdDisablePalette(vgaHWPtr hwp)
275{
276    (void) pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
277    pci_io_write8(hwp->io, VGA_ATTR_INDEX, 0x20);
278    hwp->paletteEnabled = FALSE;
279}
280
281static void
282stdWriteDacMask(vgaHWPtr hwp, CARD8 value)
283{
284    pci_io_write8(hwp->io, VGA_DAC_MASK, value);
285}
286
287static CARD8
288stdReadDacMask(vgaHWPtr hwp)
289{
290    return pci_io_read8(hwp->io, VGA_DAC_MASK);
291}
292
293static void
294stdWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
295{
296    pci_io_write8(hwp->io, VGA_DAC_READ_ADDR, value);
297}
298
299static void
300stdWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
301{
302    pci_io_write8(hwp->io, VGA_DAC_WRITE_ADDR, value);
303}
304
305static void
306stdWriteDacData(vgaHWPtr hwp, CARD8 value)
307{
308    pci_io_write8(hwp->io, VGA_DAC_DATA, value);
309}
310
311static CARD8
312stdReadDacData(vgaHWPtr hwp)
313{
314    return pci_io_read8(hwp->io, VGA_DAC_DATA);
315}
316
317static CARD8
318stdReadEnable(vgaHWPtr hwp)
319{
320    return pci_io_read8(hwp->io, VGA_ENABLE);
321}
322
323static void
324stdWriteEnable(vgaHWPtr hwp, CARD8 value)
325{
326    pci_io_write8(hwp->io, 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->readEnable = stdReadEnable;
355    hwp->writeEnable = stdWriteEnable;
356
357    hwp->io = pci_legacy_open_io(hwp->dev, 0, 64 * 1024);
358}
359
360/*
361 * MMIO versions of the register access functions.  These require
362 * hwp->MemBase to be set in such a way that when the standard VGA port
363 * adderss is added the correct memory address results.
364 */
365
366#define minb(p) MMIO_IN8(hwp->MMIOBase, (hwp->MMIOOffset + (p)))
367#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (hwp->MMIOOffset + (p)),(v))
368
369static void
370mmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
371{
372    moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
373    moutb(hwp->IOBase + VGA_CRTC_DATA_OFFSET, value);
374}
375
376static CARD8
377mmioReadCrtc(vgaHWPtr hwp, CARD8 index)
378{
379    moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
380    return minb(hwp->IOBase + VGA_CRTC_DATA_OFFSET);
381}
382
383static void
384mmioWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
385{
386    moutb(VGA_GRAPH_INDEX, index);
387    moutb(VGA_GRAPH_DATA, value);
388}
389
390static CARD8
391mmioReadGr(vgaHWPtr hwp, CARD8 index)
392{
393    moutb(VGA_GRAPH_INDEX, index);
394    return minb(VGA_GRAPH_DATA);
395}
396
397static void
398mmioWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
399{
400    moutb(VGA_SEQ_INDEX, index);
401    moutb(VGA_SEQ_DATA, value);
402}
403
404static CARD8
405mmioReadSeq(vgaHWPtr hwp, CARD8 index)
406{
407    moutb(VGA_SEQ_INDEX, index);
408    return minb(VGA_SEQ_DATA);
409}
410
411static CARD8
412mmioReadST00(vgaHWPtr hwp)
413{
414    return minb(VGA_IN_STAT_0);
415}
416
417static CARD8
418mmioReadST01(vgaHWPtr hwp)
419{
420    return minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
421}
422
423static CARD8
424mmioReadFCR(vgaHWPtr hwp)
425{
426    return minb(VGA_FEATURE_R);
427}
428
429static void
430mmioWriteFCR(vgaHWPtr hwp, CARD8 value)
431{
432    moutb(hwp->IOBase + VGA_FEATURE_W_OFFSET, value);
433}
434
435static void
436mmioWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
437{
438    if (hwp->paletteEnabled)
439        index &= ~0x20;
440    else
441        index |= 0x20;
442
443    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
444    moutb(VGA_ATTR_INDEX, index);
445    moutb(VGA_ATTR_DATA_W, value);
446}
447
448static CARD8
449mmioReadAttr(vgaHWPtr hwp, CARD8 index)
450{
451    if (hwp->paletteEnabled)
452        index &= ~0x20;
453    else
454        index |= 0x20;
455
456    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
457    moutb(VGA_ATTR_INDEX, index);
458    return minb(VGA_ATTR_DATA_R);
459}
460
461static void
462mmioWriteMiscOut(vgaHWPtr hwp, CARD8 value)
463{
464    moutb(VGA_MISC_OUT_W, value);
465}
466
467static CARD8
468mmioReadMiscOut(vgaHWPtr hwp)
469{
470    return minb(VGA_MISC_OUT_R);
471}
472
473static void
474mmioEnablePalette(vgaHWPtr hwp)
475{
476    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
477    moutb(VGA_ATTR_INDEX, 0x00);
478    hwp->paletteEnabled = TRUE;
479}
480
481static void
482mmioDisablePalette(vgaHWPtr hwp)
483{
484    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
485    moutb(VGA_ATTR_INDEX, 0x20);
486    hwp->paletteEnabled = FALSE;
487}
488
489static void
490mmioWriteDacMask(vgaHWPtr hwp, CARD8 value)
491{
492    moutb(VGA_DAC_MASK, value);
493}
494
495static CARD8
496mmioReadDacMask(vgaHWPtr hwp)
497{
498    return minb(VGA_DAC_MASK);
499}
500
501static void
502mmioWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
503{
504    moutb(VGA_DAC_READ_ADDR, value);
505}
506
507static void
508mmioWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
509{
510    moutb(VGA_DAC_WRITE_ADDR, value);
511}
512
513static void
514mmioWriteDacData(vgaHWPtr hwp, CARD8 value)
515{
516    moutb(VGA_DAC_DATA, value);
517}
518
519static CARD8
520mmioReadDacData(vgaHWPtr hwp)
521{
522    return minb(VGA_DAC_DATA);
523}
524
525static CARD8
526mmioReadEnable(vgaHWPtr hwp)
527{
528    return minb(VGA_ENABLE);
529}
530
531static void
532mmioWriteEnable(vgaHWPtr hwp, CARD8 value)
533{
534    moutb(VGA_ENABLE, value);
535}
536
537void
538vgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset)
539{
540    hwp->writeCrtc = mmioWriteCrtc;
541    hwp->readCrtc = mmioReadCrtc;
542    hwp->writeGr = mmioWriteGr;
543    hwp->readGr = mmioReadGr;
544    hwp->readST00 = mmioReadST00;
545    hwp->readST01 = mmioReadST01;
546    hwp->readFCR = mmioReadFCR;
547    hwp->writeFCR = mmioWriteFCR;
548    hwp->writeAttr = mmioWriteAttr;
549    hwp->readAttr = mmioReadAttr;
550    hwp->writeSeq = mmioWriteSeq;
551    hwp->readSeq = mmioReadSeq;
552    hwp->writeMiscOut = mmioWriteMiscOut;
553    hwp->readMiscOut = mmioReadMiscOut;
554    hwp->enablePalette = mmioEnablePalette;
555    hwp->disablePalette = mmioDisablePalette;
556    hwp->writeDacMask = mmioWriteDacMask;
557    hwp->readDacMask = mmioReadDacMask;
558    hwp->writeDacWriteAddr = mmioWriteDacWriteAddr;
559    hwp->writeDacReadAddr = mmioWriteDacReadAddr;
560    hwp->writeDacData = mmioWriteDacData;
561    hwp->readDacData = mmioReadDacData;
562    hwp->MMIOBase = base;
563    hwp->MMIOOffset = offset;
564    hwp->readEnable = mmioReadEnable;
565    hwp->writeEnable = mmioWriteEnable;
566}
567
568/*
569 * vgaHWProtect --
570 *	Protect VGA registers and memory from corruption during loads.
571 */
572
573void
574vgaHWProtect(ScrnInfoPtr pScrn, Bool on)
575{
576    vgaHWPtr hwp = VGAHWPTR(pScrn);
577
578    unsigned char tmp;
579
580    if (pScrn->vtSema) {
581        if (on) {
582            /*
583             * Turn off screen and disable sequencer.
584             */
585            tmp = hwp->readSeq(hwp, 0x01);
586
587            vgaHWSeqReset(hwp, TRUE);   /* start synchronous reset */
588            hwp->writeSeq(hwp, 0x01, tmp | 0x20);       /* disable the display */
589
590            hwp->enablePalette(hwp);
591        }
592        else {
593            /*
594             * Re-enable sequencer, then turn on screen.
595             */
596
597            tmp = hwp->readSeq(hwp, 0x01);
598
599            hwp->writeSeq(hwp, 0x01, tmp & ~0x20);      /* re-enable display */
600            vgaHWSeqReset(hwp, FALSE);  /* clear synchronousreset */
601
602            hwp->disablePalette(hwp);
603        }
604    }
605}
606
607vgaHWProtectProc *
608vgaHWProtectWeak(void)
609{
610    return vgaHWProtect;
611}
612
613/*
614 * vgaHWBlankScreen -- blank the screen.
615 */
616
617void
618vgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on)
619{
620    vgaHWPtr hwp = VGAHWPTR(pScrn);
621    unsigned char scrn;
622
623    scrn = hwp->readSeq(hwp, 0x01);
624
625    if (on) {
626        scrn &= ~0x20;          /* enable screen */
627    }
628    else {
629        scrn |= 0x20;           /* blank screen */
630    }
631
632    vgaHWSeqReset(hwp, TRUE);
633    hwp->writeSeq(hwp, 0x01, scrn);     /* change mode */
634    vgaHWSeqReset(hwp, FALSE);
635}
636
637vgaHWBlankScreenProc *
638vgaHWBlankScreenWeak(void)
639{
640    return vgaHWBlankScreen;
641}
642
643/*
644 * vgaHWSaveScreen -- blank the screen.
645 */
646
647Bool
648vgaHWSaveScreen(ScreenPtr pScreen, int mode)
649{
650    ScrnInfoPtr pScrn = NULL;
651    Bool on;
652
653    if (pScreen != NULL)
654        pScrn = xf86ScreenToScrn(pScreen);
655
656    on = xf86IsUnblank(mode);
657
658#if 0
659    if (on)
660        SetTimeSinceLastInputEvent();
661#endif
662
663    if ((pScrn != NULL) && pScrn->vtSema) {
664        vgaHWBlankScreen(pScrn, on);
665    }
666    return TRUE;
667}
668
669/*
670 * vgaHWDPMSSet -- Sets VESA Display Power Management Signaling (DPMS) Mode
671 *
672 * This generic VGA function can only set the Off and On modes.  If the
673 * Standby and Suspend modes are to be supported, a chip specific replacement
674 * for this function must be written.
675 */
676
677void
678vgaHWDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
679{
680    unsigned char seq1 = 0, crtc17 = 0;
681    vgaHWPtr hwp = VGAHWPTR(pScrn);
682
683    if (!pScrn->vtSema)
684        return;
685
686    switch (PowerManagementMode) {
687    case DPMSModeOn:
688        /* Screen: On; HSync: On, VSync: On */
689        seq1 = 0x00;
690        crtc17 = 0x80;
691        break;
692    case DPMSModeStandby:
693        /* Screen: Off; HSync: Off, VSync: On -- Not Supported */
694        seq1 = 0x20;
695        crtc17 = 0x80;
696        break;
697    case DPMSModeSuspend:
698        /* Screen: Off; HSync: On, VSync: Off -- Not Supported */
699        seq1 = 0x20;
700        crtc17 = 0x80;
701        break;
702    case DPMSModeOff:
703        /* Screen: Off; HSync: Off, VSync: Off */
704        seq1 = 0x20;
705        crtc17 = 0x00;
706        break;
707    }
708    hwp->writeSeq(hwp, 0x00, 0x01);     /* Synchronous Reset */
709    seq1 |= hwp->readSeq(hwp, 0x01) & ~0x20;
710    hwp->writeSeq(hwp, 0x01, seq1);
711    crtc17 |= hwp->readCrtc(hwp, 0x17) & ~0x80;
712    usleep(10000);
713    hwp->writeCrtc(hwp, 0x17, crtc17);
714    hwp->writeSeq(hwp, 0x00, 0x03);     /* End Reset */
715}
716
717/*
718 * vgaHWSeqReset
719 *      perform a sequencer reset.
720 */
721
722void
723vgaHWSeqReset(vgaHWPtr hwp, Bool start)
724{
725    if (start)
726        hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */
727    else
728        hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */
729}
730
731void
732vgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
733{
734#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
735    vgaHWPtr hwp = VGAHWPTR(scrninfp);
736    int savedIOBase;
737    unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4;
738    Bool doMap = FALSE;
739
740    /* If nothing to do, return now */
741    if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo)
742        return;
743
744    if (hwp->Base == NULL) {
745        doMap = TRUE;
746        if (!vgaHWMapMem(scrninfp)) {
747            xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
748                       "vgaHWRestoreFonts: vgaHWMapMem() failed\n");
749            return;
750        }
751    }
752
753    /* save the registers that are needed here */
754    miscOut = hwp->readMiscOut(hwp);
755    attr10 = hwp->readAttr(hwp, 0x10);
756    gr1 = hwp->readGr(hwp, 0x01);
757    gr3 = hwp->readGr(hwp, 0x03);
758    gr4 = hwp->readGr(hwp, 0x04);
759    gr5 = hwp->readGr(hwp, 0x05);
760    gr6 = hwp->readGr(hwp, 0x06);
761    gr8 = hwp->readGr(hwp, 0x08);
762    seq2 = hwp->readSeq(hwp, 0x02);
763    seq4 = hwp->readSeq(hwp, 0x04);
764
765    /* save hwp->IOBase and temporarily set it for colour mode */
766    savedIOBase = hwp->IOBase;
767    hwp->IOBase = VGA_IOBASE_COLOR;
768
769    /* Force into colour mode */
770    hwp->writeMiscOut(hwp, miscOut | 0x01);
771
772    vgaHWBlankScreen(scrninfp, FALSE);
773
774    /*
775     * here we temporarily switch to 16 colour planar mode, to simply
776     * copy the font-info and saved text.
777     *
778     * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
779     */
780#if 0
781    hwp->writeAttr(hwp, 0x10, 0x01);    /* graphics mode */
782#endif
783
784    hwp->writeSeq(hwp, 0x04, 0x06);     /* enable plane graphics */
785    hwp->writeGr(hwp, 0x05, 0x00);      /* write mode 0, read mode 0 */
786    hwp->writeGr(hwp, 0x06, 0x05);      /* set graphics */
787
788    if (scrninfp->depth == 4) {
789        /* GJA */
790        hwp->writeGr(hwp, 0x03, 0x00);  /* don't rotate, write unmodified */
791        hwp->writeGr(hwp, 0x08, 0xFF);  /* write all bits in a byte */
792        hwp->writeGr(hwp, 0x01, 0x00);  /* all planes come from CPU */
793    }
794
795#if SAVE_FONT1
796    if (hwp->FontInfo1) {
797        hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */
798        hwp->writeGr(hwp, 0x04, 0x02);  /* read plane 2 */
799        slowbcopy_tobus(hwp->FontInfo1, hwp->Base, FONT_AMOUNT);
800    }
801#endif
802
803#if SAVE_FONT2
804    if (hwp->FontInfo2) {
805        hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */
806        hwp->writeGr(hwp, 0x04, 0x03);  /* read plane 3 */
807        slowbcopy_tobus(hwp->FontInfo2, hwp->Base, FONT_AMOUNT);
808    }
809#endif
810
811#if SAVE_TEXT
812    if (hwp->TextInfo) {
813        hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */
814        hwp->writeGr(hwp, 0x04, 0x00);  /* read plane 0 */
815        slowbcopy_tobus(hwp->TextInfo, hwp->Base, TEXT_AMOUNT);
816        hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */
817        hwp->writeGr(hwp, 0x04, 0x01);  /* read plane 1 */
818        slowbcopy_tobus((unsigned char *) hwp->TextInfo + TEXT_AMOUNT,
819                        hwp->Base, TEXT_AMOUNT);
820    }
821#endif
822
823    vgaHWBlankScreen(scrninfp, TRUE);
824
825    /* restore the registers that were changed */
826    hwp->writeMiscOut(hwp, miscOut);
827    hwp->writeAttr(hwp, 0x10, attr10);
828    hwp->writeGr(hwp, 0x01, gr1);
829    hwp->writeGr(hwp, 0x03, gr3);
830    hwp->writeGr(hwp, 0x04, gr4);
831    hwp->writeGr(hwp, 0x05, gr5);
832    hwp->writeGr(hwp, 0x06, gr6);
833    hwp->writeGr(hwp, 0x08, gr8);
834    hwp->writeSeq(hwp, 0x02, seq2);
835    hwp->writeSeq(hwp, 0x04, seq4);
836    hwp->IOBase = savedIOBase;
837
838    if (doMap)
839        vgaHWUnmapMem(scrninfp);
840
841#endif                          /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
842}
843
844void
845vgaHWRestoreMode(ScrnInfoPtr scrninfp, vgaRegPtr restore)
846{
847    vgaHWPtr hwp = VGAHWPTR(scrninfp);
848    int i;
849
850    if (restore->MiscOutReg & 0x01)
851        hwp->IOBase = VGA_IOBASE_COLOR;
852    else
853        hwp->IOBase = VGA_IOBASE_MONO;
854
855    hwp->writeMiscOut(hwp, restore->MiscOutReg);
856
857    for (i = 1; i < restore->numSequencer; i++)
858        hwp->writeSeq(hwp, i, restore->Sequencer[i]);
859
860    /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
861    hwp->writeCrtc(hwp, 17, restore->CRTC[17] & ~0x80);
862
863    for (i = 0; i < restore->numCRTC; i++)
864        hwp->writeCrtc(hwp, i, restore->CRTC[i]);
865
866    for (i = 0; i < restore->numGraphics; i++)
867        hwp->writeGr(hwp, i, restore->Graphics[i]);
868
869    hwp->enablePalette(hwp);
870    for (i = 0; i < restore->numAttribute; i++)
871        hwp->writeAttr(hwp, i, restore->Attribute[i]);
872    hwp->disablePalette(hwp);
873}
874
875void
876vgaHWRestoreColormap(ScrnInfoPtr scrninfp, vgaRegPtr restore)
877{
878    vgaHWPtr hwp = VGAHWPTR(scrninfp);
879    int i;
880
881#if 0
882    hwp->enablePalette(hwp);
883#endif
884
885    hwp->writeDacMask(hwp, 0xFF);
886    hwp->writeDacWriteAddr(hwp, 0x00);
887    for (i = 0; i < 768; i++) {
888        hwp->writeDacData(hwp, restore->DAC[i]);
889        DACDelay(hwp);
890    }
891
892    hwp->disablePalette(hwp);
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,
993                          TEXT_AMOUNT);
994    }
995#endif                          /* SAVE_TEXT */
996
997    /* Restore clobbered registers */
998    hwp->writeAttr(hwp, 0x10, attr10);
999    hwp->writeSeq(hwp, 0x02, seq2);
1000    hwp->writeSeq(hwp, 0x04, seq4);
1001    hwp->writeGr(hwp, 0x04, gr4);
1002    hwp->writeGr(hwp, 0x05, gr5);
1003    hwp->writeGr(hwp, 0x06, gr6);
1004    hwp->writeMiscOut(hwp, miscOut);
1005    hwp->IOBase = savedIOBase;
1006
1007    vgaHWBlankScreen(scrninfp, TRUE);
1008
1009    if (doMap)
1010        vgaHWUnmapMem(scrninfp);
1011
1012#endif                          /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
1013}
1014
1015void
1016vgaHWSaveMode(ScrnInfoPtr scrninfp, vgaRegPtr save)
1017{
1018    vgaHWPtr hwp = VGAHWPTR(scrninfp);
1019    int i;
1020
1021    save->MiscOutReg = hwp->readMiscOut(hwp);
1022    if (save->MiscOutReg & 0x01)
1023        hwp->IOBase = VGA_IOBASE_COLOR;
1024    else
1025        hwp->IOBase = VGA_IOBASE_MONO;
1026
1027    for (i = 0; i < save->numCRTC; i++) {
1028        save->CRTC[i] = hwp->readCrtc(hwp, i);
1029        DebugF("CRTC[0x%02x] = 0x%02x\n", i, save->CRTC[i]);
1030    }
1031
1032    hwp->enablePalette(hwp);
1033    for (i = 0; i < save->numAttribute; i++) {
1034        save->Attribute[i] = hwp->readAttr(hwp, i);
1035        DebugF("Attribute[0x%02x] = 0x%02x\n", i, save->Attribute[i]);
1036    }
1037    hwp->disablePalette(hwp);
1038
1039    for (i = 0; i < save->numGraphics; i++) {
1040        save->Graphics[i] = hwp->readGr(hwp, i);
1041        DebugF("Graphics[0x%02x] = 0x%02x\n", i, save->Graphics[i]);
1042    }
1043
1044    for (i = 1; i < save->numSequencer; i++) {
1045        save->Sequencer[i] = hwp->readSeq(hwp, i);
1046        DebugF("Sequencer[0x%02x] = 0x%02x\n", i, save->Sequencer[i]);
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    }
1119    else {
1120        /* save the colourmap */
1121        hwp->writeDacReadAddr(hwp, 0x02);
1122        for (i = 6; i < 768; i++) {
1123            save->DAC[i] = hwp->readDacData(hwp);
1124            DACDelay(hwp);
1125            switch (i % 3) {
1126            case 0:
1127                DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
1128                break;
1129            case 1:
1130                DebugF("0x%02x, ", save->DAC[i]);
1131                break;
1132            case 2:
1133                DebugF("0x%02x\n", save->DAC[i]);
1134            }
1135        }
1136    }
1137
1138    hwp->disablePalette(hwp);
1139    hwp->cmapSaved = TRUE;
1140#endif
1141}
1142
1143/*
1144 * vgaHWSave --
1145 *      save the current VGA state
1146 */
1147
1148void
1149vgaHWSave(ScrnInfoPtr scrninfp, vgaRegPtr save, int flags)
1150{
1151    if (save == NULL)
1152        return;
1153
1154    if (flags & VGA_SR_CMAP)
1155        vgaHWSaveColormap(scrninfp, save);
1156
1157    if (flags & VGA_SR_MODE)
1158        vgaHWSaveMode(scrninfp, save);
1159
1160    if (flags & VGA_SR_FONTS)
1161        vgaHWSaveFonts(scrninfp, save);
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        regp->MiscOutReg = 0x23;
1192        if (mode->Flags & V_NHSYNC)
1193            regp->MiscOutReg |= 0x40;
1194        if (mode->Flags & V_NVSYNC)
1195            regp->MiscOutReg |= 0x80;
1196    }
1197    else {
1198        int VDisplay = mode->VDisplay;
1199
1200        if (mode->Flags & V_DBLSCAN)
1201            VDisplay *= 2;
1202        if (mode->VScan > 1)
1203            VDisplay *= mode->VScan;
1204        if (VDisplay < 400)
1205            regp->MiscOutReg = 0xA3;    /* +hsync -vsync */
1206        else if (VDisplay < 480)
1207            regp->MiscOutReg = 0x63;    /* -hsync +vsync */
1208        else if (VDisplay < 768)
1209            regp->MiscOutReg = 0xE3;    /* -hsync -vsync */
1210        else
1211            regp->MiscOutReg = 0x23;    /* +hsync +vsync */
1212    }
1213
1214    regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2;
1215
1216    /*
1217     * Time Sequencer
1218     */
1219    if (depth == 4)
1220        regp->Sequencer[0] = 0x02;
1221    else
1222        regp->Sequencer[0] = 0x00;
1223    if (mode->Flags & V_CLKDIV2)
1224        regp->Sequencer[1] = 0x09;
1225    else
1226        regp->Sequencer[1] = 0x01;
1227    if (depth == 1)
1228        regp->Sequencer[2] = 1 << BIT_PLANE;
1229    else
1230        regp->Sequencer[2] = 0x0F;
1231    regp->Sequencer[3] = 0x00;  /* Font select */
1232    if (depth < 8)
1233        regp->Sequencer[4] = 0x06;      /* Misc */
1234    else
1235        regp->Sequencer[4] = 0x0E;      /* Misc */
1236
1237    /*
1238     * CRTC Controller
1239     */
1240    regp->CRTC[0] = (mode->CrtcHTotal >> 3) - 5;
1241    regp->CRTC[1] = (mode->CrtcHDisplay >> 3) - 1;
1242    regp->CRTC[2] = (mode->CrtcHBlankStart >> 3) - 1;
1243    regp->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
1244    i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F);
1245    if (i < 0x80)
1246        regp->CRTC[3] |= i;
1247    regp->CRTC[4] = (mode->CrtcHSyncStart >> 3);
1248    regp->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
1249        | (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
1250    regp->CRTC[6] = (mode->CrtcVTotal - 2) & 0xFF;
1251    regp->CRTC[7] = (((mode->CrtcVTotal - 2) & 0x100) >> 8)
1252        | (((mode->CrtcVDisplay - 1) & 0x100) >> 7)
1253        | ((mode->CrtcVSyncStart & 0x100) >> 6)
1254        | (((mode->CrtcVBlankStart - 1) & 0x100) >> 5)
1255        | 0x10 | (((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    }
1303    else {
1304        regp->Graphics[4] = 0x00;
1305        if (depth == 4)
1306            regp->Graphics[5] = 0x02;
1307        else
1308            regp->Graphics[5] = 0x40;
1309    }
1310    regp->Graphics[6] = 0x05;   /* only map 64k VGA memory !!!! */
1311    regp->Graphics[7] = 0x0F;
1312    regp->Graphics[8] = 0xFF;
1313
1314    if (depth == 1) {
1315        /* Initialise the Mono map according to which bit-plane gets used */
1316
1317        Bool flipPixels = xf86GetFlipPixels();
1318
1319        for (i = 0; i < 16; i++)
1320            if (((i & (1 << BIT_PLANE)) != 0) != flipPixels)
1321                regp->Attribute[i] = WHITE_VALUE;
1322            else
1323                regp->Attribute[i] = BLACK_VALUE;
1324
1325        regp->Attribute[16] = 0x01;     /* -VGA2- *//* wrong for the ET4000 */
1326        if (!hwp->ShowOverscan)
1327            regp->Attribute[OVERSCAN] = OVERSCAN_VALUE; /* -VGA2- */
1328    }
1329    else {
1330        regp->Attribute[0] = 0x00;      /* standard colormap translation */
1331        regp->Attribute[1] = 0x01;
1332        regp->Attribute[2] = 0x02;
1333        regp->Attribute[3] = 0x03;
1334        regp->Attribute[4] = 0x04;
1335        regp->Attribute[5] = 0x05;
1336        regp->Attribute[6] = 0x06;
1337        regp->Attribute[7] = 0x07;
1338        regp->Attribute[8] = 0x08;
1339        regp->Attribute[9] = 0x09;
1340        regp->Attribute[10] = 0x0A;
1341        regp->Attribute[11] = 0x0B;
1342        regp->Attribute[12] = 0x0C;
1343        regp->Attribute[13] = 0x0D;
1344        regp->Attribute[14] = 0x0E;
1345        regp->Attribute[15] = 0x0F;
1346        if (depth == 4)
1347            regp->Attribute[16] = 0x81; /* wrong for the ET4000 */
1348        else
1349            regp->Attribute[16] = 0x41; /* wrong for the ET4000 */
1350        /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */
1351    }
1352    regp->Attribute[18] = 0x0F;
1353    regp->Attribute[19] = 0x00;
1354    regp->Attribute[20] = 0x00;
1355
1356    return TRUE;
1357}
1358
1359    /*
1360     * OK, so much for theory.  Now, let's deal with the >real< world...
1361     *
1362     * The above CRTC settings are precise in theory, except that many, if not
1363     * most, VGA clones fail to reset the blanking signal when the character or
1364     * line counter reaches [HV]Total.  In this case, the signal is only
1365     * unblanked when the counter reaches [HV]BlankEnd (mod 64, 128 or 256 as
1366     * the case may be) at the start of the >next< scanline or frame, which
1367     * means only part of the screen shows.  This affects how null overscans
1368     * are to be implemented on such adapters.
1369     *
1370     * Henceforth, VGA cores that implement this broken, but unfortunately
1371     * common, behaviour are to be designated as KGA's, in honour of Koen
1372     * Gadeyne, whose zeal to eliminate overscans (read: fury) set in motion
1373     * a series of events that led to the discovery of this problem.
1374     *
1375     * Some VGA's are KGA's only in the horizontal, or only in the vertical,
1376     * some in both, others in neither.  Don't let anyone tell you there is
1377     * such a thing as a VGA "standard"...  And, thank the Creator for the fact
1378     * that Hilbert spaces are not yet implemented in this industry.
1379     *
1380     * The following implements a trick suggested by David Dawes.  This sets
1381     * [HV]BlankEnd to zero if the blanking interval does not already contain a
1382     * 0-point, and decrements it by one otherwise.  In the latter case, this
1383     * will produce a left and/or top overscan which the colourmap code will
1384     * (still) need to ensure is as close to black as possible.  This will make
1385     * the behaviour consistent across all chipsets, while allowing all
1386     * chipsets to display the entire screen.  Non-KGA drivers can ignore the
1387     * following in their own copy of this code.
1388     *
1389     * --  TSI @ UQV,  1998.08.21
1390     */
1391
1392CARD32
1393vgaHWHBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1394               unsigned int Flags)
1395{
1396    int nExtBits = (nBits < 6) ? 0 : nBits - 6;
1397    CARD32 ExtBits;
1398    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6;
1399
1400    regp->CRTC[3] = (regp->CRTC[3] & ~0x1F)
1401        | (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F);
1402    regp->CRTC[5] = (regp->CRTC[5] & ~0x80)
1403        | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2);
1404    ExtBits = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask;
1405
1406    /* First the horizontal case */
1407    if ((Flags & KGA_FIX_OVERSCAN)
1408        && ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3))) {
1409        int i = (regp->CRTC[3] & 0x1F)
1410            | ((regp->CRTC[5] & 0x80) >> 2)
1411            | ExtBits;
1412
1413        if (Flags & KGA_ENABLE_ON_ZERO) {
1414            if ((i-- > (((mode->CrtcHBlankStart >> 3) - 1)
1415                        & (0x3F | ExtBitMask)))
1416                && (mode->CrtcHBlankEnd == mode->CrtcHTotal))
1417                i = 0;
1418        }
1419        else if (Flags & KGA_BE_TOT_DEC)
1420            i--;
1421        regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F);
1422        regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80);
1423        ExtBits = i & ExtBitMask;
1424    }
1425    return ExtBits >> 6;
1426}
1427
1428    /*
1429     * The vertical case is a little trickier.  Some VGA's ignore bit 0x80 of
1430     * CRTC[22].  Also, in some cases, a zero CRTC[22] will still blank the
1431     * very first scanline in a double- or multi-scanned mode.  This last case
1432     * needs further investigation.
1433     */
1434CARD32
1435vgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1436               unsigned int Flags)
1437{
1438    CARD32 ExtBits;
1439    CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8);
1440    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8;
1441
1442    /* If width is not known nBits should be 0. In this
1443     * case BitMask is set to 0 so we can check for it. */
1444    CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1);
1445    int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF;
1446
1447    regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1448    ExtBits = (mode->CrtcVBlankEnd - 1) & ExtBitMask;
1449
1450    if ((Flags & KGA_FIX_OVERSCAN)
1451        && (mode->CrtcVBlankEnd == mode->CrtcVTotal))
1452        /* Null top overscan */
1453    {
1454        int i = regp->CRTC[22] | ExtBits;
1455
1456        if (Flags & KGA_ENABLE_ON_ZERO) {
1457            if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask)))
1458                 || ((i > VBlankStart) &&       /* 8-bit case */
1459                     ((i & 0x7F) > (VBlankStart & 0x7F)))) &&   /* 7-bit case */
1460                !(regp->CRTC[9] & 0x9F))        /* 1 scanline/row */
1461                i = 0;
1462            else
1463                i = (i - 1);
1464        }
1465        else if (Flags & KGA_BE_TOT_DEC)
1466            i = (i - 1);
1467
1468        regp->CRTC[22] = i & 0xFF;
1469        ExtBits = i & 0xFF00;
1470    }
1471    return ExtBits >> 8;
1472}
1473
1474/*
1475 * these are some more hardware specific helpers, formerly in vga.c
1476 */
1477static void
1478vgaHWGetHWRecPrivate(void)
1479{
1480    if (vgaHWPrivateIndex < 0)
1481        vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
1482    return;
1483}
1484
1485static void
1486vgaHWFreeRegs(vgaRegPtr regp)
1487{
1488    free(regp->CRTC);
1489
1490    regp->CRTC = regp->Sequencer = regp->Graphics = regp->Attribute = NULL;
1491
1492    regp->numCRTC =
1493        regp->numSequencer = regp->numGraphics = regp->numAttribute = 0;
1494}
1495
1496static Bool
1497vgaHWAllocRegs(vgaRegPtr regp)
1498{
1499    unsigned char *buf;
1500
1501    if ((regp->numCRTC + regp->numSequencer + regp->numGraphics +
1502         regp->numAttribute) == 0)
1503        return FALSE;
1504
1505    buf = calloc(regp->numCRTC +
1506                 regp->numSequencer +
1507                 regp->numGraphics + regp->numAttribute, 1);
1508    if (!buf)
1509        return FALSE;
1510
1511    regp->CRTC = buf;
1512    regp->Sequencer = regp->CRTC + regp->numCRTC;
1513    regp->Graphics = regp->Sequencer + regp->numSequencer;
1514    regp->Attribute = regp->Graphics + regp->numGraphics;
1515
1516    return TRUE;
1517}
1518
1519Bool
1520vgaHWAllocDefaultRegs(vgaRegPtr regp)
1521{
1522    regp->numCRTC = VGA_NUM_CRTC;
1523    regp->numSequencer = VGA_NUM_SEQ;
1524    regp->numGraphics = VGA_NUM_GFX;
1525    regp->numAttribute = VGA_NUM_ATTR;
1526
1527    return vgaHWAllocRegs(regp);
1528}
1529
1530Bool
1531vgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer,
1532                  int numGraphics, int numAttribute)
1533{
1534#define VGAHWMINNUM(regtype) \
1535	((newMode.num##regtype < regp->num##regtype) ? \
1536	 (newMode.num##regtype) : (regp->num##regtype))
1537#define VGAHWCOPYREGSET(regtype) \
1538	memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype))
1539
1540    vgaRegRec newMode, newSaved;
1541    vgaRegPtr regp;
1542
1543    regp = &VGAHWPTR(scrp)->ModeReg;
1544    memcpy(&newMode, regp, sizeof(vgaRegRec));
1545
1546    /* allocate space for new registers */
1547
1548    regp = &newMode;
1549    regp->numCRTC = numCRTC;
1550    regp->numSequencer = numSequencer;
1551    regp->numGraphics = numGraphics;
1552    regp->numAttribute = numAttribute;
1553    if (!vgaHWAllocRegs(regp))
1554        return FALSE;
1555
1556    regp = &VGAHWPTR(scrp)->SavedReg;
1557    memcpy(&newSaved, regp, sizeof(vgaRegRec));
1558
1559    regp = &newSaved;
1560    regp->numCRTC = numCRTC;
1561    regp->numSequencer = numSequencer;
1562    regp->numGraphics = numGraphics;
1563    regp->numAttribute = numAttribute;
1564    if (!vgaHWAllocRegs(regp)) {
1565        vgaHWFreeRegs(&newMode);
1566        return FALSE;
1567    }
1568
1569    /* allocations succeeded, copy register data into new space */
1570
1571    regp = &VGAHWPTR(scrp)->ModeReg;
1572    VGAHWCOPYREGSET(CRTC);
1573    VGAHWCOPYREGSET(Sequencer);
1574    VGAHWCOPYREGSET(Graphics);
1575    VGAHWCOPYREGSET(Attribute);
1576
1577    regp = &VGAHWPTR(scrp)->SavedReg;
1578    VGAHWCOPYREGSET(CRTC);
1579    VGAHWCOPYREGSET(Sequencer);
1580    VGAHWCOPYREGSET(Graphics);
1581    VGAHWCOPYREGSET(Attribute);
1582
1583    /* free old register arrays */
1584
1585    regp = &VGAHWPTR(scrp)->ModeReg;
1586    vgaHWFreeRegs(regp);
1587    memcpy(regp, &newMode, sizeof(vgaRegRec));
1588
1589    regp = &VGAHWPTR(scrp)->SavedReg;
1590    vgaHWFreeRegs(regp);
1591    memcpy(regp, &newSaved, sizeof(vgaRegRec));
1592
1593    return TRUE;
1594
1595#undef VGAHWMINNUM
1596#undef VGAHWCOPYREGSET
1597}
1598
1599Bool
1600vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)
1601{
1602    vgaHWFreeRegs(dst);
1603
1604    memcpy(dst, src, sizeof(vgaRegRec));
1605
1606    if (!vgaHWAllocRegs(dst))
1607        return FALSE;
1608
1609    memcpy(dst->CRTC, src->CRTC, src->numCRTC);
1610    memcpy(dst->Sequencer, src->Sequencer, src->numSequencer);
1611    memcpy(dst->Graphics, src->Graphics, src->numGraphics);
1612    memcpy(dst->Attribute, src->Attribute, src->numAttribute);
1613
1614    return TRUE;
1615}
1616
1617Bool
1618vgaHWGetHWRec(ScrnInfoPtr scrp)
1619{
1620    vgaRegPtr regp;
1621    vgaHWPtr hwp;
1622    int i;
1623
1624    /*
1625     * Let's make sure that the private exists and allocate one.
1626     */
1627    vgaHWGetHWRecPrivate();
1628    /*
1629     * New privates are always set to NULL, so we can check if the allocation
1630     * has already been done.
1631     */
1632    if (VGAHWPTR(scrp))
1633        return TRUE;
1634    hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1);
1635    regp = &VGAHWPTR(scrp)->ModeReg;
1636
1637    if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) ||
1638        (!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) {
1639        free(hwp);
1640        return FALSE;
1641    }
1642
1643    if (scrp->bitsPerPixel == 1) {
1644        rgb blackColour = scrp->display->blackColour,
1645            whiteColour = scrp->display->whiteColour;
1646
1647        if (blackColour.red > 0x3F)
1648            blackColour.red = 0x3F;
1649        if (blackColour.green > 0x3F)
1650            blackColour.green = 0x3F;
1651        if (blackColour.blue > 0x3F)
1652            blackColour.blue = 0x3F;
1653
1654        if (whiteColour.red > 0x3F)
1655            whiteColour.red = 0x3F;
1656        if (whiteColour.green > 0x3F)
1657            whiteColour.green = 0x3F;
1658        if (whiteColour.blue > 0x3F)
1659            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++)
1673            regp->DAC[i] = 0x00;
1674        for (i = 3; i < 768; i++)
1675            regp->DAC[i] = 0x3F;
1676        i = BLACK_VALUE * 3;
1677        regp->DAC[i++] = blackColour.red;
1678        regp->DAC[i++] = blackColour.green;
1679        regp->DAC[i] = blackColour.blue;
1680        i = WHITE_VALUE * 3;
1681        regp->DAC[i++] = whiteColour.red;
1682        regp->DAC[i++] = whiteColour.green;
1683        regp->DAC[i] = whiteColour.blue;
1684        i = OVERSCAN_VALUE * 3;
1685        regp->DAC[i++] = 0x00;
1686        regp->DAC[i++] = 0x00;
1687        regp->DAC[i] = 0x00;
1688    }
1689    else {
1690        /* Set all colours to black */
1691        for (i = 0; i < 768; i++)
1692            regp->DAC[i] = 0x00;
1693        /* ... and the overscan */
1694        if (scrp->depth >= 4)
1695            regp->Attribute[OVERSCAN] = 0xFF;
1696    }
1697    if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) {
1698        xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan");
1699        xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n");
1700        regp->DAC[765] = 0x3F;
1701        regp->DAC[766] = 0x00;
1702        regp->DAC[767] = 0x3F;
1703        regp->Attribute[OVERSCAN] = 0xFF;
1704        hwp->ShowOverscan = TRUE;
1705    }
1706    else
1707        hwp->ShowOverscan = FALSE;
1708
1709    hwp->paletteEnabled = FALSE;
1710    hwp->cmapSaved = FALSE;
1711    hwp->MapSize = 0;
1712    hwp->pScrn = scrp;
1713
1714    hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]);
1715
1716    return TRUE;
1717}
1718
1719void
1720vgaHWFreeHWRec(ScrnInfoPtr scrp)
1721{
1722    if (vgaHWPrivateIndex >= 0) {
1723        vgaHWPtr hwp = VGAHWPTR(scrp);
1724
1725        if (!hwp)
1726            return;
1727
1728        pci_device_close_io(hwp->dev, hwp->io);
1729
1730        free(hwp->FontInfo1);
1731        free(hwp->FontInfo2);
1732        free(hwp->TextInfo);
1733
1734        vgaHWFreeRegs(&hwp->ModeReg);
1735        vgaHWFreeRegs(&hwp->SavedReg);
1736
1737        free(hwp);
1738        VGAHWPTRLVAL(scrp) = NULL;
1739    }
1740}
1741
1742Bool
1743vgaHWMapMem(ScrnInfoPtr scrp)
1744{
1745    vgaHWPtr hwp = VGAHWPTR(scrp);
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    pci_device_map_legacy(hwp->dev, hwp->MapPhys, hwp->MapSize,
1764                          PCI_DEV_MAP_FLAG_WRITABLE, &hwp->Base);
1765    return hwp->Base != NULL;
1766}
1767
1768void
1769vgaHWUnmapMem(ScrnInfoPtr scrp)
1770{
1771    vgaHWPtr hwp = VGAHWPTR(scrp);
1772
1773    if (hwp->Base == NULL)
1774        return;
1775
1776    DebugF("Unmapping VGAMem\n");
1777    pci_device_unmap_legacy(hwp->dev, hwp->Base, hwp->MapSize);
1778    hwp->Base = NULL;
1779}
1780
1781int
1782vgaHWGetIndex(void)
1783{
1784    return vgaHWPrivateIndex;
1785}
1786
1787void
1788vgaHWGetIOBase(vgaHWPtr hwp)
1789{
1790    hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ?
1791        VGA_IOBASE_COLOR : VGA_IOBASE_MONO;
1792    xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3,
1793                   "vgaHWGetIOBase: hwp->IOBase is 0x%04x\n", hwp->IOBase);
1794}
1795
1796void
1797vgaHWLock(vgaHWPtr hwp)
1798{
1799    /* Protect CRTC[0-7] */
1800    hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80);
1801}
1802
1803void
1804vgaHWUnlock(vgaHWPtr hwp)
1805{
1806    /* Unprotect CRTC[0-7] */
1807    hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80);
1808}
1809
1810void
1811vgaHWEnable(vgaHWPtr hwp)
1812{
1813    hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01);
1814}
1815
1816void
1817vgaHWDisable(vgaHWPtr hwp)
1818{
1819    hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01);
1820}
1821
1822static void
1823vgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors,
1824                 VisualPtr pVisual)
1825{
1826    vgaHWPtr hwp = VGAHWPTR(pScrn);
1827    int i, index;
1828
1829    for (i = 0; i < numColors; i++) {
1830        index = indices[i];
1831        hwp->writeDacWriteAddr(hwp, index);
1832        DACDelay(hwp);
1833        hwp->writeDacData(hwp, colors[index].red);
1834        DACDelay(hwp);
1835        hwp->writeDacData(hwp, colors[index].green);
1836        DACDelay(hwp);
1837        hwp->writeDacData(hwp, colors[index].blue);
1838        DACDelay(hwp);
1839    }
1840
1841    /* This shouldn't be necessary, but we'll play safe. */
1842    hwp->disablePalette(hwp);
1843}
1844
1845static void
1846vgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan)
1847{
1848    vgaHWPtr hwp = VGAHWPTR(pScrn);
1849
1850    if (overscan < 0 || overscan > 255)
1851        return;
1852
1853    hwp->enablePalette(hwp);
1854    hwp->writeAttr(hwp, OVERSCAN, overscan);
1855
1856#ifdef DEBUGOVERSCAN
1857    {
1858        int ov = hwp->readAttr(hwp, OVERSCAN);
1859        int red, green, blue;
1860
1861        hwp->writeDacReadAddr(hwp, ov);
1862        red = hwp->readDacData(hwp);
1863        green = hwp->readDacData(hwp);
1864        blue = hwp->readDacData(hwp);
1865        ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n",
1866               ov, red, green, blue);
1867    }
1868#endif
1869
1870    hwp->disablePalette(hwp);
1871}
1872
1873Bool
1874vgaHWHandleColormaps(ScreenPtr pScreen)
1875{
1876    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1877
1878    if (pScrn->depth > 1 && pScrn->depth <= 8) {
1879        return xf86HandleColormaps(pScreen, 1 << pScrn->depth,
1880                                   pScrn->rgbBits, vgaHWLoadPalette,
1881                                   pScrn->depth > 4 ? vgaHWSetOverscan : NULL,
1882                                   CMAP_RELOAD_ON_MODE_SWITCH);
1883    }
1884    return TRUE;
1885}
1886
1887/* ----------------------- DDC support ------------------------*/
1888/*
1889 * Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total
1890 * to read out EDID at a faster rate. Allowed maximum is 25kHz with
1891 * 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen
1892 * readback, enable access to cr00-cr07.
1893 */
1894
1895/* vertical timings */
1896#define DISPLAY_END 0x04
1897#define BLANK_START DISPLAY_END
1898#define SYNC_START BLANK_START
1899#define SYNC_END 0x09
1900#define BLANK_END SYNC_END
1901#define V_TOTAL BLANK_END
1902/* this function doesn't have to be reentrant for our purposes */
1903struct _vgaDdcSave {
1904    unsigned char cr03;
1905    unsigned char cr06;
1906    unsigned char cr07;
1907    unsigned char cr09;
1908    unsigned char cr10;
1909    unsigned char cr11;
1910    unsigned char cr12;
1911    unsigned char cr15;
1912    unsigned char cr16;
1913    unsigned char msr;
1914};
1915
1916void
1917vgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed)
1918{
1919    vgaHWPtr hwp = VGAHWPTR(pScrn);
1920    unsigned char tmp;
1921    struct _vgaDdcSave *save;
1922
1923    switch (speed) {
1924    case DDC_FAST:
1925
1926        if (hwp->ddc != NULL)
1927            break;
1928        hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave), 1);
1929        save = (struct _vgaDdcSave *) hwp->ddc;
1930        /* Lightpen register disable - allow access to cr10 & 11; just in case */
1931        save->cr03 = hwp->readCrtc(hwp, 0x03);
1932        hwp->writeCrtc(hwp, 0x03, (save->cr03 | 0x80));
1933        save->cr12 = hwp->readCrtc(hwp, 0x12);
1934        hwp->writeCrtc(hwp, 0x12, DISPLAY_END);
1935        save->cr15 = hwp->readCrtc(hwp, 0x15);
1936        hwp->writeCrtc(hwp, 0x15, BLANK_START);
1937        save->cr10 = hwp->readCrtc(hwp, 0x10);
1938        hwp->writeCrtc(hwp, 0x10, SYNC_START);
1939        save->cr11 = hwp->readCrtc(hwp, 0x11);
1940        /* unprotect group 1 registers; just in case ... */
1941        hwp->writeCrtc(hwp, 0x11, ((save->cr11 & 0x70) | SYNC_END));
1942        save->cr16 = hwp->readCrtc(hwp, 0x16);
1943        hwp->writeCrtc(hwp, 0x16, BLANK_END);
1944        save->cr06 = hwp->readCrtc(hwp, 0x06);
1945        hwp->writeCrtc(hwp, 0x06, V_TOTAL);
1946        /* all values have less than 8 bit - mask out 9th and 10th bits */
1947        save->cr09 = hwp->readCrtc(hwp, 0x09);
1948        hwp->writeCrtc(hwp, 0x09, (save->cr09 & 0xDF));
1949        save->cr07 = hwp->readCrtc(hwp, 0x07);
1950        hwp->writeCrtc(hwp, 0x07, (save->cr07 & 0x10));
1951        /* vsync polarity negative & ensure a 25MHz clock */
1952        save->msr = hwp->readMiscOut(hwp);
1953        hwp->writeMiscOut(hwp, ((save->msr & 0xF3) | 0x80));
1954        break;
1955    case DDC_SLOW:
1956        if (hwp->ddc == NULL)
1957            break;
1958        save = (struct _vgaDdcSave *) hwp->ddc;
1959        hwp->writeMiscOut(hwp, save->msr);
1960        hwp->writeCrtc(hwp, 0x07, save->cr07);
1961        tmp = hwp->readCrtc(hwp, 0x09);
1962        hwp->writeCrtc(hwp, 0x09, ((save->cr09 & 0x20) | (tmp & 0xDF)));
1963        hwp->writeCrtc(hwp, 0x06, save->cr06);
1964        hwp->writeCrtc(hwp, 0x16, save->cr16);
1965        hwp->writeCrtc(hwp, 0x11, save->cr11);
1966        hwp->writeCrtc(hwp, 0x10, save->cr10);
1967        hwp->writeCrtc(hwp, 0x15, save->cr15);
1968        hwp->writeCrtc(hwp, 0x12, save->cr12);
1969        hwp->writeCrtc(hwp, 0x03, save->cr03);
1970        free(save);
1971        hwp->ddc = NULL;
1972        break;
1973    default:
1974        break;
1975    }
1976}
1977
1978DDC1SetSpeedProc
1979vgaHWddc1SetSpeedWeak(void)
1980{
1981    return vgaHWddc1SetSpeed;
1982}
1983
1984SaveScreenProcPtr
1985vgaHWSaveScreenWeak(void)
1986{
1987    return vgaHWSaveScreen;
1988}
1989
1990/*
1991 * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ...
1992 */
1993void
1994xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc) (ScrnInfoPtr, int),
1995              void (*ProtectRegs) (ScrnInfoPtr, Bool),
1996              void (*BlankScreen) (ScrnInfoPtr, Bool),
1997              unsigned long vertsyncreg, int maskval, int knownclkindex,
1998              int knownclkvalue)
1999{
2000    register int status = vertsyncreg;
2001    unsigned long i, cnt, rcnt, sync;
2002    vgaHWPtr hwp = VGAHWPTR(pScrn);
2003
2004    /* First save registers that get written on */
2005    (*ClockFunc) (pScrn, CLK_REG_SAVE);
2006
2007    if (num > MAXCLOCKS)
2008        num = MAXCLOCKS;
2009
2010    for (i = 0; i < num; i++) {
2011        if (ProtectRegs)
2012            (*ProtectRegs) (pScrn, TRUE);
2013        if (!(*ClockFunc) (pScrn, i)) {
2014            pScrn->clock[i] = -1;
2015            continue;
2016        }
2017        if (ProtectRegs)
2018            (*ProtectRegs) (pScrn, FALSE);
2019        if (BlankScreen)
2020            (*BlankScreen) (pScrn, FALSE);
2021
2022        usleep(50000);          /* let VCO stabilise */
2023
2024        cnt = 0;
2025        sync = 200000;
2026
2027        while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
2028            if (sync-- == 0)
2029                goto finish;
2030        /* Something appears to be happening, so reset sync count */
2031        sync = 200000;
2032        while ((pci_io_read8(hwp->io, status) & maskval) == maskval)
2033            if (sync-- == 0)
2034                goto finish;
2035        /* Something appears to be happening, so reset sync count */
2036        sync = 200000;
2037        while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
2038            if (sync-- == 0)
2039                goto finish;
2040
2041        for (rcnt = 0; rcnt < 5; rcnt++) {
2042            while (!(pci_io_read8(hwp->io, status) & maskval))
2043                cnt++;
2044            while ((pci_io_read8(hwp->io, status) & maskval))
2045                cnt++;
2046        }
2047
2048 finish:
2049        pScrn->clock[i] = cnt ? cnt : -1;
2050        if (BlankScreen)
2051            (*BlankScreen) (pScrn, TRUE);
2052    }
2053
2054    for (i = 0; i < num; i++) {
2055        if (i != knownclkindex) {
2056            if (pScrn->clock[i] == -1) {
2057                pScrn->clock[i] = 0;
2058            }
2059            else {
2060                pScrn->clock[i] = (int) (0.5 +
2061                                         (((float) knownclkvalue) *
2062                                          pScrn->clock[knownclkindex]) /
2063                                         (pScrn->clock[i]));
2064                /* Round to nearest 10KHz */
2065                pScrn->clock[i] += 5;
2066                pScrn->clock[i] /= 10;
2067                pScrn->clock[i] *= 10;
2068            }
2069        }
2070    }
2071
2072    pScrn->clock[knownclkindex] = knownclkvalue;
2073    pScrn->numClocks = num;
2074
2075    /* Restore registers that were written on */
2076    (*ClockFunc) (pScrn, CLK_REG_RESTORE);
2077}
2078