summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aux/vga/s3generic.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aux/vga/s3generic.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/vga/s3generic.c')
-rwxr-xr-xsys/src/cmd/aux/vga/s3generic.c381
1 files changed, 381 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/vga/s3generic.c b/sys/src/cmd/aux/vga/s3generic.c
new file mode 100755
index 000000000..dcd547715
--- /dev/null
+++ b/sys/src/cmd/aux/vga/s3generic.c
@@ -0,0 +1,381 @@
+#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 */
+};