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