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