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