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