vreset.c revision 1.1 1 /* $Id: vreset.c,v 1.1 1998/01/16 04:18:06 sakamoto Exp $ */
2
3 /*
4 * Copyright (C) 1995-1997 Gary Thomas (gdt (at) linuxppc.org)
5 * All rights reserved.
6 *
7 * Initialize the VGA control registers to 80x25 text mode.
8 *
9 * Adapted from a program by:
10 * Steve Sellgren
11 * San Francisco Indigo Company
12 * sfindigo!sellgren (at) uunet.uu.net
13 * Adapted for Moto boxes by:
14 * Pat Kane & Mark Scott, 1996
15 * Fixed for IBM/PowerStack II Pat Kane 1997
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. All advertising materials mentioning features or use of this software
26 * must display the following acknowledgement:
27 * This product includes software developed by Gary Thomas.
28 * 4. The name of the author may not be used to endorse or promote products
29 * derived from this software without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
32 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 */
42
43 #ifdef CONS_VGA
44 #ifndef lint
45 static char rcsid[] = "vreset.c 2.0 1997 kane PEK'97 Exp $";
46 #endif
47
48 #include "iso_font.h"
49 /*
50 * VGA Register
51 */
52 struct VgaRegs
53 {
54 unsigned short io_port;
55 unsigned char io_index;
56 unsigned char io_value;
57 };
58
59 /*
60 * Default console text mode registers used to reset
61 * graphics adapter.
62 */
63 #define NREGS 54
64 #define ENDMK 0xFFFF /* End marker */
65
66 #define S3Vendor 0x5333
67 #define CirrusVendor 0x1013
68 #define DiamondVendor 0x100E
69 #define MatroxVendor 0x102B
70
71 struct VgaRegs GenVgaTextRegs[NREGS+1] = {
72 /* port index value */
73 /* SR Regs */
74 0x3c4, 0x1, 0x0,
75 0x3c4, 0x2, 0x3,
76 0x3c4, 0x3, 0x0,
77 0x3c4, 0x4, 0x2,
78 /* CR Regs */
79 0x3d4, 0x0, 0x5f,
80 0x3d4, 0x1, 0x4f,
81 0x3d4, 0x2, 0x50,
82 0x3d4, 0x3, 0x82,
83 0x3d4, 0x4, 0x55,
84 0x3d4, 0x5, 0x81,
85 0x3d4, 0x6, 0xbf,
86 0x3d4, 0x7, 0x1f,
87 0x3d4, 0x8, 0x00,
88 0x3d4, 0x9, 0x4f,
89 0x3d4, 0xa, 0x0d,
90 0x3d4, 0xb, 0x0e,
91 0x3d4, 0xc, 0x00,
92 0x3d4, 0xd, 0x00,
93 0x3d4, 0xe, 0x00,
94 0x3d4, 0xf, 0x00,
95 0x3d4, 0x10, 0x9c,
96 0x3d4, 0x11, 0x8e,
97 0x3d4, 0x12, 0x8f,
98 0x3d4, 0x13, 0x28,
99 0x3d4, 0x14, 0x1f,
100 0x3d4, 0x15, 0x96,
101 0x3d4, 0x16, 0xb9,
102 0x3d4, 0x17, 0xa3,
103 /* GR Regs */
104 0x3ce, 0x0, 0x0,
105 0x3ce, 0x1, 0x0,
106 0x3ce, 0x2, 0x0,
107 0x3ce, 0x3, 0x0,
108 0x3ce, 0x4, 0x0,
109 0x3ce, 0x5, 0x10,
110 0x3ce, 0x6, 0xe,
111 0x3ce, 0x7, 0x0,
112 0x3ce, 0x8, 0xff,
113 ENDMK
114 };
115
116 struct VgaRegs S3TextRegs[NREGS+1] = {
117 /* port index value */
118 /* SR Regs */
119 0x3c4, 0x1, 0x0,
120 0x3c4, 0x2, 0x3,
121 0x3c4, 0x3, 0x0,
122 0x3c4, 0x4, 0x2,
123 /* CR Regs */
124 0x3d4, 0x0, 0x5f,
125 0x3d4, 0x1, 0x4f,
126 0x3d4, 0x2, 0x50,
127 0x3d4, 0x3, 0x82,
128 0x3d4, 0x4, 0x55,
129 0x3d4, 0x5, 0x81,
130 0x3d4, 0x6, 0xbf,
131 0x3d4, 0x7, 0x1f,
132 0x3d4, 0x8, 0x00,
133 0x3d4, 0x9, 0x4f,
134 0x3d4, 0xa, 0x0d,
135 0x3d4, 0xb, 0x0e,
136 0x3d4, 0xc, 0x00,
137 0x3d4, 0xd, 0x00,
138 0x3d4, 0xe, 0x00,
139 0x3d4, 0xf, 0x00,
140 0x3d4, 0x10, 0x9c,
141 0x3d4, 0x11, 0x8e,
142 0x3d4, 0x12, 0x8f,
143 0x3d4, 0x13, 0x28,
144 0x3d4, 0x14, 0x1f,
145 0x3d4, 0x15, 0x96,
146 0x3d4, 0x16, 0xb9,
147 0x3d4, 0x17, 0xa3,
148 /* GR Regs */
149 0x3ce, 0x0, 0x0,
150 0x3ce, 0x1, 0x0,
151 0x3ce, 0x2, 0x0,
152 0x3ce, 0x3, 0x0,
153 0x3ce, 0x4, 0x0,
154 0x3ce, 0x5, 0x10,
155 0x3ce, 0x6, 0xe,
156 0x3ce, 0x7, 0x0,
157 0x3ce, 0x8, 0xff,
158 ENDMK
159 };
160
161 struct RGBColors
162 {
163 unsigned char r, g, b;
164 };
165
166 /*
167 * Default console text mode color table.
168 * These values were obtained by booting Linux with
169 * text mode firmware & then dumping the registers.
170 */
171 struct RGBColors TextCLUT[256] =
172 {
173 /* red green blue */
174 0x0, 0x0, 0x0,
175 0x0, 0x0, 0x2a,
176 0x0, 0x2a, 0x0,
177 0x0, 0x2a, 0x2a,
178 0x2a, 0x0, 0x0,
179 0x2a, 0x0, 0x2a,
180 0x2a, 0x2a, 0x0,
181 0x2a, 0x2a, 0x2a,
182 0x0, 0x0, 0x15,
183 0x0, 0x0, 0x3f,
184 0x0, 0x2a, 0x15,
185 0x0, 0x2a, 0x3f,
186 0x2a, 0x0, 0x15,
187 0x2a, 0x0, 0x3f,
188 0x2a, 0x2a, 0x15,
189 0x2a, 0x2a, 0x3f,
190 0x0, 0x15, 0x0,
191 0x0, 0x15, 0x2a,
192 0x0, 0x3f, 0x0,
193 0x0, 0x3f, 0x2a,
194 0x2a, 0x15, 0x0,
195 0x2a, 0x15, 0x2a,
196 0x2a, 0x3f, 0x0,
197 0x2a, 0x3f, 0x2a,
198 0x0, 0x15, 0x15,
199 0x0, 0x15, 0x3f,
200 0x0, 0x3f, 0x15,
201 0x0, 0x3f, 0x3f,
202 0x2a, 0x15, 0x15,
203 0x2a, 0x15, 0x3f,
204 0x2a, 0x3f, 0x15,
205 0x2a, 0x3f, 0x3f,
206 0x15, 0x0, 0x0,
207 0x15, 0x0, 0x2a,
208 0x15, 0x2a, 0x0,
209 0x15, 0x2a, 0x2a,
210 0x3f, 0x0, 0x0,
211 0x3f, 0x0, 0x2a,
212 0x3f, 0x2a, 0x0,
213 0x3f, 0x2a, 0x2a,
214 0x15, 0x0, 0x15,
215 0x15, 0x0, 0x3f,
216 0x15, 0x2a, 0x15,
217 0x15, 0x2a, 0x3f,
218 0x3f, 0x0, 0x15,
219 0x3f, 0x0, 0x3f,
220 0x3f, 0x2a, 0x15,
221 0x3f, 0x2a, 0x3f,
222 0x15, 0x15, 0x0,
223 0x15, 0x15, 0x2a,
224 0x15, 0x3f, 0x0,
225 0x15, 0x3f, 0x2a,
226 0x3f, 0x15, 0x0,
227 0x3f, 0x15, 0x2a,
228 0x3f, 0x3f, 0x0,
229 0x3f, 0x3f, 0x2a,
230 0x15, 0x15, 0x15,
231 0x15, 0x15, 0x3f,
232 0x15, 0x3f, 0x15,
233 0x15, 0x3f, 0x3f,
234 0x3f, 0x15, 0x15,
235 0x3f, 0x15, 0x3f,
236 0x3f, 0x3f, 0x15,
237 0x3f, 0x3f, 0x3f,
238 0x39, 0xc, 0x5,
239 0x15, 0x2c, 0xf,
240 0x26, 0x10, 0x3d,
241 0x29, 0x29, 0x38,
242 0x4, 0x1a, 0xe,
243 0x2, 0x1e, 0x3a,
244 0x3c, 0x25, 0x33,
245 0x3c, 0xc, 0x2c,
246 0x3f, 0x3, 0x2b,
247 0x1c, 0x9, 0x13,
248 0x25, 0x2a, 0x35,
249 0x1e, 0xa, 0x38,
250 0x24, 0x8, 0x3,
251 0x3, 0xe, 0x36,
252 0xc, 0x6, 0x2a,
253 0x26, 0x3, 0x32,
254 0x5, 0x2f, 0x33,
255 0x3c, 0x35, 0x2f,
256 0x2d, 0x26, 0x3e,
257 0xd, 0xa, 0x10,
258 0x25, 0x3c, 0x11,
259 0xd, 0x4, 0x2e,
260 0x5, 0x19, 0x3e,
261 0xc, 0x13, 0x34,
262 0x2b, 0x6, 0x24,
263 0x4, 0x3, 0xd,
264 0x2f, 0x3c, 0xc,
265 0x2a, 0x37, 0x1f,
266 0xf, 0x12, 0x38,
267 0x38, 0xe, 0x2a,
268 0x12, 0x2f, 0x19,
269 0x29, 0x2e, 0x31,
270 0x25, 0x13, 0x3e,
271 0x33, 0x3e, 0x33,
272 0x1d, 0x2c, 0x25,
273 0x15, 0x15, 0x5,
274 0x32, 0x25, 0x39,
275 0x1a, 0x7, 0x1f,
276 0x13, 0xe, 0x1d,
277 0x36, 0x17, 0x34,
278 0xf, 0x15, 0x23,
279 0x2, 0x35, 0xd,
280 0x15, 0x3f, 0xc,
281 0x14, 0x2f, 0xf,
282 0x19, 0x21, 0x3e,
283 0x27, 0x11, 0x2f,
284 0x38, 0x3f, 0x3c,
285 0x36, 0x2d, 0x15,
286 0x16, 0x17, 0x2,
287 0x1, 0xa, 0x3d,
288 0x1b, 0x11, 0x3f,
289 0x21, 0x3c, 0xd,
290 0x1a, 0x39, 0x3d,
291 0x8, 0xe, 0xe,
292 0x22, 0x21, 0x23,
293 0x1e, 0x30, 0x5,
294 0x1f, 0x22, 0x3d,
295 0x1e, 0x2f, 0xa,
296 0x0, 0x1c, 0xe,
297 0x0, 0x1c, 0x15,
298 0x0, 0x1c, 0x1c,
299 0x0, 0x15, 0x1c,
300 0x0, 0xe, 0x1c,
301 0x0, 0x7, 0x1c,
302 0xe, 0xe, 0x1c,
303 0x11, 0xe, 0x1c,
304 0x15, 0xe, 0x1c,
305 0x18, 0xe, 0x1c,
306 0x1c, 0xe, 0x1c,
307 0x1c, 0xe, 0x18,
308 0x1c, 0xe, 0x15,
309 0x1c, 0xe, 0x11,
310 0x1c, 0xe, 0xe,
311 0x1c, 0x11, 0xe,
312 0x1c, 0x15, 0xe,
313 0x1c, 0x18, 0xe,
314 0x1c, 0x1c, 0xe,
315 0x18, 0x1c, 0xe,
316 0x15, 0x1c, 0xe,
317 0x11, 0x1c, 0xe,
318 0xe, 0x1c, 0xe,
319 0xe, 0x1c, 0x11,
320 0xe, 0x1c, 0x15,
321 0xe, 0x1c, 0x18,
322 0xe, 0x1c, 0x1c,
323 0xe, 0x18, 0x1c,
324 0xe, 0x15, 0x1c,
325 0xe, 0x11, 0x1c,
326 0x14, 0x14, 0x1c,
327 0x16, 0x14, 0x1c,
328 0x18, 0x14, 0x1c,
329 0x1a, 0x14, 0x1c,
330 0x1c, 0x14, 0x1c,
331 0x1c, 0x14, 0x1a,
332 0x1c, 0x14, 0x18,
333 0x1c, 0x14, 0x16,
334 0x1c, 0x14, 0x14,
335 0x1c, 0x16, 0x14,
336 0x1c, 0x18, 0x14,
337 0x1c, 0x1a, 0x14,
338 0x1c, 0x1c, 0x14,
339 0x1a, 0x1c, 0x14,
340 0x18, 0x1c, 0x14,
341 0x16, 0x1c, 0x14,
342 0x14, 0x1c, 0x14,
343 0x14, 0x1c, 0x16,
344 0x14, 0x1c, 0x18,
345 0x14, 0x1c, 0x1a,
346 0x14, 0x1c, 0x1c,
347 0x14, 0x1a, 0x1c,
348 0x14, 0x18, 0x1c,
349 0x14, 0x16, 0x1c,
350 0x0, 0x0, 0x10,
351 0x4, 0x0, 0x10,
352 0x8, 0x0, 0x10,
353 0xc, 0x0, 0x10,
354 0x10, 0x0, 0x10,
355 0x10, 0x0, 0xc,
356 0x10, 0x0, 0x8,
357 0x10, 0x0, 0x4,
358 0x10, 0x0, 0x0,
359 0x10, 0x4, 0x0,
360 0x10, 0x8, 0x0,
361 0x10, 0xc, 0x0,
362 0x10, 0x10, 0x0,
363 0xc, 0x10, 0x0,
364 0x8, 0x10, 0x0,
365 0x4, 0x10, 0x0,
366 0x0, 0x10, 0x0,
367 0x0, 0x10, 0x4,
368 0x0, 0x10, 0x8,
369 0x0, 0x10, 0xc,
370 0x0, 0x10, 0x10,
371 0x0, 0xc, 0x10,
372 0x0, 0x8, 0x10,
373 0x0, 0x4, 0x10,
374 0x8, 0x8, 0x10,
375 0xa, 0x8, 0x10,
376 0xc, 0x8, 0x10,
377 0xe, 0x8, 0x10,
378 0x10, 0x8, 0x10,
379 0x10, 0x8, 0xe,
380 0x10, 0x8, 0xc,
381 0x10, 0x8, 0xa,
382 0x10, 0x8, 0x8,
383 0x10, 0xa, 0x8,
384 0x10, 0xc, 0x8,
385 0x10, 0xe, 0x8,
386 0x10, 0x10, 0x8,
387 0xe, 0x10, 0x8,
388 0xc, 0x10, 0x8,
389 0xa, 0x10, 0x8,
390 0x8, 0x10, 0x8,
391 0x8, 0x10, 0xa,
392 0x8, 0x10, 0xc,
393 0x8, 0x10, 0xe,
394 0x8, 0x10, 0x10,
395 0x8, 0xe, 0x10,
396 0x8, 0xc, 0x10,
397 0x8, 0xa, 0x10,
398 0xb, 0xb, 0x10,
399 0xc, 0xb, 0x10,
400 0xd, 0xb, 0x10,
401 0xf, 0xb, 0x10,
402 0x10, 0xb, 0x10,
403 0x10, 0xb, 0xf,
404 0x10, 0xb, 0xd,
405 0x10, 0xb, 0xc,
406 0x10, 0xb, 0xb,
407 0x10, 0xc, 0xb,
408 0x10, 0xd, 0xb,
409 0x10, 0xf, 0xb,
410 0x10, 0x10, 0xb,
411 0xf, 0x10, 0xb,
412 0xd, 0x10, 0xb,
413 0xc, 0x10, 0xb,
414 0xb, 0x10, 0xb,
415 0xb, 0x10, 0xc,
416 0xb, 0x10, 0xd,
417 0xb, 0x10, 0xf,
418 0xb, 0x10, 0x10,
419 0xb, 0xf, 0x10,
420 0xb, 0xd, 0x10,
421 0xb, 0xc, 0x10,
422 0x0, 0x0, 0x0,
423 0x0, 0x0, 0x0,
424 0x0, 0x0, 0x0,
425 0x0, 0x0, 0x0,
426 0x0, 0x0, 0x0,
427 0x0, 0x0, 0x0,
428 0x0, 0x0, 0x0
429 };
430
431 unsigned char AC[21] = {
432 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
433 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
434 0x0C, 0x00, 0x0F, 0x08, 0x00};
435
436 static int scanPCI(void);
437 static int PCIVendor(int);
438 static void printslots(void);
439 int delayLoop(int);
440 void unlockS3();
441
442 void puthex(unsigned long val)
443 {
444 printf("%08X ", val);
445 }
446
447 void puts(const char *s)
448 {
449 printf("%s", s);
450 }
451
452 static inline
453 outw(int port, unsigned short val)
454 {
455 outb(port, val >> 8);
456 outb(port+1, val);
457 }
458
459 vga_init(unsigned char *ISA_mem)
460 {
461 int slot;
462 struct VgaRegs *VgaTextRegs;
463
464 /* See if VGA already in TEXT mode - exit if so! */
465 outb(0x3CE, 0x06);
466 if ((inb(0x3CF) & 0x01) == 0) return;
467
468 /* If no VGA responding in text mode, then we have some work to do... */
469 slot = scanPCI(); /* find video card in use */
470 enablePCIvideo(slot); /* enable I/O to card */
471
472 /*
473 * Note: the PCI scanning code does not yet work correctly
474 * for non-Moto boxes, so the switch below only
475 * defaults to using an S3 card if it does not
476 * find a Cirrus card.
477 *
478 * The only reason we need to scan the bus looking for
479 * a graphics card is so we could do the "enablePCIvideo(slot)"
480 * call above; it is needed because Moto's OpenFirmware
481 * disables I/O to the graphics adapter before it gives
482 * us control. PEK'97
483 */
484
485 switch (PCIVendor(slot)) {
486 default: /* Assume S3 */
487 /* case(S3Vendor): */
488 unlockS3();
489 VgaTextRegs = S3TextRegs;
490 outw(0x3C4, 0x0120); /* disable video */
491 setTextRegs(VgaTextRegs); /* initial register setup */
492 setTextCLUT(); /* load color lookup table */
493 loadFont(ISA_mem); /* load font */
494 setTextRegs(VgaTextRegs); /* reload registers */
495 outw(0x3C4, 0x0100); /* re-enable video */
496 outb(0x3c2, 0x63); /* MISC */
497 outb(0x3c2, 0x67); /* MISC */
498 break;
499
500 case(CirrusVendor):
501 VgaTextRegs = GenVgaTextRegs;
502 outw(0x3C4, 0x0612); /* unlock ext regs */
503 outw(0x3C4, 0x0700); /* reset ext sequence mode */
504 outw(0x3C4, 0x0120); /* disable video */
505 setTextRegs(VgaTextRegs); /* initial register setup */
506 setTextCLUT(); /* load color lookup table */
507 loadFont(ISA_mem); /* load font */
508 setTextRegs(VgaTextRegs); /* reload registers */
509 outw(0x3C4, 0x0100); /* re-enable video */
510 outb(0x3c2, 0x63); /* MISC */
511 break;
512
513 case (DiamondVendor):
514 case (MatroxVendor):
515 /*
516 * The following code is almost enuf to get the Matrox
517 * working (on a Moto box) but the video is not stable.
518 * We probably need to tweak the TVP3026 Video PLL regs. PEK'97
519 */
520 VgaTextRegs=GenVgaTextRegs;
521 outw(0x3C4, 0x0120); /* disable video */
522 setTextRegs(VgaTextRegs); /* initial register setup */
523 setTextCLUT(); /* load color lookup table */
524 loadFont(ISA_mem); /* load font */
525 setTextRegs(VgaTextRegs); /* reload registers */
526 outw(0x3C4, 0x0100); /* re-enable video */
527 outb(0x3c2, 0x63); /* MISC */
528 puts("VGA Chip Vendor ID: ");
529 puthex(PCIVendor(slot));
530 puts("\n");
531 delayLoop(1);
532 break;
533 };
534
535
536 #ifdef DEBUG
537 printslots();
538 delayLoop(5);
539 #endif
540
541 delayLoop(2); /* give time for the video monitor to come up */
542 }
543
544 static int
545 NOP(int x)
546 {
547 }
548
549 /*
550 * Write to VGA Attribute registers.
551 */
552 writeAttr(index, data, videoOn)
553 unsigned char index;
554 unsigned char data;
555 unsigned char videoOn; /* video on flag */
556 {
557 unsigned char v;
558 v = inb(0x3da); /* reset attr. address toggle */
559 if (videoOn)
560 outb(0x3c0, (index & 0x1F) | 0x20);
561 else
562 outb(0x3c0, (index & 0x1F));
563 outb(0x3c0, data);
564 }
565
566 setTextRegs(struct VgaRegs *svp)
567 {
568 int i;
569
570 /*
571 * saved settings
572 */
573 while( svp->io_port != ENDMK ) {
574 outb(svp->io_port, svp->io_index);
575 outb(svp->io_port+1, svp->io_value);
576 svp++;
577 }
578
579 outb(0x3c2, 0x67); /* MISC */
580 outb(0x3c6, 0xff); /* MASK */
581
582 for ( i = 0; i < 0x10; i++)
583 writeAttr(i, AC[i], 0); /* pallete */
584 writeAttr(0x10, 0x0c, 0); /* text mode */
585 writeAttr(0x11, 0x00, 0); /* overscan color (border) */
586 writeAttr(0x12, 0x0f, 0); /* plane enable */
587 writeAttr(0x13, 0x08, 0); /* pixel panning */
588 writeAttr(0x14, 0x00, 1); /* color select; video on */
589
590 }
591
592 setTextCLUT()
593 {
594 int i;
595
596 outb(0x3C6, 0xFF);
597 i = inb(0x3C7);
598 outb(0x3C8, 0);
599 i = inb(0x3C7);
600
601 for ( i = 0; i < 256; i++) {
602 outb(0x3C9, TextCLUT[i].r);
603 outb(0x3C9, TextCLUT[i].g);
604 outb(0x3C9, TextCLUT[i].b);
605 }
606 }
607
608
609 loadFont(unsigned char *ISA_mem)
610 {
611 int i, j;
612 unsigned char *font_page = (unsigned char *) &ISA_mem[0xA0000];
613
614 outb(0x3C2, 0x67);
615 /*
616 * Load font
617 */
618 i = inb(0x3DA); /* Reset Attr toggle */
619
620 outb(0x3C0,0x30);
621 outb(0x3C0, 0x01); /* graphics mode */
622
623 outw(0x3C4, 0x0001); /* reset sequencer */
624 outw(0x3C4, 0x0204); /* write to plane 2 */
625 outw(0x3C4, 0x0406); /* enable plane graphics */
626 outw(0x3C4, 0x0003); /* reset sequencer */
627 outw(0x3CE, 0x0402); /* read plane 2 */
628 outw(0x3CE, 0x0500); /* write mode 0, read mode 0 */
629 outw(0x3CE, 0x0605); /* set graphics mode */
630
631 for (i = 0; i < sizeof(font); i += 16) {
632 for (j = 0; j < 16; j++) {
633 __asm__ volatile("eieio");
634 font_page[(2*i)+j] = font[i+j];
635 }
636 }
637 }
638
639
640 void
641 unlockS3()
642 {
643 /* From the S3 manual */
644 outb(0x46E8, 0x10); /* Put into setup mode */
645 outb(0x3C3, 0x10);
646 outb(0x102, 0x01); /* Enable registers */
647 outb(0x46E8, 0x08); /* Enable video */
648 outb(0x3C3, 0x08);
649 outb(0x4AE8, 0x00);
650
651 outb(0x42E8, 0x80); /* Reset graphics engine? */
652
653 outb(0x3D4, 0x38); /* Unlock all registers */
654 outb(0x3D5, 0x48);
655 outb(0x3D4, 0x39);
656 outb(0x3D5, 0xA5);
657 outb(0x3D4, 0x40);
658 outb(0x3D5, inb(0x3D5)|0x01);
659 outb(0x3D4, 0x33);
660 outb(0x3D5, inb(0x3D5)&~0x52);
661 outb(0x3D4, 0x35);
662 outb(0x3D5, inb(0x3D5)&~0x30);
663 outb(0x3D4, 0x3A);
664 outb(0x3D5, 0x00);
665 outb(0x3D4, 0x53);
666 outb(0x3D5, 0x00);
667 outb(0x3D4, 0x31);
668 outb(0x3D5, inb(0x3D5)&~0x4B);
669 outb(0x3D4, 0x58);
670
671 outb(0x3D5, 0);
672
673 outb(0x3D4, 0x54);
674 outb(0x3D5, 0x38);
675 outb(0x3D4, 0x60);
676 outb(0x3D5, 0x07);
677 outb(0x3D4, 0x61);
678 outb(0x3D5, 0x80);
679 outb(0x3D4, 0x62);
680 outb(0x3D5, 0xA1);
681 outb(0x3D4, 0x69); /* High order bits for cursor address */
682 outb(0x3D5, 0);
683
684 outb(0x3D4, 0x32);
685 outb(0x3D5, inb(0x3D5)&~0x10);
686 }
687
688 /* ============ */
689
690
691 #define NSLOTS 4
692 #define NPCIREGS 5
693
694
695 /*
696 * should use devfunc number/indirect method to be totally safe on
697 * all machines, this works for now on 3 slot Moto boxes
698 */
699
700 struct PCI_ConfigInfo {
701 unsigned long * config_addr;
702 unsigned long regs[NPCIREGS];
703 } PCI_slots [NSLOTS] = {
704 { (unsigned long *)0x80808000, { 0xDE, 0xAD, 0xBE, 0xEF } }, /* onboard */
705 { (unsigned long *)0x80810000, { 0xDE, 0xAD, 0xBE, 0xEF } }, /* slot A/1 */
706 { (unsigned long *)0x80820000, { 0xDE, 0xAD, 0xBE, 0xEF } }, /* slot B/2 */
707 { (unsigned long *)0x80840000, { 0xDE, 0xAD, 0xBE, 0xEF } } /* slot C/3 */
708 };
709
710
711 /*
712 * The following code modifies the PCI Command register
713 * to enable memory and I/O accesses.
714 */
715 enablePCIvideo(slot)
716 {
717 volatile unsigned char * ppci;
718
719 ppci = (unsigned char * )PCI_slots[slot].config_addr;
720 ppci[4] = 0x0003; /* enable memory and I/O accesses */
721 __asm__ volatile("eieio");
722
723 outb(0x3d4, 0x11);
724 outb(0x3d5, 0x0e); /* unlock CR0-CR7 */
725 }
726
727 long
728 SwapBytes(long lv) /* turn little endian into big indian long */
729 {
730 long t;
731 t = (lv&0x000000FF) << 24;
732 t |= (lv&0x0000FF00) << 8;
733 t |= (lv&0x00FF0000) >> 8;
734 t |= (lv&0xFF000000) >> 24;
735 return(t);
736 }
737
738
739 #define DEVID 0
740 #define CMD 1
741 #define CLASS 2
742 #define MEMBASE 4
743
744 int
745 scanPCI(void)
746 {
747 int slt, r;
748 struct PCI_ConfigInfo *pslot;
749 int theSlot = -1;
750 int highVgaSlot = -1;
751
752 for ( slt = 0; slt < NSLOTS; slt++) {
753 pslot = &PCI_slots[slt];
754 for ( r = 0; r < NPCIREGS; r++) {
755 pslot->regs[r] = SwapBytes ( pslot->config_addr[r] );
756 }
757
758 if ( pslot->regs[DEVID] != 0xFFFFFFFF ) { /* card in slot ? */
759 if ( (pslot->regs[CLASS] & 0xFFFFFF00) == 0x03000000 ) { /* VGA ? */
760 highVgaSlot = slt;
761 if ( (pslot->regs[CMD] & 0x03) ) { /* did firmware enable it ? */
762 theSlot = slt;
763 }
764 }
765 }
766 }
767
768 if ( theSlot == -1 )
769 theSlot = highVgaSlot;
770
771 return ( theSlot );
772 }
773
774
775 int
776 delayLoop(int k)
777 {
778 volatile int a, b;
779 volatile int i, j;
780 a = 0;
781 do {
782 for ( i = 0; i < 500; i++) {
783 b = i;
784 for ( j = 0; j < 200; j++) {
785 a = b+j;
786 }
787 }
788 } while (k--);
789 return(a);
790 }
791
792
793 /* return Vendor ID of card in the slot */
794 static
795 int PCIVendor(int slotnum)
796 {
797 struct PCI_ConfigInfo *pslot;
798
799 pslot = &PCI_slots[slotnum];
800
801 return (pslot->regs[DEVID] & 0xFFFF);
802 }
803
804 static
805 void printslots(void)
806 {
807 int i;
808 for(i=0; i < NSLOTS; i++) {
809
810 puts("PCI Slot number: "); puthex(i);
811 puts(" Vendor ID: ");
812 puthex(PCIVendor(i)); puts("\n");
813
814 }
815 }
816 #endif /* CONS_VGA */
817