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