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 
83 static 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 
90 static 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  */
161 static void
stdWriteCrtc(vgaHWPtr hwp,CARD8 index,CARD8 value)162 stdWriteCrtc(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 
168 static CARD8
stdReadCrtc(vgaHWPtr hwp,CARD8 index)169 stdReadCrtc(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 
175 static void
stdWriteGr(vgaHWPtr hwp,CARD8 index,CARD8 value)176 stdWriteGr(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 
182 static CARD8
stdReadGr(vgaHWPtr hwp,CARD8 index)183 stdReadGr(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 
189 static void
stdWriteSeq(vgaHWPtr hwp,CARD8 index,CARD8 value)190 stdWriteSeq(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 
196 static CARD8
stdReadSeq(vgaHWPtr hwp,CARD8 index)197 stdReadSeq(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 
203 static CARD8
stdReadST00(vgaHWPtr hwp)204 stdReadST00(vgaHWPtr hwp)
205 {
206     return pci_io_read8(hwp->io, VGA_IN_STAT_0);
207 }
208 
209 static CARD8
stdReadST01(vgaHWPtr hwp)210 stdReadST01(vgaHWPtr hwp)
211 {
212     return pci_io_read8(hwp->io, hwp->IOBase + VGA_IN_STAT_1_OFFSET);
213 }
214 
215 static CARD8
stdReadFCR(vgaHWPtr hwp)216 stdReadFCR(vgaHWPtr hwp)
217 {
218     return pci_io_read8(hwp->io, VGA_FEATURE_R);
219 }
220 
221 static void
stdWriteFCR(vgaHWPtr hwp,CARD8 value)222 stdWriteFCR(vgaHWPtr hwp, CARD8 value)
223 {
224     pci_io_write8(hwp->io, hwp->IOBase + VGA_FEATURE_W_OFFSET, value);
225 }
226 
227 static void
stdWriteAttr(vgaHWPtr hwp,CARD8 index,CARD8 value)228 stdWriteAttr(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 
240 static CARD8
stdReadAttr(vgaHWPtr hwp,CARD8 index)241 stdReadAttr(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 
253 static void
stdWriteMiscOut(vgaHWPtr hwp,CARD8 value)254 stdWriteMiscOut(vgaHWPtr hwp, CARD8 value)
255 {
256     pci_io_write8(hwp->io, VGA_MISC_OUT_W, value);
257 }
258 
259 static CARD8
stdReadMiscOut(vgaHWPtr hwp)260 stdReadMiscOut(vgaHWPtr hwp)
261 {
262     return pci_io_read8(hwp->io, VGA_MISC_OUT_R);
263 }
264 
265 static void
stdEnablePalette(vgaHWPtr hwp)266 stdEnablePalette(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 
273 static void
stdDisablePalette(vgaHWPtr hwp)274 stdDisablePalette(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 
281 static void
stdWriteDacMask(vgaHWPtr hwp,CARD8 value)282 stdWriteDacMask(vgaHWPtr hwp, CARD8 value)
283 {
284     pci_io_write8(hwp->io, VGA_DAC_MASK, value);
285 }
286 
287 static CARD8
stdReadDacMask(vgaHWPtr hwp)288 stdReadDacMask(vgaHWPtr hwp)
289 {
290     return pci_io_read8(hwp->io, VGA_DAC_MASK);
291 }
292 
293 static void
stdWriteDacReadAddr(vgaHWPtr hwp,CARD8 value)294 stdWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
295 {
296     pci_io_write8(hwp->io, VGA_DAC_READ_ADDR, value);
297 }
298 
299 static void
stdWriteDacWriteAddr(vgaHWPtr hwp,CARD8 value)300 stdWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
301 {
302     pci_io_write8(hwp->io, VGA_DAC_WRITE_ADDR, value);
303 }
304 
305 static void
stdWriteDacData(vgaHWPtr hwp,CARD8 value)306 stdWriteDacData(vgaHWPtr hwp, CARD8 value)
307 {
308     pci_io_write8(hwp->io, VGA_DAC_DATA, value);
309 }
310 
311 static CARD8
stdReadDacData(vgaHWPtr hwp)312 stdReadDacData(vgaHWPtr hwp)
313 {
314     return pci_io_read8(hwp->io, VGA_DAC_DATA);
315 }
316 
317 static CARD8
stdReadEnable(vgaHWPtr hwp)318 stdReadEnable(vgaHWPtr hwp)
319 {
320     return pci_io_read8(hwp->io, VGA_ENABLE);
321 }
322 
323 static void
stdWriteEnable(vgaHWPtr hwp,CARD8 value)324 stdWriteEnable(vgaHWPtr hwp, CARD8 value)
325 {
326     pci_io_write8(hwp->io, VGA_ENABLE, value);
327 }
328 
329 void
vgaHWSetStdFuncs(vgaHWPtr hwp)330 vgaHWSetStdFuncs(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 
369 static void
mmioWriteCrtc(vgaHWPtr hwp,CARD8 index,CARD8 value)370 mmioWriteCrtc(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 
376 static CARD8
mmioReadCrtc(vgaHWPtr hwp,CARD8 index)377 mmioReadCrtc(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 
383 static void
mmioWriteGr(vgaHWPtr hwp,CARD8 index,CARD8 value)384 mmioWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
385 {
386     moutb(VGA_GRAPH_INDEX, index);
387     moutb(VGA_GRAPH_DATA, value);
388 }
389 
390 static CARD8
mmioReadGr(vgaHWPtr hwp,CARD8 index)391 mmioReadGr(vgaHWPtr hwp, CARD8 index)
392 {
393     moutb(VGA_GRAPH_INDEX, index);
394     return minb(VGA_GRAPH_DATA);
395 }
396 
397 static void
mmioWriteSeq(vgaHWPtr hwp,CARD8 index,CARD8 value)398 mmioWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
399 {
400     moutb(VGA_SEQ_INDEX, index);
401     moutb(VGA_SEQ_DATA, value);
402 }
403 
404 static CARD8
mmioReadSeq(vgaHWPtr hwp,CARD8 index)405 mmioReadSeq(vgaHWPtr hwp, CARD8 index)
406 {
407     moutb(VGA_SEQ_INDEX, index);
408     return minb(VGA_SEQ_DATA);
409 }
410 
411 static CARD8
mmioReadST00(vgaHWPtr hwp)412 mmioReadST00(vgaHWPtr hwp)
413 {
414     return minb(VGA_IN_STAT_0);
415 }
416 
417 static CARD8
mmioReadST01(vgaHWPtr hwp)418 mmioReadST01(vgaHWPtr hwp)
419 {
420     return minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
421 }
422 
423 static CARD8
mmioReadFCR(vgaHWPtr hwp)424 mmioReadFCR(vgaHWPtr hwp)
425 {
426     return minb(VGA_FEATURE_R);
427 }
428 
429 static void
mmioWriteFCR(vgaHWPtr hwp,CARD8 value)430 mmioWriteFCR(vgaHWPtr hwp, CARD8 value)
431 {
432     moutb(hwp->IOBase + VGA_FEATURE_W_OFFSET, value);
433 }
434 
435 static void
mmioWriteAttr(vgaHWPtr hwp,CARD8 index,CARD8 value)436 mmioWriteAttr(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 
448 static CARD8
mmioReadAttr(vgaHWPtr hwp,CARD8 index)449 mmioReadAttr(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 
461 static void
mmioWriteMiscOut(vgaHWPtr hwp,CARD8 value)462 mmioWriteMiscOut(vgaHWPtr hwp, CARD8 value)
463 {
464     moutb(VGA_MISC_OUT_W, value);
465 }
466 
467 static CARD8
mmioReadMiscOut(vgaHWPtr hwp)468 mmioReadMiscOut(vgaHWPtr hwp)
469 {
470     return minb(VGA_MISC_OUT_R);
471 }
472 
473 static void
mmioEnablePalette(vgaHWPtr hwp)474 mmioEnablePalette(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 
481 static void
mmioDisablePalette(vgaHWPtr hwp)482 mmioDisablePalette(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 
489 static void
mmioWriteDacMask(vgaHWPtr hwp,CARD8 value)490 mmioWriteDacMask(vgaHWPtr hwp, CARD8 value)
491 {
492     moutb(VGA_DAC_MASK, value);
493 }
494 
495 static CARD8
mmioReadDacMask(vgaHWPtr hwp)496 mmioReadDacMask(vgaHWPtr hwp)
497 {
498     return minb(VGA_DAC_MASK);
499 }
500 
501 static void
mmioWriteDacReadAddr(vgaHWPtr hwp,CARD8 value)502 mmioWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
503 {
504     moutb(VGA_DAC_READ_ADDR, value);
505 }
506 
507 static void
mmioWriteDacWriteAddr(vgaHWPtr hwp,CARD8 value)508 mmioWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
509 {
510     moutb(VGA_DAC_WRITE_ADDR, value);
511 }
512 
513 static void
mmioWriteDacData(vgaHWPtr hwp,CARD8 value)514 mmioWriteDacData(vgaHWPtr hwp, CARD8 value)
515 {
516     moutb(VGA_DAC_DATA, value);
517 }
518 
519 static CARD8
mmioReadDacData(vgaHWPtr hwp)520 mmioReadDacData(vgaHWPtr hwp)
521 {
522     return minb(VGA_DAC_DATA);
523 }
524 
525 static CARD8
mmioReadEnable(vgaHWPtr hwp)526 mmioReadEnable(vgaHWPtr hwp)
527 {
528     return minb(VGA_ENABLE);
529 }
530 
531 static void
mmioWriteEnable(vgaHWPtr hwp,CARD8 value)532 mmioWriteEnable(vgaHWPtr hwp, CARD8 value)
533 {
534     moutb(VGA_ENABLE, value);
535 }
536 
537 void
vgaHWSetMmioFuncs(vgaHWPtr hwp,CARD8 * base,int offset)538 vgaHWSetMmioFuncs(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 
573 void
vgaHWProtect(ScrnInfoPtr pScrn,Bool on)574 vgaHWProtect(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              * Reenable sequencer, then turn on screen.
595              */
596 
597             tmp = hwp->readSeq(hwp, 0x01);
598 
599             hwp->writeSeq(hwp, 0x01, tmp & ~0x20);      /* reenable display */
600             vgaHWSeqReset(hwp, FALSE);  /* clear synchronousreset */
601 
602             hwp->disablePalette(hwp);
603         }
604     }
605 }
606 
607 vgaHWProtectProc *
vgaHWProtectWeak(void)608 vgaHWProtectWeak(void)
609 {
610     return vgaHWProtect;
611 }
612 
613 /*
614  * vgaHWBlankScreen -- blank the screen.
615  */
616 
617 void
vgaHWBlankScreen(ScrnInfoPtr pScrn,Bool on)618 vgaHWBlankScreen(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 
637 vgaHWBlankScreenProc *
vgaHWBlankScreenWeak(void)638 vgaHWBlankScreenWeak(void)
639 {
640     return vgaHWBlankScreen;
641 }
642 
643 /*
644  * vgaHWSaveScreen -- blank the screen.
645  */
646 
647 Bool
vgaHWSaveScreen(ScreenPtr pScreen,int mode)648 vgaHWSaveScreen(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 
677 void
vgaHWDPMSSet(ScrnInfoPtr pScrn,int PowerManagementMode,int flags)678 vgaHWDPMSSet(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 
722 void
vgaHWSeqReset(vgaHWPtr hwp,Bool start)723 vgaHWSeqReset(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 
731 void
vgaHWRestoreFonts(ScrnInfoPtr scrninfp,vgaRegPtr restore)732 vgaHWRestoreFonts(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 
844 void
vgaHWRestoreMode(ScrnInfoPtr scrninfp,vgaRegPtr restore)845 vgaHWRestoreMode(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 
875 void
vgaHWRestoreColormap(ScrnInfoPtr scrninfp,vgaRegPtr restore)876 vgaHWRestoreColormap(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 
900 void
vgaHWRestore(ScrnInfoPtr scrninfp,vgaRegPtr restore,int flags)901 vgaHWRestore(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 
913 void
vgaHWSaveFonts(ScrnInfoPtr scrninfp,vgaRegPtr save)914 vgaHWSaveFonts(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 
1015 void
vgaHWSaveMode(ScrnInfoPtr scrninfp,vgaRegPtr save)1016 vgaHWSaveMode(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 
1050 void
vgaHWSaveColormap(ScrnInfoPtr scrninfp,vgaRegPtr save)1051 vgaHWSaveColormap(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 
1148 void
vgaHWSave(ScrnInfoPtr scrninfp,vgaRegPtr save,int flags)1149 vgaHWSave(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 
1170 Bool
vgaHWInit(ScrnInfoPtr scrninfp,DisplayModePtr mode)1171 vgaHWInit(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 
1392 CARD32
vgaHWHBlankKGA(DisplayModePtr mode,vgaRegPtr regp,int nBits,unsigned int Flags)1393 vgaHWHBlankKGA(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      */
1434 CARD32
vgaHWVBlankKGA(DisplayModePtr mode,vgaRegPtr regp,int nBits,unsigned int Flags)1435 vgaHWVBlankKGA(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  */
1477 static void
vgaHWGetHWRecPrivate(void)1478 vgaHWGetHWRecPrivate(void)
1479 {
1480     if (vgaHWPrivateIndex < 0)
1481         vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
1482     return;
1483 }
1484 
1485 static void
vgaHWFreeRegs(vgaRegPtr regp)1486 vgaHWFreeRegs(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 
1496 static Bool
vgaHWAllocRegs(vgaRegPtr regp)1497 vgaHWAllocRegs(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 
1519 Bool
vgaHWAllocDefaultRegs(vgaRegPtr regp)1520 vgaHWAllocDefaultRegs(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 
1530 Bool
vgaHWSetRegCounts(ScrnInfoPtr scrp,int numCRTC,int numSequencer,int numGraphics,int numAttribute)1531 vgaHWSetRegCounts(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 
1599 Bool
vgaHWCopyReg(vgaRegPtr dst,vgaRegPtr src)1600 vgaHWCopyReg(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 
1617 Bool
vgaHWGetHWRec(ScrnInfoPtr scrp)1618 vgaHWGetHWRec(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 
1719 void
vgaHWFreeHWRec(ScrnInfoPtr scrp)1720 vgaHWFreeHWRec(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 
1742 Bool
vgaHWMapMem(ScrnInfoPtr scrp)1743 vgaHWMapMem(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 
1768 void
vgaHWUnmapMem(ScrnInfoPtr scrp)1769 vgaHWUnmapMem(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 
1781 int
vgaHWGetIndex(void)1782 vgaHWGetIndex(void)
1783 {
1784     return vgaHWPrivateIndex;
1785 }
1786 
1787 void
vgaHWGetIOBase(vgaHWPtr hwp)1788 vgaHWGetIOBase(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 
1796 void
vgaHWLock(vgaHWPtr hwp)1797 vgaHWLock(vgaHWPtr hwp)
1798 {
1799     /* Protect CRTC[0-7] */
1800     hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80);
1801 }
1802 
1803 void
vgaHWUnlock(vgaHWPtr hwp)1804 vgaHWUnlock(vgaHWPtr hwp)
1805 {
1806     /* Unprotect CRTC[0-7] */
1807     hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80);
1808 }
1809 
1810 void
vgaHWEnable(vgaHWPtr hwp)1811 vgaHWEnable(vgaHWPtr hwp)
1812 {
1813     hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01);
1814 }
1815 
1816 void
vgaHWDisable(vgaHWPtr hwp)1817 vgaHWDisable(vgaHWPtr hwp)
1818 {
1819     hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01);
1820 }
1821 
1822 static void
vgaHWLoadPalette(ScrnInfoPtr pScrn,int numColors,int * indices,LOCO * colors,VisualPtr pVisual)1823 vgaHWLoadPalette(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 
1845 static void
vgaHWSetOverscan(ScrnInfoPtr pScrn,int overscan)1846 vgaHWSetOverscan(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 
1873 Bool
vgaHWHandleColormaps(ScreenPtr pScreen)1874 vgaHWHandleColormaps(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 */
1903 struct _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 
1916 void
vgaHWddc1SetSpeed(ScrnInfoPtr pScrn,xf86ddcSpeed speed)1917 vgaHWddc1SetSpeed(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 negativ & 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 
1978 DDC1SetSpeedProc
vgaHWddc1SetSpeedWeak(void)1979 vgaHWddc1SetSpeedWeak(void)
1980 {
1981     return vgaHWddc1SetSpeed;
1982 }
1983 
1984 SaveScreenProcPtr
vgaHWSaveScreenWeak(void)1985 vgaHWSaveScreenWeak(void)
1986 {
1987     return vgaHWSaveScreen;
1988 }
1989 
1990 /*
1991  * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ...
1992  */
1993 void
xf86GetClocks(ScrnInfoPtr pScrn,int num,Bool (* ClockFunc)(ScrnInfoPtr,int),void (* ProtectRegs)(ScrnInfoPtr,Bool),void (* BlankScreen)(ScrnInfoPtr,Bool),unsigned long vertsyncreg,int maskval,int knownclkindex,int knownclkvalue)1994 xf86GetClocks(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