ref: ab3492f05e5998f79befe6e7397175f4bdb39149
dir: /sys/src/9/pc/vgaark2000pv.c/
#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" static int ark2000pvpageset(VGAscr*, int page) { uchar seq15; seq15 = vgaxi(Seqx, 0x15); vgaxo(Seqx, 0x15, page); vgaxo(Seqx, 0x16, page); return seq15; } static void ark2000pvpage(VGAscr* scr, int page) { lock(&scr->devlock); ark2000pvpageset(scr, page); unlock(&scr->devlock); } static void ark2000pvdisable(VGAscr*) { uchar seq20; seq20 = vgaxi(Seqx, 0x20) & ~0x08; vgaxo(Seqx, 0x20, seq20); } static void ark2000pvenable(VGAscr* scr) { uchar seq20; ulong storage; /* * Disable the cursor then configure for X-Windows style, * 32x32 and 4/8-bit colour depth. * Set cursor colours for 4/8-bit. */ seq20 = vgaxi(Seqx, 0x20) & ~0x1F; vgaxo(Seqx, 0x20, seq20); seq20 |= 0x18; vgaxo(Seqx, 0x26, 0x00); vgaxo(Seqx, 0x27, 0x00); vgaxo(Seqx, 0x28, 0x00); vgaxo(Seqx, 0x29, 0xFF); vgaxo(Seqx, 0x2A, 0xFF); vgaxo(Seqx, 0x2B, 0xFF); /* * Cursor storage is a 256 byte or 1Kb block located in the last * 16Kb of video memory. Crt25 is the index of which block. */ storage = (vgaxi(Seqx, 0x10)>>6) & 0x03; storage = (1024*1024)<<storage; storage -= 256; scr->storage = storage; vgaxo(Seqx, 0x25, 0x3F); /* * Enable the cursor. */ vgaxo(Seqx, 0x20, seq20); } static void ark2000pvload(VGAscr* scr, Cursor* curs) { uchar *p, seq10; int opage, x, y; /* * Is linear addressing turned on? This will determine * how we access the cursor storage. */ seq10 = vgaxi(Seqx, 0x10); opage = 0; p = scr->vaddr; if(!(seq10 & 0x10)){ lock(&scr->devlock); opage = ark2000pvpageset(scr, scr->storage>>16); p += (scr->storage & 0xFFFF); } else p += scr->storage; /* * The cursor is set in X11 mode which gives the following * truth table: * and xor colour * 0 0 underlying pixel colour * 0 1 underlying pixel colour * 1 0 background colour * 1 1 foreground colour * Put the cursor into the top-left of the 32x32 array. * The manual doesn't say what the data layout in memory is - * this worked out by trial and error. */ for(y = 0; y < 32; y++){ for(x = 0; x < 32/8; x++){ if(x < 16/8 && y < 16){ *p++ = curs->clr[2*y + x]|curs->set[2*y + x]; *p++ = curs->set[2*y + x]; } else { *p++ = 0x00; *p++ = 0x00; } } } if(!(seq10 & 0x10)){ ark2000pvpageset(scr, opage); unlock(&scr->devlock); } /* * Save the cursor hotpoint. */ scr->offset = curs->offset; } static int ark2000pvmove(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(Seqx, 0x2C, xo); vgaxo(Seqx, 0x2D, yo); vgaxo(Seqx, 0x21, (x>>8) & 0x0F); vgaxo(Seqx, 0x22, x & 0xFF); vgaxo(Seqx, 0x23, (y>>8) & 0x0F); vgaxo(Seqx, 0x24, y & 0xFF); return 0; } VGAdev vgaark2000pvdev = { "ark2000pv", 0, 0, ark2000pvpage, 0, }; VGAcur vgaark2000pvcur = { "ark2000pvhwgc", ark2000pvenable, ark2000pvdisable, ark2000pvload, ark2000pvmove, };