summaryrefslogtreecommitdiff
path: root/os/pc/vgabt485.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/vgabt485.c
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'os/pc/vgabt485.c')
-rw-r--r--os/pc/vgabt485.c245
1 files changed, 245 insertions, 0 deletions
diff --git a/os/pc/vgabt485.c b/os/pc/vgabt485.c
new file mode 100644
index 00000000..1c155e6d
--- /dev/null
+++ b/os/pc/vgabt485.c
@@ -0,0 +1,245 @@
+#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"
+
+/*
+ * Hardware graphics cursor support for
+ * Brooktree Bt485 Monolithic True-Color RAMDAC.
+ * Assumes hooked up to an S3 86C928.
+ *
+ * BUGS:
+ * 64x64x2 cursor always used;
+ * no support for interlaced mode.
+ */
+enum {
+ AddrW = 0x00, /* Address register; palette/cursor RAM write */
+ Palette = 0x01, /* 6/8-bit color palette data */
+ Pmask = 0x02, /* Pixel mask register */
+ AddrR = 0x03, /* Address register; palette/cursor RAM read */
+ ColorW = 0x04, /* Address register; cursor/overscan color write */
+ Color = 0x05, /* Cursor/overscan color data */
+ Cmd0 = 0x06, /* Command register 0 */
+ ColorR = 0x07, /* Address register; cursor/overscan color read */
+ Cmd1 = 0x08, /* Command register 1 */
+ Cmd2 = 0x09, /* Command register 2 */
+ Status = 0x0A, /* Status */
+ Cmd3 = 0x1A, /* Command register 3 */
+ Cram = 0x0B, /* Cursor RAM array data */
+ Cxlr = 0x0C, /* Cursor x-low register */
+ Cxhr = 0x0D, /* Cursor x-high register */
+ Cylr = 0x0E, /* Cursor y-low register */
+ Cyhr = 0x0F, /* Cursor y-high register */
+
+ Nreg = 0x10,
+};
+
+/*
+ * Lower 2-bits of indirect DAC register
+ * addressing.
+ */
+static ushort dacxreg[4] = {
+ PaddrW, Pdata, Pixmask, PaddrR
+};
+
+static uchar
+bt485io(uchar reg)
+{
+ uchar crt55, cr0;
+
+ crt55 = vgaxi(Crtx, 0x55) & 0xFC;
+ if((reg & 0x0F) == Status){
+ /*
+ * 1,2: Set indirect addressing for Status or
+ * Cmd3 - set bit7 of Cr0.
+ */
+ vgaxo(Crtx, 0x55, crt55|((Cmd0>>2) & 0x03));
+ cr0 = vgai(dacxreg[Cmd0 & 0x03])|0x80;
+ vgao(dacxreg[Cmd0 & 0x03], cr0);
+
+ /*
+ * 3,4: Set the index into the Write register,
+ * index == 0x00 for Status, 0x01 for Cmd3.
+ */
+ vgaxo(Crtx, 0x55, crt55|((AddrW>>2) & 0x03));
+ vgao(dacxreg[AddrW & 0x03], (reg == Status) ? 0x00: 0x01);
+
+ /*
+ * 5,6: Get the contents of the appropriate
+ * register at 0x0A.
+ */
+ }
+
+ return crt55;
+}
+
+static uchar
+bt485i(uchar reg)
+{
+ uchar crt55, r;
+
+ crt55 = bt485io(reg);
+ vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
+ r = vgai(dacxreg[reg & 0x03]);
+ vgaxo(Crtx, 0x55, crt55);
+
+ return r;
+}
+
+static void
+bt485o(uchar reg, uchar data)
+{
+ uchar crt55;
+
+ crt55 = bt485io(reg);
+ vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
+ vgao(dacxreg[reg & 0x03], data);
+ vgaxo(Crtx, 0x55, crt55);
+}
+
+static void
+bt485disable(VGAscr*)
+{
+ uchar r;
+
+ /*
+ * Disable
+ * cursor mode 3;
+ * cursor control enable for Bt485 DAC;
+ * the hardware cursor external operation mode.
+ */
+ r = bt485i(Cmd2) & ~0x03;
+ bt485o(Cmd2, r);
+
+ r = vgaxi(Crtx, 0x45) & ~0x20;
+ vgaxo(Crtx, 0x45, r);
+
+ r = vgaxi(Crtx, 0x55) & ~0x20;
+ vgaxo(Crtx, 0x55, r);
+}
+
+static void
+bt485enable(VGAscr*)
+{
+ uchar r;
+
+ /*
+ * Turn cursor off.
+ */
+ r = bt485i(Cmd2) & 0xFC;
+ bt485o(Cmd2, r);
+
+ /*
+ * Overscan colour,
+ * cursor colour 1 (white),
+ * cursor colour 2, 3 (black).
+ */
+ bt485o(ColorW, 0x00);
+ bt485o(Color, Pwhite); bt485o(Color, Pwhite); bt485o(Color, Pwhite);
+
+ bt485o(Color, Pwhite); bt485o(Color, Pwhite); bt485o(Color, Pwhite);
+
+ bt485o(Color, Pblack); bt485o(Color, Pblack); bt485o(Color, Pblack);
+ bt485o(Color, Pblack); bt485o(Color, Pblack); bt485o(Color, Pblack);
+
+ /*
+ * Finally, enable
+ * the hardware cursor external operation mode;
+ * cursor control enable for Bt485 DAC.
+ * The #9GXE cards seem to need the 86C928 Bt485 support
+ * enabled in order to work at all in enhanced mode.
+ */
+
+ r = vgaxi(Crtx, 0x55)|0x20;
+ vgaxo(Crtx, 0x55, r);
+
+ r = vgaxi(Crtx, 0x45)|0x20;
+ vgaxo(Crtx, 0x45, r);
+}
+
+static void
+bt485load(VGAscr* scr, Cursor* curs)
+{
+ uchar r;
+ int x, y;
+
+ /*
+ * Turn cursor off;
+ * put cursor into 64x64x2 mode and clear MSBs of address;
+ * clear LSBs of address;
+ */
+ r = bt485i(Cmd2) & 0xFC;
+ bt485o(Cmd2, r);
+
+ r = (bt485i(Cmd3) & 0xFC)|0x04;
+ bt485o(Cmd3, r);
+
+ bt485o(AddrW, 0x00);
+
+ /*
+ * Now load the cursor RAM array, both planes.
+ * The cursor is 16x16, the array 64x64; put
+ * the cursor in the top left. The 0,0 cursor
+ * point is bottom-right, so positioning will
+ * have to take that into account.
+ */
+ for(y = 0; y < 64; y++){
+ for(x = 0; x < 64/8; x++){
+ if(x < 16/8 && y < 16)
+ bt485o(Cram, curs->clr[x+y*2]);
+ else
+ bt485o(Cram, 0x00);
+ }
+ }
+ for(y = 0; y < 64; y++){
+ for(x = 0; x < 64/8; x++){
+ if(x < 16/8 && y < 16)
+ bt485o(Cram, curs->set[x+y*2]);
+ else
+ bt485o(Cram, 0x00);
+ }
+ }
+
+ /*
+ * Initialise the cursor hot-point
+ * and enable the cursor.
+ */
+ scr->offset.x = 64+curs->offset.x;
+ scr->offset.y = 64+curs->offset.y;
+
+ r = (bt485i(Cmd2) & 0xFC)|0x01;
+ bt485o(Cmd2, r);
+}
+
+static int
+bt485move(VGAscr* scr, Point p)
+{
+ int x, y;
+
+ x = p.x+scr->offset.x;
+ y = p.y+scr->offset.y;
+
+ bt485o(Cxlr, x & 0xFF);
+ bt485o(Cxhr, (x>>8) & 0x0F);
+ bt485o(Cylr, y & 0xFF);
+ bt485o(Cyhr, (y>>8) & 0x0F);
+
+ return 0;
+}
+
+VGAcur vgabt485cur = {
+ "bt485hwgc",
+
+ bt485enable,
+ bt485disable,
+ bt485load,
+ bt485move,
+};