mga_vga.c revision a9060c92
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include "misc.h"
6#include "xf86.h"
7#include "xf86_OSproc.h"
8#include <X11/Xos.h>
9#include "vgaHW.h"
10#include "compiler.h"
11#include "xf86cmap.h"
12#include "mga.h"
13#include "mga_reg.h"
14
15#define TEXT_AMOUNT 16384
16#define FONT_AMOUNT (8*8192)
17
18void
19MGAG200SERestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore)
20{
21    vgaHWPtr hwp = VGAHWPTR(scrninfp);
22    MGAPtr pMga = MGAPTR(scrninfp);
23    int savedIOBase;
24    unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4;
25    Bool doMap = FALSE;
26    unsigned char scrn;
27
28    /* If nothing to do, return now */
29    if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo)
30	return;
31
32    if (hwp->Base == NULL) {
33	doMap = TRUE;
34	if (!vgaHWMapMem(scrninfp)) {
35	    xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
36		    "vgaHWRestoreFonts: vgaHWMapMem() failed\n");
37	    return;
38	}
39    }
40
41    /* save the registers that are needed here */
42    miscOut = hwp->readMiscOut(hwp);
43    attr10 = hwp->readAttr(hwp, 0x10);
44    gr1 = hwp->readGr(hwp, 0x01);
45    gr3 = hwp->readGr(hwp, 0x03);
46    gr4 = hwp->readGr(hwp, 0x04);
47    gr5 = hwp->readGr(hwp, 0x05);
48    gr6 = hwp->readGr(hwp, 0x06);
49    gr8 = hwp->readGr(hwp, 0x08);
50    seq2 = hwp->readSeq(hwp, 0x02);
51    seq4 = hwp->readSeq(hwp, 0x04);
52
53    /* save hwp->IOBase and temporarily set it for colour mode */
54    savedIOBase = hwp->IOBase;
55    hwp->IOBase = VGA_IOBASE_COLOR;
56
57    /* Force into colour mode */
58    hwp->writeMiscOut(hwp, miscOut | 0x01);
59
60    scrn = hwp->readSeq(hwp, 0x01);
61    scrn |= 0x20;/* blank screen */
62    vgaHWSeqReset(hwp, TRUE);
63    MGAWAITVSYNC();
64    MGAWAITBUSY();
65    hwp->writeSeq(hwp, 0x01, scrn);/* change mode */
66    usleep(20000);
67    vgaHWSeqReset(hwp, FALSE);
68
69    /*
70     * here we temporarily switch to 16 colour planar mode, to simply
71     * copy the font-info and saved text.
72     *
73     * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
74     */
75#if 0
76    hwp->writeAttr(hwp, 0x10, 0x01);   /* graphics mode */
77#endif
78    if (scrninfp->depth == 4) {
79	/* GJA */
80	hwp->writeGr(hwp, 0x03, 0x00);  /* don't rotate, write unmodified */
81	hwp->writeGr(hwp, 0x08, 0xFF);  /* write all bits in a byte */
82	hwp->writeGr(hwp, 0x01, 0x00);  /* all planes come from CPU */
83    }
84
85    hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */
86    hwp->writeGr(hwp, 0x05, 0x00);  /* write mode 0, read mode 0 */
87    hwp->writeGr(hwp, 0x06, 0x05);  /* set graphics */
88
89    if (hwp->FontInfo1) {
90	hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */
91	hwp->writeGr(hwp, 0x04, 0x02);  /* read plane 2 */
92	slowbcopy_tobus(hwp->FontInfo1, hwp->Base, FONT_AMOUNT);
93    }
94
95    if (hwp->FontInfo2) {
96	hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */
97	hwp->writeGr(hwp, 0x04, 0x03);  /* read plane 3 */
98	slowbcopy_tobus(hwp->FontInfo2, hwp->Base, FONT_AMOUNT);
99    }
100
101    if (hwp->TextInfo) {
102	hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */
103	hwp->writeGr(hwp, 0x04, 0x00);  /* read plane 0 */
104	slowbcopy_tobus(hwp->TextInfo, hwp->Base, TEXT_AMOUNT);
105	hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */
106	hwp->writeGr(hwp, 0x04, 0x01);  /* read plane 1 */
107	slowbcopy_tobus((unsigned char *)hwp->TextInfo + TEXT_AMOUNT,
108		hwp->Base, TEXT_AMOUNT);
109    }
110
111    /* restore the registers that were changed */
112    hwp->writeMiscOut(hwp, miscOut);
113    hwp->writeAttr(hwp, 0x10, attr10);
114    hwp->writeGr(hwp, 0x01, gr1);
115    hwp->writeGr(hwp, 0x03, gr3);
116    hwp->writeGr(hwp, 0x04, gr4);
117    hwp->writeGr(hwp, 0x05, gr5);
118    hwp->writeGr(hwp, 0x06, gr6);
119    hwp->writeGr(hwp, 0x08, gr8);
120    hwp->writeSeq(hwp, 0x02, seq2);
121    hwp->writeSeq(hwp, 0x04, seq4);
122    hwp->IOBase = savedIOBase;
123
124    scrn = hwp->readSeq(hwp, 0x01);
125    scrn &= ~0x20;/* enable screen */
126    vgaHWSeqReset(hwp, TRUE);
127    MGAWAITVSYNC();
128    MGAWAITBUSY();
129    hwp->writeSeq(hwp, 0x01, scrn);/* change mode */
130    usleep(20000);
131    vgaHWSeqReset(hwp, FALSE);
132
133    if (doMap)
134	vgaHWUnmapMem(scrninfp);
135}
136
137
138void
139MGAG200SESaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save)
140{
141    vgaHWPtr hwp = VGAHWPTR(scrninfp);
142    MGAPtr pMga = MGAPTR(scrninfp);
143    int savedIOBase;
144    unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4;
145    Bool doMap = FALSE;
146    unsigned char scrn;
147
148    if (hwp->Base == NULL) {
149	doMap = TRUE;
150	if (!vgaHWMapMem(scrninfp)) {
151	    xf86DrvMsg(scrninfp->scrnIndex, X_ERROR,
152		    "vgaHWSaveFonts: vgaHWMapMem() failed\n");
153	    return;
154	}
155    }
156
157    /* If in graphics mode, don't save anything */
158    attr10 = hwp->readAttr(hwp, 0x10);
159    if (attr10 & 0x01)
160	return;
161
162    /* save the registers that are needed here */
163    miscOut = hwp->readMiscOut(hwp);
164    gr4 = hwp->readGr(hwp, 0x04);
165    gr5 = hwp->readGr(hwp, 0x05);
166    gr6 = hwp->readGr(hwp, 0x06);
167    seq2 = hwp->readSeq(hwp, 0x02);
168    seq4 = hwp->readSeq(hwp, 0x04);
169
170    /* save hwp->IOBase and temporarily set it for colour mode */
171    savedIOBase = hwp->IOBase;
172    hwp->IOBase = VGA_IOBASE_COLOR;
173
174    /* Force into colour mode */
175    hwp->writeMiscOut(hwp, miscOut | 0x01);
176
177    scrn = hwp->readSeq(hwp, 0x01);
178    scrn |= 0x20;/* blank screen */
179    vgaHWSeqReset(hwp, TRUE);
180    MGAWAITVSYNC();
181    MGAWAITBUSY();
182    hwp->writeSeq(hwp, 0x01, scrn);/* change mode */
183    usleep(20000);
184    vgaHWSeqReset(hwp, FALSE);
185
186    /*
187     * get the character sets, and text screen if required
188     */
189    /*
190     * Here we temporarily switch to 16 colour planar mode, to simply
191     * copy the font-info
192     *
193     * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly!
194     */
195#if 0
196    hwp->writeAttr(hwp, 0x10, 0x01);   /* graphics mode */
197#endif
198    hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */
199    hwp->writeGr(hwp, 0x05, 0x00);  /* write mode 0, read mode 0 */
200    hwp->writeGr(hwp, 0x06, 0x05);  /* set graphics */
201    if (hwp->FontInfo1 || (hwp->FontInfo1 = xalloc(FONT_AMOUNT))) {
202	hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */
203	hwp->writeGr(hwp, 0x04, 0x02);  /* read plane 2 */
204	slowbcopy_frombus(hwp->Base, hwp->FontInfo1, FONT_AMOUNT);
205    }
206    if (hwp->FontInfo2 || (hwp->FontInfo2 = xalloc(FONT_AMOUNT))) {
207	hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */
208	hwp->writeGr(hwp, 0x04, 0x03);  /* read plane 3 */
209	slowbcopy_frombus(hwp->Base, hwp->FontInfo2, FONT_AMOUNT);
210    }
211    if (hwp->TextInfo || (hwp->TextInfo = xalloc(2 * TEXT_AMOUNT))) {
212	hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */
213	hwp->writeGr(hwp, 0x04, 0x00);  /* read plane 0 */
214	slowbcopy_frombus(hwp->Base, hwp->TextInfo, TEXT_AMOUNT);
215	hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */
216	hwp->writeGr(hwp, 0x04, 0x01);  /* read plane 1 */
217	slowbcopy_frombus(hwp->Base,
218		(unsigned char *)hwp->TextInfo + TEXT_AMOUNT, TEXT_AMOUNT);
219    }
220
221    /* Restore clobbered registers */
222    hwp->writeAttr(hwp, 0x10, attr10);
223    hwp->writeGr(hwp, 0x04, gr4);
224    hwp->writeGr(hwp, 0x05, gr5);
225    hwp->writeGr(hwp, 0x06, gr6);
226    hwp->writeSeq(hwp, 0x02, seq2);
227    hwp->writeSeq(hwp, 0x04, seq4);
228    hwp->writeMiscOut(hwp, miscOut);
229    hwp->IOBase = savedIOBase;
230
231    scrn = hwp->readSeq(hwp, 0x01);
232    scrn &= ~0x20;/* enable screen */
233    vgaHWSeqReset(hwp, TRUE);
234    MGAWAITVSYNC();
235    MGAWAITBUSY();
236    hwp->writeSeq(hwp, 0x01, scrn);/* change mode */
237    usleep(20000);
238    vgaHWSeqReset(hwp, FALSE);
239
240    if (doMap)
241	vgaHWUnmapMem(scrninfp);
242}
243
244void
245MGAG200SERestoreMode(ScrnInfoPtr scrninfp, vgaRegPtr restore)
246{
247    vgaHWPtr hwp = VGAHWPTR(scrninfp);
248    MGAPtr pMga = MGAPTR(scrninfp);
249    int i;
250    unsigned char scrn;
251
252    if (restore->MiscOutReg & 0x01)
253    hwp->IOBase = VGA_IOBASE_COLOR;
254    else
255    hwp->IOBase = VGA_IOBASE_MONO;
256
257    hwp->writeMiscOut(hwp, restore->MiscOutReg);
258
259
260    for (i = 1; i < restore->numSequencer; i++)
261    {
262    MGAWAITVSYNC();
263    MGAWAITBUSY();
264	hwp->writeSeq(hwp, i, restore->Sequencer[i]);
265	usleep(20000);
266    }
267
268    scrn = hwp->readSeq(hwp, 0x01);
269    scrn |= 0x20;/* blank screen */
270    vgaHWSeqReset(hwp, TRUE);
271    MGAWAITVSYNC();
272    MGAWAITBUSY();
273    hwp->writeSeq(hwp, 0x01, scrn);/* change mode */
274    usleep(20000);
275
276    /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
277    hwp->writeCrtc(hwp, 17, restore->CRTC[17] & ~0x80);
278
279    for (i = 0; i < restore->numCRTC; i++)
280	hwp->writeCrtc(hwp, i, restore->CRTC[i]);
281
282    for (i = 0; i < restore->numGraphics; i++)
283    hwp->writeGr(hwp, i, restore->Graphics[i]);
284
285    hwp->enablePalette(hwp);
286    for (i = 0; i < restore->numAttribute; i++)
287    hwp->writeAttr(hwp, i, restore->Attribute[i]);
288    hwp->disablePalette(hwp);
289
290    MGAWAITVSYNC();
291    MGAWAITBUSY();
292	hwp->writeSeq(hwp, 1, restore->Sequencer[1]);
293    usleep(20000);
294}
295
296void
297MGAG200SESaveMode(ScrnInfoPtr scrninfp, vgaRegPtr save)
298{
299    vgaHWPtr hwp = VGAHWPTR(scrninfp);
300    int i;
301
302    save->MiscOutReg = hwp->readMiscOut(hwp);
303    if (save->MiscOutReg & 0x01)
304    hwp->IOBase = VGA_IOBASE_COLOR;
305    else
306    hwp->IOBase = VGA_IOBASE_MONO;
307
308    for (i = 0; i < save->numCRTC; i++) {
309    save->CRTC[i] = hwp->readCrtc(hwp, i);
310#ifdef DEBUG
311    ErrorF("CRTC[0x%02x] = 0x%02x\n", i, save->CRTC[i]);
312#endif
313    }
314
315    hwp->enablePalette(hwp);
316    for (i = 0; i < save->numAttribute; i++) {
317    save->Attribute[i] = hwp->readAttr(hwp, i);
318#ifdef DEBUG
319    ErrorF("Attribute[0x%02x] = 0x%02x\n", i, save->Attribute[i]);
320#endif
321    }
322    hwp->disablePalette(hwp);
323
324    for (i = 0; i < save->numGraphics; i++) {
325    save->Graphics[i] = hwp->readGr(hwp, i);
326#ifdef DEBUG
327    ErrorF("Graphics[0x%02x] = 0x%02x\n", i, save->Graphics[i]);
328#endif
329    }
330
331    for (i = 1; i < save->numSequencer; i++) {
332    save->Sequencer[i] = hwp->readSeq(hwp, i);
333#ifdef DEBUG
334    ErrorF("Sequencer[0x%02x] = 0x%02x\n", i, save->Sequencer[i]);
335#endif
336    }
337}
338
339void
340MGAG200SEHWProtect(ScrnInfoPtr pScrn, Bool on)
341{
342  vgaHWPtr hwp = VGAHWPTR(pScrn);
343  MGAPtr pMga = MGAPTR(pScrn);
344
345  unsigned char tmp;
346
347  if (pScrn->vtSema) {
348    if (on) {
349      /*
350       * Turn off screen and disable sequencer.
351       */
352      tmp = hwp->readSeq(hwp, 0x01);
353
354      vgaHWSeqReset(hwp, TRUE);         /* start synchronous reset */
355      MGAWAITVSYNC();
356      MGAWAITBUSY();
357      hwp->writeSeq(hwp, 0x01, tmp | 0x20); /* disable the display */
358      usleep(20000);
359      hwp->enablePalette(hwp);
360    } else {
361      /*
362       * Reenable sequencer, then turn on screen.
363       */
364
365      tmp = hwp->readSeq(hwp, 0x01);
366
367      MGAWAITVSYNC();
368      MGAWAITBUSY();
369      hwp->writeSeq(hwp, 0x01, tmp & ~0x20);    /* reenable display */
370      usleep(20000);
371      vgaHWSeqReset(hwp, FALSE);        /* clear synchronousreset */
372
373      hwp->disablePalette(hwp);
374    }
375  }
376}
377