summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aux/vga/vga.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/vga.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/vga/vga.c')
-rwxr-xr-xsys/src/cmd/aux/vga/vga.c486
1 files changed, 486 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/vga/vga.c b/sys/src/cmd/aux/vga/vga.c
new file mode 100755
index 000000000..7fb79c2a7
--- /dev/null
+++ b/sys/src/cmd/aux/vga/vga.c
@@ -0,0 +1,486 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#include "pci.h"
+#include "vga.h"
+
+enum {
+ NSeqx = 0x05,
+ NCrtx = 0x19,
+ NGrx = 0x09,
+ NAttrx = 0x15,
+};
+
+uchar
+vgai(long port)
+{
+ uchar data;
+
+ switch(port){
+
+ case MiscR:
+ case Status0:
+ case Status1:
+ case FeatureR:
+ case PaddrW:
+ case Pdata:
+ case Pixmask:
+ case Pstatus:
+ data = inportb(port);
+ break;
+
+ default:
+ error("vgai(0x%4.4lX): unknown port\n", port);
+ /*NOTREACHED*/
+ data = 0xFF;
+ break;
+ }
+ return data;
+}
+
+uchar
+vgaxi(long port, uchar index)
+{
+ uchar data;
+
+ switch(port){
+
+ case Seqx:
+ case Crtx:
+ case Grx:
+ outportb(port, index);
+ data = inportb(port+1);
+ break;
+
+ case Attrx:
+ /*
+ * Allow processor access to the colour
+ * palette registers. Writes to Attrx must
+ * be preceded by a read from Status1 to
+ * initialise the register to point to the
+ * index register and not the data register.
+ * Processor access is allowed by turning
+ * off bit 0x20.
+ */
+ inportb(Status1);
+ if(index < 0x10){
+ outportb(Attrx, index);
+ data = inportb(Attrx+1);
+ inportb(Status1);
+ outportb(Attrx, 0x20|index);
+ }
+ else{
+ outportb(Attrx, 0x20|index);
+ data = inportb(Attrx+1);
+ }
+ break;
+
+ default:
+ error("vgaxi(0x%4.4lx, 0x%2.2uX): unknown port\n", port, index);
+ /*NOTREACHED*/
+ data = 0xFF;
+ break;
+ }
+ return data;
+}
+
+void
+vgao(long port, uchar data)
+{
+ switch(port){
+
+ case MiscW:
+ case FeatureW:
+ case PaddrW:
+ case Pdata:
+ case Pixmask:
+ case PaddrR:
+ outportb(port, data);
+ break;
+
+ default:
+ error("vgao(0x%4.4lX, 0x%2.2uX): unknown port\n", port, data);
+ /*NOTREACHED*/
+ break;
+ }
+}
+
+void
+vgaxo(long port, uchar index, uchar data)
+{
+ switch(port){
+
+ case Seqx:
+ case Crtx:
+ case Grx:
+ /*
+ * We could use an outport here, but some chips
+ * (e.g. 86C928) have trouble with that for some
+ * registers.
+ */
+ outportb(port, index);
+ outportb(port+1, data);
+ break;
+
+ case Attrx:
+ inportb(Status1);
+ if(index < 0x10){
+ outportb(Attrx, index);
+ outportb(Attrx, data);
+ inportb(Status1);
+ outportb(Attrx, 0x20|index);
+ }
+ else{
+ outportb(Attrx, 0x20|index);
+ outportb(Attrx, data);
+ }
+ break;
+
+ default:
+ error("vgaxo(0x%4.4lX, 0x%2.2uX, 0x%2.2uX): unknown port\n",
+ port, index, data);
+ break;
+ }
+}
+
+static void
+snarf(Vga* vga, Ctlr* ctlr)
+{
+ int i;
+
+ /*
+ * Generic VGA registers:
+ * misc, feature;
+ * sequencer;
+ * crt;
+ * graphics;
+ * attribute;
+ * palette.
+ */
+ vga->misc = vgai(MiscR);
+ vga->feature = vgai(FeatureR);
+
+ for(i = 0; i < NSeqx; i++)
+ vga->sequencer[i] = vgaxi(Seqx, i);
+
+ for(i = 0; i < NCrtx; i++)
+ vga->crt[i] = vgaxi(Crtx, i);
+
+ for(i = 0; i < NGrx; i++)
+ vga->graphics[i] = vgaxi(Grx, i);
+
+ for(i = 0; i < NAttrx; i++)
+ vga->attribute[i] = vgaxi(Attrx, i);
+
+ if(dflag)
+ palette.snarf(vga, ctlr);
+
+ ctlr->flag |= Fsnarf;
+}
+
+static void
+init(Vga* vga, Ctlr* ctlr)
+{
+ Mode *mode;
+ int vt, vde, vrs, vre;
+ ulong tmp;
+
+ mode = vga->mode;
+
+ memset(vga->sequencer, 0, NSeqx*sizeof(vga->sequencer[0]));
+ memset(vga->crt, 0, NCrtx*sizeof(vga->crt[0]));
+ memset(vga->graphics, 0, NGrx*sizeof(vga->graphics[0]));
+ memset(vga->attribute, 0, NAttrx*sizeof(vga->attribute[0]));
+ if(dflag)
+ memset(vga->palette, 0, sizeof(vga->palette));
+
+ /*
+ * Misc. If both the horizontal and vertical sync polarity
+ * options are set, use them. Otherwise use the defaults for
+ * the given vertical size.
+ */
+ vga->misc = 0x23;
+ if(mode->frequency == VgaFreq1)
+ vga->misc |= 0x04;
+ if(mode->hsync && mode->vsync){
+ if(mode->hsync == '-')
+ vga->misc |= 0x40;
+ if(mode->vsync == '-')
+ vga->misc |= 0x80;
+ }
+ else{
+ if(mode->y < 480)
+ vga->misc |= 0x40;
+ else if(mode->y < 400)
+ vga->misc |= 0x80;
+ else if(mode->y < 768)
+ vga->misc |= 0xC0;
+ }
+
+ /*
+ * Sequencer
+ */
+ vga->sequencer[0x00] = 0x03;
+ vga->sequencer[0x01] = 0x01;
+ vga->sequencer[0x02] = 0x0F;
+ vga->sequencer[0x03] = 0x00;
+ if(mode->z >= 8)
+ vga->sequencer[0x04] = 0x0A;
+ else
+ vga->sequencer[0x04] = 0x06;
+
+ /*
+ * Crt. Most of the work here is in dealing
+ * with field overflow.
+ */
+ memset(vga->crt, 0, NCrtx);
+
+ vga->crt[0x00] = (mode->ht>>3)-5;
+ vga->crt[0x01] = (mode->x>>3)-1;
+ vga->crt[0x02] = (mode->shb>>3)-1;
+
+ /*
+ * End Horizontal Blank is a 6-bit field, 5-bits
+ * in Crt3, high bit in Crt5.
+ */
+ tmp = mode->ehb>>3;
+ vga->crt[0x03] = 0x80|(tmp & 0x1F);
+ if(tmp & 0x20)
+ vga->crt[0x05] |= 0x80;
+
+ if(mode->shs == 0)
+ mode->shs = mode->shb;
+ vga->crt[0x04] = mode->shs>>3;
+ if(mode->ehs == 0)
+ mode->ehs = mode->ehb;
+ vga->crt[0x05] |= ((mode->ehs>>3) & 0x1F);
+
+ /*
+ * Vertical Total is 10-bits, 8 in Crt6, the high
+ * two bits in Crt7. What if vt is >= 1024? We hope
+ * the specific controller has some more overflow
+ * bits.
+ *
+ * Interlace: if 'v', divide the vertical timing
+ * values by 2.
+ */
+ vt = mode->vt;
+ vde = mode->y;
+ vrs = mode->vrs;
+ vre = mode->vre;
+
+ if(mode->interlace == 'v'){
+ vt /= 2;
+ vde /= 2;
+ vrs /= 2;
+ vre /= 2;
+ }
+
+ tmp = vt-2;
+ vga->crt[0x06] = tmp;
+ if(tmp & 0x100)
+ vga->crt[0x07] |= 0x01;
+ if(tmp & 0x200)
+ vga->crt[0x07] |= 0x20;
+
+ tmp = vrs;
+ vga->crt[0x10] = tmp;
+ if(tmp & 0x100)
+ vga->crt[0x07] |= 0x04;
+ if(tmp & 0x200)
+ vga->crt[0x07] |= 0x80;
+
+ vga->crt[0x11] = 0x20|(vre & 0x0F);
+
+ tmp = vde-1;
+ vga->crt[0x12] = tmp;
+ if(tmp & 0x100)
+ vga->crt[0x07] |= 0x02;
+ if(tmp & 0x200)
+ vga->crt[0x07] |= 0x40;
+
+ vga->crt[0x15] = vrs;
+ if(vrs & 0x100)
+ vga->crt[0x07] |= 0x08;
+ if(vrs & 0x200)
+ vga->crt[0x09] |= 0x20;
+
+ vga->crt[0x16] = (vrs+1);
+
+ vga->crt[0x17] = 0x83;
+ tmp = ((vga->virtx*mode->z)/8);
+ if(tmp >= 512){
+ vga->crt[0x14] |= 0x60;
+ tmp /= 8;
+ }
+ else if(tmp >= 256){
+ vga->crt[0x17] |= 0x08;
+ tmp /= 4;
+ }
+ else{
+ vga->crt[0x17] |= 0x40;
+ tmp /= 2;
+ }
+ vga->crt[0x13] = tmp;
+
+ if(mode->x*mode->y*mode->z/8 > 64*1024)
+ vga->crt[0x17] |= 0x20;
+
+ vga->crt[0x18] = 0x7FF;
+ if(vga->crt[0x18] & 0x100)
+ vga->crt[0x07] |= 0x10;
+ if(vga->crt[0x18] & 0x200)
+ vga->crt[0x09] |= 0x40;
+
+ /*
+ * Graphics
+ */
+ memset(vga->graphics, 0, NGrx);
+ if((vga->sequencer[0x04] & 0x04) == 0)
+ vga->graphics[0x05] |= 0x10;
+ if(mode->z >= 8)
+ vga->graphics[0x05] |= 0x40;
+ vga->graphics[0x06] = 0x05;
+ vga->graphics[0x07] = 0x0F;
+ vga->graphics[0x08] = 0xFF;
+
+ /*
+ * Attribute
+ */
+ memset(vga->attribute, 0, NAttrx);
+ for(tmp = 0; tmp < 0x10; tmp++)
+ vga->attribute[tmp] = tmp;
+ vga->attribute[0x10] = 0x01;
+ if(mode->z >= 8)
+ vga->attribute[0x10] |= 0x40;
+ vga->attribute[0x11] = 0xFF;
+ vga->attribute[0x12] = 0x0F;
+
+ /*
+ * Palette
+ */
+ if(dflag)
+ palette.init(vga, ctlr);
+
+ ctlr->flag |= Finit;
+}
+
+static void
+load(Vga* vga, Ctlr* ctlr)
+{
+ int i;
+
+ /*
+ * Reset the sequencer and leave it off.
+ * Load the generic VGA registers:
+ * misc;
+ * sequencer (but not seq01, display enable);
+ * take the sequencer out of reset;
+ * take off write-protect on crt[0x00-0x07];
+ * crt;
+ * graphics;
+ * attribute;
+ * palette.
+ vgaxo(Seqx, 0x00, 0x00);
+ */
+
+ vgao(MiscW, vga->misc);
+
+ for(i = 2; i < NSeqx; i++)
+ vgaxo(Seqx, i, vga->sequencer[i]);
+ /*vgaxo(Seqx, 0x00, 0x03);*/
+
+ vgaxo(Crtx, 0x11, vga->crt[0x11] & ~0x80);
+ for(i = 0; i < NCrtx; i++)
+ vgaxo(Crtx, i, vga->crt[i]);
+
+ for(i = 0; i < NGrx; i++)
+ vgaxo(Grx, i, vga->graphics[i]);
+
+ for(i = 0; i < NAttrx; i++)
+ vgaxo(Attrx, i, vga->attribute[i]);
+
+ if(dflag)
+ palette.load(vga, ctlr);
+
+ ctlr->flag |= Fload;
+}
+
+static void
+dump(Vga* vga, Ctlr* ctlr)
+{
+ int i;
+
+ printitem(ctlr->name, "misc");
+ printreg(vga->misc);
+ printitem(ctlr->name, "feature");
+ printreg(vga->feature);
+
+ printitem(ctlr->name, "sequencer");
+ for(i = 0; i < NSeqx; i++)
+ printreg(vga->sequencer[i]);
+
+ printitem(ctlr->name, "crt");
+ for(i = 0; i < NCrtx; i++)
+ printreg(vga->crt[i]);
+
+ printitem(ctlr->name, "graphics");
+ for(i = 0; i < NGrx; i++)
+ printreg(vga->graphics[i]);
+
+ printitem(ctlr->name, "attribute");
+ for(i = 0; i < NAttrx; i++)
+ printreg(vga->attribute[i]);
+
+ if(dflag)
+ palette.dump(vga, ctlr);
+
+ printitem(ctlr->name, "virtual");
+ Bprint(&stdout, "%ld %ld\n", vga->virtx, vga->virty);
+ printitem(ctlr->name, "panning");
+ Bprint(&stdout, "%s\n", vga->panning ? "on" : "off");
+ if(vga->f[0]){
+ printitem(ctlr->name, "clock[0] f");
+ Bprint(&stdout, "%9ld\n", vga->f[0]);
+ printitem(ctlr->name, "clock[0] d i m");
+ Bprint(&stdout, "%9ld %8ld - %8ld\n",
+ vga->d[0], vga->i[0], vga->m[0]);
+ printitem(ctlr->name, "clock[0] n p q r");
+ Bprint(&stdout, "%9ld %8ld - %8ld %8ld\n",
+ vga->n[0], vga->p[0], vga->q[0], vga->r[0]);
+ }
+ if(vga->f[1]){
+ printitem(ctlr->name, "clock[1] f");
+ Bprint(&stdout, "%9ld\n", vga->f[1]);
+ printitem(ctlr->name, "clock[1] d i m");
+ Bprint(&stdout, "%9ld %8ld - %8ld\n",
+ vga->d[1], vga->i[1], vga->m[1]);
+ printitem(ctlr->name, "clock[1] n p q r");
+ Bprint(&stdout, "%9ld %8ld - %8ld %8ld\n",
+ vga->n[1], vga->p[1], vga->q[1], vga->r[1]);
+ }
+
+ if(vga->vma || vga->vmb){
+ printitem(ctlr->name, "vm a b");
+ Bprint(&stdout, "%9lud %8lud\n", vga->vma, vga->vmb);
+ }
+ if(vga->vmz){
+ printitem(ctlr->name, "vmz");
+ Bprint(&stdout, "%9lud\n", vga->vmz);
+ }
+ printitem(ctlr->name, "apz");
+ Bprint(&stdout, "%9lud\n", vga->apz);
+
+ printitem(ctlr->name, "linear");
+ Bprint(&stdout, "%9d\n", vga->linear);
+}
+
+Ctlr generic = {
+ "vga", /* name */
+ snarf, /* snarf */
+ 0, /* options */
+ init, /* init */
+ load, /* load */
+ dump, /* dump */
+};