vgaHW.c revision ed6184df
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        for (i = 0; i < 16; i++)
1318            if ((i & (1 << BIT_PLANE)) != 0)
1319                regp->Attribute[i] = WHITE_VALUE;
1320            else
1321                regp->Attribute[i] = BLACK_VALUE;
1322
1323        regp->Attribute[16] = 0x01;     /* -VGA2- *//* wrong for the ET4000 */
1324        if (!hwp->ShowOverscan)
1325            regp->Attribute[OVERSCAN] = OVERSCAN_VALUE; /* -VGA2- */
1326    }
1327    else {
1328        regp->Attribute[0] = 0x00;      /* standard colormap translation */
1329        regp->Attribute[1] = 0x01;
1330        regp->Attribute[2] = 0x02;
1331        regp->Attribute[3] = 0x03;
1332        regp->Attribute[4] = 0x04;
1333        regp->Attribute[5] = 0x05;
1334        regp->Attribute[6] = 0x06;
1335        regp->Attribute[7] = 0x07;
1336        regp->Attribute[8] = 0x08;
1337        regp->Attribute[9] = 0x09;
1338        regp->Attribute[10] = 0x0A;
1339        regp->Attribute[11] = 0x0B;
1340        regp->Attribute[12] = 0x0C;
1341        regp->Attribute[13] = 0x0D;
1342        regp->Attribute[14] = 0x0E;
1343        regp->Attribute[15] = 0x0F;
1344        if (depth == 4)
1345            regp->Attribute[16] = 0x81; /* wrong for the ET4000 */
1346        else
1347            regp->Attribute[16] = 0x41; /* wrong for the ET4000 */
1348        /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */
1349    }
1350    regp->Attribute[18] = 0x0F;
1351    regp->Attribute[19] = 0x00;
1352    regp->Attribute[20] = 0x00;
1353
1354    return TRUE;
1355}
1356
1357    /*
1358     * OK, so much for theory.  Now, let's deal with the >real< world...
1359     *
1360     * The above CRTC settings are precise in theory, except that many, if not
1361     * most, VGA clones fail to reset the blanking signal when the character or
1362     * line counter reaches [HV]Total.  In this case, the signal is only
1363     * unblanked when the counter reaches [HV]BlankEnd (mod 64, 128 or 256 as
1364     * the case may be) at the start of the >next< scanline or frame, which
1365     * means only part of the screen shows.  This affects how null overscans
1366     * are to be implemented on such adapters.
1367     *
1368     * Henceforth, VGA cores that implement this broken, but unfortunately
1369     * common, behaviour are to be designated as KGA's, in honour of Koen
1370     * Gadeyne, whose zeal to eliminate overscans (read: fury) set in motion
1371     * a series of events that led to the discovery of this problem.
1372     *
1373     * Some VGA's are KGA's only in the horizontal, or only in the vertical,
1374     * some in both, others in neither.  Don't let anyone tell you there is
1375     * such a thing as a VGA "standard"...  And, thank the Creator for the fact
1376     * that Hilbert spaces are not yet implemented in this industry.
1377     *
1378     * The following implements a trick suggested by David Dawes.  This sets
1379     * [HV]BlankEnd to zero if the blanking interval does not already contain a
1380     * 0-point, and decrements it by one otherwise.  In the latter case, this
1381     * will produce a left and/or top overscan which the colourmap code will
1382     * (still) need to ensure is as close to black as possible.  This will make
1383     * the behaviour consistent across all chipsets, while allowing all
1384     * chipsets to display the entire screen.  Non-KGA drivers can ignore the
1385     * following in their own copy of this code.
1386     *
1387     * --  TSI @ UQV,  1998.08.21
1388     */
1389
1390CARD32
1391vgaHWHBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1392               unsigned int Flags)
1393{
1394    int nExtBits = (nBits < 6) ? 0 : nBits - 6;
1395    CARD32 ExtBits;
1396    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6;
1397
1398    regp->CRTC[3] = (regp->CRTC[3] & ~0x1F)
1399        | (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F);
1400    regp->CRTC[5] = (regp->CRTC[5] & ~0x80)
1401        | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2);
1402    ExtBits = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask;
1403
1404    /* First the horizontal case */
1405    if ((Flags & KGA_FIX_OVERSCAN)
1406        && ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3))) {
1407        int i = (regp->CRTC[3] & 0x1F)
1408            | ((regp->CRTC[5] & 0x80) >> 2)
1409            | ExtBits;
1410
1411        if (Flags & KGA_ENABLE_ON_ZERO) {
1412            if ((i-- > (((mode->CrtcHBlankStart >> 3) - 1)
1413                        & (0x3F | ExtBitMask)))
1414                && (mode->CrtcHBlankEnd == mode->CrtcHTotal))
1415                i = 0;
1416        }
1417        else if (Flags & KGA_BE_TOT_DEC)
1418            i--;
1419        regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F);
1420        regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80);
1421        ExtBits = i & ExtBitMask;
1422    }
1423    return ExtBits >> 6;
1424}
1425
1426    /*
1427     * The vertical case is a little trickier.  Some VGA's ignore bit 0x80 of
1428     * CRTC[22].  Also, in some cases, a zero CRTC[22] will still blank the
1429     * very first scanline in a double- or multi-scanned mode.  This last case
1430     * needs further investigation.
1431     */
1432CARD32
1433vgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1434               unsigned int Flags)
1435{
1436    CARD32 ExtBits;
1437    CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8);
1438    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8;
1439
1440    /* If width is not known nBits should be 0. In this
1441     * case BitMask is set to 0 so we can check for it. */
1442    CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1);
1443    int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF;
1444
1445    regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1446    ExtBits = (mode->CrtcVBlankEnd - 1) & ExtBitMask;
1447
1448    if ((Flags & KGA_FIX_OVERSCAN)
1449        && (mode->CrtcVBlankEnd == mode->CrtcVTotal))
1450        /* Null top overscan */
1451    {
1452        int i = regp->CRTC[22] | ExtBits;
1453
1454        if (Flags & KGA_ENABLE_ON_ZERO) {
1455            if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask)))
1456                 || ((i > VBlankStart) &&       /* 8-bit case */
1457                     ((i & 0x7F) > (VBlankStart & 0x7F)))) &&   /* 7-bit case */
1458                !(regp->CRTC[9] & 0x9F))        /* 1 scanline/row */
1459                i = 0;
1460            else
1461                i = (i - 1);
1462        }
1463        else if (Flags & KGA_BE_TOT_DEC)
1464            i = (i - 1);
1465
1466        regp->CRTC[22] = i & 0xFF;
1467        ExtBits = i & 0xFF00;
1468    }
1469    return ExtBits >> 8;
1470}
1471
1472/*
1473 * these are some more hardware specific helpers, formerly in vga.c
1474 */
1475static void
1476vgaHWGetHWRecPrivate(void)
1477{
1478    if (vgaHWPrivateIndex < 0)
1479        vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
1480    return;
1481}
1482
1483static void
1484vgaHWFreeRegs(vgaRegPtr regp)
1485{
1486    free(regp->CRTC);
1487
1488    regp->CRTC = regp->Sequencer = regp->Graphics = regp->Attribute = NULL;
1489
1490    regp->numCRTC =
1491        regp->numSequencer = regp->numGraphics = regp->numAttribute = 0;
1492}
1493
1494static Bool
1495vgaHWAllocRegs(vgaRegPtr regp)
1496{
1497    unsigned char *buf;
1498
1499    if ((regp->numCRTC + regp->numSequencer + regp->numGraphics +
1500         regp->numAttribute) == 0)
1501        return FALSE;
1502
1503    buf = calloc(regp->numCRTC +
1504                 regp->numSequencer +
1505                 regp->numGraphics + regp->numAttribute, 1);
1506    if (!buf)
1507        return FALSE;
1508
1509    regp->CRTC = buf;
1510    regp->Sequencer = regp->CRTC + regp->numCRTC;
1511    regp->Graphics = regp->Sequencer + regp->numSequencer;
1512    regp->Attribute = regp->Graphics + regp->numGraphics;
1513
1514    return TRUE;
1515}
1516
1517Bool
1518vgaHWAllocDefaultRegs(vgaRegPtr regp)
1519{
1520    regp->numCRTC = VGA_NUM_CRTC;
1521    regp->numSequencer = VGA_NUM_SEQ;
1522    regp->numGraphics = VGA_NUM_GFX;
1523    regp->numAttribute = VGA_NUM_ATTR;
1524
1525    return vgaHWAllocRegs(regp);
1526}
1527
1528Bool
1529vgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer,
1530                  int numGraphics, int numAttribute)
1531{
1532#define VGAHWMINNUM(regtype) \
1533	((newMode.num##regtype < regp->num##regtype) ? \
1534	 (newMode.num##regtype) : (regp->num##regtype))
1535#define VGAHWCOPYREGSET(regtype) \
1536	memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype))
1537
1538    vgaRegRec newMode, newSaved;
1539    vgaRegPtr regp;
1540
1541    regp = &VGAHWPTR(scrp)->ModeReg;
1542    memcpy(&newMode, regp, sizeof(vgaRegRec));
1543
1544    /* allocate space for new registers */
1545
1546    regp = &newMode;
1547    regp->numCRTC = numCRTC;
1548    regp->numSequencer = numSequencer;
1549    regp->numGraphics = numGraphics;
1550    regp->numAttribute = numAttribute;
1551    if (!vgaHWAllocRegs(regp))
1552        return FALSE;
1553
1554    regp = &VGAHWPTR(scrp)->SavedReg;
1555    memcpy(&newSaved, regp, sizeof(vgaRegRec));
1556
1557    regp = &newSaved;
1558    regp->numCRTC = numCRTC;
1559    regp->numSequencer = numSequencer;
1560    regp->numGraphics = numGraphics;
1561    regp->numAttribute = numAttribute;
1562    if (!vgaHWAllocRegs(regp)) {
1563        vgaHWFreeRegs(&newMode);
1564        return FALSE;
1565    }
1566
1567    /* allocations succeeded, copy register data into new space */
1568
1569    regp = &VGAHWPTR(scrp)->ModeReg;
1570    VGAHWCOPYREGSET(CRTC);
1571    VGAHWCOPYREGSET(Sequencer);
1572    VGAHWCOPYREGSET(Graphics);
1573    VGAHWCOPYREGSET(Attribute);
1574
1575    regp = &VGAHWPTR(scrp)->SavedReg;
1576    VGAHWCOPYREGSET(CRTC);
1577    VGAHWCOPYREGSET(Sequencer);
1578    VGAHWCOPYREGSET(Graphics);
1579    VGAHWCOPYREGSET(Attribute);
1580
1581    /* free old register arrays */
1582
1583    regp = &VGAHWPTR(scrp)->ModeReg;
1584    vgaHWFreeRegs(regp);
1585    memcpy(regp, &newMode, sizeof(vgaRegRec));
1586
1587    regp = &VGAHWPTR(scrp)->SavedReg;
1588    vgaHWFreeRegs(regp);
1589    memcpy(regp, &newSaved, sizeof(vgaRegRec));
1590
1591    return TRUE;
1592
1593#undef VGAHWMINNUM
1594#undef VGAHWCOPYREGSET
1595}
1596
1597Bool
1598vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)
1599{
1600    vgaHWFreeRegs(dst);
1601
1602    memcpy(dst, src, sizeof(vgaRegRec));
1603
1604    if (!vgaHWAllocRegs(dst))
1605        return FALSE;
1606
1607    memcpy(dst->CRTC, src->CRTC, src->numCRTC);
1608    memcpy(dst->Sequencer, src->Sequencer, src->numSequencer);
1609    memcpy(dst->Graphics, src->Graphics, src->numGraphics);
1610    memcpy(dst->Attribute, src->Attribute, src->numAttribute);
1611
1612    return TRUE;
1613}
1614
1615Bool
1616vgaHWGetHWRec(ScrnInfoPtr scrp)
1617{
1618    vgaRegPtr regp;
1619    vgaHWPtr hwp;
1620    int i;
1621
1622    /*
1623     * Let's make sure that the private exists and allocate one.
1624     */
1625    vgaHWGetHWRecPrivate();
1626    /*
1627     * New privates are always set to NULL, so we can check if the allocation
1628     * has already been done.
1629     */
1630    if (VGAHWPTR(scrp))
1631        return TRUE;
1632    hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1);
1633    regp = &VGAHWPTR(scrp)->ModeReg;
1634
1635    if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) ||
1636        (!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) {
1637        free(hwp);
1638        return FALSE;
1639    }
1640
1641    if (scrp->bitsPerPixel == 1) {
1642        rgb blackColour = scrp->display->blackColour,
1643            whiteColour = scrp->display->whiteColour;
1644
1645        if (blackColour.red > 0x3F)
1646            blackColour.red = 0x3F;
1647        if (blackColour.green > 0x3F)
1648            blackColour.green = 0x3F;
1649        if (blackColour.blue > 0x3F)
1650            blackColour.blue = 0x3F;
1651
1652        if (whiteColour.red > 0x3F)
1653            whiteColour.red = 0x3F;
1654        if (whiteColour.green > 0x3F)
1655            whiteColour.green = 0x3F;
1656        if (whiteColour.blue > 0x3F)
1657            whiteColour.blue = 0x3F;
1658
1659        if ((blackColour.red == whiteColour.red) &&
1660            (blackColour.green == whiteColour.green) &&
1661            (blackColour.blue == whiteColour.blue)) {
1662            blackColour.red ^= 0x3F;
1663            blackColour.green ^= 0x3F;
1664            blackColour.blue ^= 0x3F;
1665        }
1666
1667        /*
1668         * initialize default colormap for monochrome
1669         */
1670        for (i = 0; i < 3; i++)
1671            regp->DAC[i] = 0x00;
1672        for (i = 3; i < 768; i++)
1673            regp->DAC[i] = 0x3F;
1674        i = BLACK_VALUE * 3;
1675        regp->DAC[i++] = blackColour.red;
1676        regp->DAC[i++] = blackColour.green;
1677        regp->DAC[i] = blackColour.blue;
1678        i = WHITE_VALUE * 3;
1679        regp->DAC[i++] = whiteColour.red;
1680        regp->DAC[i++] = whiteColour.green;
1681        regp->DAC[i] = whiteColour.blue;
1682        i = OVERSCAN_VALUE * 3;
1683        regp->DAC[i++] = 0x00;
1684        regp->DAC[i++] = 0x00;
1685        regp->DAC[i] = 0x00;
1686    }
1687    else {
1688        /* Set all colours to black */
1689        for (i = 0; i < 768; i++)
1690            regp->DAC[i] = 0x00;
1691        /* ... and the overscan */
1692        if (scrp->depth >= 4)
1693            regp->Attribute[OVERSCAN] = 0xFF;
1694    }
1695    if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) {
1696        xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan");
1697        xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n");
1698        regp->DAC[765] = 0x3F;
1699        regp->DAC[766] = 0x00;
1700        regp->DAC[767] = 0x3F;
1701        regp->Attribute[OVERSCAN] = 0xFF;
1702        hwp->ShowOverscan = TRUE;
1703    }
1704    else
1705        hwp->ShowOverscan = FALSE;
1706
1707    hwp->paletteEnabled = FALSE;
1708    hwp->cmapSaved = FALSE;
1709    hwp->MapSize = 0;
1710    hwp->pScrn = scrp;
1711
1712    hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]);
1713
1714    return TRUE;
1715}
1716
1717void
1718vgaHWFreeHWRec(ScrnInfoPtr scrp)
1719{
1720    if (vgaHWPrivateIndex >= 0) {
1721        vgaHWPtr hwp = VGAHWPTR(scrp);
1722
1723        if (!hwp)
1724            return;
1725
1726        pci_device_close_io(hwp->dev, hwp->io);
1727
1728        free(hwp->FontInfo1);
1729        free(hwp->FontInfo2);
1730        free(hwp->TextInfo);
1731
1732        vgaHWFreeRegs(&hwp->ModeReg);
1733        vgaHWFreeRegs(&hwp->SavedReg);
1734
1735        free(hwp);
1736        VGAHWPTRLVAL(scrp) = NULL;
1737    }
1738}
1739
1740Bool
1741vgaHWMapMem(ScrnInfoPtr scrp)
1742{
1743    vgaHWPtr hwp = VGAHWPTR(scrp);
1744
1745    if (hwp->Base)
1746        return TRUE;
1747
1748    /* If not set, initialise with the defaults */
1749    if (hwp->MapSize == 0)
1750        hwp->MapSize = VGA_DEFAULT_MEM_SIZE;
1751    if (hwp->MapPhys == 0)
1752        hwp->MapPhys = VGA_DEFAULT_PHYS_ADDR;
1753
1754    /*
1755     * Map as VIDMEM_MMIO_32BIT because WC
1756     * is bad when there is page flipping.
1757     * XXX This is not correct but we do it
1758     * for now.
1759     */
1760    DebugF("Mapping VGAMem\n");
1761    pci_device_map_legacy(hwp->dev, hwp->MapPhys, hwp->MapSize,
1762                          PCI_DEV_MAP_FLAG_WRITABLE, &hwp->Base);
1763    return hwp->Base != NULL;
1764}
1765
1766void
1767vgaHWUnmapMem(ScrnInfoPtr scrp)
1768{
1769    vgaHWPtr hwp = VGAHWPTR(scrp);
1770
1771    if (hwp->Base == NULL)
1772        return;
1773
1774    DebugF("Unmapping VGAMem\n");
1775    pci_device_unmap_legacy(hwp->dev, hwp->Base, hwp->MapSize);
1776    hwp->Base = NULL;
1777}
1778
1779int
1780vgaHWGetIndex(void)
1781{
1782    return vgaHWPrivateIndex;
1783}
1784
1785void
1786vgaHWGetIOBase(vgaHWPtr hwp)
1787{
1788    hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ?
1789        VGA_IOBASE_COLOR : VGA_IOBASE_MONO;
1790    xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3,
1791                   "vgaHWGetIOBase: hwp->IOBase is 0x%04x\n", hwp->IOBase);
1792}
1793
1794void
1795vgaHWLock(vgaHWPtr hwp)
1796{
1797    /* Protect CRTC[0-7] */
1798    hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80);
1799}
1800
1801void
1802vgaHWUnlock(vgaHWPtr hwp)
1803{
1804    /* Unprotect CRTC[0-7] */
1805    hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80);
1806}
1807
1808void
1809vgaHWEnable(vgaHWPtr hwp)
1810{
1811    hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01);
1812}
1813
1814void
1815vgaHWDisable(vgaHWPtr hwp)
1816{
1817    hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01);
1818}
1819
1820static void
1821vgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors,
1822                 VisualPtr pVisual)
1823{
1824    vgaHWPtr hwp = VGAHWPTR(pScrn);
1825    int i, index;
1826
1827    for (i = 0; i < numColors; i++) {
1828        index = indices[i];
1829        hwp->writeDacWriteAddr(hwp, index);
1830        DACDelay(hwp);
1831        hwp->writeDacData(hwp, colors[index].red);
1832        DACDelay(hwp);
1833        hwp->writeDacData(hwp, colors[index].green);
1834        DACDelay(hwp);
1835        hwp->writeDacData(hwp, colors[index].blue);
1836        DACDelay(hwp);
1837    }
1838
1839    /* This shouldn't be necessary, but we'll play safe. */
1840    hwp->disablePalette(hwp);
1841}
1842
1843static void
1844vgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan)
1845{
1846    vgaHWPtr hwp = VGAHWPTR(pScrn);
1847
1848    if (overscan < 0 || overscan > 255)
1849        return;
1850
1851    hwp->enablePalette(hwp);
1852    hwp->writeAttr(hwp, OVERSCAN, overscan);
1853
1854#ifdef DEBUGOVERSCAN
1855    {
1856        int ov = hwp->readAttr(hwp, OVERSCAN);
1857        int red, green, blue;
1858
1859        hwp->writeDacReadAddr(hwp, ov);
1860        red = hwp->readDacData(hwp);
1861        green = hwp->readDacData(hwp);
1862        blue = hwp->readDacData(hwp);
1863        ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n",
1864               ov, red, green, blue);
1865    }
1866#endif
1867
1868    hwp->disablePalette(hwp);
1869}
1870
1871Bool
1872vgaHWHandleColormaps(ScreenPtr pScreen)
1873{
1874    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1875
1876    if (pScrn->depth > 1 && pScrn->depth <= 8) {
1877        return xf86HandleColormaps(pScreen, 1 << pScrn->depth,
1878                                   pScrn->rgbBits, vgaHWLoadPalette,
1879                                   pScrn->depth > 4 ? vgaHWSetOverscan : NULL,
1880                                   CMAP_RELOAD_ON_MODE_SWITCH);
1881    }
1882    return TRUE;
1883}
1884
1885/* ----------------------- DDC support ------------------------*/
1886/*
1887 * Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total
1888 * to read out EDID at a faster rate. Allowed maximum is 25kHz with
1889 * 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen
1890 * readback, enable access to cr00-cr07.
1891 */
1892
1893/* vertical timings */
1894#define DISPLAY_END 0x04
1895#define BLANK_START DISPLAY_END
1896#define SYNC_START BLANK_START
1897#define SYNC_END 0x09
1898#define BLANK_END SYNC_END
1899#define V_TOTAL BLANK_END
1900/* this function doesn't have to be reentrant for our purposes */
1901struct _vgaDdcSave {
1902    unsigned char cr03;
1903    unsigned char cr06;
1904    unsigned char cr07;
1905    unsigned char cr09;
1906    unsigned char cr10;
1907    unsigned char cr11;
1908    unsigned char cr12;
1909    unsigned char cr15;
1910    unsigned char cr16;
1911    unsigned char msr;
1912};
1913
1914void
1915vgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed)
1916{
1917    vgaHWPtr hwp = VGAHWPTR(pScrn);
1918    unsigned char tmp;
1919    struct _vgaDdcSave *save;
1920
1921    switch (speed) {
1922    case DDC_FAST:
1923
1924        if (hwp->ddc != NULL)
1925            break;
1926        hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave), 1);
1927        save = (struct _vgaDdcSave *) hwp->ddc;
1928        /* Lightpen register disable - allow access to cr10 & 11; just in case */
1929        save->cr03 = hwp->readCrtc(hwp, 0x03);
1930        hwp->writeCrtc(hwp, 0x03, (save->cr03 | 0x80));
1931        save->cr12 = hwp->readCrtc(hwp, 0x12);
1932        hwp->writeCrtc(hwp, 0x12, DISPLAY_END);
1933        save->cr15 = hwp->readCrtc(hwp, 0x15);
1934        hwp->writeCrtc(hwp, 0x15, BLANK_START);
1935        save->cr10 = hwp->readCrtc(hwp, 0x10);
1936        hwp->writeCrtc(hwp, 0x10, SYNC_START);
1937        save->cr11 = hwp->readCrtc(hwp, 0x11);
1938        /* unprotect group 1 registers; just in case ... */
1939        hwp->writeCrtc(hwp, 0x11, ((save->cr11 & 0x70) | SYNC_END));
1940        save->cr16 = hwp->readCrtc(hwp, 0x16);
1941        hwp->writeCrtc(hwp, 0x16, BLANK_END);
1942        save->cr06 = hwp->readCrtc(hwp, 0x06);
1943        hwp->writeCrtc(hwp, 0x06, V_TOTAL);
1944        /* all values have less than 8 bit - mask out 9th and 10th bits */
1945        save->cr09 = hwp->readCrtc(hwp, 0x09);
1946        hwp->writeCrtc(hwp, 0x09, (save->cr09 & 0xDF));
1947        save->cr07 = hwp->readCrtc(hwp, 0x07);
1948        hwp->writeCrtc(hwp, 0x07, (save->cr07 & 0x10));
1949        /* vsync polarity negative & ensure a 25MHz clock */
1950        save->msr = hwp->readMiscOut(hwp);
1951        hwp->writeMiscOut(hwp, ((save->msr & 0xF3) | 0x80));
1952        break;
1953    case DDC_SLOW:
1954        if (hwp->ddc == NULL)
1955            break;
1956        save = (struct _vgaDdcSave *) hwp->ddc;
1957        hwp->writeMiscOut(hwp, save->msr);
1958        hwp->writeCrtc(hwp, 0x07, save->cr07);
1959        tmp = hwp->readCrtc(hwp, 0x09);
1960        hwp->writeCrtc(hwp, 0x09, ((save->cr09 & 0x20) | (tmp & 0xDF)));
1961        hwp->writeCrtc(hwp, 0x06, save->cr06);
1962        hwp->writeCrtc(hwp, 0x16, save->cr16);
1963        hwp->writeCrtc(hwp, 0x11, save->cr11);
1964        hwp->writeCrtc(hwp, 0x10, save->cr10);
1965        hwp->writeCrtc(hwp, 0x15, save->cr15);
1966        hwp->writeCrtc(hwp, 0x12, save->cr12);
1967        hwp->writeCrtc(hwp, 0x03, save->cr03);
1968        free(save);
1969        hwp->ddc = NULL;
1970        break;
1971    default:
1972        break;
1973    }
1974}
1975
1976DDC1SetSpeedProc
1977vgaHWddc1SetSpeedWeak(void)
1978{
1979    return vgaHWddc1SetSpeed;
1980}
1981
1982SaveScreenProcPtr
1983vgaHWSaveScreenWeak(void)
1984{
1985    return vgaHWSaveScreen;
1986}
1987
1988/*
1989 * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ...
1990 */
1991void
1992xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc) (ScrnInfoPtr, int),
1993              void (*ProtectRegs) (ScrnInfoPtr, Bool),
1994              void (*BlankScreen) (ScrnInfoPtr, Bool),
1995              unsigned long vertsyncreg, int maskval, int knownclkindex,
1996              int knownclkvalue)
1997{
1998    register int status = vertsyncreg;
1999    unsigned long i, cnt, rcnt, sync;
2000    vgaHWPtr hwp = VGAHWPTR(pScrn);
2001
2002    /* First save registers that get written on */
2003    (*ClockFunc) (pScrn, CLK_REG_SAVE);
2004
2005    if (num > MAXCLOCKS)
2006        num = MAXCLOCKS;
2007
2008    for (i = 0; i < num; i++) {
2009        if (ProtectRegs)
2010            (*ProtectRegs) (pScrn, TRUE);
2011        if (!(*ClockFunc) (pScrn, i)) {
2012            pScrn->clock[i] = -1;
2013            continue;
2014        }
2015        if (ProtectRegs)
2016            (*ProtectRegs) (pScrn, FALSE);
2017        if (BlankScreen)
2018            (*BlankScreen) (pScrn, FALSE);
2019
2020        usleep(50000);          /* let VCO stabilise */
2021
2022        cnt = 0;
2023        sync = 200000;
2024
2025        while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
2026            if (sync-- == 0)
2027                goto finish;
2028        /* Something appears to be happening, so reset sync count */
2029        sync = 200000;
2030        while ((pci_io_read8(hwp->io, status) & maskval) == maskval)
2031            if (sync-- == 0)
2032                goto finish;
2033        /* Something appears to be happening, so reset sync count */
2034        sync = 200000;
2035        while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
2036            if (sync-- == 0)
2037                goto finish;
2038
2039        for (rcnt = 0; rcnt < 5; rcnt++) {
2040            while (!(pci_io_read8(hwp->io, status) & maskval))
2041                cnt++;
2042            while ((pci_io_read8(hwp->io, status) & maskval))
2043                cnt++;
2044        }
2045
2046 finish:
2047        pScrn->clock[i] = cnt ? cnt : -1;
2048        if (BlankScreen)
2049            (*BlankScreen) (pScrn, TRUE);
2050    }
2051
2052    for (i = 0; i < num; i++) {
2053        if (i != knownclkindex) {
2054            if (pScrn->clock[i] == -1) {
2055                pScrn->clock[i] = 0;
2056            }
2057            else {
2058                pScrn->clock[i] = (int) (0.5 +
2059                                         (((float) knownclkvalue) *
2060                                          pScrn->clock[knownclkindex]) /
2061                                         (pScrn->clock[i]));
2062                /* Round to nearest 10KHz */
2063                pScrn->clock[i] += 5;
2064                pScrn->clock[i] /= 10;
2065                pScrn->clock[i] *= 10;
2066            }
2067        }
2068    }
2069
2070    pScrn->clock[knownclkindex] = knownclkvalue;
2071    pScrn->numClocks = num;
2072
2073    /* Restore registers that were written on */
2074    (*ClockFunc) (pScrn, CLK_REG_RESTORE);
2075}
2076