summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aux/vga/et4000.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/et4000.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/vga/et4000.c')
-rwxr-xr-xsys/src/cmd/aux/vga/et4000.c340
1 files changed, 340 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/vga/et4000.c b/sys/src/cmd/aux/vga/et4000.c
new file mode 100755
index 000000000..f44b792ee
--- /dev/null
+++ b/sys/src/cmd/aux/vga/et4000.c
@@ -0,0 +1,340 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#include "pci.h"
+#include "vga.h"
+
+/*
+ * Tseng Labs Inc. ET4000 Video Controller.
+ */
+enum {
+ Crtcbx = 0x217A, /* Secondary CRT controller */
+
+ Sprite = 0xE0,
+ NSprite = 0x10,
+
+ Ima = 0xF0,
+ NIma = 0x08,
+};
+
+static void
+setkey(void)
+{
+ outportb(0x3BF, 0x03);
+ outportb(0x3D8, 0xA0);
+ outportb(0x3CD, 0x00);
+}
+
+static void
+snarf(Vga* vga, Ctlr* ctlr)
+{
+ int i;
+
+ setkey();
+
+ vga->sequencer[0x06] = vgaxi(Seqx, 0x06);
+ vga->sequencer[0x07] = vgaxi(Seqx, 0x07);
+
+ for(i = 0x30; i < 0x38; i++)
+ vga->crt[i] = vgaxi(Crtx, i);
+ vga->crt[0x3F] = vgaxi(Crtx, 0x3F);
+
+ vga->attribute[0x16] = vgaxi(Attrx, 0x16);
+ vga->attribute[0x17] = vgaxi(Attrx, 0x17);
+
+ /*
+ * Memory size.
+ */
+ switch(vga->crt[0x37] & 0x03){
+
+ case 1:
+ vga->vmz = 256*1024;
+ break;
+
+ case 2:
+ vga->vmz = 512*1024;
+ break;
+
+ case 3:
+ vga->vmz = 1024*1024;
+ break;
+ }
+ if(strncmp(ctlr->name, "et4000-w32", 10) == 0){
+ if(vga->crt[0x32] & 0x80)
+ vga->vmz *= 2;
+ }
+ else if(vga->crt[0x37] & 0x80)
+ vga->vmz *= 2;
+
+ ctlr->flag |= Fsnarf;
+}
+
+static void
+options(Vga* vga, Ctlr* ctlr)
+{
+ /*
+ * The ET4000 does not need to have the vertical
+ * timing values divided by 2 for interlace mode.
+ */
+ if(vga->mode->interlace == 'v')
+ vga->mode->interlace = 'V';
+
+ if(strncmp(ctlr->name, "et4000-w32", 10) == 0)
+ ctlr->flag |= Hpclk2x8;
+
+ ctlr->flag |= Hclkdiv|Foptions;
+}
+
+static void
+init(Vga* vga, Ctlr* ctlr)
+{
+ Mode *mode;
+ ulong x;
+
+ if(vga->mode->z > 8)
+ error("depth %d not supported\n", vga->mode->z);
+
+ if(ctlr->flag & Upclk2x8){
+ mode = vga->mode;
+ vga->crt[0x00] = ((mode->ht/2)>>3)-5;
+ vga->crt[0x01] = ((mode->x/2)>>3)-1;
+ vga->crt[0x02] = ((mode->shb/2)>>3)-1;
+
+ x = (mode->ehb/2)>>3;
+ vga->crt[0x03] = 0x80|(x & 0x1F);
+ vga->crt[0x04] = (mode->shs/2)>>3;
+ vga->crt[0x05] = ((mode->ehs/2)>>3) & 0x1F;
+ if(x & 0x20)
+ vga->crt[0x05] |= 0x80;
+ }
+ /*
+ * Itth a mythtawee.
+ */
+ if(vga->crt[0x14] & 0x20)
+ vga->crt[0x17] |= 0x08;
+ vga->crt[0x17] &= ~0x20;
+
+ vga->crt[0x30] = 0x00;
+ vga->crt[0x33] = 0x00;
+
+ /*
+ * Overflow High.
+ */
+ vga->crt[0x35] = 0x00;
+ if(vga->crt[0x15] & 0x400)
+ vga->crt[0x35] |= 0x01;
+ if(vga->crt[0x06] & 0x400)
+ vga->crt[0x35] |= 0x02;
+ if(vga->crt[0x12] & 0x400)
+ vga->crt[0x35] |= 0x04;
+ if(vga->crt[0x10] & 0x400)
+ vga->crt[0x35] |= 0x08;
+ if(vga->crt[0x18] & 0x400)
+ vga->crt[0x35] |= 0x10;
+ if(vga->mode->interlace == 'V')
+ vga->crt[0x35] |= 0x80;
+
+ /*
+ * Horizontal Overflow.
+ */
+ vga->crt[0x3F] = 0x00;
+ if(vga->crt[0x00] & 0x100)
+ vga->crt[0x3F] |= 0x01;
+ if(vga->crt[0x02] & 0x100)
+ vga->crt[0x3F] |= 0x04;
+ if(vga->crt[0x04] & 0x100)
+ vga->crt[0x3F] |= 0x10;
+ if(vga->crt[0x13] & 0x100)
+ vga->crt[0x3F] |= 0x80;
+
+ /*
+ * Turn off MMU buffers, linear map
+ * and memory-mapped registers.
+ */
+ vga->crt[0x36] &= ~0x38;
+
+ if(strncmp(ctlr->name, "et4000-w32", 10) == 0)
+ vga->crt[0x37] |= 0x80;
+
+ vga->sequencer[0x06] = 0x00;
+
+ /*
+ * Clock select.
+ */
+ if(vga->f[0] > 86000000)
+ error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
+ vga->misc &= ~0x0C;
+ vga->misc |= (vga->i[0] & 0x03)<<2;
+ if(vga->i[0] & 0x04)
+ vga->crt[0x34] |= 0x02;
+ else
+ vga->crt[0x34] &= ~0x02;
+ vga->crt[0x31] &= ~0xC0;
+ vga->crt[0x31] |= (vga->i[0] & 0x18)<<3;
+
+ vga->sequencer[0x07] &= ~0x41;
+ if(vga->d[0] == 4)
+ vga->sequencer[0x07] |= 0x01;
+ else if(vga->d[0] == 2)
+ vga->sequencer[0x07] |= 0x40;
+
+ vga->attribute[0x10] &= ~0x40;
+ vga->attribute[0x11] = Pblack;
+ vga->attribute[0x16] = 0x80;
+
+ if(ctlr->flag & Upclk2x8)
+ vga->attribute[0x16] |= 0x20;
+
+ ctlr->flag |= Finit;
+}
+
+static void
+load(Vga* vga, Ctlr* ctlr)
+{
+ vgaxo(Crtx, 0x30, vga->crt[0x30]);
+ vgaxo(Crtx, 0x31, vga->crt[0x31]);
+ vgaxo(Crtx, 0x33, vga->crt[0x33]);
+ vgaxo(Crtx, 0x34, vga->crt[0x34]);
+ vgaxo(Crtx, 0x35, vga->crt[0x35]);
+ vgaxo(Crtx, 0x36, vga->crt[0x36]);
+ vgaxo(Crtx, 0x37, vga->crt[0x37]);
+ vgaxo(Crtx, 0x3F, vga->crt[0x3F]);
+
+ vgaxo(Seqx, 0x06, vga->sequencer[0x06]);
+ vgaxo(Seqx, 0x07, vga->sequencer[0x07]);
+
+ vgaxo(Attrx, 0x16, vga->attribute[0x16]);
+
+ ctlr->flag |= Fload;
+}
+
+static void
+dump(Vga* vga, Ctlr* ctlr)
+{
+ int i;
+ char *name;
+ ushort shb, vrs, x;
+
+ name = ctlr->name;
+
+ printitem(name, "Seq06");
+ printreg(vga->sequencer[0x06]);
+ printreg(vga->sequencer[0x07]);
+
+ printitem(name, "Crt30");
+ for(i = 0x30; i < 0x38; i++)
+ printreg(vga->crt[i]);
+ printitem(name, "Crt3F");
+ printreg(vga->crt[0x3F]);
+
+ printitem(name, "Attr16");
+ printreg(vga->attribute[0x16]);
+ printreg(vga->attribute[0x17]);
+
+ if(strncmp(name, "et4000-w32", 10) == 0){
+ printitem(name, "SpriteE0");
+ for(i = Sprite; i < Sprite+NSprite; i++){
+ outportb(Crtcbx, i);
+ printreg(inportb(Crtcbx+1));
+ }
+ printitem(name, "ImaF0");
+ for(i = Ima; i < Ima+NIma; i++){
+ outportb(Crtcbx, i);
+ printreg(inportb(Crtcbx+1));
+ }
+ }
+
+ /*
+ * Try to disassemble the snarfed values into
+ * understandable numbers.
+ * Only do this if we weren't called after Finit.
+ */
+ if(ctlr->flag & Finit)
+ return;
+
+ x = (vga->crt[0x01]+1)<<3;
+ printitem(name, "hde");
+ printreg(x);
+ Bprint(&stdout, "%6ud", x);
+
+ shb = ((((vga->crt[0x3F] & 0x04)<<6)|vga->crt[0x02])+1)<<3;
+ printitem(name, "shb");
+ printreg(shb);
+ Bprint(&stdout, "%6ud", shb);
+
+ x = (((vga->crt[0x05] & 0x80)>>2)|(vga->crt[0x03] & 0x1F))<<3;
+ printitem(name, "ehb");
+ printreg(x);
+ for(i = 0; x < shb; i++)
+ x |= 0x200<<i;
+ Bprint(&stdout, "%6ud", x);
+
+ x = ((((vga->crt[0x3F] & 0x01)<<8)|vga->crt[0x00])+5)<<3;
+ printitem(name, "ht");
+ printreg(x);
+ Bprint(&stdout, "%6ud", x);
+
+ x = vga->crt[0x12];
+ if(vga->crt[0x07] & 0x02)
+ x |= 0x100;
+ if(vga->crt[0x07] & 0x40)
+ x |= 0x200;
+ if(vga->crt[0x35] & 0x04)
+ x |= 0x400;
+ x += 1;
+ 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[0x35] & 0x08)
+ vrs |= 0x400;
+ printitem(name, "vrs");
+ printreg(vrs);
+ Bprint(&stdout, "%6ud", vrs);
+
+ x = (vrs & ~0x0F)|(vga->crt[0x11] & 0x0F);
+ 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[0x35] & 0x02)
+ x |= 0x400;
+ x += 2;
+ printitem(name, "vt");
+ printreg(x);
+ Bprint(&stdout, "%6ud", x);
+
+ printitem(name, "d i");
+ if(vga->sequencer[0x07] & 0x01)
+ x = 4;
+ else if(vga->sequencer[0x07] & 0x40)
+ x = 2;
+ else
+ x = 0;
+ Bprint(&stdout, "%9ud", x);
+ x = (vga->misc & 0x0C)>>2;
+ if(vga->crt[0x34] & 0x02)
+ x |= 0x04;
+ x |= (vga->crt[0x31] & 0xC0)>>3;
+ Bprint(&stdout, "%8ud\n", x);
+}
+
+Ctlr et4000 = {
+ "et4000", /* name */
+ snarf, /* snarf */
+ options, /* options */
+ init, /* init */
+ load, /* load */
+ dump, /* dump */
+};