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, id, interlace, mul, div; 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 /* 260 * If hde <= 400, assume this is a 928 or Vision964 261 * and the horizontal values have been divided by 4. 262 * 263 * if ViRGE/[DG]X and 15 or 16bpp, horizontal values have 264 * been multiplied by 2. 265 */ 266 mul = 1; 267 div = 1; 268 269 if(strcmp(name, "virge") == 0){ 270 id = (vga->crt[0x2D]<<8)|vga->crt[0x2E]; 271 /* S3 ViRGE/[DG]X */ 272 if(id==0x8A01 && ((vga->crt[0x67] & 0x30) || (vga->crt[0x67] & 0x50))){ 273 mul = 1; 274 div = 2; 275 } 276 } 277 278 x = vga->crt[0x01]; 279 if(vga->crt[0x5D] & 0x02) 280 x |= 0x100; 281 x = (x+1)<<3; 282 283 if(x <= 400){ 284 mul = 4; 285 div = 1; 286 } 287 288 x = (x * mul) / div; 289 printitem(name, "hde"); 290 printreg(x); 291 Bprint(&stdout, "%6ud", x); 292 293 shb = vga->crt[0x02]; 294 if(vga->crt[0x5D] & 0x04) 295 shb |= 0x100; 296 shb = (shb+1)<<3; 297 shb = (shb * mul) / div; 298 printitem(name, "shb"); 299 printreg(shb); 300 Bprint(&stdout, "%6ud", shb); 301 302 x = vga->crt[0x03] & 0x1F; 303 if(vga->crt[0x05] & 0x80) 304 x |= 0x20; 305 x = (x * mul) / div; 306 x = shb|x; /* ???? */ 307 if(vga->crt[0x5D] & 0x08) 308 x += 64; 309 printitem(name, "ehb"); 310 printreg(x); 311 Bprint(&stdout, "%6ud", x); 312 313 x = vga->crt[0x00]; 314 if(vga->crt[0x5D] & 0x01) 315 x |= 0x100; 316 x = (x+5)<<3; 317 x = (x * mul) / div; 318 printitem(name, "ht"); 319 printreg(x); 320 Bprint(&stdout, "%6ud", x); 321 322 interlace = vga->crt[0x42] & 0x20; 323 x = vga->crt[0x12]; 324 if(vga->crt[0x07] & 0x02) 325 x |= 0x100; 326 if(vga->crt[0x07] & 0x40) 327 x |= 0x200; 328 if(vga->crt[0x5E] & 0x02) 329 x |= 0x400; 330 x += 1; 331 if(interlace) 332 x *= 2; 333 printitem(name, "vde"); 334 printreg(x); 335 Bprint(&stdout, "%6ud", x); 336 337 vrs = vga->crt[0x10]; 338 if(vga->crt[0x07] & 0x04) 339 vrs |= 0x100; 340 if(vga->crt[0x07] & 0x80) 341 vrs |= 0x200; 342 if(vga->crt[0x5E] & 0x10) 343 vrs |= 0x400; 344 if(interlace) 345 vrs *= 2; 346 printitem(name, "vrs"); 347 printreg(vrs); 348 Bprint(&stdout, "%6ud", vrs); 349 350 if(interlace) 351 vrs /= 2; 352 x = (vrs & ~0x0F)|(vga->crt[0x11] & 0x0F); 353 if(interlace) 354 x *= 2; 355 printitem(name, "vre"); 356 printreg(x); 357 Bprint(&stdout, "%6ud", x); 358 359 x = vga->crt[0x06]; 360 if(vga->crt[0x07] & 0x01) 361 x |= 0x100; 362 if(vga->crt[0x07] & 0x20) 363 x |= 0x200; 364 if(vga->crt[0x5E] & 0x01) 365 x |= 0x400; 366 x += 2; 367 if(interlace) 368 x *= 2; 369 printitem(name, "vt"); 370 printreg(x); 371 Bprint(&stdout, "%6ud", x); 372 } 373 374 Ctlr s3generic = { 375 "s3", /* name */ 376 snarf, /* snarf */ 377 0, /* options */ 378 init, /* init */ 379 load, /* load */ 380 dump, /* dump */ 381 }; 382