1 /*
2  * vreset.c
3  *
4  * Initialize the VGA control registers to 80x25 text mode.
5  *
6  * Adapted from a program by:
7  *                                      Steve Sellgren
8  *                                      San Francisco Indigo Company
9  *                                      sfindigo!sellgren@uunet.uu.net
10  *
11  * Original concept by:
12  *                                      Gary Thomas <gdt@linuxppc.org>
13  * Adapted for Moto boxes by:
14  *                                      Pat Kane & Mark Scott, 1996
15  * Adapted for IBM portables by:
16  *                                      Takeshi Ishimoto
17  * Multi-console support:
18  *                                      Terje Malmedal <terje.malmedal@usit.uio.no>
19  */
20 
21 #include "iso_font.h"
22 #include "nonstdio.h"
23 
24 extern char *vidmem;
25 extern int lines, cols;
26 struct VaRegs;
27 
28 /*
29  * VGA Register
30  */
31 struct VgaRegs
32 {
33 	unsigned short io_port;
34 	unsigned char  io_index;
35 	unsigned char  io_value;
36 };
37 
38 void unlockVideo(int slot);
39 void setTextRegs(struct VgaRegs *svp);
40 void setTextCLUT(int shift);
41 void clearVideoMemory(void);
42 void loadFont(unsigned char *ISA_mem);
43 
mdelay(int ms)44 static void mdelay(int ms)
45 {
46 	for (; ms > 0; --ms)
47 		udelay(1000);
48 }
49 
50 /*
51  * Default console text mode registers  used to reset
52  * graphics adapter.
53  */
54 #define NREGS 54
55 #define ENDMK  0xFFFF  /* End marker */
56 
57 #define S3Vendor	0x5333
58 #define CirrusVendor    0x1013
59 #define DiamondVendor   0x100E
60 #define MatroxVendor    0x102B
61 #define ParadiseVendor  0x101C
62 
63 struct VgaRegs GenVgaTextRegs[NREGS+1] = {
64 	/* port		index	value  */
65 	/* SR Regs */
66 	{ 0x3c4,	0x1,	0x0 },
67 	{ 0x3c4,	0x2,	0x3 },
68 	{ 0x3c4,	0x3,	0x0 },
69 	{ 0x3c4,	0x4,	0x2 },
70 	 /* CR Regs */
71 	{ 0x3d4,	0x0,	0x5f },
72 	{ 0x3d4,	0x1,	0x4f },
73 	{ 0x3d4,	0x2,	0x50 },
74 	{ 0x3d4,	0x3,	0x82 },
75 	{ 0x3d4,	0x4,	0x55 },
76 	{ 0x3d4,	0x5,	0x81 },
77 	{ 0x3d4,	0x6,	0xbf },
78 	{ 0x3d4,	0x7,	0x1f },
79 	{ 0x3d4,	0x8,	0x00 },
80 	{ 0x3d4,	0x9,	0x4f },
81 	{ 0x3d4,	0xa,	0x0d },
82 	{ 0x3d4,	0xb,	0x0e },
83 	{ 0x3d4,	0xc,	0x00 },
84 	{ 0x3d4,	0xd,	0x00 },
85 	{ 0x3d4,	0xe,	0x00 },
86 	{ 0x3d4,	0xf,	0x00 },
87 	{ 0x3d4,	0x10,	0x9c },
88 	{ 0x3d4,	0x11,	0x8e },
89 	{ 0x3d4,	0x12,	0x8f },
90 	{ 0x3d4,	0x13,	0x28 },
91 	{ 0x3d4,	0x14,	0x1f },
92 	{ 0x3d4,	0x15,	0x96 },
93 	{ 0x3d4,	0x16,	0xb9 },
94 	{ 0x3d4,	0x17,	0xa3 },
95 	 /* GR Regs */
96 	{ 0x3ce,	0x0,	0x0 },
97 	{ 0x3ce,	0x1,	0x0 },
98 	{ 0x3ce,	0x2,	0x0 },
99 	{ 0x3ce,	0x3,	0x0 },
100 	{ 0x3ce,	0x4,	0x0 },
101 	{ 0x3ce,	0x5,	0x10 },
102 	{ 0x3ce,	0x6,	0xe },
103 	{ 0x3ce,	0x7,	0x0 },
104 	{ 0x3ce,	0x8,	0xff },
105 	{ ENDMK }
106 };
107 
108 struct RGBColors
109 {
110   unsigned char r, g, b;
111 };
112 
113 /*
114  * Default console text mode color table.
115  * These values were obtained by booting Linux with
116  * text mode firmware & then dumping the registers.
117  */
118 struct RGBColors TextCLUT[256] =
119 {
120 	/* red	green	blue  */
121 	{ 0x0,	0x0,	0x0 },
122 	{ 0x0,	0x0,	0x2a },
123 	{ 0x0,	0x2a,	0x0 },
124 	{ 0x0,	0x2a,	0x2a },
125 	{ 0x2a,	0x0,	0x0 },
126 	{ 0x2a,	0x0,	0x2a },
127 	{ 0x2a,	0x2a,	0x0 },
128 	{ 0x2a,	0x2a,	0x2a },
129 	{ 0x0,	0x0,	0x15 },
130 	{ 0x0,	0x0,	0x3f },
131 	{ 0x0,	0x2a,	0x15 },
132 	{ 0x0,	0x2a,	0x3f },
133 	{ 0x2a,	0x0,	0x15 },
134 	{ 0x2a,	0x0,	0x3f },
135 	{ 0x2a,	0x2a,	0x15 },
136 	{ 0x2a,	0x2a,	0x3f },
137 	{ 0x0,	0x15,	0x0 },
138 	{ 0x0,	0x15,	0x2a },
139 	{ 0x0,	0x3f,	0x0 },
140 	{ 0x0,	0x3f,	0x2a },
141 	{ 0x2a,	0x15,	0x0 },
142 	{ 0x2a,	0x15,	0x2a },
143 	{ 0x2a,	0x3f,	0x0 },
144 	{ 0x2a,	0x3f,	0x2a },
145 	{ 0x0,	0x15,	0x15 },
146 	{ 0x0,	0x15,	0x3f },
147 	{ 0x0,	0x3f,	0x15 },
148 	{ 0x0,	0x3f,	0x3f },
149 	{ 0x2a,	0x15,	0x15 },
150 	{ 0x2a,	0x15,	0x3f },
151 	{ 0x2a,	0x3f,	0x15 },
152 	{ 0x2a,	0x3f,	0x3f },
153 	{ 0x15,	0x0,	0x0 },
154 	{ 0x15,	0x0,	0x2a },
155 	{ 0x15,	0x2a,	0x0 },
156 	{ 0x15,	0x2a,	0x2a },
157 	{ 0x3f,	0x0,	0x0 },
158 	{ 0x3f,	0x0,	0x2a },
159 	{ 0x3f,	0x2a,	0x0 },
160 	{ 0x3f,	0x2a,	0x2a },
161 	{ 0x15,	0x0,	0x15 },
162 	{ 0x15,	0x0,	0x3f },
163 	{ 0x15,	0x2a,	0x15 },
164 	{ 0x15,	0x2a,	0x3f },
165 	{ 0x3f,	0x0,	0x15 },
166 	{ 0x3f,	0x0,	0x3f },
167 	{ 0x3f,	0x2a,	0x15 },
168 	{ 0x3f,	0x2a,	0x3f },
169 	{ 0x15,	0x15,	0x0 },
170 	{ 0x15,	0x15,	0x2a },
171 	{ 0x15,	0x3f,	0x0 },
172 	{ 0x15,	0x3f,	0x2a },
173 	{ 0x3f,	0x15,	0x0 },
174 	{ 0x3f,	0x15,	0x2a },
175 	{ 0x3f,	0x3f,	0x0 },
176 	{ 0x3f,	0x3f,	0x2a },
177 	{ 0x15,	0x15,	0x15 },
178 	{ 0x15,	0x15,	0x3f },
179 	{ 0x15,	0x3f,	0x15 },
180 	{ 0x15,	0x3f,	0x3f },
181 	{ 0x3f,	0x15,	0x15 },
182 	{ 0x3f,	0x15,	0x3f },
183 	{ 0x3f,	0x3f,	0x15 },
184 	{ 0x3f,	0x3f,	0x3f },
185 	{ 0x39,	0xc,	0x5 },
186 	{ 0x15,	0x2c,	0xf },
187 	{ 0x26,	0x10,	0x3d },
188 	{ 0x29,	0x29,	0x38 },
189 	{ 0x4,	0x1a,	0xe },
190 	{ 0x2,	0x1e,	0x3a },
191 	{ 0x3c,	0x25,	0x33 },
192 	{ 0x3c,	0xc,	0x2c },
193 	{ 0x3f,	0x3,	0x2b },
194 	{ 0x1c,	0x9,	0x13 },
195 	{ 0x25,	0x2a,	0x35 },
196 	{ 0x1e,	0xa,	0x38 },
197 	{ 0x24,	0x8,	0x3 },
198 	{ 0x3,	0xe,	0x36 },
199 	{ 0xc,	0x6,	0x2a },
200 	{ 0x26,	0x3,	0x32 },
201 	{ 0x5,	0x2f,	0x33 },
202 	{ 0x3c,	0x35,	0x2f },
203 	{ 0x2d,	0x26,	0x3e },
204 	{ 0xd,	0xa,	0x10 },
205 	{ 0x25,	0x3c,	0x11 },
206 	{ 0xd,	0x4,	0x2e },
207 	{ 0x5,	0x19,	0x3e },
208 	{ 0xc,	0x13,	0x34 },
209 	{ 0x2b,	0x6,	0x24 },
210 	{ 0x4,	0x3,	0xd },
211 	{ 0x2f,	0x3c,	0xc },
212 	{ 0x2a,	0x37,	0x1f },
213 	{ 0xf,	0x12,	0x38 },
214 	{ 0x38,	0xe,	0x2a },
215 	{ 0x12,	0x2f,	0x19 },
216 	{ 0x29,	0x2e,	0x31 },
217 	{ 0x25,	0x13,	0x3e },
218 	{ 0x33,	0x3e,	0x33 },
219 	{ 0x1d,	0x2c,	0x25 },
220 	{ 0x15,	0x15,	0x5 },
221 	{ 0x32,	0x25,	0x39 },
222 	{ 0x1a,	0x7,	0x1f },
223 	{ 0x13,	0xe,	0x1d },
224 	{ 0x36,	0x17,	0x34 },
225 	{ 0xf,	0x15,	0x23 },
226 	{ 0x2,	0x35,	0xd },
227 	{ 0x15,	0x3f,	0xc },
228 	{ 0x14,	0x2f,	0xf },
229 	{ 0x19,	0x21,	0x3e },
230 	{ 0x27,	0x11,	0x2f },
231 	{ 0x38,	0x3f,	0x3c },
232 	{ 0x36,	0x2d,	0x15 },
233 	{ 0x16,	0x17,	0x2 },
234 	{ 0x1,	0xa,	0x3d },
235 	{ 0x1b,	0x11,	0x3f },
236 	{ 0x21,	0x3c,	0xd },
237 	{ 0x1a,	0x39,	0x3d },
238 	{ 0x8,	0xe,	0xe },
239 	{ 0x22,	0x21,	0x23 },
240 	{ 0x1e,	0x30,	0x5 },
241 	{ 0x1f,	0x22,	0x3d },
242 	{ 0x1e,	0x2f,	0xa },
243 	{ 0x0,	0x1c,	0xe },
244 	{ 0x0,	0x1c,	0x15 },
245 	{ 0x0,	0x1c,	0x1c },
246 	{ 0x0,	0x15,	0x1c },
247 	{ 0x0,	0xe,	0x1c },
248 	{ 0x0,	0x7,	0x1c },
249 	{ 0xe,	0xe,	0x1c },
250 	{ 0x11,	0xe,	0x1c },
251 	{ 0x15,	0xe,	0x1c },
252 	{ 0x18,	0xe,	0x1c },
253 	{ 0x1c,	0xe,	0x1c },
254 	{ 0x1c,	0xe,	0x18 },
255 	{ 0x1c,	0xe,	0x15 },
256 	{ 0x1c,	0xe,	0x11 },
257 	{ 0x1c,	0xe,	0xe },
258 	{ 0x1c,	0x11,	0xe },
259 	{ 0x1c,	0x15,	0xe },
260 	{ 0x1c,	0x18,	0xe },
261 	{ 0x1c,	0x1c,	0xe },
262 	{ 0x18,	0x1c,	0xe },
263 	{ 0x15,	0x1c,	0xe },
264 	{ 0x11,	0x1c,	0xe },
265 	{ 0xe,	0x1c,	0xe },
266 	{ 0xe,	0x1c,	0x11 },
267 	{ 0xe,	0x1c,	0x15 },
268 	{ 0xe,	0x1c,	0x18 },
269 	{ 0xe,	0x1c,	0x1c },
270 	{ 0xe,	0x18,	0x1c },
271 	{ 0xe,	0x15,	0x1c },
272 	{ 0xe,	0x11,	0x1c },
273 	{ 0x14,	0x14,	0x1c },
274 	{ 0x16,	0x14,	0x1c },
275 	{ 0x18,	0x14,	0x1c },
276 	{ 0x1a,	0x14,	0x1c },
277 	{ 0x1c,	0x14,	0x1c },
278 	{ 0x1c,	0x14,	0x1a },
279 	{ 0x1c,	0x14,	0x18 },
280 	{ 0x1c,	0x14,	0x16 },
281 	{ 0x1c,	0x14,	0x14 },
282 	{ 0x1c,	0x16,	0x14 },
283 	{ 0x1c,	0x18,	0x14 },
284 	{ 0x1c,	0x1a,	0x14 },
285 	{ 0x1c,	0x1c,	0x14 },
286 	{ 0x1a,	0x1c,	0x14 },
287 	{ 0x18,	0x1c,	0x14 },
288 	{ 0x16,	0x1c,	0x14 },
289 	{ 0x14,	0x1c,	0x14 },
290 	{ 0x14,	0x1c,	0x16 },
291 	{ 0x14,	0x1c,	0x18 },
292 	{ 0x14,	0x1c,	0x1a },
293 	{ 0x14,	0x1c,	0x1c },
294 	{ 0x14,	0x1a,	0x1c },
295 	{ 0x14,	0x18,	0x1c },
296 	{ 0x14,	0x16,	0x1c },
297 	{ 0x0,	0x0,	0x10 },
298 	{ 0x4,	0x0,	0x10 },
299 	{ 0x8,	0x0,	0x10 },
300 	{ 0xc,	0x0,	0x10 },
301 	{ 0x10,	0x0,	0x10 },
302 	{ 0x10,	0x0,	0xc },
303 	{ 0x10,	0x0,	0x8 },
304 	{ 0x10,	0x0,	0x4 },
305 	{ 0x10,	0x0,	0x0 },
306 	{ 0x10,	0x4,	0x0 },
307 	{ 0x10,	0x8,	0x0 },
308 	{ 0x10,	0xc,	0x0 },
309 	{ 0x10,	0x10,	0x0 },
310 	{ 0xc,	0x10,	0x0 },
311 	{ 0x8,	0x10,	0x0 },
312 	{ 0x4,	0x10,	0x0 },
313 	{ 0x0,	0x10,	0x0 },
314 	{ 0x0,	0x10,	0x4 },
315 	{ 0x0,	0x10,	0x8 },
316 	{ 0x0,	0x10,	0xc },
317 	{ 0x0,	0x10,	0x10 },
318 	{ 0x0,	0xc,	0x10 },
319 	{ 0x0,	0x8,	0x10 },
320 	{ 0x0,	0x4,	0x10 },
321 	{ 0x8,	0x8,	0x10 },
322 	{ 0xa,	0x8,	0x10 },
323 	{ 0xc,	0x8,	0x10 },
324 	{ 0xe,	0x8,	0x10 },
325 	{ 0x10,	0x8,	0x10 },
326 	{ 0x10,	0x8,	0xe },
327 	{ 0x10,	0x8,	0xc },
328 	{ 0x10,	0x8,	0xa },
329 	{ 0x10,	0x8,	0x8 },
330 	{ 0x10,	0xa,	0x8 },
331 	{ 0x10,	0xc,	0x8 },
332 	{ 0x10,	0xe,	0x8 },
333 	{ 0x10,	0x10,	0x8 },
334 	{ 0xe,	0x10,	0x8 },
335 	{ 0xc,	0x10,	0x8 },
336 	{ 0xa,	0x10,	0x8 },
337 	{ 0x8,	0x10,	0x8 },
338 	{ 0x8,	0x10,	0xa },
339 	{ 0x8,	0x10,	0xc },
340 	{ 0x8,	0x10,	0xe },
341 	{ 0x8,	0x10,	0x10 },
342 	{ 0x8,	0xe,	0x10 },
343 	{ 0x8,	0xc,	0x10 },
344 	{ 0x8,	0xa,	0x10 },
345 	{ 0xb,	0xb,	0x10 },
346 	{ 0xc,	0xb,	0x10 },
347 	{ 0xd,	0xb,	0x10 },
348 	{ 0xf,	0xb,	0x10 },
349 	{ 0x10,	0xb,	0x10 },
350 	{ 0x10,	0xb,	0xf },
351 	{ 0x10,	0xb,	0xd },
352 	{ 0x10,	0xb,	0xc },
353 	{ 0x10,	0xb,	0xb },
354 	{ 0x10,	0xc,	0xb },
355 	{ 0x10,	0xd,	0xb },
356 	{ 0x10,	0xf,	0xb },
357 	{ 0x10,	0x10,	0xb },
358 	{ 0xf,	0x10,	0xb },
359 	{ 0xd,	0x10,	0xb },
360 	{ 0xc,	0x10,	0xb },
361 	{ 0xb,	0x10,	0xb },
362 	{ 0xb,	0x10,	0xc },
363 	{ 0xb,	0x10,	0xd },
364 	{ 0xb,	0x10,	0xf },
365 	{ 0xb,	0x10,	0x10 },
366 	{ 0xb,	0xf,	0x10 },
367 	{ 0xb,	0xd,	0x10 },
368 	{ 0xb,	0xc,	0x10 },
369 	{ 0x0,	0x0,	0x0 },
370 	{ 0x0,	0x0,	0x0 },
371 	{ 0x0,	0x0,	0x0 },
372 	{ 0x0,	0x0,	0x0 },
373 	{ 0x0,	0x0,	0x0 },
374 	{ 0x0,	0x0,	0x0 },
375 	{ 0x0,	0x0,	0x0 }
376 };
377 
378 unsigned char AC[21] = {
379     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
380     0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
381     0x0C, 0x00, 0x0F, 0x08, 0x00};
382 
383 static int scanPCI(int start_slt);
384 static int PCIVendor(int);
385 #ifdef DEBUG
386 static void printslots(void);
387 #endif
388 extern void puthex(unsigned long);
389 extern void puts(const char *);
390 static void unlockS3(void);
391 
392 static inline void
outw(int port,unsigned short val)393 outw(int port, unsigned short val)
394 {
395 	outb(port, val >> 8);
396 	outb(port+1, val);
397 }
398 
399 int
vga_init(unsigned char * ISA_mem)400 vga_init(unsigned char *ISA_mem)
401 {
402 	int slot;
403 	struct VgaRegs *VgaTextRegs;
404 
405 	/* See if VGA already in TEXT mode - exit if so! */
406 	outb(0x3CE, 0x06);
407 	if ((inb(0x3CF) & 0x01) == 0){
408 		puts("VGA already in text mode\n");
409 		return 0;
410 	}
411 
412 	/* If no VGA responding in text mode, then we have some work to do...
413 	 */
414 	slot = -1;
415 	while((slot = scanPCI(slot)) > -1) { /* find video card in use  */
416 		unlockVideo(slot);           /* enable I/O to card      */
417 		VgaTextRegs = GenVgaTextRegs;
418 
419 		switch (PCIVendor(slot)) {
420 		default:
421 			break;
422 		case(S3Vendor):
423 			unlockS3();
424 			break;
425 
426 		case(CirrusVendor):
427 			outw(0x3C4, 0x0612);       /* unlock ext regs */
428 			outw(0x3C4, 0x0700);       /* reset ext sequence mode */
429 			break;
430 
431 		case(ParadiseVendor):                 /* IBM Portable 850 */
432 			outw(0x3ce, 0x0f05);      /* unlock pardise registers */
433 			outw(0x3c4, 0x0648);
434 			outw(0x3d4, 0x2985);
435 			outw(0x3d4, 0x34a6);
436 			outb(0x3ce, 0x0b);       /* disable linear addressing */
437 			outb(0x3cf, inb(0x3cf) & ~0x30);
438 			outw(0x3c4, 0x1400);
439 			outb(0x3ce, 0x0e);       /* disable 256 color mode */
440 			outb(0x3cf, inb(0x3cf) & ~0x01);
441 			outb(0xd00, 0xff);       /* enable auto-centering */
442 			if (!(inb(0xd01) & 0x03)) {
443 				outb(0x3d4, 0x33);
444 				outb(0x3d5, inb(0x3d5) & ~0x90);
445 				outb(0x3d4, 0x32);
446 				outb(0x3d5, inb(0x3d5) | 0x04);
447 				outw(0x3d4, 0x0250);
448 				outw(0x3d4, 0x07ba);
449 				outw(0x3d4, 0x0900);
450 				outw(0x3d4, 0x15e7);
451 				outw(0x3d4, 0x2a95);
452 			}
453 			outw(0x3d4, 0x34a0);
454 			break;
455 
456 	#if 0 /* Untested - probably doesn't work */
457 		case(MatroxVendor):
458 		case(DiamondVendor):
459 			puts("VGA Chip Vendor ID: ");
460 			puthex(PCIVendor(slot));
461 			puts("\n");
462 			mdelay(1000);
463 	#endif
464 		};
465 
466 		outw(0x3C4, 0x0120);           /* disable video              */
467 		setTextRegs(VgaTextRegs);      /* initial register setup     */
468 		setTextCLUT(0);                /* load color lookup table    */
469 		loadFont(ISA_mem);             /* load font                  */
470 		setTextRegs(VgaTextRegs);      /* reload registers           */
471 		outw(0x3C4, 0x0100);           /* re-enable video            */
472 		clearVideoMemory();
473 
474 		if (PCIVendor(slot) == S3Vendor) {
475 			outb(0x3c2, 0x63);                  /* MISC */
476 		} /* endif */
477 
478 	#ifdef DEBUG
479 		printslots();
480 		mdelay(5000);
481 	#endif
482 
483 		mdelay(1000);	/* give time for the video monitor to come up */
484         }
485 	return (1);  /* 'CRT' I/O supported */
486 }
487 
488 /*
489  * Write to VGA Attribute registers.
490  */
491 void
writeAttr(unsigned char index,unsigned char data,unsigned char videoOn)492 writeAttr(unsigned char index, unsigned char data, unsigned char videoOn)
493 {
494 	unsigned char v;
495 	v = inb(0x3da);   /* reset attr. address toggle */
496 	if (videoOn)
497 		outb(0x3c0, (index & 0x1F) | 0x20);
498 	else
499 		outb(0x3c0, (index & 0x1F));
500 	outb(0x3c0, data);
501 }
502 
503 void
setTextRegs(struct VgaRegs * svp)504 setTextRegs(struct VgaRegs *svp)
505 {
506 	int i;
507 
508 	/*
509 	 *  saved settings
510 	 */
511 	while( svp->io_port != ENDMK ) {
512 		outb(svp->io_port,   svp->io_index);
513 		outb(svp->io_port+1, svp->io_value);
514 		svp++;
515 	}
516 
517 	outb(0x3c2, 0x67);  /* MISC */
518 	outb(0x3c6, 0xff);  /* MASK */
519 
520 	for ( i = 0; i < 0x10; i++)
521 		writeAttr(i, AC[i], 0);  /* pallete */
522 	writeAttr(0x10, 0x0c, 0);    /* text mode */
523 	writeAttr(0x11, 0x00, 0);    /* overscan color (border) */
524 	writeAttr(0x12, 0x0f, 0);    /* plane enable */
525 	writeAttr(0x13, 0x08, 0);    /* pixel panning */
526 	writeAttr(0x14, 0x00, 1);    /* color select; video on  */
527 }
528 
529 void
setTextCLUT(int shift)530 setTextCLUT(int shift)
531 {
532 	int i;
533 
534 	outb(0x3C6, 0xFF);
535 	i = inb(0x3C7);
536 	outb(0x3C8, 0);
537 	i = inb(0x3C7);
538 
539 	for ( i = 0; i < 256; i++) {
540 		outb(0x3C9, TextCLUT[i].r << shift);
541 		outb(0x3C9, TextCLUT[i].g << shift);
542 		outb(0x3C9, TextCLUT[i].b << shift);
543 	}
544 }
545 
546 void
loadFont(unsigned char * ISA_mem)547 loadFont(unsigned char *ISA_mem)
548 {
549 	int i, j;
550 	unsigned char *font_page = (unsigned char *) &ISA_mem[0xA0000];
551 
552 	outb(0x3C2, 0x67);
553 	/*
554 	 * Load font
555 	 */
556 	i = inb(0x3DA);  /* Reset Attr toggle */
557 
558 	outb(0x3C0,0x30);
559 	outb(0x3C0, 0x01);      /* graphics mode */
560 
561 	outw(0x3C4, 0x0001);    /* reset sequencer */
562 	outw(0x3C4, 0x0204);    /* write to plane 2 */
563 	outw(0x3C4, 0x0406);    /* enable plane graphics */
564 	outw(0x3C4, 0x0003);    /* reset sequencer */
565 	outw(0x3CE, 0x0402);    /* read plane 2 */
566 	outw(0x3CE, 0x0500);    /* write mode 0, read mode 0 */
567 	outw(0x3CE, 0x0605);    /* set graphics mode */
568 
569 	for (i = 0;  i < sizeof(font);  i += 16) {
570 		for (j = 0;  j < 16;  j++) {
571 			__asm__ volatile("eieio");
572 			font_page[(2*i)+j] = font[i+j];
573 		}
574 	}
575 }
576 
577 static void
unlockS3(void)578 unlockS3(void)
579 {
580         int s3_device_id;
581 	outw(0x3d4, 0x3848);
582 	outw(0x3d4, 0x39a5);
583 	outb(0x3d4, 0x2d);
584 	s3_device_id = inb(0x3d5) << 8;
585 	outb(0x3d4, 0x2e);
586 	s3_device_id |= inb(0x3d5);
587 
588 	if (s3_device_id != 0x8812) {
589 		/* From the S3 manual */
590 		outb(0x46E8, 0x10);  /* Put into setup mode */
591 		outb(0x3C3, 0x10);
592 		outb(0x102, 0x01);   /* Enable registers */
593 		outb(0x46E8, 0x08);  /* Enable video */
594 		outb(0x3C3, 0x08);
595 		outb(0x4AE8, 0x00);
596 
597 #if 0
598 		outb(0x42E8, 0x80);  /* Reset graphics engine? */
599 #endif
600 
601 		outb(0x3D4, 0x38);  /* Unlock all registers */
602 		outb(0x3D5, 0x48);
603 		outb(0x3D4, 0x39);
604 		outb(0x3D5, 0xA5);
605 		outb(0x3D4, 0x40);
606 		outb(0x3D5, inb(0x3D5)|0x01);
607 		outb(0x3D4, 0x33);
608 		outb(0x3D5, inb(0x3D5)&~0x52);
609 		outb(0x3D4, 0x35);
610 		outb(0x3D5, inb(0x3D5)&~0x30);
611 		outb(0x3D4, 0x3A);
612 		outb(0x3D5, 0x00);
613 		outb(0x3D4, 0x53);
614 		outb(0x3D5, 0x00);
615 		outb(0x3D4, 0x31);
616 		outb(0x3D5, inb(0x3D5)&~0x4B);
617 		outb(0x3D4, 0x58);
618 
619 		outb(0x3D5, 0);
620 
621 		outb(0x3D4, 0x54);
622 		outb(0x3D5, 0x38);
623 		outb(0x3D4, 0x60);
624 		outb(0x3D5, 0x07);
625 		outb(0x3D4, 0x61);
626 		outb(0x3D5, 0x80);
627 		outb(0x3D4, 0x62);
628 		outb(0x3D5, 0xA1);
629 		outb(0x3D4, 0x69);  /* High order bits for cursor address */
630 		outb(0x3D5, 0);
631 
632 		outb(0x3D4, 0x32);
633 		outb(0x3D5, inb(0x3D5)&~0x10);
634 	} else {
635                 outw(0x3c4, 0x0806);            /* IBM Portable 860 */
636                 outw(0x3c4, 0x1041);
637                 outw(0x3c4, 0x1128);
638                 outw(0x3d4, 0x4000);
639                 outw(0x3d4, 0x3100);
640                 outw(0x3d4, 0x3a05);
641                 outw(0x3d4, 0x6688);
642                 outw(0x3d4, 0x5800);            /* disable linear addressing */
643                 outw(0x3d4, 0x4500);            /* disable H/W cursor */
644                 outw(0x3c4, 0x5410);            /* enable auto-centering */
645                 outw(0x3c4, 0x561f);
646                 outw(0x3c4, 0x1b80);            /* lock DCLK selection */
647                 outw(0x3d4, 0x3900);            /* lock S3 registers */
648                 outw(0x3d4, 0x3800);
649 	} /* endif */
650 }
651 
652 /*
653  * cursor() sets an offset (0-1999) into the 80x25 text area.
654  */
655 void
cursor(int x,int y)656 cursor(int x, int y)
657 {
658 	int pos = (y*cols)+x;
659 	outb(0x3D4, 14);
660 	outb(0x3D5, pos >> 8);
661 	outb(0x3D4, 15);
662 	outb(0x3D5, pos);
663 }
664 
665 void
clearVideoMemory(void)666 clearVideoMemory(void)
667 {
668 	int i, j;
669 	for (i = 0;  i < lines;  i++) {
670 		for (j = 0;  j < cols;  j++) {
671 			vidmem[((i*cols)+j)*2] = 0x20;	/* fill with space character */
672 			vidmem[((i*cols)+j)*2+1] = 0x07;  /* set bg & fg attributes */
673 		}
674 	}
675 }
676 
677 /* ============ */
678 
679 
680 #define NSLOTS 8
681 #define NPCIREGS  5
682 
683 
684 /*
685  should use devfunc number/indirect method to be totally safe on
686  all machines, this works for now on 3 slot Moto boxes
687 */
688 
689 struct PCI_ConfigInfo {
690   unsigned long * config_addr;
691   unsigned long regs[NPCIREGS];
692 } PCI_slots [NSLOTS] = {
693 
694     { (unsigned long *)0x80808000, {0xDEADBEEF,} },   /* onboard */
695     { (unsigned long *)0x80800800, {0xDEADBEEF,} },   /* onboard */
696     { (unsigned long *)0x80801000, {0xDEADBEEF,} },   /* onboard */
697     { (unsigned long *)0x80802000, {0xDEADBEEF,} },   /* onboard */
698     { (unsigned long *)0x80804000, {0xDEADBEEF,} },   /* onboard */
699     { (unsigned long *)0x80810000, {0xDEADBEEF,} },   /* slot A/1 */
700     { (unsigned long *)0x80820000, {0xDEADBEEF,} },   /* slot B/2 */
701     { (unsigned long *)0x80840000, {0xDEADBEEF,} }    /* slot C/3 */
702 };
703 
704 
705 
706 /*
707  * The following code modifies the PCI Command register
708  * to enable memory and I/O accesses.
709  */
710 void
unlockVideo(int slot)711 unlockVideo(int slot)
712 {
713        volatile unsigned char * ppci;
714 
715         ppci =  (unsigned char * )PCI_slots[slot].config_addr;
716 	ppci[4] = 0x0003;         /* enable memory and I/O accesses */
717 	ppci[0x10] = 0x00000;     /* turn off memory mapping */
718 	ppci[0x11] = 0x00000;     /* mem_base = 0 */
719 	ppci[0x12] = 0x00000;
720 	ppci[0x13] = 0x00000;
721 	__asm__ volatile("eieio");
722 
723 	outb(0x3d4, 0x11);
724 	outb(0x3d5, 0x0e);   /* unlock CR0-CR7 */
725 }
726 
727 long
SwapBytes(long lv)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
scanPCI(int start_slt)745 scanPCI(int start_slt)
746 {
747 	int slt, r;
748 	struct PCI_ConfigInfo *pslot;
749 	int theSlot = -1;
750 	int highVgaSlot = 0;
751 
752 	for ( slt = start_slt + 1; 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 		/* card in slot ? */
758 		if ( pslot->regs[DEVID] != 0xFFFFFFFF ) {
759 			/* VGA ? */
760 			if ( ((pslot->regs[CLASS] & 0xFFFFFF00) == 0x03000000) ||
761 			     ((pslot->regs[CLASS] & 0xFFFFFF00) == 0x00010000)) {
762 				highVgaSlot = slt;
763 				/* did firmware enable it ? */
764 				if ( (pslot->regs[CMD] & 0x03) ) {
765 					theSlot = slt;
766 					break;
767 				}
768 			}
769 		}
770 	}
771 
772 	return ( theSlot );
773 }
774 
775 /* return Vendor ID of card in the slot */
776 static
PCIVendor(int slotnum)777 int PCIVendor(int slotnum) {
778  struct PCI_ConfigInfo *pslot;
779 
780  pslot = &PCI_slots[slotnum];
781 
782 return (pslot->regs[DEVID] & 0xFFFF);
783 }
784 
785 #ifdef DEBUG
786 static
printslots(void)787 void printslots(void)
788 {
789 	int i;
790 #if 0
791 	struct PCI_ConfigInfo *pslot;
792 #endif
793 	for(i=0; i < NSLOTS; i++) {
794 #if 0
795 		pslot = &PCI_slots[i];
796 		printf("Slot: %d, Addr: %x, Vendor: %08x, Class: %08x\n",
797 		       i, pslot->config_addr, pslot->regs[0], pslot->regs[2]);
798 #else
799 		puts("PCI Slot number: "); puthex(i);
800 		puts(" Vendor ID: ");
801 		puthex(PCIVendor(i)); puts("\n");
802 #endif
803 	}
804 }
805 #endif /* DEBUG */
806