123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- #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 */
- };
|