1706f2543Smrg
2706f2543Smrg/*
3706f2543Smrg *
4706f2543Smrg * Copyright 1991-1999 by The XFree86 Project, Inc.
5706f2543Smrg *
6706f2543Smrg * Loosely based on code bearing the following copyright:
7706f2543Smrg *
8706f2543Smrg *   Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
9706f2543Smrg *
10706f2543Smrg */
11706f2543Smrg
12706f2543Smrg#define _NEED_SYSI86
13706f2543Smrg
14706f2543Smrg#ifdef HAVE_XORG_CONFIG_H
15706f2543Smrg#include <xorg-config.h>
16706f2543Smrg#endif
17706f2543Smrg
18706f2543Smrg#include <stdlib.h>
19706f2543Smrg#include <string.h>
20706f2543Smrg#include <unistd.h>
21706f2543Smrg
22706f2543Smrg#include <X11/X.h>
23706f2543Smrg#include "misc.h"
24706f2543Smrg
25706f2543Smrg#include "xf86.h"
26706f2543Smrg#include "xf86_OSproc.h"
27706f2543Smrg#include "vgaHW.h"
28706f2543Smrg
29706f2543Smrg#include "compiler.h"
30706f2543Smrg
31706f2543Smrg#include "xf86cmap.h"
32706f2543Smrg
33706f2543Smrg#include "Pci.h"
34706f2543Smrg
35706f2543Smrg#ifndef SAVE_FONT1
36706f2543Smrg#define SAVE_FONT1 1
37706f2543Smrg#endif
38706f2543Smrg
39706f2543Smrg/*
40706f2543Smrg * These used to be OS-specific, which made this module have an undesirable
41706f2543Smrg * OS dependency.  Define them by default for all platforms.
42706f2543Smrg */
43706f2543Smrg#ifndef NEED_SAVED_CMAP
44706f2543Smrg#define NEED_SAVED_CMAP
45706f2543Smrg#endif
46706f2543Smrg#ifndef SAVE_TEXT
47706f2543Smrg#define SAVE_TEXT 1
48706f2543Smrg#endif
49706f2543Smrg#ifndef SAVE_FONT2
50706f2543Smrg#define SAVE_FONT2 1
51706f2543Smrg#endif
52706f2543Smrg
53706f2543Smrg/* bytes per plane to save for text */
54706f2543Smrg#define TEXT_AMOUNT 16384
55706f2543Smrg
56706f2543Smrg/* bytes per plane to save for font data */
57706f2543Smrg#define FONT_AMOUNT (8*8192)
58706f2543Smrg
59706f2543Smrg#if 0
60706f2543Smrg/* Override all of these for now */
61706f2543Smrg#undef SAVE_FONT1
62706f2543Smrg#define SAVE_FONT1 1
63706f2543Smrg#undef SAVE_FONT2
64706f2543Smrg#define SAVE_FONT2 1
65706f2543Smrg#undef SAVE_TEST
66706f2543Smrg#define SAVE_TEST 1
67706f2543Smrg#undef FONT_AMOUNT
68706f2543Smrg#define FONT_AMOUNT 65536
69706f2543Smrg#undef TEXT_AMOUNT
70706f2543Smrg#define TEXT_AMOUNT 65536
71706f2543Smrg#endif
72706f2543Smrg
73706f2543Smrg/* DAC indices for white and black */
74706f2543Smrg#define WHITE_VALUE 0x3F
75706f2543Smrg#define BLACK_VALUE 0x00
76706f2543Smrg#define OVERSCAN_VALUE 0x01
77706f2543Smrg
78706f2543Smrg
79706f2543Smrg/* Use a private definition of this here */
80706f2543Smrg#undef VGAHWPTR
81706f2543Smrg#define VGAHWPTRLVAL(p) (p)->privates[vgaHWPrivateIndex].ptr
82706f2543Smrg#define VGAHWPTR(p) ((vgaHWPtr)(VGAHWPTRLVAL(p)))
83706f2543Smrg
84706f2543Smrgstatic int vgaHWPrivateIndex = -1;
85706f2543Smrg
86706f2543Smrg#define DAC_TEST_MASK 0x3F
87706f2543Smrg
88706f2543Smrg#ifdef NEED_SAVED_CMAP
89706f2543Smrg/* This default colourmap is used only when it can't be read from the VGA */
90706f2543Smrg
91706f2543Smrgstatic CARD8 defaultDAC[768] =
92706f2543Smrg{
93706f2543Smrg     0,  0,  0,    0,  0, 42,    0, 42,  0,    0, 42, 42,
94706f2543Smrg    42,  0,  0,   42,  0, 42,   42, 21,  0,   42, 42, 42,
95706f2543Smrg    21, 21, 21,   21, 21, 63,   21, 63, 21,   21, 63, 63,
96706f2543Smrg    63, 21, 21,   63, 21, 63,   63, 63, 21,   63, 63, 63,
97706f2543Smrg     0,  0,  0,    5,  5,  5,    8,  8,  8,   11, 11, 11,
98706f2543Smrg    14, 14, 14,   17, 17, 17,   20, 20, 20,   24, 24, 24,
99706f2543Smrg    28, 28, 28,   32, 32, 32,   36, 36, 36,   40, 40, 40,
100706f2543Smrg    45, 45, 45,   50, 50, 50,   56, 56, 56,   63, 63, 63,
101706f2543Smrg     0,  0, 63,   16,  0, 63,   31,  0, 63,   47,  0, 63,
102706f2543Smrg    63,  0, 63,   63,  0, 47,   63,  0, 31,   63,  0, 16,
103706f2543Smrg    63,  0,  0,   63, 16,  0,   63, 31,  0,   63, 47,  0,
104706f2543Smrg    63, 63,  0,   47, 63,  0,   31, 63,  0,   16, 63,  0,
105706f2543Smrg     0, 63,  0,    0, 63, 16,    0, 63, 31,    0, 63, 47,
106706f2543Smrg     0, 63, 63,    0, 47, 63,    0, 31, 63,    0, 16, 63,
107706f2543Smrg    31, 31, 63,   39, 31, 63,   47, 31, 63,   55, 31, 63,
108706f2543Smrg    63, 31, 63,   63, 31, 55,   63, 31, 47,   63, 31, 39,
109706f2543Smrg    63, 31, 31,   63, 39, 31,   63, 47, 31,   63, 55, 31,
110706f2543Smrg    63, 63, 31,   55, 63, 31,   47, 63, 31,   39, 63, 31,
111706f2543Smrg    31, 63, 31,   31, 63, 39,   31, 63, 47,   31, 63, 55,
112706f2543Smrg    31, 63, 63,   31, 55, 63,   31, 47, 63,   31, 39, 63,
113706f2543Smrg    45, 45, 63,   49, 45, 63,   54, 45, 63,   58, 45, 63,
114706f2543Smrg    63, 45, 63,   63, 45, 58,   63, 45, 54,   63, 45, 49,
115706f2543Smrg    63, 45, 45,   63, 49, 45,   63, 54, 45,   63, 58, 45,
116706f2543Smrg    63, 63, 45,   58, 63, 45,   54, 63, 45,   49, 63, 45,
117706f2543Smrg    45, 63, 45,   45, 63, 49,   45, 63, 54,   45, 63, 58,
118706f2543Smrg    45, 63, 63,   45, 58, 63,   45, 54, 63,   45, 49, 63,
119706f2543Smrg     0,  0, 28,    7,  0, 28,   14,  0, 28,   21,  0, 28,
120706f2543Smrg    28,  0, 28,   28,  0, 21,   28,  0, 14,   28,  0,  7,
121706f2543Smrg    28,  0,  0,   28,  7,  0,   28, 14,  0,   28, 21,  0,
122706f2543Smrg    28, 28,  0,   21, 28,  0,   14, 28,  0,    7, 28,  0,
123706f2543Smrg     0, 28,  0,    0, 28,  7,    0, 28, 14,    0, 28, 21,
124706f2543Smrg     0, 28, 28,    0, 21, 28,    0, 14, 28,    0,  7, 28,
125706f2543Smrg    14, 14, 28,   17, 14, 28,   21, 14, 28,   24, 14, 28,
126706f2543Smrg    28, 14, 28,   28, 14, 24,   28, 14, 21,   28, 14, 17,
127706f2543Smrg    28, 14, 14,   28, 17, 14,   28, 21, 14,   28, 24, 14,
128706f2543Smrg    28, 28, 14,   24, 28, 14,   21, 28, 14,   17, 28, 14,
129706f2543Smrg    14, 28, 14,   14, 28, 17,   14, 28, 21,   14, 28, 24,
130706f2543Smrg    14, 28, 28,   14, 24, 28,   14, 21, 28,   14, 17, 28,
131706f2543Smrg    20, 20, 28,   22, 20, 28,   24, 20, 28,   26, 20, 28,
132706f2543Smrg    28, 20, 28,   28, 20, 26,   28, 20, 24,   28, 20, 22,
133706f2543Smrg    28, 20, 20,   28, 22, 20,   28, 24, 20,   28, 26, 20,
134706f2543Smrg    28, 28, 20,   26, 28, 20,   24, 28, 20,   22, 28, 20,
135706f2543Smrg    20, 28, 20,   20, 28, 22,   20, 28, 24,   20, 28, 26,
136706f2543Smrg    20, 28, 28,   20, 26, 28,   20, 24, 28,   20, 22, 28,
137706f2543Smrg     0,  0, 16,    4,  0, 16,    8,  0, 16,   12,  0, 16,
138706f2543Smrg    16,  0, 16,   16,  0, 12,   16,  0,  8,   16,  0,  4,
139706f2543Smrg    16,  0,  0,   16,  4,  0,   16,  8,  0,   16, 12,  0,
140706f2543Smrg    16, 16,  0,   12, 16,  0,    8, 16,  0,    4, 16,  0,
141706f2543Smrg     0, 16,  0,    0, 16,  4,    0, 16,  8,    0, 16, 12,
142706f2543Smrg     0, 16, 16,    0, 12, 16,    0,  8, 16,    0,  4, 16,
143706f2543Smrg     8,  8, 16,   10,  8, 16,   12,  8, 16,   14,  8, 16,
144706f2543Smrg    16,  8, 16,   16,  8, 14,   16,  8, 12,   16,  8, 10,
145706f2543Smrg    16,  8,  8,   16, 10,  8,   16, 12,  8,   16, 14,  8,
146706f2543Smrg    16, 16,  8,   14, 16,  8,   12, 16,  8,   10, 16,  8,
147706f2543Smrg     8, 16,  8,    8, 16, 10,    8, 16, 12,    8, 16, 14,
148706f2543Smrg     8, 16, 16,    8, 14, 16,    8, 12, 16,    8, 10, 16,
149706f2543Smrg    11, 11, 16,   12, 11, 16,   13, 11, 16,   15, 11, 16,
150706f2543Smrg    16, 11, 16,   16, 11, 15,   16, 11, 13,   16, 11, 12,
151706f2543Smrg    16, 11, 11,   16, 12, 11,   16, 13, 11,   16, 15, 11,
152706f2543Smrg    16, 16, 11,   15, 16, 11,   13, 16, 11,   12, 16, 11,
153706f2543Smrg    11, 16, 11,   11, 16, 12,   11, 16, 13,   11, 16, 15,
154706f2543Smrg    11, 16, 16,   11, 15, 16,   11, 13, 16,   11, 12, 16,
155706f2543Smrg     0,  0,  0,    0,  0,  0,    0,  0,  0,    0,  0,  0,
156706f2543Smrg     0,  0,  0,    0,  0,  0,    0,  0,  0,    0,  0,  0,
157706f2543Smrg};
158706f2543Smrg#endif /* NEED_SAVED_CMAP */
159706f2543Smrg
160706f2543Smrg/*
161706f2543Smrg * Standard VGA versions of the register access functions.
162706f2543Smrg */
163706f2543Smrgstatic void
164706f2543SmrgstdWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
165706f2543Smrg{
166706f2543Smrg    outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_INDEX_OFFSET, index);
167706f2543Smrg    outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_DATA_OFFSET, value);
168706f2543Smrg}
169706f2543Smrg
170706f2543Smrgstatic CARD8
171706f2543SmrgstdReadCrtc(vgaHWPtr hwp, CARD8 index)
172706f2543Smrg{
173706f2543Smrg    outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_INDEX_OFFSET, index);
174706f2543Smrg    return inb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_DATA_OFFSET);
175706f2543Smrg}
176706f2543Smrg
177706f2543Smrgstatic void
178706f2543SmrgstdWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
179706f2543Smrg{
180706f2543Smrg    outb(hwp->PIOOffset + VGA_GRAPH_INDEX, index);
181706f2543Smrg    outb(hwp->PIOOffset + VGA_GRAPH_DATA, value);
182706f2543Smrg}
183706f2543Smrg
184706f2543Smrgstatic CARD8
185706f2543SmrgstdReadGr(vgaHWPtr hwp, CARD8 index)
186706f2543Smrg{
187706f2543Smrg    outb(hwp->PIOOffset + VGA_GRAPH_INDEX, index);
188706f2543Smrg    return inb(hwp->PIOOffset + VGA_GRAPH_DATA);
189706f2543Smrg}
190706f2543Smrg
191706f2543Smrgstatic void
192706f2543SmrgstdWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
193706f2543Smrg{
194706f2543Smrg    outb(hwp->PIOOffset + VGA_SEQ_INDEX, index);
195706f2543Smrg    outb(hwp->PIOOffset + VGA_SEQ_DATA, value);
196706f2543Smrg}
197706f2543Smrg
198706f2543Smrgstatic CARD8
199706f2543SmrgstdReadSeq(vgaHWPtr hwp, CARD8 index)
200706f2543Smrg{
201706f2543Smrg    outb(hwp->PIOOffset + VGA_SEQ_INDEX, index);
202706f2543Smrg    return inb(hwp->PIOOffset + VGA_SEQ_DATA);
203706f2543Smrg}
204706f2543Smrg
205706f2543Smrgstatic CARD8
206706f2543SmrgstdReadST00(vgaHWPtr hwp)
207706f2543Smrg{
208706f2543Smrg    return inb(hwp->PIOOffset + VGA_IN_STAT_0);
209706f2543Smrg}
210706f2543Smrg
211706f2543Smrgstatic CARD8
212706f2543SmrgstdReadST01(vgaHWPtr hwp)
213706f2543Smrg{
214706f2543Smrg    return inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET);
215706f2543Smrg}
216706f2543Smrg
217706f2543Smrgstatic CARD8
218706f2543SmrgstdReadFCR(vgaHWPtr hwp)
219706f2543Smrg{
220706f2543Smrg    return inb(hwp->PIOOffset + VGA_FEATURE_R);
221706f2543Smrg}
222706f2543Smrg
223706f2543Smrgstatic void
224706f2543SmrgstdWriteFCR(vgaHWPtr hwp, CARD8 value)
225706f2543Smrg{
226706f2543Smrg    outb(hwp->IOBase + hwp->PIOOffset + VGA_FEATURE_W_OFFSET,value);
227706f2543Smrg}
228706f2543Smrg
229706f2543Smrgstatic void
230706f2543SmrgstdWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
231706f2543Smrg{
232706f2543Smrg    if (hwp->paletteEnabled)
233706f2543Smrg	index &= ~0x20;
234706f2543Smrg    else
235706f2543Smrg	index |= 0x20;
236706f2543Smrg
237706f2543Smrg    (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET);
238706f2543Smrg    outb(hwp->PIOOffset + VGA_ATTR_INDEX, index);
239706f2543Smrg    outb(hwp->PIOOffset + VGA_ATTR_DATA_W, value);
240706f2543Smrg}
241706f2543Smrg
242706f2543Smrgstatic CARD8
243706f2543SmrgstdReadAttr(vgaHWPtr hwp, CARD8 index)
244706f2543Smrg{
245706f2543Smrg    if (hwp->paletteEnabled)
246706f2543Smrg	index &= ~0x20;
247706f2543Smrg    else
248706f2543Smrg	index |= 0x20;
249706f2543Smrg
250706f2543Smrg    (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET);
251706f2543Smrg    outb(hwp->PIOOffset + VGA_ATTR_INDEX, index);
252706f2543Smrg    return inb(hwp->PIOOffset + VGA_ATTR_DATA_R);
253706f2543Smrg}
254706f2543Smrg
255706f2543Smrgstatic void
256706f2543SmrgstdWriteMiscOut(vgaHWPtr hwp, CARD8 value)
257706f2543Smrg{
258706f2543Smrg    outb(hwp->PIOOffset + VGA_MISC_OUT_W, value);
259706f2543Smrg}
260706f2543Smrg
261706f2543Smrgstatic CARD8
262706f2543SmrgstdReadMiscOut(vgaHWPtr hwp)
263706f2543Smrg{
264706f2543Smrg    return inb(hwp->PIOOffset + VGA_MISC_OUT_R);
265706f2543Smrg}
266706f2543Smrg
267706f2543Smrgstatic void
268706f2543SmrgstdEnablePalette(vgaHWPtr hwp)
269706f2543Smrg{
270706f2543Smrg    (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET);
271706f2543Smrg    outb(hwp->PIOOffset + VGA_ATTR_INDEX, 0x00);
272706f2543Smrg    hwp->paletteEnabled = TRUE;
273706f2543Smrg}
274706f2543Smrg
275706f2543Smrgstatic void
276706f2543SmrgstdDisablePalette(vgaHWPtr hwp)
277706f2543Smrg{
278706f2543Smrg    (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET);
279706f2543Smrg    outb(hwp->PIOOffset + VGA_ATTR_INDEX, 0x20);
280706f2543Smrg    hwp->paletteEnabled = FALSE;
281706f2543Smrg}
282706f2543Smrg
283706f2543Smrgstatic void
284706f2543SmrgstdWriteDacMask(vgaHWPtr hwp, CARD8 value)
285706f2543Smrg{
286706f2543Smrg    outb(hwp->PIOOffset + VGA_DAC_MASK, value);
287706f2543Smrg}
288706f2543Smrg
289706f2543Smrgstatic CARD8
290706f2543SmrgstdReadDacMask(vgaHWPtr hwp)
291706f2543Smrg{
292706f2543Smrg    return inb(hwp->PIOOffset + VGA_DAC_MASK);
293706f2543Smrg}
294706f2543Smrg
295706f2543Smrgstatic void
296706f2543SmrgstdWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
297706f2543Smrg{
298706f2543Smrg    outb(hwp->PIOOffset + VGA_DAC_READ_ADDR, value);
299706f2543Smrg}
300706f2543Smrg
301706f2543Smrgstatic void
302706f2543SmrgstdWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
303706f2543Smrg{
304706f2543Smrg    outb(hwp->PIOOffset + VGA_DAC_WRITE_ADDR, value);
305706f2543Smrg}
306706f2543Smrg
307706f2543Smrgstatic void
308706f2543SmrgstdWriteDacData(vgaHWPtr hwp, CARD8 value)
309706f2543Smrg{
310706f2543Smrg    outb(hwp->PIOOffset + VGA_DAC_DATA, value);
311706f2543Smrg}
312706f2543Smrg
313706f2543Smrgstatic CARD8
314706f2543SmrgstdReadDacData(vgaHWPtr hwp)
315706f2543Smrg{
316706f2543Smrg    return inb(hwp->PIOOffset + VGA_DAC_DATA);
317706f2543Smrg}
318706f2543Smrg
319706f2543Smrgstatic CARD8
320706f2543SmrgstdReadEnable(vgaHWPtr hwp)
321706f2543Smrg{
322706f2543Smrg    return inb(hwp->PIOOffset + VGA_ENABLE);
323706f2543Smrg}
324706f2543Smrg
325706f2543Smrgstatic void
326706f2543SmrgstdWriteEnable(vgaHWPtr hwp, CARD8 value)
327706f2543Smrg{
328706f2543Smrg    outb(hwp->PIOOffset + VGA_ENABLE, value);
329706f2543Smrg}
330706f2543Smrg
331706f2543Smrgvoid
332706f2543SmrgvgaHWSetStdFuncs(vgaHWPtr hwp)
333706f2543Smrg{
334706f2543Smrg    hwp->writeCrtc		= stdWriteCrtc;
335706f2543Smrg    hwp->readCrtc		= stdReadCrtc;
336706f2543Smrg    hwp->writeGr		= stdWriteGr;
337706f2543Smrg    hwp->readGr			= stdReadGr;
338706f2543Smrg    hwp->readST00               = stdReadST00;
339706f2543Smrg    hwp->readST01               = stdReadST01;
340706f2543Smrg    hwp->readFCR                = stdReadFCR;
341706f2543Smrg    hwp->writeFCR               = stdWriteFCR;
342706f2543Smrg    hwp->writeAttr		= stdWriteAttr;
343706f2543Smrg    hwp->readAttr		= stdReadAttr;
344706f2543Smrg    hwp->writeSeq		= stdWriteSeq;
345706f2543Smrg    hwp->readSeq		= stdReadSeq;
346706f2543Smrg    hwp->writeMiscOut		= stdWriteMiscOut;
347706f2543Smrg    hwp->readMiscOut		= stdReadMiscOut;
348706f2543Smrg    hwp->enablePalette		= stdEnablePalette;
349706f2543Smrg    hwp->disablePalette		= stdDisablePalette;
350706f2543Smrg    hwp->writeDacMask		= stdWriteDacMask;
351706f2543Smrg    hwp->readDacMask		= stdReadDacMask;
352706f2543Smrg    hwp->writeDacWriteAddr	= stdWriteDacWriteAddr;
353706f2543Smrg    hwp->writeDacReadAddr	= stdWriteDacReadAddr;
354706f2543Smrg    hwp->writeDacData		= stdWriteDacData;
355706f2543Smrg    hwp->readDacData		= stdReadDacData;
356706f2543Smrg    hwp->PIOOffset		= 0;
357706f2543Smrg    hwp->readEnable		= stdReadEnable;
358706f2543Smrg    hwp->writeEnable		= stdWriteEnable;
359706f2543Smrg}
360706f2543Smrg
361706f2543Smrg/*
362706f2543Smrg * MMIO versions of the register access functions.  These require
363706f2543Smrg * hwp->MemBase to be set in such a way that when the standard VGA port
364706f2543Smrg * adderss is added the correct memory address results.
365706f2543Smrg */
366706f2543Smrg
367706f2543Smrg#define minb(p) MMIO_IN8(hwp->MMIOBase, (hwp->MMIOOffset + (p)))
368706f2543Smrg#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (hwp->MMIOOffset + (p)),(v))
369706f2543Smrg
370706f2543Smrgstatic void
371706f2543SmrgmmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)
372706f2543Smrg{
373706f2543Smrg    moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
374706f2543Smrg    moutb(hwp->IOBase + VGA_CRTC_DATA_OFFSET, value);
375706f2543Smrg}
376706f2543Smrg
377706f2543Smrgstatic CARD8
378706f2543SmrgmmioReadCrtc(vgaHWPtr hwp, CARD8 index)
379706f2543Smrg{
380706f2543Smrg    moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index);
381706f2543Smrg    return minb(hwp->IOBase + VGA_CRTC_DATA_OFFSET);
382706f2543Smrg}
383706f2543Smrg
384706f2543Smrgstatic void
385706f2543SmrgmmioWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value)
386706f2543Smrg{
387706f2543Smrg    moutb(VGA_GRAPH_INDEX, index);
388706f2543Smrg    moutb(VGA_GRAPH_DATA, value);
389706f2543Smrg}
390706f2543Smrg
391706f2543Smrgstatic CARD8
392706f2543SmrgmmioReadGr(vgaHWPtr hwp, CARD8 index)
393706f2543Smrg{
394706f2543Smrg    moutb(VGA_GRAPH_INDEX, index);
395706f2543Smrg    return minb(VGA_GRAPH_DATA);
396706f2543Smrg}
397706f2543Smrg
398706f2543Smrgstatic void
399706f2543SmrgmmioWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value)
400706f2543Smrg{
401706f2543Smrg    moutb(VGA_SEQ_INDEX, index);
402706f2543Smrg    moutb(VGA_SEQ_DATA, value);
403706f2543Smrg}
404706f2543Smrg
405706f2543Smrgstatic CARD8
406706f2543SmrgmmioReadSeq(vgaHWPtr hwp, CARD8 index)
407706f2543Smrg{
408706f2543Smrg    moutb(VGA_SEQ_INDEX, index);
409706f2543Smrg    return minb(VGA_SEQ_DATA);
410706f2543Smrg}
411706f2543Smrg
412706f2543Smrgstatic CARD8
413706f2543SmrgmmioReadST00(vgaHWPtr hwp)
414706f2543Smrg{
415706f2543Smrg    return minb(VGA_IN_STAT_0);
416706f2543Smrg}
417706f2543Smrg
418706f2543Smrgstatic CARD8
419706f2543SmrgmmioReadST01(vgaHWPtr hwp)
420706f2543Smrg{
421706f2543Smrg    return minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
422706f2543Smrg}
423706f2543Smrg
424706f2543Smrgstatic CARD8
425706f2543SmrgmmioReadFCR(vgaHWPtr hwp)
426706f2543Smrg{
427706f2543Smrg    return minb(VGA_FEATURE_R);
428706f2543Smrg}
429706f2543Smrg
430706f2543Smrgstatic void
431706f2543SmrgmmioWriteFCR(vgaHWPtr hwp, CARD8 value)
432706f2543Smrg{
433706f2543Smrg    moutb(hwp->IOBase + VGA_FEATURE_W_OFFSET,value);
434706f2543Smrg}
435706f2543Smrg
436706f2543Smrgstatic void
437706f2543SmrgmmioWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
438706f2543Smrg{
439706f2543Smrg    if (hwp->paletteEnabled)
440706f2543Smrg	index &= ~0x20;
441706f2543Smrg    else
442706f2543Smrg	index |= 0x20;
443706f2543Smrg
444706f2543Smrg    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
445706f2543Smrg    moutb(VGA_ATTR_INDEX, index);
446706f2543Smrg    moutb(VGA_ATTR_DATA_W, value);
447706f2543Smrg}
448706f2543Smrg
449706f2543Smrgstatic CARD8
450706f2543SmrgmmioReadAttr(vgaHWPtr hwp, CARD8 index)
451706f2543Smrg{
452706f2543Smrg    if (hwp->paletteEnabled)
453706f2543Smrg	index &= ~0x20;
454706f2543Smrg    else
455706f2543Smrg	index |= 0x20;
456706f2543Smrg
457706f2543Smrg    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
458706f2543Smrg    moutb(VGA_ATTR_INDEX, index);
459706f2543Smrg    return minb(VGA_ATTR_DATA_R);
460706f2543Smrg}
461706f2543Smrg
462706f2543Smrgstatic void
463706f2543SmrgmmioWriteMiscOut(vgaHWPtr hwp, CARD8 value)
464706f2543Smrg{
465706f2543Smrg    moutb(VGA_MISC_OUT_W, value);
466706f2543Smrg}
467706f2543Smrg
468706f2543Smrgstatic CARD8
469706f2543SmrgmmioReadMiscOut(vgaHWPtr hwp)
470706f2543Smrg{
471706f2543Smrg    return minb(VGA_MISC_OUT_R);
472706f2543Smrg}
473706f2543Smrg
474706f2543Smrgstatic void
475706f2543SmrgmmioEnablePalette(vgaHWPtr hwp)
476706f2543Smrg{
477706f2543Smrg    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
478706f2543Smrg    moutb(VGA_ATTR_INDEX, 0x00);
479706f2543Smrg    hwp->paletteEnabled = TRUE;
480706f2543Smrg}
481706f2543Smrg
482706f2543Smrgstatic void
483706f2543SmrgmmioDisablePalette(vgaHWPtr hwp)
484706f2543Smrg{
485706f2543Smrg    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
486706f2543Smrg    moutb(VGA_ATTR_INDEX, 0x20);
487706f2543Smrg    hwp->paletteEnabled = FALSE;
488706f2543Smrg}
489706f2543Smrg
490706f2543Smrgstatic void
491706f2543SmrgmmioWriteDacMask(vgaHWPtr hwp, CARD8 value)
492706f2543Smrg{
493706f2543Smrg    moutb(VGA_DAC_MASK, value);
494706f2543Smrg}
495706f2543Smrg
496706f2543Smrgstatic CARD8
497706f2543SmrgmmioReadDacMask(vgaHWPtr hwp)
498706f2543Smrg{
499706f2543Smrg    return minb(VGA_DAC_MASK);
500706f2543Smrg}
501706f2543Smrg
502706f2543Smrgstatic void
503706f2543SmrgmmioWriteDacReadAddr(vgaHWPtr hwp, CARD8 value)
504706f2543Smrg{
505706f2543Smrg    moutb(VGA_DAC_READ_ADDR, value);
506706f2543Smrg}
507706f2543Smrg
508706f2543Smrgstatic void
509706f2543SmrgmmioWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value)
510706f2543Smrg{
511706f2543Smrg    moutb(VGA_DAC_WRITE_ADDR, value);
512706f2543Smrg}
513706f2543Smrg
514706f2543Smrgstatic void
515706f2543SmrgmmioWriteDacData(vgaHWPtr hwp, CARD8 value)
516706f2543Smrg{
517706f2543Smrg    moutb(VGA_DAC_DATA, value);
518706f2543Smrg}
519706f2543Smrg
520706f2543Smrgstatic CARD8
521706f2543SmrgmmioReadDacData(vgaHWPtr hwp)
522706f2543Smrg{
523706f2543Smrg    return minb(VGA_DAC_DATA);
524706f2543Smrg}
525706f2543Smrg
526706f2543Smrgstatic CARD8
527706f2543SmrgmmioReadEnable(vgaHWPtr hwp)
528706f2543Smrg{
529706f2543Smrg    return minb(VGA_ENABLE);
530706f2543Smrg}
531706f2543Smrg
532706f2543Smrgstatic void
533706f2543SmrgmmioWriteEnable(vgaHWPtr hwp, CARD8 value)
534706f2543Smrg{
535706f2543Smrg    moutb(VGA_ENABLE, value);
536706f2543Smrg}
537706f2543Smrg
538706f2543Smrgvoid
539706f2543SmrgvgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset)
540706f2543Smrg{
541706f2543Smrg    hwp->writeCrtc		= mmioWriteCrtc;
542706f2543Smrg    hwp->readCrtc		= mmioReadCrtc;
543706f2543Smrg    hwp->writeGr		= mmioWriteGr;
544706f2543Smrg    hwp->readGr			= mmioReadGr;
545706f2543Smrg    hwp->readST00               = mmioReadST00;
546706f2543Smrg    hwp->readST01               = mmioReadST01;
547706f2543Smrg    hwp->readFCR                = mmioReadFCR;
548706f2543Smrg    hwp->writeFCR               = mmioWriteFCR;
549706f2543Smrg    hwp->writeAttr		= mmioWriteAttr;
550706f2543Smrg    hwp->readAttr		= mmioReadAttr;
551706f2543Smrg    hwp->writeSeq		= mmioWriteSeq;
552706f2543Smrg    hwp->readSeq		= mmioReadSeq;
553706f2543Smrg    hwp->writeMiscOut		= mmioWriteMiscOut;
554706f2543Smrg    hwp->readMiscOut		= mmioReadMiscOut;
555706f2543Smrg    hwp->enablePalette		= mmioEnablePalette;
556706f2543Smrg    hwp->disablePalette		= mmioDisablePalette;
557706f2543Smrg    hwp->writeDacMask		= mmioWriteDacMask;
558706f2543Smrg    hwp->readDacMask		= mmioReadDacMask;
559706f2543Smrg    hwp->writeDacWriteAddr	= mmioWriteDacWriteAddr;
560706f2543Smrg    hwp->writeDacReadAddr	= mmioWriteDacReadAddr;
561706f2543Smrg    hwp->writeDacData		= mmioWriteDacData;
562706f2543Smrg    hwp->readDacData		= mmioReadDacData;
563706f2543Smrg    hwp->MMIOBase		= base;
564706f2543Smrg    hwp->MMIOOffset		= offset;
565706f2543Smrg    hwp->readEnable		= mmioReadEnable;
566706f2543Smrg    hwp->writeEnable		= mmioWriteEnable;
567706f2543Smrg}
568706f2543Smrg
569706f2543Smrg/*
570706f2543Smrg * vgaHWProtect --
571706f2543Smrg *	Protect VGA registers and memory from corruption during loads.
572706f2543Smrg */
573706f2543Smrg
574706f2543Smrgvoid
575706f2543SmrgvgaHWProtect(ScrnInfoPtr pScrn, Bool on)
576706f2543Smrg{
577706f2543Smrg  vgaHWPtr hwp = VGAHWPTR(pScrn);
578706f2543Smrg
579706f2543Smrg  unsigned char tmp;
580706f2543Smrg
581706f2543Smrg  if (pScrn->vtSema) {
582706f2543Smrg    if (on) {
583706f2543Smrg      /*
584706f2543Smrg       * Turn off screen and disable sequencer.
585706f2543Smrg       */
586706f2543Smrg      tmp = hwp->readSeq(hwp, 0x01);
587706f2543Smrg
588706f2543Smrg      vgaHWSeqReset(hwp, TRUE);			/* start synchronous reset */
589706f2543Smrg      hwp->writeSeq(hwp, 0x01, tmp | 0x20);	/* disable the display */
590706f2543Smrg
591706f2543Smrg      hwp->enablePalette(hwp);
592706f2543Smrg    } else {
593706f2543Smrg      /*
594706f2543Smrg       * Reenable sequencer, then turn on screen.
595706f2543Smrg       */
596706f2543Smrg
597706f2543Smrg      tmp = hwp->readSeq(hwp, 0x01);
598706f2543Smrg
599706f2543Smrg      hwp->writeSeq(hwp, 0x01, tmp & ~0x20);	/* reenable display */
600706f2543Smrg      vgaHWSeqReset(hwp, FALSE);		/* clear synchronousreset */
601706f2543Smrg
602706f2543Smrg      hwp->disablePalette(hwp);
603706f2543Smrg    }
604706f2543Smrg  }
605706f2543Smrg}
606706f2543Smrg
607706f2543SmrgvgaHWProtectProc *vgaHWProtectWeak(void) {
608706f2543Smrg  return vgaHWProtect;
609706f2543Smrg}
610706f2543Smrg
611706f2543Smrg/*
612706f2543Smrg * vgaHWBlankScreen -- blank the screen.
613706f2543Smrg */
614706f2543Smrg
615706f2543Smrgvoid
616706f2543SmrgvgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on)
617706f2543Smrg{
618706f2543Smrg  vgaHWPtr hwp = VGAHWPTR(pScrn);
619706f2543Smrg  unsigned char scrn;
620706f2543Smrg
621706f2543Smrg  scrn = hwp->readSeq(hwp, 0x01);
622706f2543Smrg
623706f2543Smrg  if (on) {
624706f2543Smrg    scrn &= ~0x20;			/* enable screen */
625706f2543Smrg  } else {
626706f2543Smrg    scrn |= 0x20;			/* blank screen */
627706f2543Smrg  }
628706f2543Smrg
629706f2543Smrg  vgaHWSeqReset(hwp, TRUE);
630706f2543Smrg  hwp->writeSeq(hwp, 0x01, scrn);	/* change mode */
631706f2543Smrg  vgaHWSeqReset(hwp, FALSE);
632706f2543Smrg}
633706f2543Smrg
634706f2543SmrgvgaHWBlankScreenProc *vgaHWBlankScreenWeak(void) {
635706f2543Smrg  return vgaHWBlankScreen;
636706f2543Smrg}
637706f2543Smrg
638706f2543Smrg/*
639706f2543Smrg * vgaHWSaveScreen -- blank the screen.
640706f2543Smrg */
641706f2543Smrg
642706f2543SmrgBool
643706f2543SmrgvgaHWSaveScreen(ScreenPtr pScreen, int mode)
644706f2543Smrg{
645706f2543Smrg   ScrnInfoPtr pScrn = NULL;
646706f2543Smrg   Bool on;
647706f2543Smrg
648706f2543Smrg   if (pScreen != NULL)
649706f2543Smrg      pScrn = xf86Screens[pScreen->myNum];
650706f2543Smrg
651706f2543Smrg   on = xf86IsUnblank(mode);
652706f2543Smrg
653706f2543Smrg#if 0
654706f2543Smrg   if (on)
655706f2543Smrg      SetTimeSinceLastInputEvent();
656706f2543Smrg#endif
657706f2543Smrg
658706f2543Smrg   if ((pScrn != NULL) && pScrn->vtSema) {
659706f2543Smrg     vgaHWBlankScreen(pScrn, on);
660706f2543Smrg   }
661706f2543Smrg   return TRUE;
662706f2543Smrg}
663706f2543Smrg
664706f2543Smrg
665706f2543Smrg/*
666706f2543Smrg * vgaHWDPMSSet -- Sets VESA Display Power Management Signaling (DPMS) Mode
667706f2543Smrg *
668706f2543Smrg * This generic VGA function can only set the Off and On modes.  If the
669706f2543Smrg * Standby and Suspend modes are to be supported, a chip specific replacement
670706f2543Smrg * for this function must be written.
671706f2543Smrg */
672706f2543Smrg
673706f2543Smrgvoid
674706f2543SmrgvgaHWDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
675706f2543Smrg{
676706f2543Smrg  unsigned char seq1 = 0, crtc17 = 0;
677706f2543Smrg  vgaHWPtr hwp = VGAHWPTR(pScrn);
678706f2543Smrg
679706f2543Smrg  if (!pScrn->vtSema) return;
680706f2543Smrg
681706f2543Smrg  switch (PowerManagementMode) {
682706f2543Smrg  case DPMSModeOn:
683706f2543Smrg    /* Screen: On; HSync: On, VSync: On */
684706f2543Smrg    seq1 = 0x00;
685706f2543Smrg    crtc17 = 0x80;
686706f2543Smrg    break;
687706f2543Smrg  case DPMSModeStandby:
688706f2543Smrg    /* Screen: Off; HSync: Off, VSync: On -- Not Supported */
689706f2543Smrg    seq1 = 0x20;
690706f2543Smrg    crtc17 = 0x80;
691706f2543Smrg    break;
692706f2543Smrg  case DPMSModeSuspend:
693706f2543Smrg    /* Screen: Off; HSync: On, VSync: Off -- Not Supported */
694706f2543Smrg    seq1 = 0x20;
695706f2543Smrg    crtc17 = 0x80;
696706f2543Smrg    break;
697706f2543Smrg  case DPMSModeOff:
698706f2543Smrg    /* Screen: Off; HSync: Off, VSync: Off */
699706f2543Smrg    seq1 = 0x20;
700706f2543Smrg    crtc17 = 0x00;
701706f2543Smrg    break;
702706f2543Smrg  }
703706f2543Smrg  hwp->writeSeq(hwp, 0x00, 0x01);		/* Synchronous Reset */
704706f2543Smrg  seq1 |= hwp->readSeq(hwp, 0x01) & ~0x20;
705706f2543Smrg  hwp->writeSeq(hwp, 0x01, seq1);
706706f2543Smrg  crtc17 |= hwp->readCrtc(hwp, 0x17) & ~0x80;
707706f2543Smrg  usleep(10000);
708706f2543Smrg  hwp->writeCrtc(hwp, 0x17, crtc17);
709706f2543Smrg  hwp->writeSeq(hwp, 0x00, 0x03);		/* End Reset */
710706f2543Smrg}
711706f2543Smrg
712706f2543Smrg
713706f2543Smrg/*
714706f2543Smrg * vgaHWSeqReset
715706f2543Smrg *      perform a sequencer reset.
716706f2543Smrg */
717706f2543Smrg
718706f2543Smrgvoid
719706f2543SmrgvgaHWSeqReset(vgaHWPtr hwp, Bool start)
720706f2543Smrg{
721706f2543Smrg  if (start)
722706f2543Smrg    hwp->writeSeq(hwp, 0x00, 0x01);		/* Synchronous Reset */
723706f2543Smrg  else
724706f2543Smrg    hwp->writeSeq(hwp, 0x00, 0x03);		/* End Reset */
725706f2543Smrg}
726706f2543Smrg
727706f2543Smrg
728706f2543Smrgvoid
729706f2543SmrgvgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
730706f2543Smrg{
731706f2543Smrg#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
732706f2543Smrg    vgaHWPtr hwp = VGAHWPTR(scrninfp);
733706f2543Smrg    int savedIOBase;
734706f2543Smrg    unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4;
735706f2543Smrg    Bool doMap = FALSE;
736706f2543Smrg
737706f2543Smrg    /* If nothing to do, return now */
738706f2543Smrg    if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo)
739706f2543Smrg	return;
740706f2543Smrg
741706f2543Smrg    if (hwp->Base == NULL) {
742706f2543Smrg	doMap = TRUE;
743706f2543Smrg	if (!vgaHWMapMem(scrninfp)) {
744706f2543Smrg	    xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
745706f2543Smrg		       "vgaHWRestoreFonts: vgaHWMapMem() failed\n");
746706f2543Smrg	    return;
747706f2543Smrg	}
748706f2543Smrg    }
749706f2543Smrg
750706f2543Smrg    /* save the registers that are needed here */
751706f2543Smrg    miscOut = hwp->readMiscOut(hwp);
752706f2543Smrg    attr10 = hwp->readAttr(hwp, 0x10);
753706f2543Smrg    gr1 = hwp->readGr(hwp, 0x01);
754706f2543Smrg    gr3 = hwp->readGr(hwp, 0x03);
755706f2543Smrg    gr4 = hwp->readGr(hwp, 0x04);
756706f2543Smrg    gr5 = hwp->readGr(hwp, 0x05);
757706f2543Smrg    gr6 = hwp->readGr(hwp, 0x06);
758706f2543Smrg    gr8 = hwp->readGr(hwp, 0x08);
759706f2543Smrg    seq2 = hwp->readSeq(hwp, 0x02);
760706f2543Smrg    seq4 = hwp->readSeq(hwp, 0x04);
761706f2543Smrg
762706f2543Smrg    /* save hwp->IOBase and temporarily set it for colour mode */
763706f2543Smrg    savedIOBase = hwp->IOBase;
764706f2543Smrg    hwp->IOBase = VGA_IOBASE_COLOR;
765706f2543Smrg
766706f2543Smrg    /* Force into colour mode */
767706f2543Smrg    hwp->writeMiscOut(hwp, miscOut | 0x01);
768706f2543Smrg
769706f2543Smrg    vgaHWBlankScreen(scrninfp, FALSE);
770706f2543Smrg
771706f2543Smrg    /*
772706f2543Smrg     * here we temporarily switch to 16 colour planar mode, to simply
773706f2543Smrg     * copy the font-info and saved text.
774706f2543Smrg     *
775706f2543Smrg     * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
776706f2543Smrg     */
777706f2543Smrg#if 0
778706f2543Smrg    hwp->writeAttr(hwp, 0x10, 0x01);	/* graphics mode */
779706f2543Smrg#endif
780706f2543Smrg
781706f2543Smrg    hwp->writeSeq(hwp, 0x04, 0x06);	/* enable plane graphics */
782706f2543Smrg    hwp->writeGr(hwp, 0x05, 0x00);	/* write mode 0, read mode 0 */
783706f2543Smrg    hwp->writeGr(hwp, 0x06, 0x05);	/* set graphics */
784706f2543Smrg
785706f2543Smrg    if (scrninfp->depth == 4) {
786706f2543Smrg	/* GJA */
787706f2543Smrg	hwp->writeGr(hwp, 0x03, 0x00);	/* don't rotate, write unmodified */
788706f2543Smrg	hwp->writeGr(hwp, 0x08, 0xFF);	/* write all bits in a byte */
789706f2543Smrg	hwp->writeGr(hwp, 0x01, 0x00);	/* all planes come from CPU */
790706f2543Smrg    }
791706f2543Smrg
792706f2543Smrg#if SAVE_FONT1
793706f2543Smrg    if (hwp->FontInfo1) {
794706f2543Smrg	hwp->writeSeq(hwp, 0x02, 0x04);	/* write to plane 2 */
795706f2543Smrg	hwp->writeGr(hwp, 0x04, 0x02);	/* read plane 2 */
796706f2543Smrg	slowbcopy_tobus(hwp->FontInfo1, hwp->Base, FONT_AMOUNT);
797706f2543Smrg    }
798706f2543Smrg#endif
799706f2543Smrg
800706f2543Smrg#if SAVE_FONT2
801706f2543Smrg    if (hwp->FontInfo2) {
802706f2543Smrg	hwp->writeSeq(hwp, 0x02, 0x08);	/* write to plane 3 */
803706f2543Smrg	hwp->writeGr(hwp, 0x04, 0x03);	/* read plane 3 */
804706f2543Smrg	slowbcopy_tobus(hwp->FontInfo2, hwp->Base, FONT_AMOUNT);
805706f2543Smrg    }
806706f2543Smrg#endif
807706f2543Smrg
808706f2543Smrg#if SAVE_TEXT
809706f2543Smrg    if (hwp->TextInfo) {
810706f2543Smrg	hwp->writeSeq(hwp, 0x02, 0x01);	/* write to plane 0 */
811706f2543Smrg	hwp->writeGr(hwp, 0x04, 0x00);	/* read plane 0 */
812706f2543Smrg	slowbcopy_tobus(hwp->TextInfo, hwp->Base, TEXT_AMOUNT);
813706f2543Smrg	hwp->writeSeq(hwp, 0x02, 0x02);	/* write to plane 1 */
814706f2543Smrg	hwp->writeGr(hwp, 0x04, 0x01);	/* read plane 1 */
815706f2543Smrg	slowbcopy_tobus((unsigned char *)hwp->TextInfo + TEXT_AMOUNT,
816706f2543Smrg			hwp->Base, TEXT_AMOUNT);
817706f2543Smrg    }
818706f2543Smrg#endif
819706f2543Smrg
820706f2543Smrg    vgaHWBlankScreen(scrninfp, TRUE);
821706f2543Smrg
822706f2543Smrg    /* restore the registers that were changed */
823706f2543Smrg    hwp->writeMiscOut(hwp, miscOut);
824706f2543Smrg    hwp->writeAttr(hwp, 0x10, attr10);
825706f2543Smrg    hwp->writeGr(hwp, 0x01, gr1);
826706f2543Smrg    hwp->writeGr(hwp, 0x03, gr3);
827706f2543Smrg    hwp->writeGr(hwp, 0x04, gr4);
828706f2543Smrg    hwp->writeGr(hwp, 0x05, gr5);
829706f2543Smrg    hwp->writeGr(hwp, 0x06, gr6);
830706f2543Smrg    hwp->writeGr(hwp, 0x08, gr8);
831706f2543Smrg    hwp->writeSeq(hwp, 0x02, seq2);
832706f2543Smrg    hwp->writeSeq(hwp, 0x04, seq4);
833706f2543Smrg    hwp->IOBase = savedIOBase;
834706f2543Smrg
835706f2543Smrg    if (doMap)
836706f2543Smrg	vgaHWUnmapMem(scrninfp);
837706f2543Smrg
838706f2543Smrg#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
839706f2543Smrg}
840706f2543Smrg
841706f2543Smrg
842706f2543Smrgvoid
843706f2543SmrgvgaHWRestoreMode(ScrnInfoPtr scrninfp, vgaRegPtr restore)
844706f2543Smrg{
845706f2543Smrg    vgaHWPtr hwp = VGAHWPTR(scrninfp);
846706f2543Smrg    int i;
847706f2543Smrg
848706f2543Smrg    if (restore->MiscOutReg & 0x01)
849706f2543Smrg	hwp->IOBase = VGA_IOBASE_COLOR;
850706f2543Smrg    else
851706f2543Smrg	hwp->IOBase = VGA_IOBASE_MONO;
852706f2543Smrg
853706f2543Smrg    hwp->writeMiscOut(hwp, restore->MiscOutReg);
854706f2543Smrg
855706f2543Smrg    for (i = 1; i < restore->numSequencer; i++)
856706f2543Smrg	hwp->writeSeq(hwp, i, restore->Sequencer[i]);
857706f2543Smrg
858706f2543Smrg    /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
859706f2543Smrg    hwp->writeCrtc(hwp, 17, restore->CRTC[17] & ~0x80);
860706f2543Smrg
861706f2543Smrg    for (i = 0; i < restore->numCRTC; i++)
862706f2543Smrg	hwp->writeCrtc(hwp, i, restore->CRTC[i]);
863706f2543Smrg
864706f2543Smrg    for (i = 0; i < restore->numGraphics; i++)
865706f2543Smrg	hwp->writeGr(hwp, i, restore->Graphics[i]);
866706f2543Smrg
867706f2543Smrg    hwp->enablePalette(hwp);
868706f2543Smrg    for (i = 0; i < restore->numAttribute; i++)
869706f2543Smrg	hwp->writeAttr(hwp, i, restore->Attribute[i]);
870706f2543Smrg    hwp->disablePalette(hwp);
871706f2543Smrg}
872706f2543Smrg
873706f2543Smrg
874706f2543Smrgvoid
875706f2543SmrgvgaHWRestoreColormap(ScrnInfoPtr scrninfp, vgaRegPtr restore)
876706f2543Smrg{
877706f2543Smrg    vgaHWPtr hwp = VGAHWPTR(scrninfp);
878706f2543Smrg    int i;
879706f2543Smrg
880706f2543Smrg#if 0
881706f2543Smrg    hwp->enablePalette(hwp);
882706f2543Smrg#endif
883706f2543Smrg
884706f2543Smrg    hwp->writeDacMask(hwp, 0xFF);
885706f2543Smrg    hwp->writeDacWriteAddr(hwp, 0x00);
886706f2543Smrg    for (i = 0; i < 768; i++) {
887706f2543Smrg	hwp->writeDacData(hwp, restore->DAC[i]);
888706f2543Smrg	DACDelay(hwp);
889706f2543Smrg    }
890706f2543Smrg
891706f2543Smrg    hwp->disablePalette(hwp);
892706f2543Smrg}
893706f2543Smrg
894706f2543Smrg
895706f2543Smrg/*
896706f2543Smrg * vgaHWRestore --
897706f2543Smrg *      restore the VGA state
898706f2543Smrg */
899706f2543Smrg
900706f2543Smrgvoid
901706f2543SmrgvgaHWRestore(ScrnInfoPtr scrninfp, vgaRegPtr restore, int flags)
902706f2543Smrg{
903706f2543Smrg    if (flags & VGA_SR_MODE)
904706f2543Smrg	vgaHWRestoreMode(scrninfp, restore);
905706f2543Smrg
906706f2543Smrg    if (flags & VGA_SR_FONTS)
907706f2543Smrg	vgaHWRestoreFonts(scrninfp, restore);
908706f2543Smrg
909706f2543Smrg    if (flags & VGA_SR_CMAP)
910706f2543Smrg	vgaHWRestoreColormap(scrninfp, restore);
911706f2543Smrg}
912706f2543Smrg
913706f2543Smrgvoid
914706f2543SmrgvgaHWSaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save)
915706f2543Smrg{
916706f2543Smrg#if  SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2
917706f2543Smrg    vgaHWPtr hwp = VGAHWPTR(scrninfp);
918706f2543Smrg    int savedIOBase;
919706f2543Smrg    unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4;
920706f2543Smrg    Bool doMap = FALSE;
921706f2543Smrg
922706f2543Smrg    if (hwp->Base == NULL) {
923706f2543Smrg	doMap = TRUE;
924706f2543Smrg	if (!vgaHWMapMem(scrninfp)) {
925706f2543Smrg	    xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
926706f2543Smrg		       "vgaHWSaveFonts: vgaHWMapMem() failed\n");
927706f2543Smrg	    return;
928706f2543Smrg	}
929706f2543Smrg    }
930706f2543Smrg
931706f2543Smrg    /* If in graphics mode, don't save anything */
932706f2543Smrg    attr10 = hwp->readAttr(hwp, 0x10);
933706f2543Smrg    if (attr10 & 0x01)
934706f2543Smrg	return;
935706f2543Smrg
936706f2543Smrg    /* save the registers that are needed here */
937706f2543Smrg    miscOut = hwp->readMiscOut(hwp);
938706f2543Smrg    gr4 = hwp->readGr(hwp, 0x04);
939706f2543Smrg    gr5 = hwp->readGr(hwp, 0x05);
940706f2543Smrg    gr6 = hwp->readGr(hwp, 0x06);
941706f2543Smrg    seq2 = hwp->readSeq(hwp, 0x02);
942706f2543Smrg    seq4 = hwp->readSeq(hwp, 0x04);
943706f2543Smrg
944706f2543Smrg    /* save hwp->IOBase and temporarily set it for colour mode */
945706f2543Smrg    savedIOBase = hwp->IOBase;
946706f2543Smrg    hwp->IOBase = VGA_IOBASE_COLOR;
947706f2543Smrg
948706f2543Smrg    /* Force into colour mode */
949706f2543Smrg    hwp->writeMiscOut(hwp, miscOut | 0x01);
950706f2543Smrg
951706f2543Smrg    vgaHWBlankScreen(scrninfp, FALSE);
952706f2543Smrg
953706f2543Smrg    /*
954706f2543Smrg     * get the character sets, and text screen if required
955706f2543Smrg     */
956706f2543Smrg    /*
957706f2543Smrg     * Here we temporarily switch to 16 colour planar mode, to simply
958706f2543Smrg     * copy the font-info
959706f2543Smrg     *
960706f2543Smrg     * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
961706f2543Smrg     */
962706f2543Smrg#if 0
963706f2543Smrg    hwp->writeAttr(hwp, 0x10, 0x01);	/* graphics mode */
964706f2543Smrg#endif
965706f2543Smrg
966706f2543Smrg    hwp->writeSeq(hwp, 0x04, 0x06);	/* enable plane graphics */
967706f2543Smrg    hwp->writeGr(hwp, 0x05, 0x00);	/* write mode 0, read mode 0 */
968706f2543Smrg    hwp->writeGr(hwp, 0x06, 0x05);	/* set graphics */
969706f2543Smrg
970706f2543Smrg#if SAVE_FONT1
971706f2543Smrg    if (hwp->FontInfo1 || (hwp->FontInfo1 = malloc(FONT_AMOUNT))) {
972706f2543Smrg	hwp->writeSeq(hwp, 0x02, 0x04);	/* write to plane 2 */
973706f2543Smrg	hwp->writeGr(hwp, 0x04, 0x02);	/* read plane 2 */
974706f2543Smrg	slowbcopy_frombus(hwp->Base, hwp->FontInfo1, FONT_AMOUNT);
975706f2543Smrg    }
976706f2543Smrg#endif /* SAVE_FONT1 */
977706f2543Smrg#if SAVE_FONT2
978706f2543Smrg    if (hwp->FontInfo2 || (hwp->FontInfo2 = malloc(FONT_AMOUNT))) {
979706f2543Smrg	hwp->writeSeq(hwp, 0x02, 0x08);	/* write to plane 3 */
980706f2543Smrg	hwp->writeGr(hwp, 0x04, 0x03);	/* read plane 3 */
981706f2543Smrg	slowbcopy_frombus(hwp->Base, hwp->FontInfo2, FONT_AMOUNT);
982706f2543Smrg    }
983706f2543Smrg#endif /* SAVE_FONT2 */
984706f2543Smrg#if SAVE_TEXT
985706f2543Smrg    if (hwp->TextInfo || (hwp->TextInfo = malloc(2 * TEXT_AMOUNT))) {
986706f2543Smrg	hwp->writeSeq(hwp, 0x02, 0x01);	/* write to plane 0 */
987706f2543Smrg	hwp->writeGr(hwp, 0x04, 0x00);	/* read plane 0 */
988706f2543Smrg	slowbcopy_frombus(hwp->Base, hwp->TextInfo, TEXT_AMOUNT);
989706f2543Smrg	hwp->writeSeq(hwp, 0x02, 0x02);	/* write to plane 1 */
990706f2543Smrg	hwp->writeGr(hwp, 0x04, 0x01);	/* read plane 1 */
991706f2543Smrg	slowbcopy_frombus(hwp->Base,
992706f2543Smrg		(unsigned char *)hwp->TextInfo + TEXT_AMOUNT, TEXT_AMOUNT);
993706f2543Smrg    }
994706f2543Smrg#endif /* SAVE_TEXT */
995706f2543Smrg
996706f2543Smrg    /* Restore clobbered registers */
997706f2543Smrg    hwp->writeAttr(hwp, 0x10, attr10);
998706f2543Smrg    hwp->writeSeq(hwp, 0x02, seq2);
999706f2543Smrg    hwp->writeSeq(hwp, 0x04, seq4);
1000706f2543Smrg    hwp->writeGr(hwp, 0x04, gr4);
1001706f2543Smrg    hwp->writeGr(hwp, 0x05, gr5);
1002706f2543Smrg    hwp->writeGr(hwp, 0x06, gr6);
1003706f2543Smrg    hwp->writeMiscOut(hwp, miscOut);
1004706f2543Smrg    hwp->IOBase = savedIOBase;
1005706f2543Smrg
1006706f2543Smrg    vgaHWBlankScreen(scrninfp, TRUE);
1007706f2543Smrg
1008706f2543Smrg    if (doMap)
1009706f2543Smrg	vgaHWUnmapMem(scrninfp);
1010706f2543Smrg
1011706f2543Smrg#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */
1012706f2543Smrg}
1013706f2543Smrg
1014706f2543Smrgvoid
1015706f2543SmrgvgaHWSaveMode(ScrnInfoPtr scrninfp, vgaRegPtr save)
1016706f2543Smrg{
1017706f2543Smrg    vgaHWPtr hwp = VGAHWPTR(scrninfp);
1018706f2543Smrg    int i;
1019706f2543Smrg
1020706f2543Smrg    save->MiscOutReg = hwp->readMiscOut(hwp);
1021706f2543Smrg    if (save->MiscOutReg & 0x01)
1022706f2543Smrg	hwp->IOBase = VGA_IOBASE_COLOR;
1023706f2543Smrg    else
1024706f2543Smrg	hwp->IOBase = VGA_IOBASE_MONO;
1025706f2543Smrg
1026706f2543Smrg    for (i = 0; i < save->numCRTC; i++) {
1027706f2543Smrg	save->CRTC[i] = hwp->readCrtc(hwp, i);
1028706f2543Smrg	DebugF("CRTC[0x%02x] = 0x%02x\n", i, save->CRTC[i]);
1029706f2543Smrg    }
1030706f2543Smrg
1031706f2543Smrg    hwp->enablePalette(hwp);
1032706f2543Smrg    for (i = 0; i < save->numAttribute; i++) {
1033706f2543Smrg	save->Attribute[i] = hwp->readAttr(hwp, i);
1034706f2543Smrg	DebugF("Attribute[0x%02x] = 0x%02x\n", i, save->Attribute[i]);
1035706f2543Smrg    }
1036706f2543Smrg    hwp->disablePalette(hwp);
1037706f2543Smrg
1038706f2543Smrg    for (i = 0; i < save->numGraphics; i++) {
1039706f2543Smrg	save->Graphics[i] = hwp->readGr(hwp, i);
1040706f2543Smrg	DebugF("Graphics[0x%02x] = 0x%02x\n", i, save->Graphics[i]);
1041706f2543Smrg    }
1042706f2543Smrg
1043706f2543Smrg    for (i = 1; i < save->numSequencer; i++) {
1044706f2543Smrg	save->Sequencer[i] = hwp->readSeq(hwp, i);
1045706f2543Smrg	DebugF("Sequencer[0x%02x] = 0x%02x\n", i, save->Sequencer[i]);
1046706f2543Smrg    }
1047706f2543Smrg}
1048706f2543Smrg
1049706f2543Smrg
1050706f2543Smrgvoid
1051706f2543SmrgvgaHWSaveColormap(ScrnInfoPtr scrninfp, vgaRegPtr save)
1052706f2543Smrg{
1053706f2543Smrg    vgaHWPtr hwp = VGAHWPTR(scrninfp);
1054706f2543Smrg    Bool readError = FALSE;
1055706f2543Smrg    int i;
1056706f2543Smrg
1057706f2543Smrg#ifdef NEED_SAVED_CMAP
1058706f2543Smrg    /*
1059706f2543Smrg     * Some ET4000 chips from 1991 have a HW bug that prevents the reading
1060706f2543Smrg     * of the color lookup table.  Mask rev 9042EAI is known to have this bug.
1061706f2543Smrg     *
1062706f2543Smrg     * If the colourmap is not readable, we set the saved map to a default
1063706f2543Smrg     * map (taken from Ferraro's "Programmer's Guide to the EGA and VGA
1064706f2543Smrg     * Cards" 2nd ed).
1065706f2543Smrg     */
1066706f2543Smrg
1067706f2543Smrg    /* Only save it once */
1068706f2543Smrg    if (hwp->cmapSaved)
1069706f2543Smrg	return;
1070706f2543Smrg
1071706f2543Smrg#if 0
1072706f2543Smrg    hwp->enablePalette(hwp);
1073706f2543Smrg#endif
1074706f2543Smrg
1075706f2543Smrg    hwp->writeDacMask(hwp, 0xFF);
1076706f2543Smrg
1077706f2543Smrg    /*
1078706f2543Smrg     * check if we can read the lookup table
1079706f2543Smrg     */
1080706f2543Smrg    hwp->writeDacReadAddr(hwp, 0x00);
1081706f2543Smrg    for (i = 0; i < 6; i++) {
1082706f2543Smrg	save->DAC[i] = hwp->readDacData(hwp);
1083706f2543Smrg	switch (i % 3) {
1084706f2543Smrg	case 0:
1085706f2543Smrg	    DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
1086706f2543Smrg	    break;
1087706f2543Smrg	case 1:
1088706f2543Smrg	    DebugF("0x%02x, ", save->DAC[i]);
1089706f2543Smrg	    break;
1090706f2543Smrg	case 2:
1091706f2543Smrg	    DebugF("0x%02x\n", save->DAC[i]);
1092706f2543Smrg	}
1093706f2543Smrg    }
1094706f2543Smrg
1095706f2543Smrg    /*
1096706f2543Smrg     * Check if we can read the palette -
1097706f2543Smrg     * use foreground color to prevent flashing.
1098706f2543Smrg     */
1099706f2543Smrg    hwp->writeDacWriteAddr(hwp, 0x01);
1100706f2543Smrg    for (i = 3; i < 6; i++)
1101706f2543Smrg	hwp->writeDacData(hwp, ~save->DAC[i] & DAC_TEST_MASK);
1102706f2543Smrg    hwp->writeDacReadAddr(hwp, 0x01);
1103706f2543Smrg    for (i = 3; i < 6; i++) {
1104706f2543Smrg	if (hwp->readDacData(hwp) != (~save->DAC[i] & DAC_TEST_MASK))
1105706f2543Smrg	    readError = TRUE;
1106706f2543Smrg    }
1107706f2543Smrg    hwp->writeDacWriteAddr(hwp, 0x01);
1108706f2543Smrg    for (i = 3; i < 6; i++)
1109706f2543Smrg	hwp->writeDacData(hwp, save->DAC[i]);
1110706f2543Smrg
1111706f2543Smrg    if (readError) {
1112706f2543Smrg	/*
1113706f2543Smrg	 * save the default lookup table
1114706f2543Smrg	 */
1115706f2543Smrg	memmove(save->DAC, defaultDAC, 768);
1116706f2543Smrg	xf86DrvMsg(scrninfp->scrnIndex, X_WARNING,
1117706f2543Smrg	   "Cannot read colourmap from VGA.  Will restore with default\n");
1118706f2543Smrg    } else {
1119706f2543Smrg	/* save the colourmap */
1120706f2543Smrg	hwp->writeDacReadAddr(hwp, 0x02);
1121706f2543Smrg	for (i = 6; i < 768; i++) {
1122706f2543Smrg	    save->DAC[i] = hwp->readDacData(hwp);
1123706f2543Smrg	    DACDelay(hwp);
1124706f2543Smrg	    switch (i % 3) {
1125706f2543Smrg	    case 0:
1126706f2543Smrg		DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]);
1127706f2543Smrg		break;
1128706f2543Smrg	    case 1:
1129706f2543Smrg		DebugF("0x%02x, ", save->DAC[i]);
1130706f2543Smrg		break;
1131706f2543Smrg	    case 2:
1132706f2543Smrg		DebugF("0x%02x\n", save->DAC[i]);
1133706f2543Smrg	    }
1134706f2543Smrg	}
1135706f2543Smrg    }
1136706f2543Smrg
1137706f2543Smrg    hwp->disablePalette(hwp);
1138706f2543Smrg    hwp->cmapSaved = TRUE;
1139706f2543Smrg#endif
1140706f2543Smrg}
1141706f2543Smrg
1142706f2543Smrg/*
1143706f2543Smrg * vgaHWSave --
1144706f2543Smrg *      save the current VGA state
1145706f2543Smrg */
1146706f2543Smrg
1147706f2543Smrgvoid
1148706f2543SmrgvgaHWSave(ScrnInfoPtr scrninfp, vgaRegPtr save, int flags)
1149706f2543Smrg{
1150706f2543Smrg    if (save == NULL)
1151706f2543Smrg	return;
1152706f2543Smrg
1153706f2543Smrg   if (flags & VGA_SR_CMAP)
1154706f2543Smrg	vgaHWSaveColormap(scrninfp, save);
1155706f2543Smrg
1156706f2543Smrg   if (flags & VGA_SR_MODE)
1157706f2543Smrg	vgaHWSaveMode(scrninfp, save);
1158706f2543Smrg
1159706f2543Smrg   if (flags & VGA_SR_FONTS)
1160706f2543Smrg	vgaHWSaveFonts(scrninfp, save);
1161706f2543Smrg}
1162706f2543Smrg
1163706f2543Smrg
1164706f2543Smrg/*
1165706f2543Smrg * vgaHWInit --
1166706f2543Smrg *      Handle the initialization, etc. of a screen.
1167706f2543Smrg *      Return FALSE on failure.
1168706f2543Smrg */
1169706f2543Smrg
1170706f2543SmrgBool
1171706f2543SmrgvgaHWInit(ScrnInfoPtr scrninfp, DisplayModePtr mode)
1172706f2543Smrg{
1173706f2543Smrg    unsigned int       i;
1174706f2543Smrg    vgaHWPtr hwp;
1175706f2543Smrg    vgaRegPtr regp;
1176706f2543Smrg    int depth = scrninfp->depth;
1177706f2543Smrg
1178706f2543Smrg    /*
1179706f2543Smrg     * make sure the vgaHWRec is allocated
1180706f2543Smrg     */
1181706f2543Smrg    if (!vgaHWGetHWRec(scrninfp))
1182706f2543Smrg	return FALSE;
1183706f2543Smrg    hwp = VGAHWPTR(scrninfp);
1184706f2543Smrg    regp = &hwp->ModeReg;
1185706f2543Smrg
1186706f2543Smrg    /*
1187706f2543Smrg     * compute correct Hsync & Vsync polarity
1188706f2543Smrg     */
1189706f2543Smrg    if ((mode->Flags & (V_PHSYNC | V_NHSYNC))
1190706f2543Smrg        && (mode->Flags & (V_PVSYNC | V_NVSYNC)))
1191706f2543Smrg    {
1192706f2543Smrg        regp->MiscOutReg = 0x23;
1193706f2543Smrg        if (mode->Flags & V_NHSYNC) regp->MiscOutReg |= 0x40;
1194706f2543Smrg        if (mode->Flags & V_NVSYNC) regp->MiscOutReg |= 0x80;
1195706f2543Smrg    }
1196706f2543Smrg    else
1197706f2543Smrg    {
1198706f2543Smrg        int VDisplay = mode->VDisplay;
1199706f2543Smrg        if (mode->Flags & V_DBLSCAN)
1200706f2543Smrg            VDisplay *= 2;
1201706f2543Smrg        if (mode->VScan > 1)
1202706f2543Smrg            VDisplay *= mode->VScan;
1203706f2543Smrg        if      (VDisplay < 400)
1204706f2543Smrg            regp->MiscOutReg = 0xA3;		/* +hsync -vsync */
1205706f2543Smrg        else if (VDisplay < 480)
1206706f2543Smrg            regp->MiscOutReg = 0x63;		/* -hsync +vsync */
1207706f2543Smrg        else if (VDisplay < 768)
1208706f2543Smrg            regp->MiscOutReg = 0xE3;		/* -hsync -vsync */
1209706f2543Smrg        else
1210706f2543Smrg            regp->MiscOutReg = 0x23;		/* +hsync +vsync */
1211706f2543Smrg    }
1212706f2543Smrg
1213706f2543Smrg    regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2;
1214706f2543Smrg
1215706f2543Smrg    /*
1216706f2543Smrg     * Time Sequencer
1217706f2543Smrg     */
1218706f2543Smrg    if (depth == 4)
1219706f2543Smrg        regp->Sequencer[0] = 0x02;
1220706f2543Smrg    else
1221706f2543Smrg        regp->Sequencer[0] = 0x00;
1222706f2543Smrg    if (mode->Flags & V_CLKDIV2)
1223706f2543Smrg        regp->Sequencer[1] = 0x09;
1224706f2543Smrg    else
1225706f2543Smrg        regp->Sequencer[1] = 0x01;
1226706f2543Smrg    if (depth == 1)
1227706f2543Smrg        regp->Sequencer[2] = 1 << BIT_PLANE;
1228706f2543Smrg    else
1229706f2543Smrg        regp->Sequencer[2] = 0x0F;
1230706f2543Smrg    regp->Sequencer[3] = 0x00;                             /* Font select */
1231706f2543Smrg    if (depth < 8)
1232706f2543Smrg        regp->Sequencer[4] = 0x06;                             /* Misc */
1233706f2543Smrg    else
1234706f2543Smrg        regp->Sequencer[4] = 0x0E;                             /* Misc */
1235706f2543Smrg
1236706f2543Smrg    /*
1237706f2543Smrg     * CRTC Controller
1238706f2543Smrg     */
1239706f2543Smrg    regp->CRTC[0]  = (mode->CrtcHTotal >> 3) - 5;
1240706f2543Smrg    regp->CRTC[1]  = (mode->CrtcHDisplay >> 3) - 1;
1241706f2543Smrg    regp->CRTC[2]  = (mode->CrtcHBlankStart >> 3) - 1;
1242706f2543Smrg    regp->CRTC[3]  = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
1243706f2543Smrg    i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F);
1244706f2543Smrg    if (i < 0x80)
1245706f2543Smrg	regp->CRTC[3] |= i;
1246706f2543Smrg    regp->CRTC[4]  = (mode->CrtcHSyncStart >> 3);
1247706f2543Smrg    regp->CRTC[5]  = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
1248706f2543Smrg	| (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
1249706f2543Smrg    regp->CRTC[6]  = (mode->CrtcVTotal - 2) & 0xFF;
1250706f2543Smrg    regp->CRTC[7]  = (((mode->CrtcVTotal - 2) & 0x100) >> 8)
1251706f2543Smrg	| (((mode->CrtcVDisplay - 1) & 0x100) >> 7)
1252706f2543Smrg	| ((mode->CrtcVSyncStart & 0x100) >> 6)
1253706f2543Smrg	| (((mode->CrtcVBlankStart - 1) & 0x100) >> 5)
1254706f2543Smrg	| 0x10
1255706f2543Smrg	| (((mode->CrtcVTotal - 2) & 0x200)   >> 4)
1256706f2543Smrg	| (((mode->CrtcVDisplay - 1) & 0x200) >> 3)
1257706f2543Smrg	| ((mode->CrtcVSyncStart & 0x200) >> 2);
1258706f2543Smrg    regp->CRTC[8]  = 0x00;
1259706f2543Smrg    regp->CRTC[9]  = (((mode->CrtcVBlankStart - 1) & 0x200) >> 4) | 0x40;
1260706f2543Smrg    if (mode->Flags & V_DBLSCAN)
1261706f2543Smrg	regp->CRTC[9] |= 0x80;
1262706f2543Smrg    if (mode->VScan >= 32)
1263706f2543Smrg	regp->CRTC[9] |= 0x1F;
1264706f2543Smrg    else if (mode->VScan > 1)
1265706f2543Smrg	regp->CRTC[9] |= mode->VScan - 1;
1266706f2543Smrg    regp->CRTC[10] = 0x00;
1267706f2543Smrg    regp->CRTC[11] = 0x00;
1268706f2543Smrg    regp->CRTC[12] = 0x00;
1269706f2543Smrg    regp->CRTC[13] = 0x00;
1270706f2543Smrg    regp->CRTC[14] = 0x00;
1271706f2543Smrg    regp->CRTC[15] = 0x00;
1272706f2543Smrg    regp->CRTC[16] = mode->CrtcVSyncStart & 0xFF;
1273706f2543Smrg    regp->CRTC[17] = (mode->CrtcVSyncEnd & 0x0F) | 0x20;
1274706f2543Smrg    regp->CRTC[18] = (mode->CrtcVDisplay - 1) & 0xFF;
1275706f2543Smrg    regp->CRTC[19] = scrninfp->displayWidth >> 4;  /* just a guess */
1276706f2543Smrg    regp->CRTC[20] = 0x00;
1277706f2543Smrg    regp->CRTC[21] = (mode->CrtcVBlankStart - 1) & 0xFF;
1278706f2543Smrg    regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1279706f2543Smrg    if (depth < 8)
1280706f2543Smrg	regp->CRTC[23] = 0xE3;
1281706f2543Smrg    else
1282706f2543Smrg	regp->CRTC[23] = 0xC3;
1283706f2543Smrg    regp->CRTC[24] = 0xFF;
1284706f2543Smrg
1285706f2543Smrg    vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
1286706f2543Smrg    vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
1287706f2543Smrg
1288706f2543Smrg    /*
1289706f2543Smrg     * Theory resumes here....
1290706f2543Smrg     */
1291706f2543Smrg
1292706f2543Smrg    /*
1293706f2543Smrg     * Graphics Display Controller
1294706f2543Smrg     */
1295706f2543Smrg    regp->Graphics[0] = 0x00;
1296706f2543Smrg    regp->Graphics[1] = 0x00;
1297706f2543Smrg    regp->Graphics[2] = 0x00;
1298706f2543Smrg    regp->Graphics[3] = 0x00;
1299706f2543Smrg    if (depth == 1) {
1300706f2543Smrg        regp->Graphics[4] = BIT_PLANE;
1301706f2543Smrg        regp->Graphics[5] = 0x00;
1302706f2543Smrg    } else {
1303706f2543Smrg        regp->Graphics[4] = 0x00;
1304706f2543Smrg        if (depth == 4)
1305706f2543Smrg            regp->Graphics[5] = 0x02;
1306706f2543Smrg        else
1307706f2543Smrg            regp->Graphics[5] = 0x40;
1308706f2543Smrg    }
1309706f2543Smrg    regp->Graphics[6] = 0x05;   /* only map 64k VGA memory !!!! */
1310706f2543Smrg    regp->Graphics[7] = 0x0F;
1311706f2543Smrg    regp->Graphics[8] = 0xFF;
1312706f2543Smrg
1313706f2543Smrg    if (depth == 1) {
1314706f2543Smrg        /* Initialise the Mono map according to which bit-plane gets used */
1315706f2543Smrg
1316706f2543Smrg	Bool flipPixels = xf86GetFlipPixels();
1317706f2543Smrg
1318706f2543Smrg        for (i=0; i<16; i++)
1319706f2543Smrg            if (((i & (1 << BIT_PLANE)) != 0) != flipPixels)
1320706f2543Smrg                regp->Attribute[i] = WHITE_VALUE;
1321706f2543Smrg            else
1322706f2543Smrg                regp->Attribute[i] = BLACK_VALUE;
1323706f2543Smrg
1324706f2543Smrg        regp->Attribute[16] = 0x01;  /* -VGA2- */ /* wrong for the ET4000 */
1325706f2543Smrg	if (!hwp->ShowOverscan)
1326706f2543Smrg            regp->Attribute[OVERSCAN] = OVERSCAN_VALUE;  /* -VGA2- */
1327706f2543Smrg    } else {
1328706f2543Smrg        regp->Attribute[0]  = 0x00; /* standard colormap translation */
1329706f2543Smrg        regp->Attribute[1]  = 0x01;
1330706f2543Smrg        regp->Attribute[2]  = 0x02;
1331706f2543Smrg        regp->Attribute[3]  = 0x03;
1332706f2543Smrg        regp->Attribute[4]  = 0x04;
1333706f2543Smrg        regp->Attribute[5]  = 0x05;
1334706f2543Smrg        regp->Attribute[6]  = 0x06;
1335706f2543Smrg        regp->Attribute[7]  = 0x07;
1336706f2543Smrg        regp->Attribute[8]  = 0x08;
1337706f2543Smrg        regp->Attribute[9]  = 0x09;
1338706f2543Smrg        regp->Attribute[10] = 0x0A;
1339706f2543Smrg        regp->Attribute[11] = 0x0B;
1340706f2543Smrg        regp->Attribute[12] = 0x0C;
1341706f2543Smrg        regp->Attribute[13] = 0x0D;
1342706f2543Smrg        regp->Attribute[14] = 0x0E;
1343706f2543Smrg        regp->Attribute[15] = 0x0F;
1344706f2543Smrg        if (depth == 4)
1345706f2543Smrg            regp->Attribute[16] = 0x81; /* wrong for the ET4000 */
1346706f2543Smrg        else
1347706f2543Smrg            regp->Attribute[16] = 0x41; /* wrong for the ET4000 */
1348706f2543Smrg        /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */
1349706f2543Smrg    }
1350706f2543Smrg    regp->Attribute[18] = 0x0F;
1351706f2543Smrg    regp->Attribute[19] = 0x00;
1352706f2543Smrg    regp->Attribute[20] = 0x00;
1353706f2543Smrg
1354706f2543Smrg    return TRUE;
1355706f2543Smrg}
1356706f2543Smrg
1357706f2543Smrg    /*
1358706f2543Smrg     * OK, so much for theory.  Now, let's deal with the >real< world...
1359706f2543Smrg     *
1360706f2543Smrg     * The above CRTC settings are precise in theory, except that many, if not
1361706f2543Smrg     * most, VGA clones fail to reset the blanking signal when the character or
1362706f2543Smrg     * line counter reaches [HV]Total.  In this case, the signal is only
1363706f2543Smrg     * unblanked when the counter reaches [HV]BlankEnd (mod 64, 128 or 256 as
1364706f2543Smrg     * the case may be) at the start of the >next< scanline or frame, which
1365706f2543Smrg     * means only part of the screen shows.  This affects how null overscans
1366706f2543Smrg     * are to be implemented on such adapters.
1367706f2543Smrg     *
1368706f2543Smrg     * Henceforth, VGA cores that implement this broken, but unfortunately
1369706f2543Smrg     * common, behaviour are to be designated as KGA's, in honour of Koen
1370706f2543Smrg     * Gadeyne, whose zeal to eliminate overscans (read: fury) set in motion
1371706f2543Smrg     * a series of events that led to the discovery of this problem.
1372706f2543Smrg     *
1373706f2543Smrg     * Some VGA's are KGA's only in the horizontal, or only in the vertical,
1374706f2543Smrg     * some in both, others in neither.  Don't let anyone tell you there is
1375706f2543Smrg     * such a thing as a VGA "standard"...  And, thank the Creator for the fact
1376706f2543Smrg     * that Hilbert spaces are not yet implemented in this industry.
1377706f2543Smrg     *
1378706f2543Smrg     * The following implements a trick suggested by David Dawes.  This sets
1379706f2543Smrg     * [HV]BlankEnd to zero if the blanking interval does not already contain a
1380706f2543Smrg     * 0-point, and decrements it by one otherwise.  In the latter case, this
1381706f2543Smrg     * will produce a left and/or top overscan which the colourmap code will
1382706f2543Smrg     * (still) need to ensure is as close to black as possible.  This will make
1383706f2543Smrg     * the behaviour consistent across all chipsets, while allowing all
1384706f2543Smrg     * chipsets to display the entire screen.  Non-KGA drivers can ignore the
1385706f2543Smrg     * following in their own copy of this code.
1386706f2543Smrg     *
1387706f2543Smrg     * --  TSI @ UQV,  1998.08.21
1388706f2543Smrg     */
1389706f2543Smrg
1390706f2543SmrgCARD32
1391706f2543SmrgvgaHWHBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1392706f2543Smrg	       unsigned int Flags)
1393706f2543Smrg{
1394706f2543Smrg    int nExtBits = (nBits < 6) ? 0 : nBits - 6;
1395706f2543Smrg    CARD32 ExtBits;
1396706f2543Smrg    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6;
1397706f2543Smrg
1398706f2543Smrg    regp->CRTC[3]  = (regp->CRTC[3] & ~0x1F)
1399706f2543Smrg                     | (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F);
1400706f2543Smrg    regp->CRTC[5]  = (regp->CRTC[5] & ~0x80)
1401706f2543Smrg                     | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2);
1402706f2543Smrg    ExtBits        = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask;
1403706f2543Smrg
1404706f2543Smrg    /* First the horizontal case */
1405706f2543Smrg    if ((Flags & KGA_FIX_OVERSCAN)
1406706f2543Smrg	&& ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3)))
1407706f2543Smrg    {
1408706f2543Smrg	int i = (regp->CRTC[3] & 0x1F)
1409706f2543Smrg	    | ((regp->CRTC[5] & 0x80) >> 2)
1410706f2543Smrg	    | ExtBits;
1411706f2543Smrg	if (Flags & KGA_ENABLE_ON_ZERO) {
1412706f2543Smrg	    if ((i-- > (((mode->CrtcHBlankStart >> 3) - 1)
1413706f2543Smrg		       & (0x3F | ExtBitMask)))
1414706f2543Smrg	    && (mode->CrtcHBlankEnd == mode->CrtcHTotal))
1415706f2543Smrg	    i = 0;
1416706f2543Smrg	} else if (Flags & KGA_BE_TOT_DEC)
1417706f2543Smrg	    i--;
1418706f2543Smrg	regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F);
1419706f2543Smrg	regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80);
1420706f2543Smrg	ExtBits = i & ExtBitMask;
1421706f2543Smrg    }
1422706f2543Smrg    return ExtBits >> 6;
1423706f2543Smrg}
1424706f2543Smrg
1425706f2543Smrg    /*
1426706f2543Smrg     * The vertical case is a little trickier.  Some VGA's ignore bit 0x80 of
1427706f2543Smrg     * CRTC[22].  Also, in some cases, a zero CRTC[22] will still blank the
1428706f2543Smrg     * very first scanline in a double- or multi-scanned mode.  This last case
1429706f2543Smrg     * needs further investigation.
1430706f2543Smrg     */
1431706f2543SmrgCARD32
1432706f2543SmrgvgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits,
1433706f2543Smrg	       unsigned int Flags)
1434706f2543Smrg{
1435706f2543Smrg    CARD32 ExtBits;
1436706f2543Smrg    CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8);
1437706f2543Smrg    CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8;
1438706f2543Smrg    /* If width is not known nBits should be 0. In this
1439706f2543Smrg     * case BitMask is set to 0 so we can check for it. */
1440706f2543Smrg    CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1);
1441706f2543Smrg    int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF;
1442706f2543Smrg    regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1443706f2543Smrg    ExtBits        = (mode->CrtcVBlankEnd - 1) & ExtBitMask;
1444706f2543Smrg
1445706f2543Smrg    if ((Flags & KGA_FIX_OVERSCAN)
1446706f2543Smrg	&& (mode->CrtcVBlankEnd == mode->CrtcVTotal))
1447706f2543Smrg      /* Null top overscan */
1448706f2543Smrg    {
1449706f2543Smrg	int i = regp->CRTC[22] | ExtBits;
1450706f2543Smrg	if (Flags & KGA_ENABLE_ON_ZERO) {
1451706f2543Smrg	    if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask)))
1452706f2543Smrg	     || ((i > VBlankStart)  &&  		/* 8-bit case */
1453706f2543Smrg	    ((i & 0x7F) > (VBlankStart & 0x7F)))) &&	/* 7-bit case */
1454706f2543Smrg	    !(regp->CRTC[9] & 0x9F))			/* 1 scanline/row */
1455706f2543Smrg	    i = 0;
1456706f2543Smrg	else
1457706f2543Smrg	    i = (i - 1);
1458706f2543Smrg	} else if (Flags & KGA_BE_TOT_DEC)
1459706f2543Smrg	    i = (i - 1);
1460706f2543Smrg
1461706f2543Smrg	regp->CRTC[22] = i & 0xFF;
1462706f2543Smrg	ExtBits = i & 0xFF00;
1463706f2543Smrg    }
1464706f2543Smrg    return ExtBits >> 8;
1465706f2543Smrg}
1466706f2543Smrg
1467706f2543Smrg/*
1468706f2543Smrg * these are some more hardware specific helpers, formerly in vga.c
1469706f2543Smrg */
1470706f2543Smrgstatic void
1471706f2543SmrgvgaHWGetHWRecPrivate(void)
1472706f2543Smrg{
1473706f2543Smrg    if (vgaHWPrivateIndex < 0)
1474706f2543Smrg	vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
1475706f2543Smrg    return;
1476706f2543Smrg}
1477706f2543Smrg
1478706f2543Smrg
1479706f2543Smrgstatic void
1480706f2543SmrgvgaHWFreeRegs(vgaRegPtr regp)
1481706f2543Smrg{
1482706f2543Smrg    free(regp->CRTC);
1483706f2543Smrg
1484706f2543Smrg    regp->CRTC =
1485706f2543Smrg    regp->Sequencer =
1486706f2543Smrg    regp->Graphics =
1487706f2543Smrg    regp->Attribute = NULL;
1488706f2543Smrg
1489706f2543Smrg    regp->numCRTC =
1490706f2543Smrg    regp->numSequencer =
1491706f2543Smrg    regp->numGraphics =
1492706f2543Smrg    regp->numAttribute = 0;
1493706f2543Smrg}
1494706f2543Smrg
1495706f2543Smrg
1496706f2543Smrg
1497706f2543Smrgstatic Bool
1498706f2543SmrgvgaHWAllocRegs(vgaRegPtr regp)
1499706f2543Smrg{
1500706f2543Smrg    unsigned char *buf;
1501706f2543Smrg
1502706f2543Smrg    if ((regp->numCRTC + regp->numSequencer + regp->numGraphics +
1503706f2543Smrg         regp->numAttribute) == 0)
1504706f2543Smrg        return FALSE;
1505706f2543Smrg
1506706f2543Smrg    buf = calloc(regp->numCRTC +
1507706f2543Smrg    		  regp->numSequencer +
1508706f2543Smrg		  regp->numGraphics +
1509706f2543Smrg		  regp->numAttribute, 1);
1510706f2543Smrg    if (!buf)
1511706f2543Smrg    	return FALSE;
1512706f2543Smrg
1513706f2543Smrg    regp->CRTC = buf;
1514706f2543Smrg    regp->Sequencer = regp->CRTC + regp->numCRTC;
1515706f2543Smrg    regp->Graphics = regp->Sequencer + regp->numSequencer;
1516706f2543Smrg    regp->Attribute = regp->Graphics + regp->numGraphics;
1517706f2543Smrg
1518706f2543Smrg    return TRUE;
1519706f2543Smrg}
1520706f2543Smrg
1521706f2543Smrg
1522706f2543SmrgBool
1523706f2543SmrgvgaHWAllocDefaultRegs(vgaRegPtr regp)
1524706f2543Smrg{
1525706f2543Smrg    regp->numCRTC = VGA_NUM_CRTC;
1526706f2543Smrg    regp->numSequencer = VGA_NUM_SEQ;
1527706f2543Smrg    regp->numGraphics = VGA_NUM_GFX;
1528706f2543Smrg    regp->numAttribute = VGA_NUM_ATTR;
1529706f2543Smrg
1530706f2543Smrg    return vgaHWAllocRegs(regp);
1531706f2543Smrg}
1532706f2543Smrg
1533706f2543Smrg
1534706f2543SmrgBool
1535706f2543SmrgvgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer,
1536706f2543Smrg		  int numGraphics, int numAttribute)
1537706f2543Smrg{
1538706f2543Smrg#define VGAHWMINNUM(regtype) \
1539706f2543Smrg	((newMode.num##regtype < regp->num##regtype) ? \
1540706f2543Smrg	 (newMode.num##regtype) : (regp->num##regtype))
1541706f2543Smrg#define VGAHWCOPYREGSET(regtype) \
1542706f2543Smrg	memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype))
1543706f2543Smrg
1544706f2543Smrg    vgaRegRec newMode, newSaved;
1545706f2543Smrg    vgaRegPtr regp;
1546706f2543Smrg
1547706f2543Smrg    regp = &VGAHWPTR(scrp)->ModeReg;
1548706f2543Smrg    memcpy (&newMode, regp, sizeof(vgaRegRec));
1549706f2543Smrg
1550706f2543Smrg    /* allocate space for new registers */
1551706f2543Smrg
1552706f2543Smrg    regp = &newMode;
1553706f2543Smrg    regp->numCRTC = numCRTC;
1554706f2543Smrg    regp->numSequencer = numSequencer;
1555706f2543Smrg    regp->numGraphics = numGraphics;
1556706f2543Smrg    regp->numAttribute = numAttribute;
1557706f2543Smrg    if (!vgaHWAllocRegs(regp))
1558706f2543Smrg    	return FALSE;
1559706f2543Smrg
1560706f2543Smrg    regp = &VGAHWPTR(scrp)->SavedReg;
1561706f2543Smrg    memcpy (&newSaved, regp, sizeof(vgaRegRec));
1562706f2543Smrg
1563706f2543Smrg    regp = &newSaved;
1564706f2543Smrg    regp->numCRTC = numCRTC;
1565706f2543Smrg    regp->numSequencer = numSequencer;
1566706f2543Smrg    regp->numGraphics = numGraphics;
1567706f2543Smrg    regp->numAttribute = numAttribute;
1568706f2543Smrg    if (!vgaHWAllocRegs(regp)) {
1569706f2543Smrg        vgaHWFreeRegs(&newMode);
1570706f2543Smrg    	return FALSE;
1571706f2543Smrg    }
1572706f2543Smrg
1573706f2543Smrg    /* allocations succeeded, copy register data into new space */
1574706f2543Smrg
1575706f2543Smrg    regp = &VGAHWPTR(scrp)->ModeReg;
1576706f2543Smrg    VGAHWCOPYREGSET(CRTC);
1577706f2543Smrg    VGAHWCOPYREGSET(Sequencer);
1578706f2543Smrg    VGAHWCOPYREGSET(Graphics);
1579706f2543Smrg    VGAHWCOPYREGSET(Attribute);
1580706f2543Smrg
1581706f2543Smrg    regp = &VGAHWPTR(scrp)->SavedReg;
1582706f2543Smrg    VGAHWCOPYREGSET(CRTC);
1583706f2543Smrg    VGAHWCOPYREGSET(Sequencer);
1584706f2543Smrg    VGAHWCOPYREGSET(Graphics);
1585706f2543Smrg    VGAHWCOPYREGSET(Attribute);
1586706f2543Smrg
1587706f2543Smrg    /* free old register arrays */
1588706f2543Smrg
1589706f2543Smrg    regp = &VGAHWPTR(scrp)->ModeReg;
1590706f2543Smrg    vgaHWFreeRegs(regp);
1591706f2543Smrg    memcpy(regp, &newMode, sizeof(vgaRegRec));
1592706f2543Smrg
1593706f2543Smrg    regp = &VGAHWPTR(scrp)->SavedReg;
1594706f2543Smrg    vgaHWFreeRegs(regp);
1595706f2543Smrg    memcpy(regp, &newSaved, sizeof(vgaRegRec));
1596706f2543Smrg
1597706f2543Smrg    return TRUE;
1598706f2543Smrg
1599706f2543Smrg#undef VGAHWMINNUM
1600706f2543Smrg#undef VGAHWCOPYREGSET
1601706f2543Smrg}
1602706f2543Smrg
1603706f2543Smrg
1604706f2543SmrgBool
1605706f2543SmrgvgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)
1606706f2543Smrg{
1607706f2543Smrg    vgaHWFreeRegs(dst);
1608706f2543Smrg
1609706f2543Smrg    memcpy(dst, src, sizeof(vgaRegRec));
1610706f2543Smrg
1611706f2543Smrg    if (!vgaHWAllocRegs(dst))
1612706f2543Smrg	return FALSE;
1613706f2543Smrg
1614706f2543Smrg    memcpy(dst->CRTC, src->CRTC, src->numCRTC);
1615706f2543Smrg    memcpy(dst->Sequencer, src->Sequencer, src->numSequencer);
1616706f2543Smrg    memcpy(dst->Graphics, src->Graphics, src->numGraphics);
1617706f2543Smrg    memcpy(dst->Attribute, src->Attribute, src->numAttribute);
1618706f2543Smrg
1619706f2543Smrg    return TRUE;
1620706f2543Smrg}
1621706f2543Smrg
1622706f2543Smrg
1623706f2543SmrgBool
1624706f2543SmrgvgaHWGetHWRec(ScrnInfoPtr scrp)
1625706f2543Smrg{
1626706f2543Smrg    vgaRegPtr regp;
1627706f2543Smrg    vgaHWPtr hwp;
1628706f2543Smrg    int i;
1629706f2543Smrg
1630706f2543Smrg    /*
1631706f2543Smrg     * Let's make sure that the private exists and allocate one.
1632706f2543Smrg     */
1633706f2543Smrg    vgaHWGetHWRecPrivate();
1634706f2543Smrg    /*
1635706f2543Smrg     * New privates are always set to NULL, so we can check if the allocation
1636706f2543Smrg     * has already been done.
1637706f2543Smrg     */
1638706f2543Smrg    if (VGAHWPTR(scrp))
1639706f2543Smrg	return TRUE;
1640706f2543Smrg    hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1);
1641706f2543Smrg    regp = &VGAHWPTR(scrp)->ModeReg;
1642706f2543Smrg
1643706f2543Smrg    if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) ||
1644706f2543Smrg    	(!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) {
1645706f2543Smrg        free(hwp);
1646706f2543Smrg	return FALSE;
1647706f2543Smrg    }
1648706f2543Smrg
1649706f2543Smrg    if (scrp->bitsPerPixel == 1) {
1650706f2543Smrg	rgb blackColour = scrp->display->blackColour,
1651706f2543Smrg	    whiteColour = scrp->display->whiteColour;
1652706f2543Smrg
1653706f2543Smrg	if (blackColour.red   > 0x3F) blackColour.red   = 0x3F;
1654706f2543Smrg	if (blackColour.green > 0x3F) blackColour.green = 0x3F;
1655706f2543Smrg	if (blackColour.blue  > 0x3F) blackColour.blue  = 0x3F;
1656706f2543Smrg
1657706f2543Smrg	if (whiteColour.red   > 0x3F) whiteColour.red   = 0x3F;
1658706f2543Smrg	if (whiteColour.green > 0x3F) whiteColour.green = 0x3F;
1659706f2543Smrg	if (whiteColour.blue  > 0x3F) whiteColour.blue  = 0x3F;
1660706f2543Smrg
1661706f2543Smrg	if ((blackColour.red   == whiteColour.red  ) &&
1662706f2543Smrg	    (blackColour.green == whiteColour.green) &&
1663706f2543Smrg	    (blackColour.blue  == whiteColour.blue )) {
1664706f2543Smrg	    blackColour.red   ^= 0x3F;
1665706f2543Smrg	    blackColour.green ^= 0x3F;
1666706f2543Smrg	    blackColour.blue  ^= 0x3F;
1667706f2543Smrg	}
1668706f2543Smrg
1669706f2543Smrg        /*
1670706f2543Smrg         * initialize default colormap for monochrome
1671706f2543Smrg         */
1672706f2543Smrg        for (i=0; i<3;   i++) regp->DAC[i] = 0x00;
1673706f2543Smrg        for (i=3; i<768; i++) regp->DAC[i] = 0x3F;
1674706f2543Smrg        i = BLACK_VALUE * 3;
1675706f2543Smrg        regp->DAC[i++] = blackColour.red;
1676706f2543Smrg        regp->DAC[i++] = blackColour.green;
1677706f2543Smrg        regp->DAC[i] = blackColour.blue;
1678706f2543Smrg        i = WHITE_VALUE * 3;
1679706f2543Smrg        regp->DAC[i++] = whiteColour.red;
1680706f2543Smrg        regp->DAC[i++] = whiteColour.green;
1681706f2543Smrg        regp->DAC[i] = whiteColour.blue;
1682706f2543Smrg        i = OVERSCAN_VALUE * 3;
1683706f2543Smrg        regp->DAC[i++] = 0x00;
1684706f2543Smrg        regp->DAC[i++] = 0x00;
1685706f2543Smrg        regp->DAC[i] = 0x00;
1686706f2543Smrg    } else {
1687706f2543Smrg	/* Set all colours to black */
1688706f2543Smrg        for (i=0; i<768; i++) regp->DAC[i] = 0x00;
1689706f2543Smrg        /* ... and the overscan */
1690706f2543Smrg        if (scrp->depth >= 4)
1691706f2543Smrg            regp->Attribute[OVERSCAN] = 0xFF;
1692706f2543Smrg    }
1693706f2543Smrg    if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) {
1694706f2543Smrg	xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan");
1695706f2543Smrg	xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n");
1696706f2543Smrg	regp->DAC[765] = 0x3F;
1697706f2543Smrg	regp->DAC[766] = 0x00;
1698706f2543Smrg	regp->DAC[767] = 0x3F;
1699706f2543Smrg	regp->Attribute[OVERSCAN] = 0xFF;
1700706f2543Smrg	hwp->ShowOverscan = TRUE;
1701706f2543Smrg    } else
1702706f2543Smrg	hwp->ShowOverscan = FALSE;
1703706f2543Smrg
1704706f2543Smrg    hwp->paletteEnabled = FALSE;
1705706f2543Smrg    hwp->cmapSaved = FALSE;
1706706f2543Smrg    hwp->MapSize = 0;
1707706f2543Smrg    hwp->pScrn = scrp;
1708706f2543Smrg
1709706f2543Smrg    /* Initialise the function pointers with the standard VGA versions */
1710706f2543Smrg    vgaHWSetStdFuncs(hwp);
1711706f2543Smrg
1712706f2543Smrg    hwp->PIOOffset = scrp->domainIOBase;
1713706f2543Smrg    hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]);
1714706f2543Smrg
1715706f2543Smrg    return TRUE;
1716706f2543Smrg}
1717706f2543Smrg
1718706f2543Smrg
1719706f2543Smrgvoid
1720706f2543SmrgvgaHWFreeHWRec(ScrnInfoPtr scrp)
1721706f2543Smrg{
1722706f2543Smrg    if (vgaHWPrivateIndex >= 0) {
1723706f2543Smrg	vgaHWPtr hwp = VGAHWPTR(scrp);
1724706f2543Smrg
1725706f2543Smrg	if (!hwp)
1726706f2543Smrg	    return;
1727706f2543Smrg
1728706f2543Smrg	free(hwp->FontInfo1);
1729706f2543Smrg	free(hwp->FontInfo2);
1730706f2543Smrg	free(hwp->TextInfo);
1731706f2543Smrg
1732706f2543Smrg	vgaHWFreeRegs (&hwp->ModeReg);
1733706f2543Smrg	vgaHWFreeRegs (&hwp->SavedReg);
1734706f2543Smrg
1735706f2543Smrg	free(hwp);
1736706f2543Smrg	VGAHWPTRLVAL(scrp) = NULL;
1737706f2543Smrg    }
1738706f2543Smrg}
1739706f2543Smrg
1740706f2543Smrg
1741706f2543SmrgBool
1742706f2543SmrgvgaHWMapMem(ScrnInfoPtr scrp)
1743706f2543Smrg{
1744706f2543Smrg    vgaHWPtr hwp = VGAHWPTR(scrp);
1745706f2543Smrg    int scr_index = scrp->scrnIndex;
1746706f2543Smrg
1747706f2543Smrg    if (hwp->Base)
1748706f2543Smrg	return TRUE;
1749706f2543Smrg
1750706f2543Smrg    /* If not set, initialise with the defaults */
1751706f2543Smrg    if (hwp->MapSize == 0)
1752706f2543Smrg	hwp->MapSize = VGA_DEFAULT_MEM_SIZE;
1753706f2543Smrg    if (hwp->MapPhys == 0)
1754706f2543Smrg	hwp->MapPhys = VGA_DEFAULT_PHYS_ADDR;
1755706f2543Smrg
1756706f2543Smrg    /*
1757706f2543Smrg     * Map as VIDMEM_MMIO_32BIT because WC
1758706f2543Smrg     * is bad when there is page flipping.
1759706f2543Smrg     * XXX This is not correct but we do it
1760706f2543Smrg     * for now.
1761706f2543Smrg     */
1762706f2543Smrg    DebugF("Mapping VGAMem\n");
1763706f2543Smrg    hwp->Base = xf86MapDomainMemory(scr_index, VIDMEM_MMIO_32BIT, hwp->dev,
1764706f2543Smrg				    hwp->MapPhys, hwp->MapSize);
1765706f2543Smrg    return hwp->Base != NULL;
1766706f2543Smrg}
1767706f2543Smrg
1768706f2543Smrg
1769706f2543Smrgvoid
1770706f2543SmrgvgaHWUnmapMem(ScrnInfoPtr scrp)
1771706f2543Smrg{
1772706f2543Smrg    vgaHWPtr hwp = VGAHWPTR(scrp);
1773706f2543Smrg    int scr_index = scrp->scrnIndex;
1774706f2543Smrg
1775706f2543Smrg    if (hwp->Base == NULL)
1776706f2543Smrg	return;
1777706f2543Smrg
1778706f2543Smrg    DebugF("Unmapping VGAMem\n");
1779706f2543Smrg    xf86UnMapVidMem(scr_index, hwp->Base, hwp->MapSize);
1780706f2543Smrg    hwp->Base = NULL;
1781706f2543Smrg}
1782706f2543Smrg
1783706f2543Smrgint
1784706f2543SmrgvgaHWGetIndex(void)
1785706f2543Smrg{
1786706f2543Smrg    return vgaHWPrivateIndex;
1787706f2543Smrg}
1788706f2543Smrg
1789706f2543Smrg
1790706f2543Smrgvoid
1791706f2543SmrgvgaHWGetIOBase(vgaHWPtr hwp)
1792706f2543Smrg{
1793706f2543Smrg    hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ?
1794706f2543Smrg				VGA_IOBASE_COLOR : VGA_IOBASE_MONO;
1795706f2543Smrg    xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3,
1796706f2543Smrg	"vgaHWGetIOBase: hwp->IOBase is 0x%04x, hwp->PIOOffset is 0x%04lx\n",
1797706f2543Smrg	hwp->IOBase, hwp->PIOOffset);
1798706f2543Smrg}
1799706f2543Smrg
1800706f2543Smrg
1801706f2543Smrgvoid
1802706f2543SmrgvgaHWLock(vgaHWPtr hwp)
1803706f2543Smrg{
1804706f2543Smrg    /* Protect CRTC[0-7] */
1805706f2543Smrg    hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80);
1806706f2543Smrg}
1807706f2543Smrg
1808706f2543Smrgvoid
1809706f2543SmrgvgaHWUnlock(vgaHWPtr hwp)
1810706f2543Smrg{
1811706f2543Smrg    /* Unprotect CRTC[0-7] */
1812706f2543Smrg     hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80);
1813706f2543Smrg}
1814706f2543Smrg
1815706f2543Smrg
1816706f2543Smrgvoid
1817706f2543SmrgvgaHWEnable(vgaHWPtr hwp)
1818706f2543Smrg{
1819706f2543Smrg    hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01);
1820706f2543Smrg}
1821706f2543Smrg
1822706f2543Smrg
1823706f2543Smrgvoid
1824706f2543SmrgvgaHWDisable(vgaHWPtr hwp)
1825706f2543Smrg{
1826706f2543Smrg    hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01);
1827706f2543Smrg}
1828706f2543Smrg
1829706f2543Smrg
1830706f2543Smrgstatic void
1831706f2543SmrgvgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
1832706f2543Smrg		 VisualPtr pVisual)
1833706f2543Smrg{
1834706f2543Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1835706f2543Smrg    int i, index;
1836706f2543Smrg
1837706f2543Smrg    for (i = 0; i < numColors; i++) {
1838706f2543Smrg	index = indices[i];
1839706f2543Smrg	hwp->writeDacWriteAddr(hwp, index);
1840706f2543Smrg	DACDelay(hwp);
1841706f2543Smrg	hwp->writeDacData(hwp, colors[index].red);
1842706f2543Smrg	DACDelay(hwp);
1843706f2543Smrg	hwp->writeDacData(hwp, colors[index].green);
1844706f2543Smrg	DACDelay(hwp);
1845706f2543Smrg	hwp->writeDacData(hwp, colors[index].blue);
1846706f2543Smrg	DACDelay(hwp);
1847706f2543Smrg    }
1848706f2543Smrg
1849706f2543Smrg    /* This shouldn't be necessary, but we'll play safe. */
1850706f2543Smrg    hwp->disablePalette(hwp);
1851706f2543Smrg}
1852706f2543Smrg
1853706f2543Smrg
1854706f2543Smrgstatic void
1855706f2543SmrgvgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan)
1856706f2543Smrg{
1857706f2543Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1858706f2543Smrg
1859706f2543Smrg    if (overscan < 0 || overscan > 255)
1860706f2543Smrg	return;
1861706f2543Smrg
1862706f2543Smrg    hwp->enablePalette(hwp);
1863706f2543Smrg    hwp->writeAttr(hwp, OVERSCAN, overscan);
1864706f2543Smrg
1865706f2543Smrg#ifdef DEBUGOVERSCAN
1866706f2543Smrg    {
1867706f2543Smrg	int ov = hwp->readAttr(hwp, OVERSCAN);
1868706f2543Smrg	int red, green, blue;
1869706f2543Smrg
1870706f2543Smrg	hwp->writeDacReadAddr(hwp, ov);
1871706f2543Smrg	red = hwp->readDacData(hwp);
1872706f2543Smrg	green = hwp->readDacData(hwp);
1873706f2543Smrg	blue = hwp->readDacData(hwp);
1874706f2543Smrg	ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n",
1875706f2543Smrg		ov, red, green, blue);
1876706f2543Smrg    }
1877706f2543Smrg#endif
1878706f2543Smrg
1879706f2543Smrg    hwp->disablePalette(hwp);
1880706f2543Smrg}
1881706f2543Smrg
1882706f2543Smrg
1883706f2543SmrgBool
1884706f2543SmrgvgaHWHandleColormaps(ScreenPtr pScreen)
1885706f2543Smrg{
1886706f2543Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1887706f2543Smrg
1888706f2543Smrg    if (pScrn->depth > 1 && pScrn->depth <= 8) {
1889706f2543Smrg	return xf86HandleColormaps(pScreen, 1 << pScrn->depth,
1890706f2543Smrg				   pScrn->rgbBits, vgaHWLoadPalette,
1891706f2543Smrg				   pScrn->depth > 4 ? vgaHWSetOverscan : NULL,
1892706f2543Smrg				   CMAP_RELOAD_ON_MODE_SWITCH);
1893706f2543Smrg    }
1894706f2543Smrg    return TRUE;
1895706f2543Smrg}
1896706f2543Smrg
1897706f2543Smrg/* ----------------------- DDC support ------------------------*/
1898706f2543Smrg/*
1899706f2543Smrg * Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total
1900706f2543Smrg * to read out EDID at a faster rate. Allowed maximum is 25kHz with
1901706f2543Smrg * 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen
1902706f2543Smrg * readback, enable access to cr00-cr07.
1903706f2543Smrg */
1904706f2543Smrg
1905706f2543Smrg/* vertical timings */
1906706f2543Smrg#define DISPLAY_END 0x04
1907706f2543Smrg#define BLANK_START DISPLAY_END
1908706f2543Smrg#define SYNC_START BLANK_START
1909706f2543Smrg#define SYNC_END 0x09
1910706f2543Smrg#define BLANK_END SYNC_END
1911706f2543Smrg#define V_TOTAL BLANK_END
1912706f2543Smrg/* this function doesn't have to be reentrant for our purposes */
1913706f2543Smrgstruct _vgaDdcSave {
1914706f2543Smrg    unsigned char cr03;
1915706f2543Smrg    unsigned char cr06;
1916706f2543Smrg    unsigned char cr07;
1917706f2543Smrg    unsigned char cr09;
1918706f2543Smrg    unsigned char cr10;
1919706f2543Smrg    unsigned char cr11;
1920706f2543Smrg    unsigned char cr12;
1921706f2543Smrg    unsigned char cr15;
1922706f2543Smrg    unsigned char cr16;
1923706f2543Smrg    unsigned char msr;
1924706f2543Smrg};
1925706f2543Smrg
1926706f2543Smrgvoid
1927706f2543SmrgvgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed)
1928706f2543Smrg{
1929706f2543Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1930706f2543Smrg    unsigned char tmp;
1931706f2543Smrg    struct _vgaDdcSave* save;
1932706f2543Smrg    switch (speed) {
1933706f2543Smrg    case DDC_FAST:
1934706f2543Smrg
1935706f2543Smrg        if (hwp->ddc != NULL) break;
1936706f2543Smrg        hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave),1);
1937706f2543Smrg	save = (struct _vgaDdcSave *)hwp->ddc;
1938706f2543Smrg      /* Lightpen register disable - allow access to cr10 & 11; just in case */
1939706f2543Smrg	save->cr03 = hwp->readCrtc(hwp, 0x03);
1940706f2543Smrg	hwp->writeCrtc(hwp,0x03,(save->cr03 |0x80));
1941706f2543Smrg	save->cr12 = hwp->readCrtc(hwp, 0x12);
1942706f2543Smrg	hwp->writeCrtc(hwp,0x12,DISPLAY_END);
1943706f2543Smrg	save->cr15 = hwp->readCrtc(hwp, 0x15);
1944706f2543Smrg	hwp->writeCrtc(hwp,0x15,BLANK_START);
1945706f2543Smrg	save->cr10 = hwp->readCrtc(hwp, 0x10);
1946706f2543Smrg	hwp->writeCrtc(hwp,0x10,SYNC_START);
1947706f2543Smrg	save->cr11 = hwp->readCrtc(hwp, 0x11);
1948706f2543Smrg	/* unprotect group 1 registers; just in case ...*/
1949706f2543Smrg	hwp->writeCrtc(hwp,0x11,((save->cr11 & 0x70) | SYNC_END));
1950706f2543Smrg	save->cr16 = hwp->readCrtc(hwp, 0x16);
1951706f2543Smrg	hwp->writeCrtc(hwp,0x16,BLANK_END);
1952706f2543Smrg	save->cr06 = hwp->readCrtc(hwp, 0x06);
1953706f2543Smrg	hwp->writeCrtc(hwp,0x06,V_TOTAL);
1954706f2543Smrg	/* all values have less than 8 bit - mask out 9th and 10th bits */
1955706f2543Smrg	save->cr09 = hwp->readCrtc(hwp, 0x09);
1956706f2543Smrg	hwp->writeCrtc(hwp,0x09,(save->cr09 &0xDF));
1957706f2543Smrg	save->cr07 = hwp->readCrtc(hwp, 0x07);
1958706f2543Smrg	hwp->writeCrtc(hwp,0x07,(save->cr07 &0x10));
1959706f2543Smrg	/* vsync polarity negativ & ensure a 25MHz clock */
1960706f2543Smrg	save->msr = hwp->readMiscOut(hwp);
1961706f2543Smrg	hwp->writeMiscOut(hwp,((save->msr & 0xF3) | 0x80));
1962706f2543Smrg	break;
1963706f2543Smrg    case DDC_SLOW:
1964706f2543Smrg        if (hwp->ddc == NULL) break;
1965706f2543Smrg	save = (struct _vgaDdcSave *)hwp->ddc;
1966706f2543Smrg	hwp->writeMiscOut(hwp,save->msr);
1967706f2543Smrg	hwp->writeCrtc(hwp,0x07,save->cr07);
1968706f2543Smrg	tmp = hwp->readCrtc(hwp, 0x09);
1969706f2543Smrg	hwp->writeCrtc(hwp,0x09,((save->cr09 & 0x20) | (tmp & 0xDF)));
1970706f2543Smrg	hwp->writeCrtc(hwp,0x06,save->cr06);
1971706f2543Smrg	hwp->writeCrtc(hwp,0x16,save->cr16);
1972706f2543Smrg	hwp->writeCrtc(hwp,0x11,save->cr11);
1973706f2543Smrg	hwp->writeCrtc(hwp,0x10,save->cr10);
1974706f2543Smrg	hwp->writeCrtc(hwp,0x15,save->cr15);
1975706f2543Smrg	hwp->writeCrtc(hwp,0x12,save->cr12);
1976706f2543Smrg	hwp->writeCrtc(hwp,0x03,save->cr03);
1977706f2543Smrg	free(save);
1978706f2543Smrg	hwp->ddc = NULL;
1979706f2543Smrg	break;
1980706f2543Smrg    default:
1981706f2543Smrg	break;
1982706f2543Smrg    }
1983706f2543Smrg}
1984706f2543Smrg
1985706f2543SmrgDDC1SetSpeedProc
1986706f2543SmrgvgaHWddc1SetSpeedWeak(void)
1987706f2543Smrg{
1988706f2543Smrg    return vgaHWddc1SetSpeed;
1989706f2543Smrg}
1990706f2543Smrg
1991706f2543SmrgSaveScreenProcPtr vgaHWSaveScreenWeak(void)
1992706f2543Smrg{
1993706f2543Smrg    return vgaHWSaveScreen;
1994706f2543Smrg}
1995