xref: /netbsd-src/sys/arch/bebox/stand/boot/vreset.c (revision 274254cdae52594c1aa480a736aef78313d15c9c)
1 /*	$NetBSD: vreset.c,v 1.11 2008/05/26 16:28:39 kiyohara 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 <sys/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 writeAttr(u_char, u_char, u_char);
444 void setTextRegs(struct VgaRegs *);
445 void setTextCLUT(void);
446 void loadFont(u_char *);
447 void unlockS3(void);
448 #ifdef DEBUG
449 static void printslots(void);
450 #endif
451 
452 void
453 vga_reset(u_char *ISA_mem)
454 {
455 	int slot;
456         struct VgaRegs *VgaTextRegs;
457 
458 	/* See if VGA already in TEXT mode - exit if so! */
459 	outb(0x3CE, 0x06);
460 	if ((inb(0x3CF) & 0x01) == 0)
461 		return;
462 
463 	/* If no VGA responding in text mode, then we have some work to do... */
464 	slot = scanPCI();            	/* find video card in use  */
465 	enablePCIvideo(slot);          	/* enable I/O to card      */
466 
467 	/*
468          * Note: the PCI scanning code does not yet work correctly
469          *       for non-Moto boxes, so the switch below only
470          *       defaults to using an S3 card if it does not
471          *       find a Cirrus card.
472          *
473          *       The only reason we need to scan the bus looking for
474          *       a graphics card is so we could do the "enablePCIvideo(slot)"
475          *       call above; it is needed because Moto's OpenFirmware
476          *       disables I/O to the graphics adapter before it gives
477          *       us control.                                       PEK'97
478          */
479 
480 	switch (PCIVendor(slot)) {
481 	default:			       /* Assume S3 */
482 #if 0
483 	case S3Vendor:
484 #endif
485 		unlockS3();
486 		VgaTextRegs = S3TextRegs;
487 		outw(0x3C4, 0x0120);           /* disable video              */
488 		setTextRegs(VgaTextRegs);      /* initial register setup     */
489 		setTextCLUT();                 /* load color lookup table    */
490 		loadFont(ISA_mem);             /* load font                  */
491 		setTextRegs(VgaTextRegs);      /* reload registers           */
492 		outw(0x3C4, 0x0100);           /* re-enable video            */
493 		outb(0x3c2, 0x63);  	       /* MISC */
494 		outb(0x3c2, 0x67);  	       /* MISC */
495 		break;
496 
497 	case CirrusVendor:
498 		VgaTextRegs = GenVgaTextRegs;
499 		outw(0x3C4, 0x0612);	       /* unlock ext regs            */
500 		outw(0x3C4, 0x0700);	       /* reset ext sequence mode    */
501 		outw(0x3C4, 0x0120);           /* disable video              */
502 		setTextRegs(VgaTextRegs);      /* initial register setup     */
503 		setTextCLUT();                 /* load color lookup table    */
504 		loadFont(ISA_mem);             /* load font                  */
505 		setTextRegs(VgaTextRegs);      /* reload registers           */
506 		outw(0x3C4, 0x0100);           /* re-enable video            */
507 		outb(0x3c2, 0x63);  	       /* MISC */
508 		break;
509 
510         case DiamondVendor:
511         case MatroxVendor:
512 	  /*
513            * The following code is almost enuf to get the Matrox
514            * working (on a Moto box) but the video is not stable.
515            * We probably need to tweak the TVP3026 Video PLL regs.   PEK'97
516            */
517 		VgaTextRegs = GenVgaTextRegs;
518 		outw(0x3C4, 0x0120);           /* disable video              */
519 		setTextRegs(VgaTextRegs);      /* initial register setup     */
520 		setTextCLUT();                 /* load color lookup table    */
521 		loadFont(ISA_mem);             /* load font                  */
522 		setTextRegs(VgaTextRegs);      /* reload registers           */
523 		outw(0x3C4, 0x0100);           /* re-enable video            */
524 		outb(0x3c2, 0x63);  	       /* MISC */
525 		delayLoop(1);
526 		break;
527 	};
528 
529 #ifdef DEBUG
530 	printslots();
531 	delayLoop(5);
532 #endif
533 	delayLoop(2);		/* give time for the video monitor to come up */
534 }
535 
536 /*
537  * Write to VGA Attribute registers.
538  */
539 void
540 writeAttr(u_char index, u_char data, u_char videoOn)
541 {
542 	u_char v;
543 	v = inb(0x3da);   /* reset attr. address toggle */
544 	if (videoOn)
545 		outb(0x3c0, (index & 0x1F) | 0x20);
546 	else
547 		outb(0x3c0, (index & 0x1F));
548 	outb(0x3c0, data);
549 }
550 
551 void
552 setTextRegs(struct VgaRegs *svp)
553 {
554 	int i;
555 
556 	/*
557 	 *  saved settings
558 	 */
559 	while (svp->io_port != ENDMK) {
560 		outb(svp->io_port,   svp->io_index);
561 		outb(svp->io_port+1, svp->io_value);
562 		svp++;
563 	}
564 
565 	outb(0x3c2, 0x67);  /* MISC */
566 	outb(0x3c6, 0xff);  /* MASK */
567 
568 	for (i = 0; i < 0x10; i++)
569 		writeAttr(i, AC[i], 0);	/* pallete */
570 	writeAttr(0x10, 0x0c, 0);	/* text mode */
571 	writeAttr(0x11, 0x00, 0);	/* overscan color (border) */
572 	writeAttr(0x12, 0x0f, 0);	/* plane enable */
573 	writeAttr(0x13, 0x08, 0);	/* pixel panning */
574 	writeAttr(0x14, 0x00, 1);	/* color select; video on */
575 }
576 
577 void
578 setTextCLUT(void)
579 {
580 	int i;
581 
582 	outb(0x3C6, 0xFF);
583 	i = inb(0x3C7);
584 	outb(0x3C8, 0);
585 	i = inb(0x3C7);
586 
587 	for (i = 0; i < 256; i++) {
588 		outb(0x3C9, TextCLUT[i].r);
589 		outb(0x3C9, TextCLUT[i].g);
590 		outb(0x3C9, TextCLUT[i].b);
591 	}
592 }
593 
594 void
595 loadFont(u_char *ISA_mem)
596 {
597 	int i, j;
598 	u_char *font_page = (u_char *)&ISA_mem[0xA0000];
599 
600 	outb(0x3C2, 0x67);
601 	/*
602 	 * Load font
603 	 */
604 	i = inb(0x3DA);		/* Reset Attr toggle */
605 
606 	outb(0x3C0,0x30);
607 	outb(0x3C0, 0x01);	/* graphics mode */
608 
609 	outw(0x3C4, 0x0001);	/* reset sequencer */
610 	outw(0x3C4, 0x0204);	/* write to plane 2 */
611 	outw(0x3C4, 0x0406);	/* enable plane graphics */
612 	outw(0x3C4, 0x0003);	/* reset sequencer */
613 	outw(0x3CE, 0x0402);	/* read plane 2 */
614 	outw(0x3CE, 0x0500);	/* write mode 0, read mode 0 */
615 	outw(0x3CE, 0x0605);	/* set graphics mode */
616 
617 	for (i = 0;  i < sizeof(font);  i += 16) {
618 		for (j = 0;  j < 16;  j++) {
619 			__asm volatile("eieio");
620 			font_page[(2*i)+j] = font[i+j];
621 		}
622 	}
623 }
624 
625 void
626 unlockS3(void)
627 {
628 	/* From the S3 manual */
629 	outb(0x46E8, 0x10);  /* Put into setup mode */
630 	outb(0x3C3, 0x10);
631 	outb(0x102, 0x01);   /* Enable registers */
632 	outb(0x46E8, 0x08);  /* Enable video */
633 	outb(0x3C3, 0x08);
634 	outb(0x4AE8, 0x00);
635 
636 	outb(0x42E8, 0x80);  /* Reset graphics engine? */
637 
638 	outb(0x3D4, 0x38);  /* Unlock all registers */
639 	outb(0x3D5, 0x48);
640 	outb(0x3D4, 0x39);
641 	outb(0x3D5, 0xA5);
642 	outb(0x3D4, 0x40);
643 	outb(0x3D5, inb(0x3D5)|0x01);
644 	outb(0x3D4, 0x33);
645 	outb(0x3D5, inb(0x3D5)&~0x52);
646 	outb(0x3D4, 0x35);
647 	outb(0x3D5, inb(0x3D5)&~0x30);
648 	outb(0x3D4, 0x3A);
649 	outb(0x3D5, 0x00);
650 	outb(0x3D4, 0x53);
651 	outb(0x3D5, 0x00);
652 	outb(0x3D4, 0x31);
653 	outb(0x3D5, inb(0x3D5)&~0x4B);
654 	outb(0x3D4, 0x58);
655 
656 	outb(0x3D5, 0);
657 
658 	outb(0x3D4, 0x54);
659 	outb(0x3D5, 0x38);
660 	outb(0x3D4, 0x60);
661 	outb(0x3D5, 0x07);
662 	outb(0x3D4, 0x61);
663 	outb(0x3D5, 0x80);
664 	outb(0x3D4, 0x62);
665 	outb(0x3D5, 0xA1);
666 	outb(0x3D4, 0x69);  /* High order bits for cursor address */
667 	outb(0x3D5, 0);
668 
669 	outb(0x3D4, 0x32);
670 	outb(0x3D5, inb(0x3D5)&~0x10);
671 }
672 
673 /* ============ */
674 
675 
676 #define NSLOTS 5
677 #define NPCIREGS  5
678 
679 /*
680  * should use devfunc number/indirect method to be totally safe on
681  * all machines, this works for now on 3 slot Moto boxes
682  */
683 
684 struct PCI_ConfigInfo {
685 	u_long * config_addr;
686 	u_long regs[NPCIREGS];
687 } PCI_slots [NSLOTS] = {
688 	{ (u_long *)0x80800800, { 0xDE, 0xAD, 0xBE, 0xEF } },
689 	{ (u_long *)0x80801000, { 0xDE, 0xAD, 0xBE, 0xEF } },
690 	{ (u_long *)0x80802000, { 0xDE, 0xAD, 0xBE, 0xEF } },
691 	{ (u_long *)0x80804000, { 0xDE, 0xAD, 0xBE, 0xEF } },
692 	{ (u_long *)0x80808000, { 0xDE, 0xAD, 0xBE, 0xEF } },
693 };
694 
695 
696 /*
697  * The following code modifies the PCI Command register
698  * to enable memory and I/O accesses.
699  */
700 void
701 enablePCIvideo(int slot)
702 {
703 	volatile u_char *ppci;
704 
705 	ppci = (u_char *)PCI_slots[slot].config_addr;
706 	ppci[4] = 0x0003;	/* enable memory and I/O accesses */
707 	__asm volatile("eieio");
708 
709 	outb(0x3d4, 0x11);
710 	outb(0x3d5, 0x0e);	/* unlock CR0-CR7 */
711 }
712 
713 #define DEVID   0
714 #define CMD     1
715 #define CLASS   2
716 #define MEMBASE 4
717 
718 int
719 scanPCI(void)
720 {
721 	int slt, r;
722 	struct PCI_ConfigInfo *pslot;
723 	int theSlot = -1;
724 	int highVgaSlot = -1;
725 
726 	for (slt = 0; slt < NSLOTS; slt++) {
727 		pslot = &PCI_slots[slt];
728 		for (r = 0; r < NPCIREGS; r++) {
729 			pslot->regs[r] = bswap32(pslot->config_addr[r]);
730 		}
731 
732 		if (pslot->regs[DEVID] != 0xFFFFFFFF) {     /* card in slot ? */
733 			if ((pslot->regs[CLASS] & 0xFFFFFF00) == 0x03000000) { /* VGA ? */
734 				highVgaSlot = slt;
735 				if ((pslot->regs[CMD] & 0x03)) { /* did firmware enable it ? */
736 					theSlot = slt;
737 				}
738 			}
739 		}
740 	}
741 
742 	if (theSlot == -1)
743 		theSlot = highVgaSlot;
744 
745 	return theSlot;
746 }
747 
748 int
749 delayLoop(int k)
750 {
751 	volatile int a, b;
752 	volatile int i, j;
753 	a = 0;
754 	do {
755 		for (i = 0; i < 500; i++) {
756 			b = i;
757 			for (j = 0; j < 200; j++) {
758 				a = b+j;
759 			}
760 		}
761 	} while (k--);
762 	return a;
763 }
764 
765 /* return Vendor ID of card in the slot */
766 static int
767 PCIVendor(int slotnum)
768 {
769 	struct PCI_ConfigInfo *pslot;
770 
771 	pslot = &PCI_slots[slotnum];
772 
773 	return (pslot->regs[DEVID] & 0xFFFF);
774 }
775 
776 #ifdef DEBUG
777 static void
778 printslots(void)
779 {
780 	int i;
781 	for (i = 0; i < NSLOTS; i++) {
782 		printf("PCI Slot number: %d", i);
783 		printf(" Vendor ID: 0x%x\n", PCIVendor(i));
784 	}
785 }
786 #endif /* DEBUG */
787 #endif /* CONS_VGA */
788