[PATCH] ppc: Fix ARCH=ppc build with xmon
[linux-3.10.git] / arch / ppc / boot / lib / vreset.c
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
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
393 outw(int port, unsigned short val)
394 {
395         outb(port, val >> 8);
396         outb(port+1, val);
397 }
398
399 int
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
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
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
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
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
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
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
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
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
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
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
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
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 */