1 #include <u.h> 2 #include <libc.h> 3 4 #include "vga.h" 5 6 enum { 7 NSeqx = 0x05, 8 NCrtx = 0x19, 9 NGrx = 0x09, 10 NAttrx = 0x15, 11 }; 12 13 uchar 14 vgai(long port) 15 { 16 uchar data; 17 18 switch(port){ 19 20 case MiscR: 21 case Status0: 22 case Status1: 23 case FeatureR: 24 case PaddrW: 25 case Pdata: 26 case Pixmask: 27 case Pstatus: 28 data = inportb(port); 29 break; 30 31 default: 32 error("vgai(0x%4.4X): unknown port\n", port); 33 /*NOTREACHED*/ 34 data = 0xFF; 35 break; 36 } 37 return data; 38 } 39 40 uchar 41 vgaxi(long port, uchar index) 42 { 43 uchar data; 44 45 switch(port){ 46 47 case Seqx: 48 case Crtx: 49 case Grx: 50 outportb(port, index); 51 data = inportb(port+1); 52 break; 53 54 case Attrx: 55 /* 56 * Allow processor access to the colour 57 * palette registers. Writes to Attrx must 58 * be preceded by a read from Status1 to 59 * initialise the register to point to the 60 * index register and not the data register. 61 * Processor access is allowed by turning 62 * off bit 0x20. 63 */ 64 inportb(Status1); 65 if(index < 0x10){ 66 outportb(Attrx, index); 67 data = inportb(Attrx+1); 68 inportb(Status1); 69 outportb(Attrx, 0x20|index); 70 } 71 else{ 72 outportb(Attrx, 0x20|index); 73 data = inportb(Attrx+1); 74 } 75 break; 76 77 default: 78 error("vgaxi(0x%4.4x, 0x%2.2X): unknown port\n", port, index); 79 /*NOTREACHED*/ 80 data = 0xFF; 81 break; 82 } 83 return data; 84 } 85 86 void 87 vgao(long port, uchar data) 88 { 89 switch(port){ 90 91 case MiscW: 92 case FeatureW: 93 case PaddrW: 94 case Pdata: 95 case Pixmask: 96 case PaddrR: 97 outportb(port, data); 98 break; 99 100 default: 101 error("vgao(0x%4.4X, 0x%2.2X): unknown port\n", port, data); 102 /*NOTREACHED*/ 103 break; 104 } 105 } 106 107 void 108 vgaxo(long port, uchar index, uchar data) 109 { 110 switch(port){ 111 112 case Seqx: 113 case Crtx: 114 case Grx: 115 /* 116 * We could use an outport here, but some chips 117 * (e.g. 86C928) have trouble with that for some 118 * registers. 119 */ 120 outportb(port, index); 121 outportb(port+1, data); 122 break; 123 124 case Attrx: 125 inportb(Status1); 126 if(index < 0x10){ 127 outportb(Attrx, index); 128 outportb(Attrx, data); 129 inportb(Status1); 130 outportb(Attrx, 0x20|index); 131 } 132 else{ 133 outportb(Attrx, 0x20|index); 134 outportb(Attrx, data); 135 } 136 break; 137 138 default: 139 error("vgaxo(0x%4.4X, 0x%2.2X, 0x%2.2X): unknown port\n", port, index, data); 140 break; 141 } 142 } 143 144 static void 145 snarf(Vga *vga, Ctlr *ctlr) 146 { 147 int i; 148 149 verbose("%s->snarf\n", ctlr->name); 150 /* 151 * Generic VGA registers: 152 * misc, feature; 153 * sequencer; 154 * crt; 155 * graphics; 156 * attribute; 157 * palette. 158 */ 159 vga->misc = vgai(MiscR); 160 vga->feature = vgai(FeatureR); 161 162 for(i = 0; i < NSeqx; i++) 163 vga->sequencer[i] = vgaxi(Seqx, i); 164 165 for(i = 0; i < NCrtx; i++) 166 vga->crt[i] = vgaxi(Crtx, i); 167 168 for(i = 0; i < NGrx; i++) 169 vga->graphics[i] = vgaxi(Grx, i); 170 171 for(i = 0; i < NAttrx; i++) 172 vga->attribute[i] = vgaxi(Attrx, i); 173 174 if(dflag) 175 (*palette.snarf)(vga, ctlr); 176 177 ctlr->flag |= Fsnarf; 178 } 179 180 static void 181 init(Vga *vga, Ctlr *ctlr) 182 { 183 Mode *mode; 184 int vt, vde, vrs, vre; 185 ulong x; 186 187 verbose("%s->init\n", ctlr->name); 188 mode = vga->mode; 189 190 memset(vga->sequencer, 0, NSeqx*sizeof(vga->sequencer[0])); 191 memset(vga->crt, 0, NCrtx*sizeof(vga->crt[0])); 192 memset(vga->graphics, 0, NGrx*sizeof(vga->graphics[0])); 193 memset(vga->attribute, 0, NAttrx*sizeof(vga->attribute[0])); 194 if(dflag) 195 memset(vga->palette, 0, sizeof(vga->palette)); 196 197 /* 198 * Misc. If both the horizontal and vertical sync polarity 199 * options are set, use them. Otherwise use the defaults for 200 * the given vertical size. 201 */ 202 vga->misc = 0x23; 203 if(mode->frequency == VgaFreq1) 204 vga->misc |= 0x04; 205 if(mode->hsync && mode->vsync){ 206 if(mode->hsync == '-') 207 vga->misc |= 0x40; 208 if(mode->vsync == '-') 209 vga->misc |= 0x80; 210 } 211 else{ 212 if(mode->y < 480) 213 vga->misc |= 0x40; 214 else if(mode->y < 400) 215 vga->misc |= 0x80; 216 else if(mode->y < 768) 217 vga->misc |= 0xC0; 218 } 219 220 /* 221 * Sequencer 222 */ 223 vga->sequencer[0x00] = 0x03; 224 vga->sequencer[0x01] = 0x01; 225 vga->sequencer[0x02] = 0x0F; 226 vga->sequencer[0x03] = 0x00; 227 if(mode->z == 8) 228 vga->sequencer[0x04] = 0x0A; 229 else 230 vga->sequencer[0x04] = 0x06; 231 232 /* 233 * Crt. Most of the work here is in dealing 234 * with field overflow. 235 */ 236 memset(vga->crt, 0, NCrtx); 237 238 vga->crt[0x00] = (mode->ht>>3)-5; 239 vga->crt[0x01] = (mode->x>>3)-1; 240 vga->crt[0x02] = (mode->shb>>3)-1; 241 242 /* 243 * End Horizontal Blank is a 6-bit field, 5-bits 244 * in Crt3, high bit in Crt5. 245 */ 246 x = mode->ehb>>3; 247 vga->crt[0x03] = 0x80|(x & 0x1F); 248 if(x & 0x20) 249 vga->crt[0x05] |= 0x80; 250 vga->crt[0x04] = mode->shb>>3; 251 vga->crt[0x05] |= (x & 0x1F); 252 253 /* 254 * Vertical Total is 10-bits, 8 in Crt6, the high 255 * two bits in Crt7. What if vt is >= 1024? We hope 256 * the specific controller has some more overflow 257 * bits. 258 * 259 * Interlace: if 'v', divide the vertical timing 260 * values by 2. 261 */ 262 vt = mode->vt; 263 vde = mode->y; 264 vrs = mode->vrs; 265 vre = mode->vre; 266 267 if(mode->interlace == 'v'){ 268 vt /= 2; 269 vde /= 2; 270 vrs /= 2; 271 vre /= 2; 272 } 273 274 x = vt-2; 275 vga->crt[0x06] = x; 276 if(x & 0x100) 277 vga->crt[0x07] |= 0x01; 278 if(x & 0x200) 279 vga->crt[0x07] |= 0x20; 280 281 x = vrs; 282 vga->crt[0x10] = x; 283 if(x & 0x100) 284 vga->crt[0x07] |= 0x04; 285 if(x & 0x200) 286 vga->crt[0x07] |= 0x80; 287 288 vga->crt[0x11] = 0x20|(vre & 0x0F); 289 290 x = vde-1; 291 vga->crt[0x12] = x; 292 if(x & 0x100) 293 vga->crt[0x07] |= 0x02; 294 if(x & 0x200) 295 vga->crt[0x07] |= 0x40; 296 297 vga->crt[0x15] = vrs; 298 if(vrs & 0x100) 299 vga->crt[0x07] |= 0x08; 300 if(vrs & 0x200) 301 vga->crt[0x09] |= 0x20; 302 303 vga->crt[0x16] = (vrs+1); 304 305 vga->crt[0x17] = 0x83; 306 x = ((mode->x*mode->z)/8); 307 if(x >= 512){ 308 vga->crt[0x14] |= 0x60; 309 x /= 8; 310 } 311 else if(x >= 256){ 312 vga->crt[0x17] |= 0x08; 313 x /= 4; 314 } 315 else{ 316 vga->crt[0x17] |= 0x40; 317 x /= 2; 318 } 319 vga->crt[0x13] = x; 320 321 if(mode->x*mode->y*mode->z/8 > 64*1024) 322 vga->crt[0x17] |= 0x20; 323 324 vga->crt[0x18] = 0x7FF; 325 if(vga->crt[0x18] & 0x100) 326 vga->crt[0x07] |= 0x10; 327 if(vga->crt[0x18] & 0x200) 328 vga->crt[0x09] |= 0x40; 329 330 /* 331 * Graphics 332 */ 333 memset(vga->graphics, 0, NGrx); 334 if((vga->sequencer[0x04] & 0x04) == 0) 335 vga->graphics[0x05] |= 0x10; 336 if(mode->z == 8) 337 vga->graphics[0x05] |= 0x40; 338 vga->graphics[0x06] = 0x05; 339 vga->graphics[0x07] = 0x0F; 340 vga->graphics[0x08] = 0xFF; 341 342 /* 343 * Attribute 344 */ 345 memset(vga->attribute, 0, NAttrx); 346 for(x = 0; x < 0x10; x++) 347 vga->attribute[x] = x; 348 vga->attribute[0x10] = 0x01; 349 if(mode->z == 8) 350 vga->attribute[0x10] |= 0x40; 351 vga->attribute[0x11] = 0xFF; 352 vga->attribute[0x12] = 0x0F; 353 354 /* 355 * Palette 356 */ 357 if(dflag) 358 (*palette.init)(vga, ctlr); 359 360 ctlr->flag |= Finit; 361 } 362 363 static void 364 load(Vga *vga, Ctlr *ctlr) 365 { 366 int i; 367 368 verbose("%s->load\n", ctlr->name); 369 /* 370 * Reset the sequencer and leave it off. 371 * Load the generic VGA registers: 372 * misc; 373 * sequencer (but not seq01, display enable); 374 * take the sequencer out of reset; 375 * take off write-protect on crt[0x00-0x07]; 376 * crt; 377 * graphics; 378 * attribute; 379 * palette. 380 vgaxo(Seqx, 0x00, 0x00); 381 */ 382 383 vgao(MiscW, vga->misc); 384 385 for(i = 2; i < NSeqx; i++) 386 vgaxo(Seqx, i, vga->sequencer[i]); 387 /*vgaxo(Seqx, 0x00, 0x03);*/ 388 389 vgaxo(Crtx, 0x11, vga->crt[0x11] & ~0x80); 390 for(i = 0; i < NCrtx; i++) 391 vgaxo(Crtx, i, vga->crt[i]); 392 393 for(i = 0; i < NGrx; i++) 394 vgaxo(Grx, i, vga->graphics[i]); 395 396 for(i = 0; i < NAttrx; i++) 397 vgaxo(Attrx, i, vga->attribute[i]); 398 399 if(dflag) 400 (*palette.load)(vga, ctlr); 401 402 ctlr->flag |= Fload; 403 } 404 405 static void 406 dump(Vga *vga, Ctlr *ctlr) 407 { 408 int i; 409 410 printitem(ctlr->name, "misc"); 411 printreg(vga->misc); 412 printitem(ctlr->name, "feature"); 413 printreg(vga->feature); 414 415 printitem(ctlr->name, "sequencer"); 416 for(i = 0; i < NSeqx; i++) 417 printreg(vga->sequencer[i]); 418 419 printitem(ctlr->name, "crt"); 420 for(i = 0; i < NCrtx; i++) 421 printreg(vga->crt[i]); 422 423 printitem(ctlr->name, "graphics"); 424 for(i = 0; i < NGrx; i++) 425 printreg(vga->graphics[i]); 426 427 printitem(ctlr->name, "attribute"); 428 for(i = 0; i < NAttrx; i++) 429 printreg(vga->attribute[i]); 430 431 if(dflag) 432 (*palette.dump)(vga, ctlr); 433 434 if(vga->f){ 435 printitem(ctlr->name, "clock f"); 436 print("%9ld\n", vga->f); 437 printitem(ctlr->name, "clock d i n p"); 438 print("%9ld %8ld - %8ld %8ld\n", vga->d, vga->i, vga->n, vga->p); 439 } 440 441 if(vga->vmb){ 442 printitem(ctlr->name, "vmb"); 443 print("%9ld\n", vga->vmb); 444 } 445 } 446 447 Ctlr generic = { 448 "vga", /* name */ 449 snarf, /* snarf */ 450 0, /* options */ 451 init, /* init */ 452 load, /* load */ 453 dump, /* dump */ 454 }; 455