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