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