123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509 |
- #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"
- typedef struct CursorNM CursorNM;
- struct CursorNM {
- int enable;
- int x;
- int y;
- int colour1;
- int colour2;
- int addr;
- };
- static void
- neomagicenable(VGAscr* scr)
- {
- Pcidev *p;
- int curoff, vmsize;
- ulong ioaddr;
- ulong iosize;
- /*
- * scr->mmio holds the virtual address of the cursor registers
- * in the MMIO space. This may need to change for older chips
- * which have the MMIO space offset in the framebuffer region.
- *
- * scr->io holds the offset into mmio of the CursorNM struct.
- */
- if(scr->mmio)
- return;
- if(p = pcimatch(nil, 0x10C8, 0)){
- switch(p->did){
- case 0x0003: /* MagicGraph 128ZV */
- curoff = 0x100;
- vmsize = 1152*1024;
- ioaddr = (p->mem[0].bar & ~0x0F) + 0x200000;
- iosize = 0x200000;
- break;
- case 0x0083: /* MagicGraph 128ZV+ */
- curoff = 0x100;
- vmsize = 1152*1024;
- ioaddr = p->mem[1].bar & ~0x0F;
- iosize = p->mem[1].size;
- break;
- case 0x0004: /* MagicGraph 128XD */
- curoff = 0x100;
- vmsize = 2048*1024;
- ioaddr = p->mem[1].bar & ~0x0F;
- iosize = p->mem[1].size;
- break;
- case 0x0005: /* MagicMedia 256AV */
- curoff = 0x1000;
- vmsize = 2560*1024;
- ioaddr = p->mem[1].bar & ~0x0F;
- iosize = p->mem[1].size;
- break;
- case 0x0006: /* MagicMedia 256ZX */
- curoff = 0x1000;
- vmsize = 4096*1024;
- ioaddr = p->mem[1].bar & ~0x0F;
- iosize = p->mem[1].size;
- break;
- default:
- return;
- }
- }
- else
- return;
- scr->pci = p;
- scr->mmio = vmap(ioaddr, iosize);
- if(scr->mmio == nil)
- return;
- addvgaseg("neomagicmmio", ioaddr, iosize);
- /*
- * Find a place for the cursor data in display memory.
- * 2 cursor images might be needed, 1KB each so use the
- * last 2KB of the framebuffer.
- */
- scr->storage = vmsize-2*1024;
- scr->io = curoff;
- vgalinearpci(scr);
- if(scr->paddr)
- addvgaseg("neomagicscreen", scr->paddr, scr->apsize);
- }
- static void
- neomagiccurdisable(VGAscr* scr)
- {
- CursorNM *cursornm;
- if(scr->mmio == 0)
- return;
- cursornm = (void*)((char*)scr->mmio + scr->io);
- cursornm->enable = 0;
- }
- static void
- neomagicinitcursor(VGAscr* scr, int xo, int yo, int index)
- {
- uchar *p;
- uint p0, p1;
- int x, y;
- p = (uchar*)scr->vaddr;
- p += scr->storage + index*1024;
- for(y = yo; y < 16; y++){
- p0 = scr->set[2*y];
- p1 = scr->set[2*y+1];
- if(xo){
- p0 = (p0<<xo)|(p1>>(8-xo));
- p1 <<= xo;
- }
- *p++ = p0;
- *p++ = p1;
- for(x = 16; x < 64; x += 8)
- *p++ = 0x00;
- p0 = scr->clr[2*y]|scr->set[2*y];
- p1 = scr->clr[2*y+1]|scr->set[2*y+1];
- if(xo){
- p0 = (p0<<xo)|(p1>>(8-xo));
- p1 <<= xo;
- }
- *p++ = p0;
- *p++ = p1;
- for(x = 16; x < 64; x += 8)
- *p++ = 0x00;
- }
- while(y < 64+yo){
- for(x = 0; x < 64; x += 8){
- *p++ = 0x00;
- *p++ = 0x00;
- }
- y++;
- }
- }
- static void
- neomagiccurload(VGAscr* scr, Cursor* curs)
- {
- CursorNM *cursornm;
- if(scr->mmio == 0)
- return;
- cursornm = (void*)((char*)scr->mmio + scr->io);
- cursornm->enable = 0;
- memmove(&scr->Cursor, curs, sizeof(Cursor));
- neomagicinitcursor(scr, 0, 0, 0);
- cursornm->enable = 1;
- }
- static int
- neomagiccurmove(VGAscr* scr, Point p)
- {
- CursorNM *cursornm;
- int addr, index, x, xo, y, yo;
- if(scr->mmio == 0)
- return 1;
- cursornm = (void*)((char*)scr->mmio + scr->io);
- index = 0;
- 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;
- if(xo || yo){
- index = 1;
- neomagicinitcursor(scr, xo, yo, index);
- }
- addr = ((scr->storage+(1024*index))>>10) & 0xFFF;
- addr = ((addr & 0x00F)<<8)|((addr>>4) & 0xFF);
- if(cursornm->addr != addr)
- cursornm->addr = addr;
- cursornm->x = x;
- cursornm->y = y;
- return 0;
- }
- static void
- neomagiccurenable(VGAscr* scr)
- {
- CursorNM *cursornm;
- neomagicenable(scr);
- if(scr->mmio == 0)
- return;
- cursornm = (void*)((char*)scr->mmio + scr->io);
- cursornm->enable = 0;
- /*
- * Cursor colours.
- */
- cursornm->colour1 = (Pblack<<16)|(Pblack<<8)|Pblack;
- cursornm->colour2 = (Pwhite<<16)|(Pwhite<<8)|Pwhite;
- /*
- * Load, locate and enable the 64x64 cursor.
- */
- neomagiccurload(scr, &arrow);
- neomagiccurmove(scr, ZP);
- cursornm->enable = 1;
- }
- static int neomagicbltflags;
- /* registers */
- enum {
- BltStat = 0,
- BltCntl = 1,
- XPColor = 2,
- FGColor = 3,
- BGColor = 4,
- Pitch = 5,
- ClipLT = 6,
- ClipRB = 7,
- SrcBitOff = 8,
- SrcStartOff = 9,
- DstStartOff = 11,
- XYExt = 12,
- PageCntl = 20,
- PageBase,
- PostBase,
- PostPtr,
- DataPtr,
- };
- /* flags */
- enum {
- NEO_BS0_BLT_BUSY = 0x00000001,
- NEO_BS0_FIFO_AVAIL = 0x00000002,
- NEO_BS0_FIFO_PEND = 0x00000004,
- NEO_BC0_DST_Y_DEC = 0x00000001,
- NEO_BC0_X_DEC = 0x00000002,
- NEO_BC0_SRC_TRANS = 0x00000004,
- NEO_BC0_SRC_IS_FG = 0x00000008,
- NEO_BC0_SRC_Y_DEC = 0x00000010,
- NEO_BC0_FILL_PAT = 0x00000020,
- NEO_BC0_SRC_MONO = 0x00000040,
- NEO_BC0_SYS_TO_VID = 0x00000080,
- NEO_BC1_DEPTH8 = 0x00000100,
- NEO_BC1_DEPTH16 = 0x00000200,
- NEO_BC1_DEPTH24 = 0x00000300,
- NEO_BC1_X_320 = 0x00000400,
- NEO_BC1_X_640 = 0x00000800,
- NEO_BC1_X_800 = 0x00000c00,
- NEO_BC1_X_1024 = 0x00001000,
- NEO_BC1_X_1152 = 0x00001400,
- NEO_BC1_X_1280 = 0x00001800,
- NEO_BC1_X_1600 = 0x00001c00,
- NEO_BC1_DST_TRANS = 0x00002000,
- NEO_BC1_MSTR_BLT = 0x00004000,
- NEO_BC1_FILTER_Z = 0x00008000,
- NEO_BC2_WR_TR_DST = 0x00800000,
- NEO_BC3_SRC_XY_ADDR = 0x01000000,
- NEO_BC3_DST_XY_ADDR = 0x02000000,
- NEO_BC3_CLIP_ON = 0x04000000,
- NEO_BC3_FIFO_EN = 0x08000000,
- NEO_BC3_BLT_ON_ADDR = 0x10000000,
- NEO_BC3_SKIP_MAPPING = 0x80000000,
- NEO_MODE1_DEPTH8 = 0x0100,
- NEO_MODE1_DEPTH16 = 0x0200,
- NEO_MODE1_DEPTH24 = 0x0300,
- NEO_MODE1_X_320 = 0x0400,
- NEO_MODE1_X_640 = 0x0800,
- NEO_MODE1_X_800 = 0x0c00,
- NEO_MODE1_X_1024 = 0x1000,
- NEO_MODE1_X_1152 = 0x1400,
- NEO_MODE1_X_1280 = 0x1800,
- NEO_MODE1_X_1600 = 0x1c00,
- NEO_MODE1_BLT_ON_ADDR = 0x2000,
- };
- /* Raster Operations */
- enum {
- GXclear = 0x000000, /* 0x0000 */
- GXand = 0x080000, /* 0x1000 */
- GXandReverse = 0x040000, /* 0x0100 */
- GXcopy = 0x0c0000, /* 0x1100 */
- GXandInvert = 0x020000, /* 0x0010 */
- GXnoop = 0x0a0000, /* 0x1010 */
- GXxor = 0x060000, /* 0x0110 */
- GXor = 0x0e0000, /* 0x1110 */
- GXnor = 0x010000, /* 0x0001 */
- GXequiv = 0x090000, /* 0x1001 */
- GXinvert = 0x050000, /* 0x0101 */
- GXorReverse = 0x0d0000, /* 0x1101 */
- GXcopyInvert = 0x030000, /* 0x0011 */
- GXorInverted = 0x0b0000, /* 0x1011 */
- GXnand = 0x070000, /* 0x0111 */
- GXset = 0x0f0000, /* 0x1111 */
- };
- static void
- waitforidle(VGAscr *scr)
- {
- ulong *mmio;
- long x;
- mmio = scr->mmio;
- x = 0;
- while((mmio[BltStat] & NEO_BS0_BLT_BUSY) && x++ < 1000000)
- ;
- //if(x >= 1000000)
- // iprint("idle stat %lud scrmmio %.8lux scr %p pc %luX\n", mmio[BltStat], scr->mmio, scr, getcallerpc(&scr));
- }
- static void
- waitforfifo(VGAscr *scr, int entries)
- {
- ulong *mmio;
- long x;
- mmio = scr->mmio;
- x = 0;
- while(((mmio[BltStat]>>8) < entries) && x++ < 1000000)
- ;
- //if(x >= 1000000)
- // iprint("fifo stat %d scrmmio %.8lux scr %p pc %luX\n", mmio[BltStat]>>8, scr->mmio, scr, getcallerpc(&scr));
- /* DirectFB says the above doesn't work. if so... */
- /* waitforidle(scr); */
- }
- static int
- neomagichwfill(VGAscr *scr, Rectangle r, ulong sval)
- {
- ulong *mmio;
- mmio = scr->mmio;
- waitforfifo(scr, 1);
- mmio[FGColor] = sval;
- waitforfifo(scr, 3);
- mmio[BltCntl] = neomagicbltflags
- | NEO_BC3_FIFO_EN
- | NEO_BC0_SRC_IS_FG
- | NEO_BC3_SKIP_MAPPING
- | GXcopy;
- mmio[DstStartOff] = scr->paddr
- + r.min.y*scr->gscreen->width*BY2WD
- + r.min.x*scr->gscreen->depth/BI2BY;
- mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
- waitforidle(scr);
- return 1;
- }
- static int
- neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
- {
- ulong *mmio;
- int pitch, pixel;
- mmio = scr->mmio;
- pitch = scr->gscreen->width*BY2WD;
- pixel = scr->gscreen->depth/BI2BY;
- waitforfifo(scr, 4);
- if (r.min.y < sr.min.y || (r.min.y == sr.min.y && r.min.x < sr.min.x)) {
- /* start from upper-left */
- mmio[BltCntl] = neomagicbltflags
- | NEO_BC3_FIFO_EN
- | NEO_BC3_SKIP_MAPPING
- | GXcopy;
- mmio[SrcStartOff] = scr->paddr
- + sr.min.y*pitch + sr.min.x*pixel;
- mmio[DstStartOff] = scr->paddr
- + r.min.y*pitch + r.min.x*pixel;
- } else {
- /* start from lower-right */
- mmio[BltCntl] = neomagicbltflags
- | NEO_BC0_X_DEC
- | NEO_BC0_DST_Y_DEC
- | NEO_BC0_SRC_Y_DEC
- | NEO_BC3_FIFO_EN
- | NEO_BC3_SKIP_MAPPING
- | GXcopy;
- mmio[SrcStartOff] = scr->paddr
- + (sr.max.y-1)*pitch + (sr.max.x-1)*pixel;
- mmio[DstStartOff] = scr->paddr
- + (r.max.y-1)*pitch + (r.max.x-1)*pixel;
- }
- mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
- waitforidle(scr);
- return 1;
- }
- static void
- neomagicdrawinit(VGAscr *scr)
- {
- ulong *mmio;
- uint bltmode, pitch;
- mmio = scr->mmio;
- pitch = scr->gscreen->width*BY2WD;
- neomagicbltflags = bltmode = 0;
- switch(scr->gscreen->depth) {
- case 8:
- bltmode |= NEO_MODE1_DEPTH8;
- neomagicbltflags |= NEO_BC1_DEPTH8;
- break;
- case 16:
- bltmode |= NEO_MODE1_DEPTH16;
- neomagicbltflags |= NEO_BC1_DEPTH16;
- break;
- case 24: /* I can't get it to work, and XFree86 doesn't either. */
- default: /* give up */
- return;
- }
- switch(Dx(scr->gscreen->r)) {
- case 320:
- bltmode |= NEO_MODE1_X_320;
- neomagicbltflags |= NEO_BC1_X_320;
- break;
- case 640:
- bltmode |= NEO_MODE1_X_640;
- neomagicbltflags |= NEO_BC1_X_640;
- break;
- case 800:
- bltmode |= NEO_MODE1_X_800;
- neomagicbltflags |= NEO_BC1_X_800;
- break;
- case 1024:
- bltmode |= NEO_MODE1_X_1024;
- neomagicbltflags |= NEO_BC1_X_1024;
- break;
- case 1152:
- bltmode |= NEO_MODE1_X_1152;
- neomagicbltflags |= NEO_BC1_X_1152;
- break;
- case 1280:
- bltmode |= NEO_MODE1_X_1280;
- neomagicbltflags |= NEO_BC1_X_1280;
- break;
- case 1600:
- bltmode |= NEO_MODE1_X_1600;
- neomagicbltflags |= NEO_BC1_X_1600;
- break;
- default:
- /* don't worry about it */
- break;
- }
- waitforidle(scr);
- mmio[BltStat] = bltmode << 16;
- mmio[Pitch] = (pitch << 16) | (pitch & 0xffff);
- scr->fill = neomagichwfill;
- scr->scroll = neomagichwscroll;
- }
- VGAdev vganeomagicdev = {
- "neomagic",
- neomagicenable,
- nil,
- nil,
- nil,
- neomagicdrawinit,
- };
- VGAcur vganeomagiccur = {
- "neomagichwgc",
- neomagiccurenable,
- neomagiccurdisable,
- neomagiccurload,
- neomagiccurmove,
- };
|