123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586 |
- #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"
- /*
- * #9 Ticket to Ride IV.
- */
- enum {
- IndexLo = 0x10/4,
- IndexHi = 0x14/4,
- Data = 0x18/4,
- IndexCtl = 0x1C/4,
- Zoom = 0x54/4,
- };
- enum { /* index registers */
- CursorSyncCtl = 0x03,
- HsyncHi = 0x01,
- HsyncLo = 0x02,
- VsyncHi = 0x04,
- VsyncLo = 0x08,
- CursorCtl = 0x30,
- CursorXLo = 0x31,
- CursorXHi = 0x32,
- CursorYLo = 0x33,
- CursorYHi = 0x34,
- CursorHotX = 0x35,
- CursorHotY = 0x36,
- CursorR1 = 0x40,
- CursorG1 = 0x41,
- CursorB1 = 0x42,
- CursorR2 = 0x43,
- CursorG2 = 0x44,
- CursorB2 = 0x45,
- CursorR3 = 0x46,
- CursorG3 = 0x47,
- CursorB3 = 0x48,
- CursorArray = 0x100,
- CursorMode32x32 = 0x23,
- CursorMode64x64 = 0x27,
- CursorMode = CursorMode32x32,
- };
- static ulong
- t2r4linear(VGAscr* scr, int* size, int* align)
- {
- ulong aperture, oaperture;
- int oapsize, wasupamem;
- Pcidev *p;
- oaperture = scr->aperture;
- oapsize = scr->apsize;
- wasupamem = scr->isupamem;
- aperture = 0;
- if(p = pcimatch(nil, 0x105D, 0)){
- switch(p->did){
- case 0x5348:
- aperture = p->mem[0].bar & ~0x0F;
- *size = p->mem[0].size;
- break;
- default:
- break;
- }
- }
- if(wasupamem){
- if(oaperture == aperture)
- return oaperture;
- upafree(oaperture, oapsize);
- }
- scr->isupamem = 0;
- aperture = upamalloc(aperture, *size, *align);
- if(aperture == 0){
- if(wasupamem && upamalloc(oaperture, oapsize, 0)){
- aperture = oaperture;
- scr->isupamem = 1;
- }
- else
- scr->isupamem = 0;
- }
- else
- scr->isupamem = 1;
- return aperture;
- }
- static void
- t2r4enable(VGAscr* scr)
- {
- Pcidev *p;
- int size, align;
- ulong aperture, mmio;
- /*
- * Only once, can't be disabled for now.
- * scr->mmio holds the virtual address of
- * the MMIO registers.
- */
- if(scr->mmio)
- return;
- if(p = pcimatch(nil, 0x105D, 0)){
- switch(p->did){
- case 0x5348:
- break;
- default:
- return;
- }
- }
- else
- return;
- mmio = upamalloc(p->mem[4].bar & ~0x0F, p->mem[4].size, 0);
- if(mmio == 0)
- return;
- addvgaseg("t2r4mmio", mmio, p->mem[4].size);
- scr->mmio = KADDR(mmio);
- size = p->mem[0].size;
- align = 0;
- aperture = t2r4linear(scr, &size, &align);
- if(aperture){
- scr->aperture = aperture;
- scr->apsize = size;
- addvgaseg("t2r4screen", aperture, size);
- }
- }
- static uchar
- t2r4xi(VGAscr* scr, int index)
- {
- ulong *mmio;
- mmio = scr->mmio;
- mmio[IndexLo] = index & 0xFF;
- mmio[IndexHi] = (index>>8) & 0xFF;
- return mmio[Data];
- }
- static void
- t2r4xo(VGAscr* scr, int index, uchar data)
- {
- ulong *mmio;
- mmio = scr->mmio;
- mmio[IndexLo] = index & 0xFF;
- mmio[IndexHi] = (index>>8) & 0xFF;
- mmio[Data] = data;
- }
- static void
- t2r4curdisable(VGAscr* scr)
- {
- if(scr->mmio == 0)
- return;
- t2r4xo(scr, CursorCtl, 0x00);
- }
- static void
- t2r4curload(VGAscr* scr, Cursor* curs)
- {
- uchar *data;
- int size, x, y, zoom;
- ulong clr, *mmio, pixels, set;
- mmio = scr->mmio;
- if(mmio == 0)
- return;
- /*
- * Make sure cursor is off by initialising the cursor
- * control to defaults.
- */
- t2r4xo(scr, CursorCtl, 0x00);
- /*
- * Set auto-increment mode for index-register addressing
- * and initialise the cursor array index.
- */
- mmio[IndexCtl] = 0x01;
- mmio[IndexLo] = CursorArray & 0xFF;
- mmio[IndexHi] = (CursorArray>>8) & 0xFF;
- /*
- * Initialise the 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 is set in X-Windows mode which gives the following
- * truth table:
- * p1 p0 colour
- * 0 0 underlying pixel colour
- * 0 1 underlying pixel colour
- * 1 0 cursor colour 1
- * 1 1 cursor colour 2
- * Put the cursor into the top-left of the array.
- *
- * Although this looks a lot like the IBM RGB524 cursor, the
- * scanlines appear to be twice as long as they should be and
- * some of the other features are missing.
- */
- if(mmio[Zoom] & 0x0F)
- zoom = 32;
- else
- zoom = 16;
- data = (uchar*)&mmio[Data];
- for(y = 0; y < zoom; y++){
- clr = (curs->clr[2*y]<<8)|curs->clr[y*2 + 1];
- set = (curs->set[2*y]<<8)|curs->set[y*2 + 1];
- pixels = 0;
- for(x = 0; x < 16; x++){
- if(set & (1<<x))
- pixels |= 0x03<<(x*2);
- else if(clr & (1<<x))
- pixels |= 0x02<<(x*2);
- }
- *data = pixels>>24;
- *data = pixels>>16;
- *data = pixels>>8;
- *data = pixels;
- *data = 0x00;
- *data = 0x00;
- *data = 0x00;
- *data = 0x00;
- if(CursorMode == CursorMode32x32 && zoom == 16)
- continue;
- *data = pixels>>24;
- *data = pixels>>16;
- *data = pixels>>8;
- *data = pixels;
- *data = 0x00;
- *data = 0x00;
- *data = 0x00;
- *data = 0x00;
- }
- if(CursorMode == CursorMode32x32)
- size = 32;
- else
- size = 64;
- while(y < size){
- for(x = 0; x < size/8; x++){
- *data = 0x00;
- *data = 0x00;
- }
- y++;
- }
- mmio[IndexCtl] = 0x00;
- /*
- * Initialise the hotpoint and enable the cursor.
- */
- t2r4xo(scr, CursorHotX, -curs->offset.x);
- zoom = (scr->mmio[Zoom] & 0x0F)+1;
- t2r4xo(scr, CursorHotY, -curs->offset.y*zoom);
- t2r4xo(scr, CursorCtl, CursorMode);
- }
- static int
- t2r4curmove(VGAscr* scr, Point p)
- {
- int y, zoom;
- if(scr->mmio == 0)
- return 1;
- t2r4xo(scr, CursorXLo, p.x & 0xFF);
- t2r4xo(scr, CursorXHi, (p.x>>8) & 0x0F);
- zoom = (scr->mmio[Zoom] & 0x0F)+1;
- y = p.y*zoom;
- t2r4xo(scr, CursorYLo, y & 0xFF);
- t2r4xo(scr, CursorYHi, (y>>8) & 0x0F);
- return 0;
- }
- static void
- t2r4curenable(VGAscr* scr)
- {
- t2r4enable(scr);
- if(scr->mmio == 0)
- return;
- /*
- * Make sure cursor is off by initialising the cursor
- * control to defaults.
- */
- t2r4xo(scr, CursorCtl, 0x00);
- /*
- * Cursor colour 1 (white),
- * cursor colour 2 (black).
- */
- t2r4xo(scr, CursorR1, Pwhite);
- t2r4xo(scr, CursorG1, Pwhite);
- t2r4xo(scr, CursorB1, Pwhite);
- t2r4xo(scr, CursorR2, Pblack);
- t2r4xo(scr, CursorG2, Pblack);
- t2r4xo(scr, CursorB2, Pblack);
- /*
- * Load, locate and enable the cursor, 64x64, mode 2.
- */
- t2r4curload(scr, &arrow);
- t2r4curmove(scr, ZP);
- t2r4xo(scr, CursorCtl, CursorMode);
- }
- enum {
- Flow = 0x08/4,
- Busy = 0x0C/4,
- BufCtl = 0x20/4,
- DeSorg = 0x28/4,
- DeDorg = 0x2C/4,
- DeSptch = 0x40/4,
- DeDptch = 0x44/4,
- CmdOpc = 0x50/4,
- CmdRop = 0x54/4,
- CmdStyle = 0x58/4,
- CmdPatrn = 0x5C/4,
- CmdClp = 0x60/4,
- CmdPf = 0x64/4,
- Fore = 0x68/4,
- Back = 0x6C/4,
- Mask = 0x70/4,
- DeKey = 0x74/4,
- Lpat = 0x78/4,
- Pctrl = 0x7C/4,
- Clptl = 0x80/4,
- Clpbr = 0x84/4,
- XY0 = 0x88/4,
- XY1 = 0x8C/4,
- XY2 = 0x90/4,
- XY3 = 0x94/4,
- XY4 = 0x98/4,
- Alpha = 0x128/4,
- ACtl = 0x16C/4,
- RBaseD = 0x4000/4,
- };
- /* wait until pipeline ready for new command */
- static void
- waitforfifo(VGAscr *scr)
- {
- int x;
- ulong *d;
- x = 0;
- d = scr->mmio + RBaseD;
- while((d[Busy]&1) && x++ < 1000000)
- ;
- if(x >= 1000000) /* shouldn't happen */
- iprint("busy %8lux\n", d[Busy]);
- }
- /* wait until command has finished executing */
- static void
- waitforcmd(VGAscr *scr)
- {
- int x;
- ulong *d;
- x = 0;
- d = scr->mmio + RBaseD;
- while((d[Flow]&0x1B) && x++ < 1000000)
- ;
- if(x >= 1000000) /* shouldn't happen */
- iprint("flow %8lux\n", d[Flow]);
- }
- /* wait until memory controller not busy (i.e. wait for writes to flush) */
- static void
- waitformem(VGAscr *scr)
- {
- int x;
- ulong *d;
- x = 0;
- d = scr->mmio + RBaseD;
- while((d[Flow]&2)&& x++ < 1000000)
- ;
- if(x >= 1000000) /* shouldn't happen */
- iprint("mem %8lux\n", d[Busy]);
- }
- static int
- t2r4hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
- {
- int ctl;
- Point dp, sp;
- ulong *d;
- int depth;
- if(r.min.y == sr.min.y){ /* a purely horizontal scroll */
- depth = scr->gscreen->depth;
- switch(depth){
- case 32:
- /*
- * Using the SGI flat panels with the Ticket-to-Ride IV, horizontal
- * 32-bit scrolls don't work perfectly on rectangles of width <= 24.
- * we bail on a bigger bound for padding.
- */
- if(Dx(r) < 32)
- return 0;
- break;
- case 16:
- /*
- * Using the SGI flat panels with the Ticket-to-Ride IV, horizontal
- * 16-bit scrolls don't work perfectly on rectangles of width <= 96.
- * we bail on a bigger bound for padding.
- */
- if(Dx(r) < 104)
- return 0;
- break;
- }
- }
- waitformem(scr);
- waitforfifo(scr);
- d = scr->mmio + RBaseD;
- ctl = 0;
- if(r.min.x <= sr.min.x){
- dp.x = r.min.x;
- sp.x = sr.min.x;
- }else{
- ctl |= 2;
- dp.x = r.max.x-1;
- sp.x = sr.max.x-1;
- }
- if(r.min.y < sr.min.y){
- dp.y = r.min.y;
- sp.y = sr.min.y;
- }else{
- ctl |= 1;
- dp.y = r.max.y-1;
- sp.y = sr.max.y-1;
- }
- d[CmdOpc] = 0x1; /* bitblt */
- d[CmdRop] = 0xC; /* copy source */
- d[CmdStyle] = 0;
- d[CmdPatrn] = 0;
- d[Fore] = 0;
- d[Back] = 0;
- /* writing XY1 executes cmd */
- d[XY3] = ctl;
- d[XY0] = (sp.x<<16)|sp.y;
- d[XY2] = (Dx(r)<<16)|Dy(r);
- d[XY4] = 0;
- d[XY1] = (dp.x<<16)|dp.y;
- waitforcmd(scr);
- return 1;
- }
- static int
- t2r4hwfill(VGAscr *scr, Rectangle r, ulong sval)
- {
- ulong *d;
- d = scr->mmio + RBaseD;
- waitformem(scr);
- waitforfifo(scr);
- d[CmdOpc] = 0x1; /* bitblt */
- d[CmdRop] = 0xC; /* copy source */
- d[CmdStyle] = 1; /* use source from Fore register */
- d[CmdPatrn] = 0; /* no stipple */
- d[Fore] = sval;
- d[Back] = sval;
- /* writing XY1 executes cmd */
- d[XY3] = 0;
- d[XY0] = (r.min.x<<16)|r.min.y;
- d[XY2] = (Dx(r)<<16)|Dy(r);
- d[XY4] = 0;
- d[XY1] = (r.min.x<<16)|r.min.y;
- waitforcmd(scr);
- return 1;
- }
- static void
- t2r4blank(VGAscr *scr, int blank)
- {
- uchar x;
- x = t2r4xi(scr, CursorSyncCtl);
- x &= ~0x0F;
- if(blank)
- x |= HsyncLo | VsyncLo;
- t2r4xo(scr, CursorSyncCtl, x);
- }
- static void
- t2r4drawinit(VGAscr *scr)
- {
- ulong pitch;
- int depth;
- int fmt;
- ulong *d;
- pitch = Dx(scr->gscreen->r);
- depth = scr->gscreen->depth;
- switch(scr->gscreen->chan){
- case RGB16:
- fmt = 3;
- break;
- case XRGB32:
- fmt = 2;
- break;
- case RGB15:
- fmt = 1;
- break;
- default:
- scr->fill = nil;
- scr->scroll = nil;
- return;
- }
- d = scr->mmio + RBaseD;
- d[BufCtl] = fmt<<24;
- d[DeSorg] = 0;
- d[DeDorg] = 0;
- d[DeSptch] = (pitch*depth)/8;
- d[DeDptch] = (pitch*depth)/8;
- d[CmdClp] = 0; /* 2 = inside rectangle */
- d[Mask] = ~0;
- d[DeKey] = 0;
- d[Clptl] = 0;
- d[Clpbr] = 0xFFF0FFF0;
- d[Alpha] = 0;
- d[ACtl] = 0;
- scr->fill = t2r4hwfill;
- scr->scroll = t2r4hwscroll;
- scr->blank = t2r4blank;
- hwblank = 1;
- }
- VGAdev vgat2r4dev = {
- "t2r4",
- t2r4enable,
- nil,
- nil,
- t2r4linear,
- t2r4drawinit,
- };
- VGAcur vgat2r4cur = {
- "t2r4hwgc",
- t2r4curenable,
- t2r4curdisable,
- t2r4curload,
- t2r4curmove,
- };
|