summaryrefslogtreecommitdiff
path: root/os/pc/vgacyber938x.c
diff options
context:
space:
mode:
Diffstat (limited to 'os/pc/vgacyber938x.c')
-rw-r--r--os/pc/vgacyber938x.c225
1 files changed, 225 insertions, 0 deletions
diff --git a/os/pc/vgacyber938x.c b/os/pc/vgacyber938x.c
new file mode 100644
index 00000000..7c86679c
--- /dev/null
+++ b/os/pc/vgacyber938x.c
@@ -0,0 +1,225 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+enum {
+ CursorON = 0xC8,
+ CursorOFF = 0x00,
+};
+
+static int
+cyber938xpageset(VGAscr*, int page)
+{
+ int opage;
+
+ opage = inb(0x3D8);
+
+ outb(0x3D8, page);
+ outb(0x3D9, page);
+
+ return opage;
+}
+
+static void
+cyber938xpage(VGAscr* scr, int page)
+{
+ lock(&scr->devlock);
+ cyber938xpageset(scr, page);
+ unlock(&scr->devlock);
+}
+
+static ulong
+cyber938xlinear(VGAscr* scr, int* size, int* align)
+{
+ ulong aperture, oaperture;
+ int oapsize, wasupamem;
+ int osize;
+ Pcidev *p;
+
+ osize = *size;
+ oaperture = scr->aperture;
+ oapsize = scr->apsize;
+ wasupamem = scr->isupamem;
+ if(wasupamem)
+ upafree(oaperture, oapsize);
+ scr->isupamem = 0;
+ scr->mmio = 0;
+
+ if(p = pcimatch(nil, 0x1023, 0)){
+ aperture = p->mem[0].bar & ~0x0F;
+ *size = p->mem[0].size;
+ /*
+ * Heuristic to detect the MMIO space. We're flying blind
+ * here, with only the XFree86 source to guide us.
+ */
+ if(p->mem[1].size == 0x20000)
+ scr->mmio = (ulong*)(p->mem[1].bar & ~0x0F);
+ }
+ else
+ aperture = 0;
+
+ aperture = upamalloc(aperture, *size, *align);
+ if(aperture == 0){
+ if(wasupamem && upamalloc(oaperture, oapsize, 0))
+ scr->isupamem = 1;
+ }
+ else
+ scr->isupamem = 1;
+
+ if(aperture)
+ addvgaseg("cyber938xscreen", aperture, osize);
+ if(scr->mmio)
+ addvgaseg("cyber938xmmio", (ulong)scr->mmio, 0x20000);
+
+ return aperture;
+}
+
+static void
+cyber938xcurdisable(VGAscr*)
+{
+ vgaxo(Crtx, 0x50, CursorOFF);
+}
+
+static void
+cyber938xcurload(VGAscr* scr, Cursor* curs)
+{
+ uchar *p;
+ int islinear, opage, y;
+
+ cyber938xcurdisable(scr);
+
+ opage = 0;
+ p = KADDR(scr->aperture);
+ islinear = vgaxi(Crtx, 0x21) & 0x20;
+ if(!islinear){
+ lock(&scr->devlock);
+ opage = cyber938xpageset(scr, scr->storage>>16);
+ p += (scr->storage & 0xFFFF);
+ }
+ else
+ p += scr->storage;
+
+ for(y = 0; y < 16; y++){
+ *p++ = curs->set[2*y]|curs->clr[2*y];
+ *p++ = curs->set[2*y + 1]|curs->clr[2*y + 1];
+ *p++ = 0x00;
+ *p++ = 0x00;
+ *p++ = curs->set[2*y];
+ *p++ = curs->set[2*y + 1];
+ *p++ = 0x00;
+ *p++ = 0x00;
+ }
+ memset(p, 0, (32-y)*8);
+
+ if(!islinear){
+ cyber938xpageset(scr, opage);
+ unlock(&scr->devlock);
+ }
+
+ /*
+ * Save the cursor hotpoint and enable the cursor.
+ */
+ scr->offset = curs->offset;
+ vgaxo(Crtx, 0x50, CursorON);
+}
+
+static int
+cyber938xcurmove(VGAscr* scr, Point p)
+{
+ int x, xo, y, yo;
+
+ /*
+ * Mustn't position the cursor offscreen even partially,
+ * or it might disappear. Therefore, if x or y is -ve, adjust the
+ * cursor origins 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;
+
+ /*
+ * Load the new values.
+ */
+ vgaxo(Crtx, 0x46, xo);
+ vgaxo(Crtx, 0x47, yo);
+ vgaxo(Crtx, 0x40, x & 0xFF);
+ vgaxo(Crtx, 0x41, (x>>8) & 0xFF);
+ vgaxo(Crtx, 0x42, y & 0xFF);
+ vgaxo(Crtx, 0x43, (y>>8) & 0xFF);
+
+ return 0;
+}
+
+static void
+cyber938xcurenable(VGAscr* scr)
+{
+ int i;
+ ulong storage;
+
+ cyber938xcurdisable(scr);
+
+ /*
+ * Cursor colours.
+ */
+ for(i = 0x48; i < 0x4C; i++)
+ vgaxo(Crtx, i, 0x00);
+ for(i = 0x4C; i < 0x50; i++)
+ vgaxo(Crtx, i, 0xFF);
+
+ /*
+ * Find a place for the cursor data in display memory.
+ */
+ storage = ((scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024);
+ vgaxo(Crtx, 0x44, storage & 0xFF);
+ vgaxo(Crtx, 0x45, (storage>>8) & 0xFF);
+ storage *= 1024;
+ scr->storage = storage;
+
+ /*
+ * Load, locate and enable the 32x32 cursor.
+ * (64x64 is bit 0, X11 format is bit 6 and cursor
+ * enable is bit 7). Bit 3 needs to be set on 9382
+ * chips otherwise even the white bits are black.
+ */
+ cyber938xcurload(scr, &arrow);
+ cyber938xcurmove(scr, ZP);
+ vgaxo(Crtx, 0x50, CursorON);
+}
+
+VGAdev vgacyber938xdev = {
+ "cyber938x",
+
+ nil, /* enable */
+ nil, /* disable */
+ cyber938xpage, /* page */
+ cyber938xlinear, /* linear */
+ nil, /* drawinit */
+};
+
+VGAcur vgacyber938xcur = {
+ "cyber938xhwgc",
+
+ cyber938xcurenable, /* enable */
+ cyber938xcurdisable, /* disable */
+ cyber938xcurload, /* load */
+ cyber938xcurmove, /* move */
+};