Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / vgahw / vgaHW.c
CommitLineData
a09e091a
JB
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 * Reenable sequencer, then turn on screen.
595 */
596
597 tmp = hwp->readSeq(hwp, 0x01);
598
599 hwp->writeSeq(hwp, 0x01, tmp & ~0x20); /* reenable display */
600 vgaHWSeqReset(hwp, FALSE); /* clear synchronousreset */
601
602 hwp->disablePalette(hwp);
603 }
604 }
605}
606
607vgaHWProtectProc *
608vgaHWProtectWeak(void)
609{
610 return vgaHWProtect;
611}
612
613/*
614 * vgaHWBlankScreen -- blank the screen.
615 */
616
617void
618vgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on)
619{
620 vgaHWPtr hwp = VGAHWPTR(pScrn);
621 unsigned char scrn;
622
623 scrn = hwp->readSeq(hwp, 0x01);
624
625 if (on) {
626 scrn &= ~0x20; /* enable screen */
627 }
628 else {
629 scrn |= 0x20; /* blank screen */
630 }
631
632 vgaHWSeqReset(hwp, TRUE);
633 hwp->writeSeq(hwp, 0x01, scrn); /* change mode */
634 vgaHWSeqReset(hwp, FALSE);
635}
636
637vgaHWBlankScreenProc *
638vgaHWBlankScreenWeak(void)
639{
640 return vgaHWBlankScreen;
641}
642
643/*
644 * vgaHWSaveScreen -- blank the screen.
645 */
646
647Bool
648vgaHWSaveScreen(ScreenPtr pScreen, int mode)
649{
650 ScrnInfoPtr pScrn = NULL;
651 Bool on;
652
653 if (pScreen != NULL)
654 pScrn = xf86ScreenToScrn(pScreen);
655
656 on = xf86IsUnblank(mode);
657
658#if 0
659 if (on)
660 SetTimeSinceLastInputEvent();
661#endif
662
663 if ((pScrn != NULL) && pScrn->vtSema) {
664 vgaHWBlankScreen(pScrn, on);
665 }
666 return TRUE;
667}
668
669/*
670 * vgaHWDPMSSet -- Sets VESA Display Power Management Signaling (DPMS) Mode
671 *
672 * This generic VGA function can only set the Off and On modes. If the
673 * Standby and Suspend modes are to be supported, a chip specific replacement
674 * for this function must be written.
675 */
676
677void
678vgaHWDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
679{
680 unsigned char seq1 = 0, crtc17 = 0;
681 vgaHWPtr hwp = VGAHWPTR(pScrn);
682
683 if (!pScrn->vtSema)
684 return;
685
686 switch (PowerManagementMode) {
687 case DPMSModeOn:
688 /* Screen: On; HSync: On, VSync: On */
689 seq1 = 0x00;
690 crtc17 = 0x80;
691 break;
692 case DPMSModeStandby:
693 /* Screen: Off; HSync: Off, VSync: On -- Not Supported */
694 seq1 = 0x20;
695 crtc17 = 0x80;
696 break;
697 case DPMSModeSuspend:
698 /* Screen: Off; HSync: On, VSync: Off -- Not Supported */
699 seq1 = 0x20;
700 crtc17 = 0x80;
701 break;
702 case DPMSModeOff:
703 /* Screen: Off; HSync: Off, VSync: Off */
704 seq1 = 0x20;
705 crtc17 = 0x00;
706 break;
707 }
708 hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */
709 seq1 |= hwp->readSeq(hwp, 0x01) & ~0x20;
710 hwp->writeSeq(hwp, 0x01, seq1);
711 crtc17 |= hwp->readCrtc(hwp, 0x17) & ~0x80;
712 usleep(10000);
713 hwp->writeCrtc(hwp, 0x17, crtc17);
714 hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */
715}
716
717/*
718 * vgaHWSeqReset
719 * perform a sequencer reset.
720 */
721
722void
723vgaHWSeqReset(vgaHWPtr hwp, Bool start)
724{
725 if (start)
726 hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */
727 else
728 hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */
729}
730
731void
732vgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
733{
734#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
735 vgaHWPtr hwp = VGAHWPTR(scrninfp);
736 int savedIOBase;
737 unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4;
738 Bool doMap = FALSE;
739
740 /* If nothing to do, return now */
741 if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo)
742 return;
743
744 if (hwp->Base == NULL) {
745 doMap = TRUE;
746 if (!vgaHWMapMem(scrninfp)) {
747 xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
748 "vgaHWRestoreFonts: vgaHWMapMem() failed\n");
749 return;
750 }
751 }
752
753 /* save the registers that are needed here */
754 miscOut = hwp->readMiscOut(hwp);
755 attr10 = hwp->readAttr(hwp, 0x10);
756 gr1 = hwp->readGr(hwp, 0x01);
757 gr3 = hwp->readGr(hwp, 0x03);
758 gr4 = hwp->readGr(hwp, 0x04);
759 gr5 = hwp->readGr(hwp, 0x05);
760 gr6 = hwp->readGr(hwp, 0x06);
761 gr8 = hwp->readGr(hwp, 0x08);
762 seq2 = hwp->readSeq(hwp, 0x02);
763 seq4 = hwp->readSeq(hwp, 0x04);
764
765 /* save hwp->IOBase and temporarily set it for colour mode */
766 savedIOBase = hwp->IOBase;
767 hwp->IOBase = VGA_IOBASE_COLOR;
768
769 /* Force into colour mode */
770 hwp->writeMiscOut(hwp, miscOut | 0x01);
771
772 vgaHWBlankScreen(scrninfp, FALSE);
773
774 /*
775 * here we temporarily switch to 16 colour planar mode, to simply
776 * copy the font-info and saved text.
777 *
778 * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
779 */
780#if 0
781 hwp->writeAttr(hwp, 0x10, 0x01); /* graphics mode */
782#endif
783
784 hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */
785 hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */
786 hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */
787
788 if (scrninfp->depth == 4) {
789 /* GJA */
790 hwp->writeGr(hwp, 0x03, 0x00); /* don't rotate, write unmodified */
791 hwp->writeGr(hwp, 0x08, 0xFF); /* write all bits in a byte */
792 hwp->writeGr(hwp, 0x01, 0x00); /* all planes come from CPU */
793 }
794
795#if SAVE_FONT1
796 if (hwp->FontInfo1) {
797 hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */
798 hwp->writeGr(hwp, 0x04, 0x02); /* read plane 2 */
799 slowbcopy_tobus(hwp->FontInfo1, hwp->Base, FONT_AMOUNT);
800 }
801#endif
802
803#if SAVE_FONT2
804 if (hwp->FontInfo2) {
805 hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */
806 hwp->writeGr(hwp, 0x04, 0x03); /* read plane 3 */
807 slowbcopy_tobus(hwp->FontInfo2, hwp->Base, FONT_AMOUNT);
808 }
809#endif
810
811#if SAVE_TEXT
812 if (hwp->TextInfo) {
813 hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */
814 hwp->writeGr(hwp, 0x04, 0x00); /* read plane 0 */
815 slowbcopy_tobus(hwp->TextInfo, hwp->Base, TEXT_AMOUNT);
816 hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */
817 hwp->writeGr(hwp, 0x04, 0x01); /* read plane 1 */
818 slowbcopy_tobus((unsigned char *) hwp->TextInfo + TEXT_AMOUNT,
819 hwp->Base, TEXT_AMOUNT);
820 }
821#endif
822
823 vgaHWBlankScreen(scrninfp, TRUE);
824
825 /* restore the registers that were changed */
826 hwp->writeMiscOut(hwp, miscOut);
827 hwp->writeAttr(hwp, 0x10, attr10);
828 hwp->writeGr(hwp, 0x01, gr1);
829 hwp->writeGr(hwp, 0x03, gr3);
830 hwp->writeGr(hwp, 0x04, gr4);
831 hwp->writeGr(hwp, 0x05, gr5);
832 hwp->writeGr(hwp, 0x06, gr6);
833 hwp->writeGr(hwp, 0x08, gr8);
834 hwp->writeSeq(hwp, 0x02, seq2);
835 hwp->writeSeq(hwp, 0x04, seq4);
836 hwp->IOBase = savedIOBase;
837
838 if (doMap)
839 vgaHWUnmapMem(scrninfp);
840
841#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
842}
843
844void
845vgaHWRestoreMode(ScrnInfoPtr scrninfp, vgaRegPtr restore)
846{
847 vgaHWPtr hwp = VGAHWPTR(scrninfp);
848 int i;
849
850 if (restore->MiscOutReg & 0x01)
851 hwp->IOBase = VGA_IOBASE_COLOR;
852 else
853 hwp->IOBase = VGA_IOBASE_MONO;
854
855 hwp->writeMiscOut(hwp, restore->MiscOutReg);
856
857 for (i = 1; i < restore->numSequencer; i++)
858 hwp->writeSeq(hwp, i, restore->Sequencer[i]);
859
860 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
861 hwp->writeCrtc(hwp, 17, restore->CRTC[17] & ~0x80);
862
863 for (i = 0; i < restore->numCRTC; i++)
864 hwp->writeCrtc(hwp, i, restore->CRTC[i]);
865
866 for (i = 0; i < restore->numGraphics; i++)
867 hwp->writeGr(hwp, i, restore->Graphics[i]);
868
869 hwp->enablePalette(hwp);
870 for (i = 0; i < restore->numAttribute; i++)
871 hwp->writeAttr(hwp, i, restore->Attribute[i]);
872 hwp->disablePalette(hwp);
873}
874
875void
876vgaHWRestoreColormap(ScrnInfoPtr scrninfp, vgaRegPtr restore)
877{
878 vgaHWPtr hwp = VGAHWPTR(scrninfp);
879 int i;
880
881#if 0
882 hwp->enablePalette(hwp);
883#endif
884
885 hwp->writeDacMask(hwp, 0xFF);
886 hwp->writeDacWriteAddr(hwp, 0x00);
887 for (i = 0; i < 768; i++) {
888 hwp->writeDacData(hwp, restore->DAC[i]);
889 DACDelay(hwp);
890 }
891
892 hwp->disablePalette(hwp);
893}
894
895/*
896 * vgaHWRestore --
897 * restore the VGA state
898 */
899
900void
901vgaHWRestore(ScrnInfoPtr scrninfp, vgaRegPtr restore, int flags)
902{
903 if (flags & VGA_SR_MODE)
904 vgaHWRestoreMode(scrninfp, restore);
905
906 if (flags & VGA_SR_FONTS)
907 vgaHWRestoreFonts(scrninfp, restore);
908
909 if (flags & VGA_SR_CMAP)
910 vgaHWRestoreColormap(scrninfp, restore);
911}
912
913void
914vgaHWSaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save)
915{
916#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
917 vgaHWPtr hwp = VGAHWPTR(scrninfp);
918 int savedIOBase;
919 unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4;
920 Bool doMap = FALSE;
921
922 if (hwp->Base == NULL) {
923 doMap = TRUE;
924 if (!vgaHWMapMem(scrninfp)) {
925 xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
926 "vgaHWSaveFonts: vgaHWMapMem() failed\n");
927 return;
928 }
929 }
930
931 /* If in graphics mode, don't save anything */
932 attr10 = hwp->readAttr(hwp, 0x10);
933 if (attr10 & 0x01)
934 return;
935
936 /* save the registers that are needed here */
937 miscOut = hwp->readMiscOut(hwp);
938 gr4 = hwp->readGr(hwp, 0x04);
939 gr5 = hwp->readGr(hwp, 0x05);
940 gr6 = hwp->readGr(hwp, 0x06);
941 seq2 = hwp->readSeq(hwp, 0x02);
942 seq4 = hwp->readSeq(hwp, 0x04);
943
944 /* save hwp->IOBase and temporarily set it for colour mode */
945 savedIOBase = hwp->IOBase;
946 hwp->IOBase = VGA_IOBASE_COLOR;
947
948 /* Force into colour mode */
949 hwp->writeMiscOut(hwp, miscOut | 0x01);
950
951 vgaHWBlankScreen(scrninfp, FALSE);
952
953 /*
954 * get the character sets, and text screen if required
955 */
956 /*
957 * Here we temporarily switch to 16 colour planar mode, to simply
958 * copy the font-info
959 *
960 * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
961 */
962#if 0
963 hwp->writeAttr(hwp, 0x10, 0x01); /* graphics mode */
964#endif
965
966 hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */
967 hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */
968 hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */
969
970#if SAVE_FONT1
971 if (hwp->FontInfo1 || (hwp->FontInfo1 = malloc(FONT_AMOUNT))) {
972 hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */
973 hwp->writeGr(hwp, 0x04, 0x02); /* read plane 2 */
974 slowbcopy_frombus(hwp->Base, hwp->FontInfo1, FONT_AMOUNT);
975 }
976#endif /* SAVE_FONT1 */
977#if SAVE_FONT2
978 if (hwp->FontInfo2 || (hwp->FontInfo2 = malloc(FONT_AMOUNT))) {
979 hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */
980 hwp->writeGr(hwp, 0x04, 0x03); /* read plane 3 */
981 slowbcopy_frombus(hwp->Base, hwp->FontInfo2, FONT_AMOUNT);
982 }
983#endif /* SAVE_FONT2 */
984#if SAVE_TEXT
985 if (hwp->TextInfo || (hwp->TextInfo = malloc(2 * TEXT_AMOUNT))) {
986 hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */
987 hwp->writeGr(hwp, 0x04, 0x00); /* read plane 0 */
988 slowbcopy_frombus(hwp->Base, hwp->TextInfo, TEXT_AMOUNT);
989 hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */
990 hwp->writeGr(hwp, 0x04, 0x01); /* read plane 1 */
991 slowbcopy_frombus(hwp->Base,
992 (unsigned char *) hwp->TextInfo + TEXT_AMOUNT,
993 TEXT_AMOUNT);
994 }
995#endif /* SAVE_TEXT */
996
997 /* Restore clobbered registers */
998 hwp->writeAttr(hwp, 0x10, attr10);
999 hwp->writeSeq(hwp, 0x02, seq2);
1000 hwp->writeSeq(hwp, 0x04, seq4);
1001 hwp->writeGr(hwp, 0x04, gr4);
1002 hwp->writeGr(hwp, 0x05, gr5);
1003 hwp->writeGr(hwp, 0x06, gr6);
1004 hwp->writeMiscOut(hwp, miscOut);
1005 hwp->IOBase = savedIOBase;
1006
1007 vgaHWBlankScreen(scrninfp, TRUE);
1008
1009 if (doMap)
1010 vgaHWUnmapMem(scrninfp);
1011
1012#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
1013}
1014
1015void
1016vgaHWSaveMode(ScrnInfoPtr scrninfp, vgaRegPtr save)
1017{
1018 vgaHWPtr hwp = VGAHWPTR(scrninfp);
1019 int i;
1020
1021 save->MiscOutReg = hwp->readMiscOut(hwp);
1022 if (save->MiscOutReg & 0x01)
1023 hwp->IOBase = VGA_IOBASE_COLOR;
1024 else
1025 hwp->IOBase = VGA_IOBASE_MONO;
1026
1027 for (i = 0; i < save->numCRTC; i++) {
1028 save->CRTC[i] = hwp->readCrtc(hwp, i);
1029 DebugF("CRTC[0x%02x] = 0x%02x\n", i, save->CRTC[i]);
1030 }
1031
1032 hwp->enablePalette(hwp);
1033 for (i = 0; i < save->numAttribute; i++) {
1034 save->Attribute[i] = hwp->readAttr(hwp, i);
1035 DebugF("Attribute[0x%02x] = 0x%02x\n", i, save->Attribute[i]);
1036 }
1037 hwp->disablePalette(hwp);
1038
1039 for (i = 0; i < save->numGraphics; i++) {
1040 save->Graphics[i] = hwp->readGr(hwp, i);
1041 DebugF("Graphics[0x%02x] = 0x%02x\n", i, save->Graphics[i]);
1042 }
1043
1044 for (i = 1; i < save->numSequencer; i++) {
1045 save->Sequencer[i] = hwp->readSeq(hwp, i);
1046 DebugF("Sequencer[0x%02x] = 0x%02x\n", i, save->Sequencer[i]);
1047 }
1048}
1049
1050void
1051vgaHWSaveColormap(ScrnInfoPtr scrninfp, vgaRegPtr save)
1052{
1053 vgaHWPtr hwp = VGAHWPTR(scrninfp);
1054 Bool readError = FALSE;
1055 int i;
1056
1057#ifdef NEED_SAVED_CMAP
1058 /*
1059 * Some ET4000 chips from 1991 have a HW bug that prevents the reading
1060 * of the color lookup table. Mask rev 9042EAI is known to have this bug.
1061 *
1062 * If the colourmap is not readable, we set the saved map to a default
1063 * map (taken from Ferraro's "Programmer's Guide to the EGA and VGA
1064 * Cards" 2nd ed).
1065 */
1066
1067 /* Only save it once */
1068 if (hwp->cmapSaved)
1069 return;
1070
1071#if 0
1072 hwp->enablePalette(hwp);
1073#endif
1074
1075 hwp->writeDacMask(hwp, 0xFF);
1076
1077 /*
1078 * check if we can read the lookup table
1079 */
1080 hwp->writeDacReadAddr(hwp, 0x00);
1081 for (i = 0; i < 6; i++) {
1082 save->DAC[i] = hwp->readDacData(hwp);
1083 switch (i % 3) {
1084 case 0:
1085 DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
1086 break;
1087 case 1:
1088 DebugF("0x%02x, ", save->DAC[i]);
1089 break;
1090 case 2:
1091 DebugF("0x%02x\n", save->DAC[i]);
1092 }
1093 }
1094
1095 /*
1096 * Check if we can read the palette -
1097 * use foreground color to prevent flashing.
1098 */
1099 hwp->writeDacWriteAddr(hwp, 0x01);
1100 for (i = 3; i < 6; i++)
1101 hwp->writeDacData(hwp, ~save->DAC[i] & DAC_TEST_MASK);
1102 hwp->writeDacReadAddr(hwp, 0x01);
1103 for (i = 3; i < 6; i++) {
1104 if (hwp->readDacData(hwp) != (~save->DAC[i] & DAC_TEST_MASK))
1105 readError = TRUE;
1106 }
1107 hwp->writeDacWriteAddr(hwp, 0x01);
1108 for (i = 3; i < 6; i++)
1109 hwp->writeDacData(hwp, save->DAC[i]);
1110
1111 if (readError) {
1112 /*
1113 * save the default lookup table
1114 */
1115 memmove(save->DAC, defaultDAC, 768);
1116 xf86DrvMsg(scrninfp->scrnIndex, X_WARNING,
1117 "Cannot read colourmap from VGA. Will restore with default\n");
1118 }
1119 else {
1120 /* save the colourmap */
1121 hwp->writeDacReadAddr(hwp, 0x02);
1122 for (i = 6; i < 768; i++) {
1123 save->DAC[i] = hwp->readDacData(hwp);
1124 DACDelay(hwp);
1125 switch (i % 3) {
1126 case 0:
1127 DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
1128 break;
1129 case 1:
1130 DebugF("0x%02x, ", save->DAC[i]);
1131 break;
1132 case 2:
1133 DebugF("0x%02x\n", save->DAC[i]);
1134 }
1135 }
1136 }
1137
1138 hwp->disablePalette(hwp);
1139 hwp->cmapSaved = TRUE;
1140#endif
1141}
1142
1143/*
1144 * vgaHWSave --
1145 * save the current VGA state
1146 */
1147
1148void
1149vgaHWSave(ScrnInfoPtr scrninfp, vgaRegPtr save, int flags)
1150{
1151 if (save == NULL)
1152 return;
1153
1154 if (flags & VGA_SR_CMAP)
1155 vgaHWSaveColormap(scrninfp, save);
1156
1157 if (flags & VGA_SR_MODE)
1158 vgaHWSaveMode(scrninfp, save);
1159
1160 if (flags & VGA_SR_FONTS)
1161 vgaHWSaveFonts(scrninfp, save);
1162}
1163
1164/*
1165 * vgaHWInit --
1166 * Handle the initialization, etc. of a screen.
1167 * Return FALSE on failure.
1168 */
1169
1170Bool
1171vgaHWInit(ScrnInfoPtr scrninfp, DisplayModePtr mode)
1172{
1173 unsigned int i;
1174 vgaHWPtr hwp;
1175 vgaRegPtr regp;
1176 int depth = scrninfp->depth;
1177
1178 /*
1179 * make sure the vgaHWRec is allocated
1180 */
1181 if (!vgaHWGetHWRec(scrninfp))
1182 return FALSE;
1183 hwp = VGAHWPTR(scrninfp);
1184 regp = &hwp->ModeReg;
1185
1186 /*
1187 * compute correct Hsync & Vsync polarity
1188 */
1189 if ((mode->Flags & (V_PHSYNC | V_NHSYNC))
1190 && (mode->Flags & (V_PVSYNC | V_NVSYNC))) {
1191 regp->MiscOutReg = 0x23;
1192 if (mode->Flags & V_NHSYNC)
1193 regp->MiscOutReg |= 0x40;
1194 if (mode->Flags & V_NVSYNC)
1195 regp->MiscOutReg |= 0x80;
1196 }
1197 else {
1198 int VDisplay = mode->VDisplay;
1199
1200 if (mode->Flags & V_DBLSCAN)
1201 VDisplay *= 2;
1202 if (mode->VScan > 1)
1203 VDisplay *= mode->VScan;
1204 if (VDisplay < 400)
1205 regp->MiscOutReg = 0xA3; /* +hsync -vsync */
1206 else if (VDisplay < 480)
1207 regp->MiscOutReg = 0x63; /* -hsync +vsync */
1208 else if (VDisplay < 768)
1209 regp->MiscOutReg = 0xE3; /* -hsync -vsync */
1210 else
1211 regp->MiscOutReg = 0x23; /* +hsync +vsync */
1212 }
1213
1214 regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2;
1215
1216 /*
1217 * Time Sequencer
1218 */
1219 if (depth == 4)
1220 regp->Sequencer[0] = 0x02;
1221 else
1222 regp->Sequencer[0] = 0x00;
1223 if (mode->Flags & V_CLKDIV2)
1224 regp->Sequencer[1] = 0x09;
1225 else
1226 regp->Sequencer[1] = 0x01;
1227 if (depth == 1)
1228 regp->Sequencer[2] = 1 << BIT_PLANE;
1229 else
1230 regp->Sequencer[2] = 0x0F;
1231 regp->Sequencer[3] = 0x00; /* Font select */
1232 if (depth < 8)
1233 regp->Sequencer[4] = 0x06; /* Misc */
1234 else
1235 regp->Sequencer[4] = 0x0E; /* Misc */
1236
1237 /*
1238 * CRTC Controller
1239 */
1240 regp->CRTC[0] = (mode->CrtcHTotal >> 3) - 5;
1241 regp->CRTC[1] = (mode->CrtcHDisplay >> 3) - 1;
1242 regp->CRTC[2] = (mode->CrtcHBlankStart >> 3) - 1;
1243 regp->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
1244 i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F);
1245 if (i < 0x80)
1246 regp->CRTC[3] |= i;
1247 regp->CRTC[4] = (mode->CrtcHSyncStart >> 3);
1248 regp->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
1249 | (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
1250 regp->CRTC[6] = (mode->CrtcVTotal - 2) & 0xFF;
1251 regp->CRTC[7] = (((mode->CrtcVTotal - 2) & 0x100) >> 8)
1252 | (((mode->CrtcVDisplay - 1) & 0x100) >> 7)
1253 | ((mode->CrtcVSyncStart & 0x100) >> 6)
1254 | (((mode->CrtcVBlankStart - 1) & 0x100) >> 5)
1255 | 0x10 | (((mode->CrtcVTotal - 2) & 0x200) >> 4)
1256 | (((mode->CrtcVDisplay - 1) & 0x200) >> 3)
1257 | ((mode->CrtcVSyncStart & 0x200) >> 2);
1258 regp->CRTC[8] = 0x00;
1259 regp->CRTC[9] = (((mode->CrtcVBlankStart - 1) & 0x200) >> 4) | 0x40;
1260 if (mode->Flags & V_DBLSCAN)
1261 regp->CRTC[9] |= 0x80;
1262 if (mode->VScan >= 32)
1263 regp->CRTC[9] |= 0x1F;
1264 else if (mode->VScan > 1)
1265 regp->CRTC[9] |= mode->VScan - 1;
1266 regp->CRTC[10] = 0x00;
1267 regp->CRTC[11] = 0x00;
1268 regp->CRTC[12] = 0x00;
1269 regp->CRTC[13] = 0x00;
1270 regp->CRTC[14] = 0x00;
1271 regp->CRTC[15] = 0x00;
1272 regp->CRTC[16] = mode->CrtcVSyncStart & 0xFF;
1273 regp->CRTC[17] = (mode->CrtcVSyncEnd & 0x0F) | 0x20;
1274 regp->CRTC[18] = (mode->CrtcVDisplay - 1) & 0xFF;
1275 regp->CRTC[19] = scrninfp->displayWidth >> 4; /* just a guess */
1276 regp->CRTC[20] = 0x00;
1277 regp->CRTC[21] = (mode->CrtcVBlankStart - 1) & 0xFF;
1278 regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1279 if (depth < 8)
1280 regp->CRTC[23] = 0xE3;
1281 else
1282 regp->CRTC[23] = 0xC3;
1283 regp->CRTC[24] = 0xFF;
1284
1285 vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
1286 vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
1287
1288 /*
1289 * Theory resumes here....
1290 */
1291
1292 /*
1293 * Graphics Display Controller
1294 */
1295 regp->Graphics[0] = 0x00;
1296 regp->Graphics[1] = 0x00;
1297 regp->Graphics[2] = 0x00;
1298 regp->Graphics[3] = 0x00;
1299 if (depth == 1) {
1300 regp->Graphics[4] = BIT_PLANE;
1301 regp->Graphics[5] = 0x00;
1302 }
1303 else {
1304 regp->Graphics[4] = 0x00;
1305 if (depth == 4)
1306 regp->Graphics[5] = 0x02;
1307 else
1308 regp->Graphics[5] = 0x40;
1309 }
1310 regp->Graphics[6] = 0x05; /* only map 64k VGA memory !!!! */
1311 regp->Graphics[7] = 0x0F;
1312 regp->Graphics[8] = 0xFF;
1313
1314 if (depth == 1) {
1315 /* Initialise the Mono map according to which bit-plane gets used */
1316
1317 Bool flipPixels = xf86GetFlipPixels();
1318
1319 for (i = 0; i < 16; i++)
1320 if (((i & (1 << BIT_PLANE)) != 0) != flipPixels)
1321 regp->Attribute[i] = WHITE_VALUE;
1322 else
1323 regp->Attribute[i] = BLACK_VALUE;
1324
1325 regp->Attribute[16] = 0x01; /* -VGA2- *//* wrong for the ET4000 */
1326 if (!hwp->ShowOverscan)
1327 regp->Attribute[OVERSCAN] = OVERSCAN_VALUE; /* -VGA2- */
1328 }
1329 else {
1330 regp->Attribute[0] = 0x00; /* standard colormap translation */
1331 regp->Attribute[1] = 0x01;
1332 regp->Attribute[2] = 0x02;
1333 regp->Attribute[3] = 0x03;
1334 regp->Attribute[4] = 0x04;
1335 regp->Attribute[5] = 0x05;
1336 regp->Attribute[6] = 0x06;
1337 regp->Attribute[7] = 0x07;
1338 regp->Attribute[8] = 0x08;
1339 regp->Attribute[9] = 0x09;
1340 regp->Attribute[10] = 0x0A;
1341 regp->Attribute[11] = 0x0B;
1342 regp->Attribute[12] = 0x0C;
1343 regp->Attribute[13] = 0x0D;
1344 regp->Attribute[14] = 0x0E;
1345 regp->Attribute[15] = 0x0F;
1346 if (depth == 4)
1347 regp->Attribute[16] = 0x81; /* wrong for the ET4000 */
1348 else
1349 regp->Attribute[16] = 0x41; /* wrong for the ET4000 */
1350 /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */
1351 }
1352 regp->Attribute[18] = 0x0F;
1353 regp->Attribute[19] = 0x00;
1354 regp->Attribute[20] = 0x00;
1355
1356 return TRUE;
1357}
1358
1359 /*
1360 * OK, so much for theory. Now, let's deal with the >real< world...
1361 *
1362 * The above CRTC settings are precise in theory, except that many, if not
1363 * most, VGA clones fail to reset the blanking signal when the character or
1364 * line counter reaches [HV]Total. In this case, the signal is only
1365 * unblanked when the counter reaches [HV]BlankEnd (mod 64, 128 or 256 as
1366 * the case may be) at the start of the >next< scanline or frame, which
1367 * means only part of the screen shows. This affects how null overscans
1368 * are to be implemented on such adapters.
1369 *
1370 * Henceforth, VGA cores that implement this broken, but unfortunately
1371 * common, behaviour are to be designated as KGA's, in honour of Koen
1372 * Gadeyne, whose zeal to eliminate overscans (read: fury) set in motion
1373 * a series of events that led to the discovery of this problem.
1374 *
1375 * Some VGA's are KGA's only in the horizontal, or only in the vertical,
1376 * some in both, others in neither. Don't let anyone tell you there is
1377 * such a thing as a VGA "standard"... And, thank the Creator for the fact
1378 * that Hilbert spaces are not yet implemented in this industry.
1379 *
1380 * The following implements a trick suggested by David Dawes. This sets
1381 * [HV]BlankEnd to zero if the blanking interval does not already contain a
1382 * 0-point, and decrements it by one otherwise. In the latter case, this
1383 * will produce a left and/or top overscan which the colourmap code will
1384 * (still) need to ensure is as close to black as possible. This will make
1385 * the behaviour consistent across all chipsets, while allowing all
1386 * chipsets to display the entire screen. Non-KGA drivers can ignore the
1387 * following in their own copy of this code.
1388 *
1389 * -- TSI @ UQV, 1998.08.21
1390 */
1391
1392CARD32
1393vgaHWHBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1394 unsigned int Flags)
1395{
1396 int nExtBits = (nBits < 6) ? 0 : nBits - 6;
1397 CARD32 ExtBits;
1398 CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6;
1399
1400 regp->CRTC[3] = (regp->CRTC[3] & ~0x1F)
1401 | (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F);
1402 regp->CRTC[5] = (regp->CRTC[5] & ~0x80)
1403 | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2);
1404 ExtBits = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask;
1405
1406 /* First the horizontal case */
1407 if ((Flags & KGA_FIX_OVERSCAN)
1408 && ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3))) {
1409 int i = (regp->CRTC[3] & 0x1F)
1410 | ((regp->CRTC[5] & 0x80) >> 2)
1411 | ExtBits;
1412
1413 if (Flags & KGA_ENABLE_ON_ZERO) {
1414 if ((i-- > (((mode->CrtcHBlankStart >> 3) - 1)
1415 & (0x3F | ExtBitMask)))
1416 && (mode->CrtcHBlankEnd == mode->CrtcHTotal))
1417 i = 0;
1418 }
1419 else if (Flags & KGA_BE_TOT_DEC)
1420 i--;
1421 regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F);
1422 regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80);
1423 ExtBits = i & ExtBitMask;
1424 }
1425 return ExtBits >> 6;
1426}
1427
1428 /*
1429 * The vertical case is a little trickier. Some VGA's ignore bit 0x80 of
1430 * CRTC[22]. Also, in some cases, a zero CRTC[22] will still blank the
1431 * very first scanline in a double- or multi-scanned mode. This last case
1432 * needs further investigation.
1433 */
1434CARD32
1435vgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1436 unsigned int Flags)
1437{
1438 CARD32 ExtBits;
1439 CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8);
1440 CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8;
1441
1442 /* If width is not known nBits should be 0. In this
1443 * case BitMask is set to 0 so we can check for it. */
1444 CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1);
1445 int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF;
1446
1447 regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1448 ExtBits = (mode->CrtcVBlankEnd - 1) & ExtBitMask;
1449
1450 if ((Flags & KGA_FIX_OVERSCAN)
1451 && (mode->CrtcVBlankEnd == mode->CrtcVTotal))
1452 /* Null top overscan */
1453 {
1454 int i = regp->CRTC[22] | ExtBits;
1455
1456 if (Flags & KGA_ENABLE_ON_ZERO) {
1457 if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask)))
1458 || ((i > VBlankStart) && /* 8-bit case */
1459 ((i & 0x7F) > (VBlankStart & 0x7F)))) && /* 7-bit case */
1460 !(regp->CRTC[9] & 0x9F)) /* 1 scanline/row */
1461 i = 0;
1462 else
1463 i = (i - 1);
1464 }
1465 else if (Flags & KGA_BE_TOT_DEC)
1466 i = (i - 1);
1467
1468 regp->CRTC[22] = i & 0xFF;
1469 ExtBits = i & 0xFF00;
1470 }
1471 return ExtBits >> 8;
1472}
1473
1474/*
1475 * these are some more hardware specific helpers, formerly in vga.c
1476 */
1477static void
1478vgaHWGetHWRecPrivate(void)
1479{
1480 if (vgaHWPrivateIndex < 0)
1481 vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
1482 return;
1483}
1484
1485static void
1486vgaHWFreeRegs(vgaRegPtr regp)
1487{
1488 free(regp->CRTC);
1489
1490 regp->CRTC = regp->Sequencer = regp->Graphics = regp->Attribute = NULL;
1491
1492 regp->numCRTC =
1493 regp->numSequencer = regp->numGraphics = regp->numAttribute = 0;
1494}
1495
1496static Bool
1497vgaHWAllocRegs(vgaRegPtr regp)
1498{
1499 unsigned char *buf;
1500
1501 if ((regp->numCRTC + regp->numSequencer + regp->numGraphics +
1502 regp->numAttribute) == 0)
1503 return FALSE;
1504
1505 buf = calloc(regp->numCRTC +
1506 regp->numSequencer +
1507 regp->numGraphics + regp->numAttribute, 1);
1508 if (!buf)
1509 return FALSE;
1510
1511 regp->CRTC = buf;
1512 regp->Sequencer = regp->CRTC + regp->numCRTC;
1513 regp->Graphics = regp->Sequencer + regp->numSequencer;
1514 regp->Attribute = regp->Graphics + regp->numGraphics;
1515
1516 return TRUE;
1517}
1518
1519Bool
1520vgaHWAllocDefaultRegs(vgaRegPtr regp)
1521{
1522 regp->numCRTC = VGA_NUM_CRTC;
1523 regp->numSequencer = VGA_NUM_SEQ;
1524 regp->numGraphics = VGA_NUM_GFX;
1525 regp->numAttribute = VGA_NUM_ATTR;
1526
1527 return vgaHWAllocRegs(regp);
1528}
1529
1530Bool
1531vgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer,
1532 int numGraphics, int numAttribute)
1533{
1534#define VGAHWMINNUM(regtype) \
1535 ((newMode.num##regtype < regp->num##regtype) ? \
1536 (newMode.num##regtype) : (regp->num##regtype))
1537#define VGAHWCOPYREGSET(regtype) \
1538 memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype))
1539
1540 vgaRegRec newMode, newSaved;
1541 vgaRegPtr regp;
1542
1543 regp = &VGAHWPTR(scrp)->ModeReg;
1544 memcpy(&newMode, regp, sizeof(vgaRegRec));
1545
1546 /* allocate space for new registers */
1547
1548 regp = &newMode;
1549 regp->numCRTC = numCRTC;
1550 regp->numSequencer = numSequencer;
1551 regp->numGraphics = numGraphics;
1552 regp->numAttribute = numAttribute;
1553 if (!vgaHWAllocRegs(regp))
1554 return FALSE;
1555
1556 regp = &VGAHWPTR(scrp)->SavedReg;
1557 memcpy(&newSaved, regp, sizeof(vgaRegRec));
1558
1559 regp = &newSaved;
1560 regp->numCRTC = numCRTC;
1561 regp->numSequencer = numSequencer;
1562 regp->numGraphics = numGraphics;
1563 regp->numAttribute = numAttribute;
1564 if (!vgaHWAllocRegs(regp)) {
1565 vgaHWFreeRegs(&newMode);
1566 return FALSE;
1567 }
1568
1569 /* allocations succeeded, copy register data into new space */
1570
1571 regp = &VGAHWPTR(scrp)->ModeReg;
1572 VGAHWCOPYREGSET(CRTC);
1573 VGAHWCOPYREGSET(Sequencer);
1574 VGAHWCOPYREGSET(Graphics);
1575 VGAHWCOPYREGSET(Attribute);
1576
1577 regp = &VGAHWPTR(scrp)->SavedReg;
1578 VGAHWCOPYREGSET(CRTC);
1579 VGAHWCOPYREGSET(Sequencer);
1580 VGAHWCOPYREGSET(Graphics);
1581 VGAHWCOPYREGSET(Attribute);
1582
1583 /* free old register arrays */
1584
1585 regp = &VGAHWPTR(scrp)->ModeReg;
1586 vgaHWFreeRegs(regp);
1587 memcpy(regp, &newMode, sizeof(vgaRegRec));
1588
1589 regp = &VGAHWPTR(scrp)->SavedReg;
1590 vgaHWFreeRegs(regp);
1591 memcpy(regp, &newSaved, sizeof(vgaRegRec));
1592
1593 return TRUE;
1594
1595#undef VGAHWMINNUM
1596#undef VGAHWCOPYREGSET
1597}
1598
1599Bool
1600vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)
1601{
1602 vgaHWFreeRegs(dst);
1603
1604 memcpy(dst, src, sizeof(vgaRegRec));
1605
1606 if (!vgaHWAllocRegs(dst))
1607 return FALSE;
1608
1609 memcpy(dst->CRTC, src->CRTC, src->numCRTC);
1610 memcpy(dst->Sequencer, src->Sequencer, src->numSequencer);
1611 memcpy(dst->Graphics, src->Graphics, src->numGraphics);
1612 memcpy(dst->Attribute, src->Attribute, src->numAttribute);
1613
1614 return TRUE;
1615}
1616
1617Bool
1618vgaHWGetHWRec(ScrnInfoPtr scrp)
1619{
1620 vgaRegPtr regp;
1621 vgaHWPtr hwp;
1622 int i;
1623
1624 /*
1625 * Let's make sure that the private exists and allocate one.
1626 */
1627 vgaHWGetHWRecPrivate();
1628 /*
1629 * New privates are always set to NULL, so we can check if the allocation
1630 * has already been done.
1631 */
1632 if (VGAHWPTR(scrp))
1633 return TRUE;
1634 hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1);
1635 regp = &VGAHWPTR(scrp)->ModeReg;
1636
1637 if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) ||
1638 (!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) {
1639 free(hwp);
1640 return FALSE;
1641 }
1642
1643 if (scrp->bitsPerPixel == 1) {
1644 rgb blackColour = scrp->display->blackColour,
1645 whiteColour = scrp->display->whiteColour;
1646
1647 if (blackColour.red > 0x3F)
1648 blackColour.red = 0x3F;
1649 if (blackColour.green > 0x3F)
1650 blackColour.green = 0x3F;
1651 if (blackColour.blue > 0x3F)
1652 blackColour.blue = 0x3F;
1653
1654 if (whiteColour.red > 0x3F)
1655 whiteColour.red = 0x3F;
1656 if (whiteColour.green > 0x3F)
1657 whiteColour.green = 0x3F;
1658 if (whiteColour.blue > 0x3F)
1659 whiteColour.blue = 0x3F;
1660
1661 if ((blackColour.red == whiteColour.red) &&
1662 (blackColour.green == whiteColour.green) &&
1663 (blackColour.blue == whiteColour.blue)) {
1664 blackColour.red ^= 0x3F;
1665 blackColour.green ^= 0x3F;
1666 blackColour.blue ^= 0x3F;
1667 }
1668
1669 /*
1670 * initialize default colormap for monochrome
1671 */
1672 for (i = 0; i < 3; i++)
1673 regp->DAC[i] = 0x00;
1674 for (i = 3; i < 768; i++)
1675 regp->DAC[i] = 0x3F;
1676 i = BLACK_VALUE * 3;
1677 regp->DAC[i++] = blackColour.red;
1678 regp->DAC[i++] = blackColour.green;
1679 regp->DAC[i] = blackColour.blue;
1680 i = WHITE_VALUE * 3;
1681 regp->DAC[i++] = whiteColour.red;
1682 regp->DAC[i++] = whiteColour.green;
1683 regp->DAC[i] = whiteColour.blue;
1684 i = OVERSCAN_VALUE * 3;
1685 regp->DAC[i++] = 0x00;
1686 regp->DAC[i++] = 0x00;
1687 regp->DAC[i] = 0x00;
1688 }
1689 else {
1690 /* Set all colours to black */
1691 for (i = 0; i < 768; i++)
1692 regp->DAC[i] = 0x00;
1693 /* ... and the overscan */
1694 if (scrp->depth >= 4)
1695 regp->Attribute[OVERSCAN] = 0xFF;
1696 }
1697 if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) {
1698 xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan");
1699 xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n");
1700 regp->DAC[765] = 0x3F;
1701 regp->DAC[766] = 0x00;
1702 regp->DAC[767] = 0x3F;
1703 regp->Attribute[OVERSCAN] = 0xFF;
1704 hwp->ShowOverscan = TRUE;
1705 }
1706 else
1707 hwp->ShowOverscan = FALSE;
1708
1709 hwp->paletteEnabled = FALSE;
1710 hwp->cmapSaved = FALSE;
1711 hwp->MapSize = 0;
1712 hwp->pScrn = scrp;
1713
1714 hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]);
1715
1716 return TRUE;
1717}
1718
1719void
1720vgaHWFreeHWRec(ScrnInfoPtr scrp)
1721{
1722 if (vgaHWPrivateIndex >= 0) {
1723 vgaHWPtr hwp = VGAHWPTR(scrp);
1724
1725 if (!hwp)
1726 return;
1727
1728 pci_device_close_io(hwp->dev, hwp->io);
1729
1730 free(hwp->FontInfo1);
1731 free(hwp->FontInfo2);
1732 free(hwp->TextInfo);
1733
1734 vgaHWFreeRegs(&hwp->ModeReg);
1735 vgaHWFreeRegs(&hwp->SavedReg);
1736
1737 free(hwp);
1738 VGAHWPTRLVAL(scrp) = NULL;
1739 }
1740}
1741
1742Bool
1743vgaHWMapMem(ScrnInfoPtr scrp)
1744{
1745 vgaHWPtr hwp = VGAHWPTR(scrp);
1746
1747 if (hwp->Base)
1748 return TRUE;
1749
1750 /* If not set, initialise with the defaults */
1751 if (hwp->MapSize == 0)
1752 hwp->MapSize = VGA_DEFAULT_MEM_SIZE;
1753 if (hwp->MapPhys == 0)
1754 hwp->MapPhys = VGA_DEFAULT_PHYS_ADDR;
1755
1756 /*
1757 * Map as VIDMEM_MMIO_32BIT because WC
1758 * is bad when there is page flipping.
1759 * XXX This is not correct but we do it
1760 * for now.
1761 */
1762 DebugF("Mapping VGAMem\n");
1763 pci_device_map_legacy(hwp->dev, hwp->MapPhys, hwp->MapSize,
1764 PCI_DEV_MAP_FLAG_WRITABLE, &hwp->Base);
1765 return hwp->Base != NULL;
1766}
1767
1768void
1769vgaHWUnmapMem(ScrnInfoPtr scrp)
1770{
1771 vgaHWPtr hwp = VGAHWPTR(scrp);
1772
1773 if (hwp->Base == NULL)
1774 return;
1775
1776 DebugF("Unmapping VGAMem\n");
1777 pci_device_unmap_legacy(hwp->dev, hwp->Base, hwp->MapSize);
1778 hwp->Base = NULL;
1779}
1780
1781int
1782vgaHWGetIndex(void)
1783{
1784 return vgaHWPrivateIndex;
1785}
1786
1787void
1788vgaHWGetIOBase(vgaHWPtr hwp)
1789{
1790 hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ?
1791 VGA_IOBASE_COLOR : VGA_IOBASE_MONO;
1792 xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3,
1793 "vgaHWGetIOBase: hwp->IOBase is 0x%04x\n", hwp->IOBase);
1794}
1795
1796void
1797vgaHWLock(vgaHWPtr hwp)
1798{
1799 /* Protect CRTC[0-7] */
1800 hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80);
1801}
1802
1803void
1804vgaHWUnlock(vgaHWPtr hwp)
1805{
1806 /* Unprotect CRTC[0-7] */
1807 hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80);
1808}
1809
1810void
1811vgaHWEnable(vgaHWPtr hwp)
1812{
1813 hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01);
1814}
1815
1816void
1817vgaHWDisable(vgaHWPtr hwp)
1818{
1819 hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01);
1820}
1821
1822static void
1823vgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors,
1824 VisualPtr pVisual)
1825{
1826 vgaHWPtr hwp = VGAHWPTR(pScrn);
1827 int i, index;
1828
1829 for (i = 0; i < numColors; i++) {
1830 index = indices[i];
1831 hwp->writeDacWriteAddr(hwp, index);
1832 DACDelay(hwp);
1833 hwp->writeDacData(hwp, colors[index].red);
1834 DACDelay(hwp);
1835 hwp->writeDacData(hwp, colors[index].green);
1836 DACDelay(hwp);
1837 hwp->writeDacData(hwp, colors[index].blue);
1838 DACDelay(hwp);
1839 }
1840
1841 /* This shouldn't be necessary, but we'll play safe. */
1842 hwp->disablePalette(hwp);
1843}
1844
1845static void
1846vgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan)
1847{
1848 vgaHWPtr hwp = VGAHWPTR(pScrn);
1849
1850 if (overscan < 0 || overscan > 255)
1851 return;
1852
1853 hwp->enablePalette(hwp);
1854 hwp->writeAttr(hwp, OVERSCAN, overscan);
1855
1856#ifdef DEBUGOVERSCAN
1857 {
1858 int ov = hwp->readAttr(hwp, OVERSCAN);
1859 int red, green, blue;
1860
1861 hwp->writeDacReadAddr(hwp, ov);
1862 red = hwp->readDacData(hwp);
1863 green = hwp->readDacData(hwp);
1864 blue = hwp->readDacData(hwp);
1865 ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n",
1866 ov, red, green, blue);
1867 }
1868#endif
1869
1870 hwp->disablePalette(hwp);
1871}
1872
1873Bool
1874vgaHWHandleColormaps(ScreenPtr pScreen)
1875{
1876 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1877
1878 if (pScrn->depth > 1 && pScrn->depth <= 8) {
1879 return xf86HandleColormaps(pScreen, 1 << pScrn->depth,
1880 pScrn->rgbBits, vgaHWLoadPalette,
1881 pScrn->depth > 4 ? vgaHWSetOverscan : NULL,
1882 CMAP_RELOAD_ON_MODE_SWITCH);
1883 }
1884 return TRUE;
1885}
1886
1887/* ----------------------- DDC support ------------------------*/
1888/*
1889 * Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total
1890 * to read out EDID at a faster rate. Allowed maximum is 25kHz with
1891 * 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen
1892 * readback, enable access to cr00-cr07.
1893 */
1894
1895/* vertical timings */
1896#define DISPLAY_END 0x04
1897#define BLANK_START DISPLAY_END
1898#define SYNC_START BLANK_START
1899#define SYNC_END 0x09
1900#define BLANK_END SYNC_END
1901#define V_TOTAL BLANK_END
1902/* this function doesn't have to be reentrant for our purposes */
1903struct _vgaDdcSave {
1904 unsigned char cr03;
1905 unsigned char cr06;
1906 unsigned char cr07;
1907 unsigned char cr09;
1908 unsigned char cr10;
1909 unsigned char cr11;
1910 unsigned char cr12;
1911 unsigned char cr15;
1912 unsigned char cr16;
1913 unsigned char msr;
1914};
1915
1916void
1917vgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed)
1918{
1919 vgaHWPtr hwp = VGAHWPTR(pScrn);
1920 unsigned char tmp;
1921 struct _vgaDdcSave *save;
1922
1923 switch (speed) {
1924 case DDC_FAST:
1925
1926 if (hwp->ddc != NULL)
1927 break;
1928 hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave), 1);
1929 save = (struct _vgaDdcSave *) hwp->ddc;
1930 /* Lightpen register disable - allow access to cr10 & 11; just in case */
1931 save->cr03 = hwp->readCrtc(hwp, 0x03);
1932 hwp->writeCrtc(hwp, 0x03, (save->cr03 | 0x80));
1933 save->cr12 = hwp->readCrtc(hwp, 0x12);
1934 hwp->writeCrtc(hwp, 0x12, DISPLAY_END);
1935 save->cr15 = hwp->readCrtc(hwp, 0x15);
1936 hwp->writeCrtc(hwp, 0x15, BLANK_START);
1937 save->cr10 = hwp->readCrtc(hwp, 0x10);
1938 hwp->writeCrtc(hwp, 0x10, SYNC_START);
1939 save->cr11 = hwp->readCrtc(hwp, 0x11);
1940 /* unprotect group 1 registers; just in case ... */
1941 hwp->writeCrtc(hwp, 0x11, ((save->cr11 & 0x70) | SYNC_END));
1942 save->cr16 = hwp->readCrtc(hwp, 0x16);
1943 hwp->writeCrtc(hwp, 0x16, BLANK_END);
1944 save->cr06 = hwp->readCrtc(hwp, 0x06);
1945 hwp->writeCrtc(hwp, 0x06, V_TOTAL);
1946 /* all values have less than 8 bit - mask out 9th and 10th bits */
1947 save->cr09 = hwp->readCrtc(hwp, 0x09);
1948 hwp->writeCrtc(hwp, 0x09, (save->cr09 & 0xDF));
1949 save->cr07 = hwp->readCrtc(hwp, 0x07);
1950 hwp->writeCrtc(hwp, 0x07, (save->cr07 & 0x10));
1951 /* vsync polarity 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
1978DDC1SetSpeedProc
1979vgaHWddc1SetSpeedWeak(void)
1980{
1981 return vgaHWddc1SetSpeed;
1982}
1983
1984SaveScreenProcPtr
1985vgaHWSaveScreenWeak(void)
1986{
1987 return vgaHWSaveScreen;
1988}
1989
1990/*
1991 * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ...
1992 */
1993void
1994xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc) (ScrnInfoPtr, int),
1995 void (*ProtectRegs) (ScrnInfoPtr, Bool),
1996 void (*BlankScreen) (ScrnInfoPtr, Bool),
1997 unsigned long vertsyncreg, int maskval, int knownclkindex,
1998 int knownclkvalue)
1999{
2000 register int status = vertsyncreg;
2001 unsigned long i, cnt, rcnt, sync;
2002 vgaHWPtr hwp = VGAHWPTR(pScrn);
2003
2004 /* First save registers that get written on */
2005 (*ClockFunc) (pScrn, CLK_REG_SAVE);
2006
2007 if (num > MAXCLOCKS)
2008 num = MAXCLOCKS;
2009
2010 for (i = 0; i < num; i++) {
2011 if (ProtectRegs)
2012 (*ProtectRegs) (pScrn, TRUE);
2013 if (!(*ClockFunc) (pScrn, i)) {
2014 pScrn->clock[i] = -1;
2015 continue;
2016 }
2017 if (ProtectRegs)
2018 (*ProtectRegs) (pScrn, FALSE);
2019 if (BlankScreen)
2020 (*BlankScreen) (pScrn, FALSE);
2021
2022 usleep(50000); /* let VCO stabilise */
2023
2024 cnt = 0;
2025 sync = 200000;
2026
2027 while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
2028 if (sync-- == 0)
2029 goto finish;
2030 /* Something appears to be happening, so reset sync count */
2031 sync = 200000;
2032 while ((pci_io_read8(hwp->io, status) & maskval) == maskval)
2033 if (sync-- == 0)
2034 goto finish;
2035 /* Something appears to be happening, so reset sync count */
2036 sync = 200000;
2037 while ((pci_io_read8(hwp->io, status) & maskval) == 0x00)
2038 if (sync-- == 0)
2039 goto finish;
2040
2041 for (rcnt = 0; rcnt < 5; rcnt++) {
2042 while (!(pci_io_read8(hwp->io, status) & maskval))
2043 cnt++;
2044 while ((pci_io_read8(hwp->io, status) & maskval))
2045 cnt++;
2046 }
2047
2048 finish:
2049 pScrn->clock[i] = cnt ? cnt : -1;
2050 if (BlankScreen)
2051 (*BlankScreen) (pScrn, TRUE);
2052 }
2053
2054 for (i = 0; i < num; i++) {
2055 if (i != knownclkindex) {
2056 if (pScrn->clock[i] == -1) {
2057 pScrn->clock[i] = 0;
2058 }
2059 else {
2060 pScrn->clock[i] = (int) (0.5 +
2061 (((float) knownclkvalue) *
2062 pScrn->clock[knownclkindex]) /
2063 (pScrn->clock[i]));
2064 /* Round to nearest 10KHz */
2065 pScrn->clock[i] += 5;
2066 pScrn->clock[i] /= 10;
2067 pScrn->clock[i] *= 10;
2068 }
2069 }
2070 }
2071
2072 pScrn->clock[knownclkindex] = knownclkvalue;
2073 pScrn->numClocks = num;
2074
2075 /* Restore registers that were written on */
2076 (*ClockFunc) (pScrn, CLK_REG_RESTORE);
2077}