1 /*
2 * Copyright 1993 Hans Oey <hans@mo.hobby.nl>
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Hans Oey not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Hans Oey makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
13 *
14 * HANS OEY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL HANS OEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 */
23
24 /* $XFree86: mit/server/ddx/x386/vga256/drivers/compaq/cpq_driver.c,v 2.10 1993/10/06 14:56:03 dawes Exp $ */
25
26 /*
27 This XFree86 driver is intended to blow up your screen
28 and crash your disks. Other damage to your system
29 may occur. If the software fails this purpose it will
30 try to make random changes to program and data files.
31 It is provided "as is" without express or implied warranty
32 by Hans Oey. On my Compaq LTE Lite/25c it failed completely
33 and only gave me a boring X screen.
34
35 The software was based on the other XFree86 drivers. I am
36 very gratefull to Thomas Roell and the XFree86 team, but
37 stacking up all copyright notices for the next twenty
38 years seems a waste of disk space.
39 */
40
41 #include "X.h"
42 #include "input.h"
43 #include "screenint.h"
44
45 #include "compiler.h"
46
47 #include "x386.h"
48 #include "x386Priv.h"
49 #include "xf86_OSlib.h"
50 #include "xf86_HWlib.h"
51 #include "vga.h"
52
53 typedef struct {
54 vgaHWRec std; /* good old IBM VGA */
55 unsigned char PageRegister0;
56 unsigned char PageRegister1;
57 unsigned char ControlRegister0;
58 unsigned char EnvironmentReg;
59 } vgaCOMPAQRec, *vgaCOMPAQPtr;
60
61
62 static Bool COMPAQProbe();
63 static char * COMPAQIdent();
64 static Bool COMPAQClockSelect();
65 static void COMPAQEnterLeave();
66 static Bool COMPAQInit();
67 static void * COMPAQSave();
68 static void COMPAQRestore();
69 static void COMPAQAdjust();
70 static void COMPAQSaveScreen();
71 extern void COMPAQSetRead();
72 extern void COMPAQSetWrite();
73 extern void COMPAQSetReadWrite();
74
75 vgaVideoChipRec COMPAQ = {
76 COMPAQProbe,
77 COMPAQIdent,
78 COMPAQEnterLeave,
79 COMPAQInit,
80 COMPAQSave,
81 COMPAQRestore,
82 COMPAQAdjust,
83 COMPAQSaveScreen,
84 NoopDDA,
85 NoopDDA,
86 COMPAQSetRead,
87 COMPAQSetWrite,
88 COMPAQSetReadWrite,
89 0x10000,
90 0x08000,
91 15,
92 0x7FFF,
93 0x00000, 0x08000,
94 0x08000, 0x10000,
95 TRUE, /* Uses 2 banks */
96 VGA_NO_DIVIDE_VERT,
97 {0,},
98 8,
99 };
100
101 #define new ((vgaCOMPAQPtr)vgaNewVideoState)
102
COMPAQIdent(n)103 char *COMPAQIdent(n)
104 int n;
105 {
106 static char *chipsets[] = {"cpq_avga"};
107
108 if (n + 1 > sizeof(chipsets) / sizeof(char *))
109 return NULL;
110 else
111 return chipsets[n];
112 }
113
114
115 /*
116 COMPAQClockSelect -- select one of the possible clocks ...
117 */
118 static Bool
COMPAQClockSelect(no)119 COMPAQClockSelect(no)
120 int no;
121 {
122 static unsigned char save1;
123 unsigned char temp;
124
125 switch(no) {
126 case CLK_REG_SAVE:
127 save1 = inb(0x3CC);
128 break;
129 case CLK_REG_RESTORE:
130 outb(0x3C2, save1);
131 break;
132 default:
133 temp = inb(0x3CC);
134 outb(0x3C2, (temp & 0xf3) | ((no << 2) & 0x0C));
135 break;
136 }
137 return(TRUE);
138 }
139
140
141 /*
142 COMPAQProbe() checks for a Compaq VGC
143 Returns TRUE or FALSE on exit.
144
145 Makes sure the following are set in vga256InfoRec:
146 chipset
147 videoRam
148 clocks
149 */
150 #define VGABIOS_START vga256InfoRec.BIOSbase
151 #define SIGNATURE_LENGTH 6
152 #define ATI_SIGNATURE_LENGTH 9
153 #define BUFSIZE ATI_SIGNATURE_LENGTH /* but at least 3 bytes */
154
155 static Bool
COMPAQProbe()156 COMPAQProbe()
157 {
158 unsigned char SetReset; /* Set/Reset Data */
159 unsigned char Rotate;
160 unsigned char EnvironmentReg;
161 unsigned char BLTConf;
162 unsigned char temp;
163
164 /*
165 * Set up I/O ports to be used by this card
166 */
167 xf86ClearIOPortList(vga256InfoRec.scrnIndex);
168 xf86AddIOPorts(vga256InfoRec.scrnIndex, Num_VGA_IOPorts, VGA_IOPorts);
169
170 if (vga256InfoRec.chipset) {
171 if (StrCaseCmp(vga256InfoRec.chipset, COMPAQIdent(0)))
172 return(FALSE);
173 COMPAQEnterLeave(ENTER);
174 }
175 else {
176 char buf[BUFSIZE];
177 char *signature = "COMPAQ";
178 char *ati_signature = "761295520";
179
180 /* check for COMPAQ VGC */
181 if (xf86ReadBIOS(VGABIOS_START, 0, (unsigned char *)buf,
182 BUFSIZE) != BUFSIZE)
183 return(FALSE);
184 if ((buf[0] != (char)0x55) || (buf[1] != (char)0xAA))
185 return(FALSE);
186 if (xf86ReadBIOS(VGABIOS_START, (buf[2] * 512) - 0x16,
187 (unsigned char *)buf,
188 SIGNATURE_LENGTH) != SIGNATURE_LENGTH)
189 return(FALSE);
190 if (strncmp(signature, buf, SIGNATURE_LENGTH))
191 return FALSE;
192
193 /*
194 * Now make sure it isn't an ATI card with a COMPAQ signature
195 * in the BIOS
196 */
197
198 if (xf86ReadBIOS(VGABIOS_START, 0x31, (unsigned char *)buf,
199 ATI_SIGNATURE_LENGTH) != ATI_SIGNATURE_LENGTH)
200 return(FALSE);
201 if (!strncmp(ati_signature, buf, ATI_SIGNATURE_LENGTH))
202 return(FALSE);
203
204 COMPAQEnterLeave(ENTER);
205
206 /* at least it is some COMPAQ :-) */
207 /* check for seperate SR and BLTConf registers. */
208 outb(0x3ce, 0x00); SetReset = inb(0x3cf);
209 outb(0x3ce, 0x03); Rotate = inb(0x3cf);
210 outb(0x3ce, 0x0f); EnvironmentReg = inb(0x3cf);
211 outb(0x3cf, 0x05); /* unlock */
212 outb(0x3ce, 0x10); BLTConf = inb(0x3cf);
213
214 if ((BLTConf & 0x0f) == SetReset) {
215 /* try another pattern */
216 temp = ~SetReset & 0xff;
217 outw(0x3ce, temp << 8 | 0x00); /*change Set/Rst Data*/
218 outb(0x3ce, 0x10); /*read BLTConf reg */
219 if ((inb(0x3cf) & 0x0f) == temp) {
220 /* restore changed registers */
221 outw(0x3ce, SetReset << 8 | 0x00);
222 outw(0x3ce, EnvironmentReg << 8 | 0x0f);
223 COMPAQEnterLeave(LEAVE);
224 return FALSE;
225 }
226 /* restore */
227 outw(0x3ce, SetReset << 8 | 0x00);
228 }
229 outw(0x3ce, EnvironmentReg << 8 | 0x0f);
230 }
231
232 /* Detect how much memory is installed, that's easy :-) */
233 if (!vga256InfoRec.videoRam)
234 vga256InfoRec.videoRam = 512;
235
236 if (!vga256InfoRec.clocks)
237 vgaGetClocks(4, COMPAQClockSelect); /* 4? clocks available */
238
239 vga256InfoRec.chipset = COMPAQIdent(0);
240 vga256InfoRec.bankedMono = FALSE; /* who cares ;-) */
241
242 return TRUE;
243 }
244
245 /*
246 COMPAQEnterLeave() -- enable/disable io-mapping
247
248 This routine is used when entering or leaving X (i.e., when starting or
249 exiting an X session, or when switching to or from a vt which does not
250 have an X session running.
251 */
COMPAQEnterLeave(enter)252 static void COMPAQEnterLeave(enter)
253 Bool enter;
254 {
255 if (enter) {
256 xf86EnableIOPorts(vga256InfoRec.scrnIndex);
257 vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
258 }
259 else {
260 xf86DisableIOPorts(vga256InfoRec.scrnIndex);
261 }
262 }
263
264 /*
265 COMPAQRestore -- restore a video mode
266 */
267
COMPAQRestore(restore)268 static void COMPAQRestore(restore)
269 vgaCOMPAQPtr restore;
270 {
271 if (restore->EnvironmentReg == 0x0f)
272 outw(0x3ce, 0 << 8 | 0x0f); /* lock */
273 else
274 outw(0x3ce, 0x05 << 8 | 0x0f); /* unlock */
275
276 vgaHWRestore(restore);
277
278 /* Compaq doesn't like the sequencer reset in vgaHWRestore */
279 outw(0x3ce, restore->ControlRegister0 << 8 | 0x40);
280 outw(0x3ce, restore->PageRegister0 << 8 | 0x45);
281 outw(0x3ce, restore->PageRegister1 << 8 | 0x46);
282
283 /*
284 * Don't need to do any clock stuff - the bits are in MiscOutReg,
285 * which is handled by vgaHWRestore.
286 */
287 }
288
289 /*
290 COMPAQSave -- save the current video mode
291 */
COMPAQSave(save)292 static void *COMPAQSave(save)
293 vgaCOMPAQPtr save;
294 {
295 unsigned char temp0, temp1, temp2, temp3;
296
297 outb(0x3ce, 0x0f); temp0 = inb(0x3cf); /* Environment Register */
298 outb(0x3ce, 0x40); temp1 = inb(0x3cf); /* Control Register 0 */
299 outb(0x3ce, 0x45); temp2 = inb(0x3cf); /* Page Register 0 */
300 outb(0x3ce, 0x46); temp3 = inb(0x3cf); /* Page Register 1 */
301
302 save = (vgaCOMPAQPtr)vgaHWSave(save, sizeof(vgaCOMPAQRec));
303
304 save->EnvironmentReg = temp0;
305 save->ControlRegister0 = temp1;
306 save->PageRegister0 = temp2;
307 save->PageRegister1 = temp3;
308
309 return ((void *) save);
310 }
311
312 /*
313 COMPAQInit -- Handle the initialization of the VGAs registers
314 */
COMPAQInit(mode)315 static Bool COMPAQInit(mode)
316 DisplayModePtr mode;
317 {
318 #ifndef MONOVGA
319 /* Double horizontal timings. */
320 mode->HTotal <<= 1;
321 mode->HDisplay <<= 1;
322 mode->HSyncStart <<= 1;
323 mode->HSyncEnd <<= 1;
324 #endif
325
326 if (!vgaHWInit(mode,sizeof(vgaCOMPAQRec)))
327 return(FALSE);
328 #ifndef MONOVGA
329 /* Restore them, they are used elsewhere */
330 mode->HTotal >>= 1;
331 mode->HDisplay >>= 1;
332 mode->HSyncStart >>= 1;
333 mode->HSyncEnd >>= 1;
334 #endif
335
336 #ifndef MONOVGA
337 new->std.Sequencer[0x02] = 0xff; /* write plane mask for 256 colors */
338 new->std.CRTC[0x13] = vga256InfoRec.virtualX >> 3;
339 new->std.CRTC[0x14] = 0x40;
340 #endif
341
342 #ifdef MONOVGA
343 new->ControlRegister0 = 0x00;
344 #else
345 new->ControlRegister0 = 0x01;
346 #endif
347
348 new->EnvironmentReg = 0x05;
349 new->PageRegister0 = 0x0;
350 new->PageRegister1 = 0x0;
351
352 return(TRUE);
353 }
354
355 /*
356 * COMPAQAdjust --
357 * adjust the current video frame to display the mousecursor
358 */
359
360 static void
COMPAQAdjust(x,y)361 COMPAQAdjust(x, y)
362 int x, y;
363 {
364 #ifdef MONOVGA
365 int Base = (y * vga256InfoRec.virtualX + x + 3) >> 3;
366 #else
367 int Base = (y * vga256InfoRec.virtualX + x + 1) >> 2;
368 #endif
369
370 outw(vgaIOBase + 4, (Base & 0x00FF00) | 0x0C);
371 outw(vgaIOBase + 4, ((Base & 0x00FF) << 8) | 0x0D);
372 }
373
374 /*
375 * COMPAQSaveScreen --
376 * Save registers that can be disrupted by a synchronous reset
377 */
378 static void
COMPAQSaveScreen(mode)379 COMPAQSaveScreen(mode)
380 int mode;
381 {
382 static unsigned char save1, save2, save3;
383
384 if (mode == SS_START)
385 {
386 outb(0x3ce, 0x45); save1 = inb(0x3cf); /* Page Register 0 */
387 outb(0x3ce, 0x46); save2 = inb(0x3cf); /* Page Register 1 */
388 outb(0x3ce, 0x40); save3 = inb(0x3cf); /* Control Register 0 */
389 }
390 else
391 {
392 outw(0x3ce, save3 << 8 | 0x40);
393 outw(0x3ce, save2 << 8 | 0x46);
394 outw(0x3ce, save1 << 8 | 0x45);
395 }
396 }
397