summaryrefslogtreecommitdiff
path: root/os/pc/vgaet4000.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
commit74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch)
treec6e220ba61db3a6ea4052e6841296d829654e664 /os/pc/vgaet4000.c
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'os/pc/vgaet4000.c')
-rw-r--r--os/pc/vgaet4000.c270
1 files changed, 270 insertions, 0 deletions
diff --git a/os/pc/vgaet4000.c b/os/pc/vgaet4000.c
new file mode 100644
index 00000000..f3ede446
--- /dev/null
+++ b/os/pc/vgaet4000.c
@@ -0,0 +1,270 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+static void
+setet4000page(int page)
+{
+ uchar p;
+
+ p = page & 0x0F;
+ p |= p<<4;
+ outb(0x3CD, p);
+
+ p = (page & 0x30);
+ p |= p>>4;
+ outb(0x3CB, p);
+}
+
+static void
+et4000page(VGAscr *scr, int page)
+{
+ lock(&scr->devlock);
+ setet4000page(page);
+ unlock(&scr->devlock);
+}
+
+static void
+et4000disable(VGAscr*)
+{
+ uchar imaF7;
+
+ outb(0x217A, 0xF7);
+ imaF7 = inb(0x217B) & ~0x80;
+ outb(0x217B, imaF7);
+}
+
+static void
+et4000enable(VGAscr *scr)
+{
+ uchar imaF7;
+
+ et4000disable(scr);
+
+ /*
+ * Configure CRTCB for Sprite, 64x64,
+ * CRTC pixel overlay.
+ */
+ outb(0x217A, 0xEF);
+ outb(0x217B, 0x02);
+
+ /*
+ * Cursor goes in the top left corner
+ * of the Sprite area, so the horizontal and
+ * vertical presets are 0.
+ */
+ outb(0x217A, 0xE2);
+ outb(0x217B, 0x00);
+ outb(0x217A, 0xE3);
+ outb(0x217B, 0x00);
+
+ outb(0x217A, 0xE6);
+ outb(0x217B, 0x00);
+ outb(0x217A, 0xE7);
+ outb(0x217B, 0x00);
+
+ /*
+ * Find a place for the cursor data in display memory.
+ * Must be on a "doubleword" boundary, but put it on a
+ * 1024-byte boundary so that there's no danger of it
+ * crossing a page.
+ */
+ scr->storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024;
+ scr->storage *= 1024/4;
+ outb(0x217A, 0xE8);
+ outb(0x217B, scr->storage & 0xFF);
+ outb(0x217A, 0xE9);
+ outb(0x217B, (scr->storage>>8) & 0xFF);
+ outb(0x217A, 0xEA);
+ outb(0x217B, (scr->storage>>16) & 0x0F);
+ scr->storage *= 4;
+
+ /*
+ * Row offset in "quadwords". Must be 2 for Sprite.
+ * Bag the pixel-panning.
+ * Colour depth, must be 2 for Sprite.
+ */
+ outb(0x217A, 0xEB);
+ outb(0x217B, 0x02);
+ outb(0x217A, 0xEC);
+ outb(0x217B, 0x00);
+
+ outb(0x217A, 0xED);
+ outb(0x217B, 0x00);
+
+ outb(0x217A, 0xEE);
+// if(vgascreen.ldepth == 3)
+ outb(0x217B, 0x01);
+// else
+// outb(0x217B, 0x00);
+
+ /*
+ * Enable the CRTCB/Sprite.
+ */
+ outb(0x217A, 0xF7);
+ imaF7 = inb(0x217B);
+ outb(0x217B, 0x80|imaF7);
+}
+
+static void
+et4000load(VGAscr *scr, Cursor *c)
+{
+ uchar p0, p1, *mem;
+ int i, x, y;
+ ushort p;
+ uchar clr[2*16], set[2*16];
+
+ /*
+ * Lock the display memory so we can update the
+ * cursor bitmap if necessary.
+ */
+ lock(&scr->devlock);
+
+ /*
+ * Disable the cursor.
+ * Set the display page (do we need to restore
+ * the current contents when done?) and the
+ * pointer to the two planes. What if this crosses
+ * into a new page?
+ */
+ et4000disable(scr);
+
+ setet4000page(scr->storage>>16);
+ mem = (uchar*)KADDR(scr->aperture) + (scr->storage & 0xFFFF);
+
+ /*
+ * Initialise the 64x64 cursor RAM array. There are 2 planes,
+ * p0 and p1. Data is written 4 pixels per byte, with p1 the
+ * MS bit of each pixel.
+ * The cursor mode gives the following truth table:
+ * p1 p0 colour
+ * 0 0 Sprite Colour 0 (defined as 0x00)
+ * 0 1 Sprite Colour 1 (defined as 0xFF)
+ * 1 0 Transparent (allow CRTC pixel pass through)
+ * 1 1 Invert (allow CRTC pixel invert through)
+ * Put the cursor into the top-left of the 64x64 array.
+ *
+ * This is almost certainly wrong, since it has not
+ * been updated for the 3rd edition color values.
+ */
+ memmove(clr, c->clr, sizeof(clr));
+// pixreverse(clr, sizeof(clr), 0);
+ memmove(set, c->set, sizeof(set));
+// pixreverse(set, sizeof(set), 0);
+ for(y = 0; y < 64; y++){
+ for(x = 0; x < 64/8; x++){
+ if(x < 16/8 && y < 16){
+ p0 = clr[x+y*2];
+ p1 = set[x+y*2];
+
+ p = 0x0000;
+ for(i = 0; i < 8; i++){
+ if(p1 & (1<<(7-i))){
+ /* nothing to do */
+ }
+ else if(p0 & (1<<(7-i)))
+ p |= 0x01<<(2*i);
+ else
+ p |= 0x02<<(2*i);
+ }
+ *mem++ = p & 0xFF;
+ *mem++ = (p>>8) & 0xFF;
+ }
+ else {
+ *mem++ = 0xAA;
+ *mem++ = 0xAA;
+ }
+ }
+ }
+
+ /*
+ * enable the cursor.
+ */
+ outb(0x217A, 0xF7);
+ p = inb(0x217B)|0x80;
+ outb(0x217B, p);
+
+ unlock(&scr->devlock);
+}
+
+static int
+et4000move(VGAscr *scr, Point p)
+{
+ int x, xo, y, yo;
+
+ if(canlock(&scr->devlock) == 0)
+ return 1;
+
+ /*
+ * Mustn't position the cursor offscreen even partially,
+ * or it disappears. Therefore, if x or y is -ve, adjust the
+ * cursor presets instead.
+ */
+ if((x = p.x+scr->offset.x) < 0){
+ xo = -x;
+ x = 0;
+ }
+ else
+ xo = 0;
+ if((y = p.y+scr->offset.y) < 0){
+ yo = -y;
+ y = 0;
+ }
+ else
+ yo = 0;
+
+ /*
+ * The cursor image is jerky if we don't do this.
+ * The cursor information is probably fetched from
+ * display memory during the horizontal blank active
+ * time and it doesn't like it if the coordinates
+ * are changed underneath.
+ */
+ while((vgai(Status1) & 0x08) == 0)
+ ;
+
+ outb(0x217A, 0xE2);
+ outb(0x217B, xo);
+
+ outb(0x217A, 0xE6);
+ outb(0x217B, yo);
+
+ outb(0x217A, 0xE1);
+ outb(0x217B, (x>>8) & 0xFF);
+ outb(0x217A, 0xE0);
+ outb(0x217B, x & 0xFF);
+ outb(0x217A, 0xE5);
+ outb(0x217B, (y>>8) & 0xFF);
+ outb(0x217A, 0xE4);
+ outb(0x217B, y & 0xFF);
+
+ unlock(&scr->devlock);
+ return 0;
+}
+
+VGAcur vgaet4000cur = {
+ "et4000hwgc",
+
+ et4000enable,
+ et4000disable,
+ et4000load,
+ et4000move,
+};
+
+VGAdev vgaet4000dev = {
+ "et4000",
+
+ 0,
+ 0,
+ et4000page,
+ 0
+};