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