1 /* $NetBSD: vreset.c,v 1.4 1999/06/28 01:20:45 sakamoto Exp $ */ 2 3 /* 4 * Copyright (C) 1995-1997 Gary Thomas (gdt@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@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