1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 5 #include "pci.h" 6 #include "vga.h" 7 8 /* 9 * Generic S3 GUI Accelerator. 10 */ 11 static void 12 snarf(Vga* vga, Ctlr* ctlr) 13 { 14 int i; 15 16 trace("%s->snarf->s3generic\n", ctlr->name); 17 18 /* 19 * Unlock extended registers. 20 * 0xA5 ensures Crt36 and Crt37 are also unlocked 21 * (0xA0 unlocks everything else). 22 */ 23 vgaxo(Crtx, 0x38, 0x48); 24 vgaxo(Crtx, 0x39, 0xA5); 25 26 /* 27 * Not all registers exist on all chips. 28 * Crt3[EF] don't exist on any. 29 */ 30 for(i = 0x30; i < 0x70; i++) 31 vga->crt[i] = vgaxi(Crtx, i); 32 33 /* 34 * Memory size. 35 */ 36 switch((vga->crt[0x36]>>5) & 0x07){ 37 38 case 0x00: 39 vga->vmz = 4*1024*1024; 40 break; 41 42 case 0x02: 43 vga->vmz = 3*1024*1024; 44 break; 45 46 case 0x04: 47 vga->vmz = 2*1024*1024; 48 break; 49 50 case 0x06: 51 vga->vmz = 1*1024*1024; 52 break; 53 54 case 0x07: 55 vga->vmz = 512*1024; 56 break; 57 } 58 59 ctlr->flag |= Fsnarf; 60 } 61 62 static void 63 init(Vga* vga, Ctlr* ctlr) 64 { 65 Mode *mode; 66 ulong x; 67 68 trace("%s->init->s3generic\n", ctlr->name); 69 mode = vga->mode; 70 71 /* 72 * Is enhanced mode is necessary? 73 */ 74 if((ctlr->flag & (Uenhanced|Henhanced)) == Henhanced){ 75 if(mode->z >= 8) 76 resyncinit(vga, ctlr, Uenhanced, 0); 77 else 78 resyncinit(vga, ctlr, 0, Uenhanced|Henhanced); 79 } 80 if((ctlr->flag & Uenhanced) == 0 && mode->x > 1024) 81 error("%s: no support for 1-bit mode > 1024x768x1\n", ctlr->name); 82 83 vga->crt[0x31] = 0x85; 84 vga->crt[0x6A] &= 0xC0; 85 vga->crt[0x32] &= ~0x40; 86 87 vga->crt[0x31] |= 0x08; 88 vga->crt[0x32] |= 0x40; 89 90 vga->crt[0x33] |= 0x20; 91 if(mode->z >= 8) 92 vga->crt[0x3A] |= 0x10; 93 else 94 vga->crt[0x3A] &= ~0x10; 95 96 vga->crt[0x34] = 0x10; 97 vga->crt[0x35] = 0x00; 98 if(mode->interlace){ 99 vga->crt[0x3C] = vga->crt[0]/2; 100 vga->crt[0x42] |= 0x20; 101 } 102 else{ 103 vga->crt[0x3C] = 0x00; 104 vga->crt[0x42] &= ~0x20; 105 } 106 107 vga->crt[0x40] = (vga->crt[0x40] & 0xF2); 108 vga->crt[0x43] = 0x00; 109 vga->crt[0x45] = 0x00; 110 111 vga->crt[0x50] &= 0x3E; 112 if(mode->x <= 640) 113 x = 0x40; 114 else if(mode->x <= 800) 115 x = 0x80; 116 else if(mode->x <= 1024) 117 x = 0x00; 118 else if(mode->x <= 1152) 119 x = 0x01; 120 else if(mode->x <= 1280) 121 x = 0xC0; 122 else 123 x = 0x81; 124 vga->crt[0x50] |= x; 125 126 vga->crt[0x51] = (vga->crt[0x51] & 0xC3)|((vga->crt[0x13]>>4) & 0x30); 127 vga->crt[0x53] &= ~0x10; 128 129 /* 130 * Set up linear aperture. For the moment it's 64K at 0xA0000. 131 * The real base address will be assigned before load is called. 132 */ 133 vga->crt[0x58] = 0x88; 134 if(ctlr->flag & Uenhanced){ 135 vga->crt[0x58] |= 0x10; 136 if(vga->linear && (ctlr->flag & Hlinear)) 137 ctlr->flag |= Ulinear; 138 if(vga->vmz <= 1024*1024) 139 vga->vma = 1024*1024; 140 else if(vga->vmz <= 2*1024*1024) 141 vga->vma = 2*1024*1024; 142 else 143 vga->vma = 8*1024*1024; 144 } 145 vga->crt[0x59] = 0x00; 146 vga->crt[0x5A] = 0x0A; 147 148 vga->crt[0x5D] &= 0x80; 149 if(vga->crt[0x00] & 0x100) 150 vga->crt[0x5D] |= 0x01; 151 if(vga->crt[0x01] & 0x100) 152 vga->crt[0x5D] |= 0x02; 153 if(vga->crt[0x02] & 0x100) 154 vga->crt[0x5D] |= 0x04; 155 if(vga->crt[0x04] & 0x100) 156 vga->crt[0x5D] |= 0x10; 157 if(vga->crt[0x3B] & 0x100) 158 vga->crt[0x5D] |= 0x40; 159 160 vga->crt[0x5E] = 0x40; 161 if(vga->crt[0x06] & 0x400) 162 vga->crt[0x5E] |= 0x01; 163 if(vga->crt[0x12] & 0x400) 164 vga->crt[0x5E] |= 0x02; 165 if(vga->crt[0x15] & 0x400) 166 vga->crt[0x5E] |= 0x04; 167 if(vga->crt[0x10] & 0x400) 168 vga->crt[0x5E] |= 0x10; 169 170 ctlr->type = s3generic.name; 171 172 ctlr->flag |= Finit; 173 } 174 175 static void 176 load(Vga* vga, Ctlr* ctlr) 177 { 178 ulong l; 179 180 trace("%s->load->s3generic\n", ctlr->name); 181 182 vgaxo(Crtx, 0x31, vga->crt[0x31]); 183 vgaxo(Crtx, 0x32, vga->crt[0x32]); 184 vgaxo(Crtx, 0x33, vga->crt[0x33]); 185 vgaxo(Crtx, 0x34, vga->crt[0x34]); 186 vgaxo(Crtx, 0x35, vga->crt[0x35]); 187 vgaxo(Crtx, 0x3A, vga->crt[0x3A]); 188 vgaxo(Crtx, 0x3B, vga->crt[0x3B]); 189 vgaxo(Crtx, 0x3C, vga->crt[0x3C]); 190 191 vgaxo(Crtx, 0x40, vga->crt[0x40]|0x01); 192 vgaxo(Crtx, 0x42, vga->crt[0x42]); 193 vgaxo(Crtx, 0x43, vga->crt[0x43]); 194 vgaxo(Crtx, 0x45, vga->crt[0x45]); 195 196 vgaxo(Crtx, 0x50, vga->crt[0x50]); 197 vgaxo(Crtx, 0x51, vga->crt[0x51]); 198 vgaxo(Crtx, 0x53, vga->crt[0x53]); 199 vgaxo(Crtx, 0x54, vga->crt[0x54]); 200 vgaxo(Crtx, 0x55, vga->crt[0x55]); 201 202 if(ctlr->flag & Ulinear){ 203 l = vga->vmb>>16; 204 vga->crt[0x59] = (l>>8) & 0xFF; 205 vga->crt[0x5A] = l & 0xFF; 206 if(vga->vmz <= 1024*1024) 207 vga->crt[0x58] |= 0x01; 208 else if(vga->vmz <= 2*1024*1024) 209 vga->crt[0x58] |= 0x02; 210 else 211 vga->crt[0x58] |= 0x03; 212 } 213 vgaxo(Crtx, 0x59, vga->crt[0x59]); 214 vgaxo(Crtx, 0x5A, vga->crt[0x5A]); 215 vgaxo(Crtx, 0x58, vga->crt[0x58]); 216 217 vgaxo(Crtx, 0x5D, vga->crt[0x5D]); 218 vgaxo(Crtx, 0x5E, vga->crt[0x5E]); 219 220 vgaxo(Crtx, 0x6A, vga->crt[0x6A]); 221 222 ctlr->flag |= Fload; 223 } 224 225 static void 226 dump(Vga* vga, Ctlr* ctlr) 227 { 228 int i, interlace, mul; 229 char *name; 230 ushort shb, vrs, x; 231 232 name = ctlr->name; 233 234 printitem(name, "Crt30"); 235 for(i = 0x30; i < 0x3E; i++) 236 printreg(vga->crt[i]); 237 238 printitem(name, "Crt40"); 239 for(i = 0x40; i < 0x50; i++) 240 printreg(vga->crt[i]); 241 242 printitem(name, "Crt50"); 243 for(i = 0x50; i < 0x60; i++) 244 printreg(vga->crt[i]); 245 246 printitem(name, "Crt60"); 247 for(i = 0x60; i < 0x70; i++) 248 printreg(vga->crt[i]); 249 250 /* 251 * Try to disassemble the snarfed values into 252 * understandable numbers. 253 * Only do this if we weren't called after Finit. 254 */ 255 if(ctlr->flag & Finit) 256 return; 257 258 /* 259 * If hde <= 400, assume this is a 928 or Vision964 260 * and the horizontal values have been divided by 4. 261 */ 262 mul = 1; 263 x = vga->crt[0x01]; 264 if(vga->crt[0x5D] & 0x02) 265 x |= 0x100; 266 x = (x+1)<<3; 267 if(x <= 400) 268 mul = 4; 269 x *= mul; 270 printitem(name, "hde"); 271 printreg(x); 272 Bprint(&stdout, "%6ud", x); 273 274 shb = vga->crt[0x02]; 275 if(vga->crt[0x5D] & 0x04) 276 shb |= 0x100; 277 shb = (shb+1)<<3; 278 shb *= mul; 279 printitem(name, "shb"); 280 printreg(shb); 281 Bprint(&stdout, "%6ud", shb); 282 283 x = vga->crt[0x03] & 0x1F; 284 if(vga->crt[0x05] & 0x80) 285 x |= 0x20; 286 x *= mul; 287 x = shb|x; /* ???? */ 288 if(vga->crt[0x5D] & 0x08) 289 x += 64; 290 printitem(name, "ehb"); 291 printreg(x); 292 Bprint(&stdout, "%6ud", x); 293 294 x = vga->crt[0x00]; 295 if(vga->crt[0x5D] & 0x01) 296 x |= 0x100; 297 x = (x+5)<<3; 298 x *= mul; 299 printitem(name, "ht"); 300 printreg(x); 301 Bprint(&stdout, "%6ud", x); 302 303 interlace = vga->crt[0x42] & 0x20; 304 x = vga->crt[0x12]; 305 if(vga->crt[0x07] & 0x02) 306 x |= 0x100; 307 if(vga->crt[0x07] & 0x40) 308 x |= 0x200; 309 if(vga->crt[0x5E] & 0x02) 310 x |= 0x400; 311 x += 1; 312 if(interlace) 313 x *= 2; 314 printitem(name, "vde"); 315 printreg(x); 316 Bprint(&stdout, "%6ud", x); 317 318 vrs = vga->crt[0x10]; 319 if(vga->crt[0x07] & 0x04) 320 vrs |= 0x100; 321 if(vga->crt[0x07] & 0x80) 322 vrs |= 0x200; 323 if(vga->crt[0x5E] & 0x10) 324 vrs |= 0x400; 325 if(interlace) 326 vrs *= 2; 327 printitem(name, "vrs"); 328 printreg(vrs); 329 Bprint(&stdout, "%6ud", vrs); 330 331 if(interlace) 332 vrs /= 2; 333 x = (vrs & ~0x0F)|(vga->crt[0x11] & 0x0F); 334 if(interlace) 335 x *= 2; 336 printitem(name, "vre"); 337 printreg(x); 338 Bprint(&stdout, "%6ud", x); 339 340 x = vga->crt[0x06]; 341 if(vga->crt[0x07] & 0x01) 342 x |= 0x100; 343 if(vga->crt[0x07] & 0x20) 344 x |= 0x200; 345 if(vga->crt[0x5E] & 0x01) 346 x |= 0x400; 347 x += 2; 348 if(interlace) 349 x *= 2; 350 printitem(name, "vt"); 351 printreg(x); 352 Bprint(&stdout, "%6ud", x); 353 } 354 355 Ctlr s3generic = { 356 "s3", /* name */ 357 snarf, /* snarf */ 358 0, /* options */ 359 init, /* init */ 360 load, /* load */ 361 dump, /* dump */ 362 }; 363