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