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