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