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