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