ref: 57741d473f9d5165d142b165bd837984f6428c66
dir: /sys/src/cmd/aux/vga/s3generic.c/
#include <u.h> #include <libc.h> #include <bio.h> #include "pci.h" #include "vga.h" /* * Generic S3 GUI Accelerator. */ static void snarf(Vga* vga, Ctlr* ctlr) { int i; trace("%s->snarf->s3generic\n", ctlr->name); /* * Unlock extended registers. * 0xA5 ensures Crt36 and Crt37 are also unlocked * (0xA0 unlocks everything else). */ vgaxo(Crtx, 0x38, 0x48); vgaxo(Crtx, 0x39, 0xA5); /* * Not all registers exist on all chips. * Crt3[EF] don't exist on any. */ for(i = 0x30; i < 0x70; i++) vga->crt[i] = vgaxi(Crtx, i); /* * Memory size. */ switch((vga->crt[0x36]>>5) & 0x07){ case 0x00: vga->vmz = 4*1024*1024; break; case 0x02: vga->vmz = 3*1024*1024; break; case 0x04: vga->vmz = 2*1024*1024; break; case 0x06: vga->vmz = 1*1024*1024; break; case 0x07: vga->vmz = 512*1024; break; } ctlr->flag |= Fsnarf; } static void init(Vga* vga, Ctlr* ctlr) { Mode *mode; ulong x; trace("%s->init->s3generic\n", ctlr->name); mode = vga->mode; /* * Is enhanced mode is necessary? */ if((ctlr->flag & (Uenhanced|Henhanced)) == Henhanced){ if(mode->z >= 8) resyncinit(vga, ctlr, Uenhanced, 0); else resyncinit(vga, ctlr, 0, Uenhanced|Henhanced); } if((ctlr->flag & Uenhanced) == 0 && mode->x > 1024) error("%s: no support for 1-bit mode > 1024x768x1\n", ctlr->name); vga->crt[0x31] = 0x85; vga->crt[0x6A] &= 0xC0; vga->crt[0x32] &= ~0x40; vga->crt[0x31] |= 0x08; vga->crt[0x32] |= 0x40; vga->crt[0x33] |= 0x20; if(mode->z >= 8) vga->crt[0x3A] |= 0x10; else vga->crt[0x3A] &= ~0x10; vga->crt[0x34] = 0x10; vga->crt[0x35] = 0x00; if(mode->interlace){ vga->crt[0x3C] = vga->crt[0]/2; vga->crt[0x42] |= 0x20; } else{ vga->crt[0x3C] = 0x00; vga->crt[0x42] &= ~0x20; } vga->crt[0x40] = (vga->crt[0x40] & 0xF2); vga->crt[0x43] = 0x00; vga->crt[0x45] = 0x00; vga->crt[0x50] &= 0x3E; if(mode->x <= 640) x = 0x40; else if(mode->x <= 800) x = 0x80; else if(mode->x <= 1024) x = 0x00; else if(mode->x <= 1152) x = 0x01; else if(mode->x <= 1280) x = 0xC0; else x = 0x81; vga->crt[0x50] |= x; vga->crt[0x51] = (vga->crt[0x51] & 0xC3)|((vga->crt[0x13]>>4) & 0x30); vga->crt[0x53] &= ~0x10; /* * Set up linear aperture. For the moment it's 64K at 0xA0000. * The real base address will be assigned before load is called. */ vga->crt[0x58] = 0x88; if(ctlr->flag & Uenhanced){ vga->crt[0x58] |= 0x10; if(vga->linear && (ctlr->flag & Hlinear)) ctlr->flag |= Ulinear; if(vga->vmz <= 1024*1024) vga->vma = 1024*1024; else if(vga->vmz <= 2*1024*1024) vga->vma = 2*1024*1024; else vga->vma = 8*1024*1024; } vga->crt[0x59] = 0x00; vga->crt[0x5A] = 0x0A; vga->crt[0x5D] &= 0x80; if(vga->crt[0x00] & 0x100) vga->crt[0x5D] |= 0x01; if(vga->crt[0x01] & 0x100) vga->crt[0x5D] |= 0x02; if(vga->crt[0x02] & 0x100) vga->crt[0x5D] |= 0x04; if(vga->crt[0x04] & 0x100) vga->crt[0x5D] |= 0x10; if(vga->crt[0x3B] & 0x100) vga->crt[0x5D] |= 0x40; vga->crt[0x5E] = 0x40; if(vga->crt[0x06] & 0x400) vga->crt[0x5E] |= 0x01; if(vga->crt[0x12] & 0x400) vga->crt[0x5E] |= 0x02; if(vga->crt[0x15] & 0x400) vga->crt[0x5E] |= 0x04; if(vga->crt[0x10] & 0x400) vga->crt[0x5E] |= 0x10; ctlr->type = s3generic.name; ctlr->flag |= Finit; } static void load(Vga* vga, Ctlr* ctlr) { ulong l; trace("%s->load->s3generic\n", ctlr->name); vgaxo(Crtx, 0x31, vga->crt[0x31]); vgaxo(Crtx, 0x32, vga->crt[0x32]); vgaxo(Crtx, 0x33, vga->crt[0x33]); vgaxo(Crtx, 0x34, vga->crt[0x34]); vgaxo(Crtx, 0x35, vga->crt[0x35]); vgaxo(Crtx, 0x3A, vga->crt[0x3A]); vgaxo(Crtx, 0x3B, vga->crt[0x3B]); vgaxo(Crtx, 0x3C, vga->crt[0x3C]); vgaxo(Crtx, 0x40, vga->crt[0x40]|0x01); vgaxo(Crtx, 0x42, vga->crt[0x42]); vgaxo(Crtx, 0x43, vga->crt[0x43]); vgaxo(Crtx, 0x45, vga->crt[0x45]); vgaxo(Crtx, 0x50, vga->crt[0x50]); vgaxo(Crtx, 0x51, vga->crt[0x51]); vgaxo(Crtx, 0x53, vga->crt[0x53]); vgaxo(Crtx, 0x54, vga->crt[0x54]); vgaxo(Crtx, 0x55, vga->crt[0x55]); if(ctlr->flag & Ulinear){ l = vga->vmb>>16; vga->crt[0x59] = (l>>8) & 0xFF; vga->crt[0x5A] = l & 0xFF; if(vga->vmz <= 1024*1024) vga->crt[0x58] |= 0x01; else if(vga->vmz <= 2*1024*1024) vga->crt[0x58] |= 0x02; else vga->crt[0x58] |= 0x03; } vgaxo(Crtx, 0x59, vga->crt[0x59]); vgaxo(Crtx, 0x5A, vga->crt[0x5A]); vgaxo(Crtx, 0x58, vga->crt[0x58]); vgaxo(Crtx, 0x5D, vga->crt[0x5D]); vgaxo(Crtx, 0x5E, vga->crt[0x5E]); vgaxo(Crtx, 0x6A, vga->crt[0x6A]); ctlr->flag |= Fload; } static void dump(Vga* vga, Ctlr* ctlr) { int i, id, interlace, mul, div; char *name; ushort shb, vrs, x; name = ctlr->name; printitem(name, "Crt30"); for(i = 0x30; i < 0x3E; i++) printreg(vga->crt[i]); printitem(name, "Crt40"); for(i = 0x40; i < 0x50; i++) printreg(vga->crt[i]); printitem(name, "Crt50"); for(i = 0x50; i < 0x60; i++) printreg(vga->crt[i]); printitem(name, "Crt60"); for(i = 0x60; i < 0x70; i++) printreg(vga->crt[i]); /* * Try to disassemble the snarfed values into * understandable numbers. * Only do this if we weren't called after Finit. */ if(ctlr->flag & Finit) return; /* * If hde <= 400, assume this is a 928 or Vision964 * and the horizontal values have been divided by 4. * * if ViRGE/[DG]X and 15 or 16bpp, horizontal values have * been multiplied by 2. */ mul = 1; div = 1; if(strcmp(name, "virge") == 0){ id = (vga->crt[0x2D]<<8)|vga->crt[0x2E]; /* S3 ViRGE/[DG]X */ if(id==0x8A01 && ((vga->crt[0x67] & 0x30) || (vga->crt[0x67] & 0x50))){ mul = 1; div = 2; } } x = vga->crt[0x01]; if(vga->crt[0x5D] & 0x02) x |= 0x100; x = (x+1)<<3; if(x <= 400){ mul = 4; div = 1; } x = (x * mul) / div; printitem(name, "hde"); printreg(x); Bprint(&stdout, "%6ud", x); shb = vga->crt[0x02]; if(vga->crt[0x5D] & 0x04) shb |= 0x100; shb = (shb+1)<<3; shb = (shb * mul) / div; printitem(name, "shb"); printreg(shb); Bprint(&stdout, "%6ud", shb); x = vga->crt[0x03] & 0x1F; if(vga->crt[0x05] & 0x80) x |= 0x20; x = (x * mul) / div; x = shb|x; /* ???? */ if(vga->crt[0x5D] & 0x08) x += 64; printitem(name, "ehb"); printreg(x); Bprint(&stdout, "%6ud", x); x = vga->crt[0x00]; if(vga->crt[0x5D] & 0x01) x |= 0x100; x = (x+5)<<3; x = (x * mul) / div; printitem(name, "ht"); printreg(x); Bprint(&stdout, "%6ud", x); interlace = vga->crt[0x42] & 0x20; x = vga->crt[0x12]; if(vga->crt[0x07] & 0x02) x |= 0x100; if(vga->crt[0x07] & 0x40) x |= 0x200; if(vga->crt[0x5E] & 0x02) x |= 0x400; x += 1; if(interlace) x *= 2; printitem(name, "vde"); printreg(x); Bprint(&stdout, "%6ud", x); vrs = vga->crt[0x10]; if(vga->crt[0x07] & 0x04) vrs |= 0x100; if(vga->crt[0x07] & 0x80) vrs |= 0x200; if(vga->crt[0x5E] & 0x10) vrs |= 0x400; if(interlace) vrs *= 2; printitem(name, "vrs"); printreg(vrs); Bprint(&stdout, "%6ud", vrs); if(interlace) vrs /= 2; x = (vrs & ~0x0F)|(vga->crt[0x11] & 0x0F); if(interlace) x *= 2; printitem(name, "vre"); printreg(x); Bprint(&stdout, "%6ud", x); x = vga->crt[0x06]; if(vga->crt[0x07] & 0x01) x |= 0x100; if(vga->crt[0x07] & 0x20) x |= 0x200; if(vga->crt[0x5E] & 0x01) x |= 0x400; x += 2; if(interlace) x *= 2; printitem(name, "vt"); printreg(x); Bprint(&stdout, "%6ud", x); } Ctlr s3generic = { "s3", /* name */ snarf, /* snarf */ 0, /* options */ init, /* init */ load, /* load */ dump, /* dump */ };