17dd7cddfSDavid du Colombier #include "u.h"
27dd7cddfSDavid du Colombier #include "../port/lib.h"
37dd7cddfSDavid du Colombier #include "mem.h"
47dd7cddfSDavid du Colombier #include "dat.h"
57dd7cddfSDavid du Colombier #include "fns.h"
67dd7cddfSDavid du Colombier #include "io.h"
77dd7cddfSDavid du Colombier #include "../port/error.h"
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier #define Image IMAGE
107dd7cddfSDavid du Colombier #include <draw.h>
117dd7cddfSDavid du Colombier #include <memdraw.h>
127dd7cddfSDavid du Colombier #include <cursor.h>
137dd7cddfSDavid du Colombier #include "screen.h"
147dd7cddfSDavid du Colombier
1559c21d95SDavid du Colombier typedef struct CursorNM CursorNM;
1659c21d95SDavid du Colombier struct CursorNM {
177dd7cddfSDavid du Colombier int enable;
187dd7cddfSDavid du Colombier int x;
197dd7cddfSDavid du Colombier int y;
207dd7cddfSDavid du Colombier int colour1;
217dd7cddfSDavid du Colombier int colour2;
227dd7cddfSDavid du Colombier int addr;
2359c21d95SDavid du Colombier };
247dd7cddfSDavid du Colombier
257dd7cddfSDavid du Colombier static void
neomagicenable(VGAscr * scr)267dd7cddfSDavid du Colombier neomagicenable(VGAscr* scr)
277dd7cddfSDavid du Colombier {
287dd7cddfSDavid du Colombier Pcidev *p;
294de34a7eSDavid du Colombier int curoff, vmsize;
30375daca8SDavid du Colombier ulong ioaddr;
31375daca8SDavid du Colombier ulong iosize;
327dd7cddfSDavid du Colombier
337dd7cddfSDavid du Colombier /*
344de34a7eSDavid du Colombier * scr->mmio holds the virtual address of the cursor registers
357dd7cddfSDavid du Colombier * in the MMIO space. This may need to change for older chips
367dd7cddfSDavid du Colombier * which have the MMIO space offset in the framebuffer region.
37e862f8a5SDavid du Colombier *
38e862f8a5SDavid du Colombier * scr->io holds the offset into mmio of the CursorNM struct.
397dd7cddfSDavid du Colombier */
404de34a7eSDavid du Colombier if(scr->mmio)
417dd7cddfSDavid du Colombier return;
427dd7cddfSDavid du Colombier if(p = pcimatch(nil, 0x10C8, 0)){
437dd7cddfSDavid du Colombier switch(p->did){
44afb30c3eSDavid du Colombier case 0x0003: /* MagicGraph 128ZV */
45375daca8SDavid du Colombier curoff = 0x100;
46375daca8SDavid du Colombier vmsize = 1152*1024;
47375daca8SDavid du Colombier ioaddr = (p->mem[0].bar & ~0x0F) + 0x200000;
48375daca8SDavid du Colombier iosize = 0x200000;
49375daca8SDavid du Colombier break;
50afb30c3eSDavid du Colombier case 0x0083: /* MagicGraph 128ZV+ */
51afb30c3eSDavid du Colombier curoff = 0x100;
52afb30c3eSDavid du Colombier vmsize = 1152*1024;
53afb30c3eSDavid du Colombier ioaddr = p->mem[1].bar & ~0x0F;
54afb30c3eSDavid du Colombier iosize = p->mem[1].size;
55afb30c3eSDavid du Colombier break;
567dd7cddfSDavid du Colombier case 0x0004: /* MagicGraph 128XD */
577dd7cddfSDavid du Colombier curoff = 0x100;
587dd7cddfSDavid du Colombier vmsize = 2048*1024;
59375daca8SDavid du Colombier ioaddr = p->mem[1].bar & ~0x0F;
60375daca8SDavid du Colombier iosize = p->mem[1].size;
617dd7cddfSDavid du Colombier break;
627dd7cddfSDavid du Colombier case 0x0005: /* MagicMedia 256AV */
637dd7cddfSDavid du Colombier curoff = 0x1000;
647dd7cddfSDavid du Colombier vmsize = 2560*1024;
65375daca8SDavid du Colombier ioaddr = p->mem[1].bar & ~0x0F;
66375daca8SDavid du Colombier iosize = p->mem[1].size;
677dd7cddfSDavid du Colombier break;
6814414594SDavid du Colombier case 0x0006: /* MagicMedia 256ZX */
6914414594SDavid du Colombier curoff = 0x1000;
7014414594SDavid du Colombier vmsize = 4096*1024;
71375daca8SDavid du Colombier ioaddr = p->mem[1].bar & ~0x0F;
72375daca8SDavid du Colombier iosize = p->mem[1].size;
7314414594SDavid du Colombier break;
74*5b7f163eSDavid du Colombier case 0x0016: /* MagicMedia 256XL+ */
75*5b7f163eSDavid du Colombier curoff = 0x1000;
76*5b7f163eSDavid du Colombier /* Vaio VESA BIOS says 6080, but then hwgc doesn't work */
77*5b7f163eSDavid du Colombier vmsize = 4096*1024;
78*5b7f163eSDavid du Colombier ioaddr = p->mem[1].bar & ~0x0F;
79*5b7f163eSDavid du Colombier iosize = p->mem[1].size;
80*5b7f163eSDavid du Colombier break;
817dd7cddfSDavid du Colombier default:
827dd7cddfSDavid du Colombier return;
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier }
857dd7cddfSDavid du Colombier else
867dd7cddfSDavid du Colombier return;
874de34a7eSDavid du Colombier scr->pci = p;
884de34a7eSDavid du Colombier
894de34a7eSDavid du Colombier scr->mmio = vmap(ioaddr, iosize);
904de34a7eSDavid du Colombier if(scr->mmio == nil)
917dd7cddfSDavid du Colombier return;
924de34a7eSDavid du Colombier addvgaseg("neomagicmmio", ioaddr, iosize);
937dd7cddfSDavid du Colombier
947dd7cddfSDavid du Colombier /*
957dd7cddfSDavid du Colombier * Find a place for the cursor data in display memory.
967dd7cddfSDavid du Colombier * 2 cursor images might be needed, 1KB each so use the
977dd7cddfSDavid du Colombier * last 2KB of the framebuffer.
987dd7cddfSDavid du Colombier */
997dd7cddfSDavid du Colombier scr->storage = vmsize-2*1024;
100e862f8a5SDavid du Colombier scr->io = curoff;
1014de34a7eSDavid du Colombier vgalinearpci(scr);
1024de34a7eSDavid du Colombier if(scr->paddr)
1034de34a7eSDavid du Colombier addvgaseg("neomagicscreen", scr->paddr, scr->apsize);
1047dd7cddfSDavid du Colombier }
1057dd7cddfSDavid du Colombier
1067dd7cddfSDavid du Colombier static void
neomagiccurdisable(VGAscr * scr)1077dd7cddfSDavid du Colombier neomagiccurdisable(VGAscr* scr)
1087dd7cddfSDavid du Colombier {
1097dd7cddfSDavid du Colombier CursorNM *cursornm;
1107dd7cddfSDavid du Colombier
1114de34a7eSDavid du Colombier if(scr->mmio == 0)
1127dd7cddfSDavid du Colombier return;
113e862f8a5SDavid du Colombier cursornm = (void*)((char*)scr->mmio + scr->io);
1147dd7cddfSDavid du Colombier cursornm->enable = 0;
1157dd7cddfSDavid du Colombier }
1167dd7cddfSDavid du Colombier
1177dd7cddfSDavid du Colombier static void
neomagicinitcursor(VGAscr * scr,int xo,int yo,int index)1187dd7cddfSDavid du Colombier neomagicinitcursor(VGAscr* scr, int xo, int yo, int index)
1197dd7cddfSDavid du Colombier {
1207dd7cddfSDavid du Colombier uchar *p;
1217dd7cddfSDavid du Colombier uint p0, p1;
1227dd7cddfSDavid du Colombier int x, y;
1237dd7cddfSDavid du Colombier
124e862f8a5SDavid du Colombier p = (uchar*)scr->vaddr;
1257dd7cddfSDavid du Colombier p += scr->storage + index*1024;
1267dd7cddfSDavid du Colombier
1277dd7cddfSDavid du Colombier for(y = yo; y < 16; y++){
1287dd7cddfSDavid du Colombier p0 = scr->set[2*y];
1297dd7cddfSDavid du Colombier p1 = scr->set[2*y+1];
1307dd7cddfSDavid du Colombier if(xo){
1317dd7cddfSDavid du Colombier p0 = (p0<<xo)|(p1>>(8-xo));
1327dd7cddfSDavid du Colombier p1 <<= xo;
1337dd7cddfSDavid du Colombier }
1347dd7cddfSDavid du Colombier *p++ = p0;
1357dd7cddfSDavid du Colombier *p++ = p1;
1367dd7cddfSDavid du Colombier
1377dd7cddfSDavid du Colombier for(x = 16; x < 64; x += 8)
1387dd7cddfSDavid du Colombier *p++ = 0x00;
1397dd7cddfSDavid du Colombier
1407dd7cddfSDavid du Colombier p0 = scr->clr[2*y]|scr->set[2*y];
1417dd7cddfSDavid du Colombier p1 = scr->clr[2*y+1]|scr->set[2*y+1];
1427dd7cddfSDavid du Colombier if(xo){
1437dd7cddfSDavid du Colombier p0 = (p0<<xo)|(p1>>(8-xo));
1447dd7cddfSDavid du Colombier p1 <<= xo;
1457dd7cddfSDavid du Colombier }
1467dd7cddfSDavid du Colombier *p++ = p0;
1477dd7cddfSDavid du Colombier *p++ = p1;
1487dd7cddfSDavid du Colombier
1497dd7cddfSDavid du Colombier for(x = 16; x < 64; x += 8)
1507dd7cddfSDavid du Colombier *p++ = 0x00;
1517dd7cddfSDavid du Colombier }
1527dd7cddfSDavid du Colombier while(y < 64+yo){
1537dd7cddfSDavid du Colombier for(x = 0; x < 64; x += 8){
1547dd7cddfSDavid du Colombier *p++ = 0x00;
1557dd7cddfSDavid du Colombier *p++ = 0x00;
1567dd7cddfSDavid du Colombier }
1577dd7cddfSDavid du Colombier y++;
1587dd7cddfSDavid du Colombier }
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier
1617dd7cddfSDavid du Colombier static void
neomagiccurload(VGAscr * scr,Cursor * curs)1627dd7cddfSDavid du Colombier neomagiccurload(VGAscr* scr, Cursor* curs)
1637dd7cddfSDavid du Colombier {
1647dd7cddfSDavid du Colombier CursorNM *cursornm;
1657dd7cddfSDavid du Colombier
1664de34a7eSDavid du Colombier if(scr->mmio == 0)
1677dd7cddfSDavid du Colombier return;
168e862f8a5SDavid du Colombier cursornm = (void*)((char*)scr->mmio + scr->io);
1697dd7cddfSDavid du Colombier
1707dd7cddfSDavid du Colombier cursornm->enable = 0;
1717dd7cddfSDavid du Colombier memmove(&scr->Cursor, curs, sizeof(Cursor));
1727dd7cddfSDavid du Colombier neomagicinitcursor(scr, 0, 0, 0);
1737dd7cddfSDavid du Colombier cursornm->enable = 1;
1747dd7cddfSDavid du Colombier }
1757dd7cddfSDavid du Colombier
1767dd7cddfSDavid du Colombier static int
neomagiccurmove(VGAscr * scr,Point p)1777dd7cddfSDavid du Colombier neomagiccurmove(VGAscr* scr, Point p)
1787dd7cddfSDavid du Colombier {
1797dd7cddfSDavid du Colombier CursorNM *cursornm;
1807dd7cddfSDavid du Colombier int addr, index, x, xo, y, yo;
1817dd7cddfSDavid du Colombier
1824de34a7eSDavid du Colombier if(scr->mmio == 0)
1837dd7cddfSDavid du Colombier return 1;
184e862f8a5SDavid du Colombier cursornm = (void*)((char*)scr->mmio + scr->io);
1857dd7cddfSDavid du Colombier
1867dd7cddfSDavid du Colombier index = 0;
1877dd7cddfSDavid du Colombier if((x = p.x+scr->offset.x) < 0){
1887dd7cddfSDavid du Colombier xo = -x;
1897dd7cddfSDavid du Colombier x = 0;
1907dd7cddfSDavid du Colombier }
1917dd7cddfSDavid du Colombier else
1927dd7cddfSDavid du Colombier xo = 0;
1937dd7cddfSDavid du Colombier if((y = p.y+scr->offset.y) < 0){
1947dd7cddfSDavid du Colombier yo = -y;
1957dd7cddfSDavid du Colombier y = 0;
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier else
1987dd7cddfSDavid du Colombier yo = 0;
1997dd7cddfSDavid du Colombier
2007dd7cddfSDavid du Colombier if(xo || yo){
2017dd7cddfSDavid du Colombier index = 1;
2027dd7cddfSDavid du Colombier neomagicinitcursor(scr, xo, yo, index);
2037dd7cddfSDavid du Colombier }
2047dd7cddfSDavid du Colombier addr = ((scr->storage+(1024*index))>>10) & 0xFFF;
2057dd7cddfSDavid du Colombier addr = ((addr & 0x00F)<<8)|((addr>>4) & 0xFF);
2067dd7cddfSDavid du Colombier if(cursornm->addr != addr)
2077dd7cddfSDavid du Colombier cursornm->addr = addr;
2087dd7cddfSDavid du Colombier
2097dd7cddfSDavid du Colombier cursornm->x = x;
2107dd7cddfSDavid du Colombier cursornm->y = y;
2117dd7cddfSDavid du Colombier
2127dd7cddfSDavid du Colombier return 0;
2137dd7cddfSDavid du Colombier }
2147dd7cddfSDavid du Colombier
2157dd7cddfSDavid du Colombier static void
neomagiccurenable(VGAscr * scr)2167dd7cddfSDavid du Colombier neomagiccurenable(VGAscr* scr)
2177dd7cddfSDavid du Colombier {
2187dd7cddfSDavid du Colombier CursorNM *cursornm;
2197dd7cddfSDavid du Colombier
2207dd7cddfSDavid du Colombier neomagicenable(scr);
2214de34a7eSDavid du Colombier if(scr->mmio == 0)
2227dd7cddfSDavid du Colombier return;
223e862f8a5SDavid du Colombier cursornm = (void*)((char*)scr->mmio + scr->io);
2247dd7cddfSDavid du Colombier cursornm->enable = 0;
2257dd7cddfSDavid du Colombier
2267dd7cddfSDavid du Colombier /*
2277dd7cddfSDavid du Colombier * Cursor colours.
2287dd7cddfSDavid du Colombier */
2297dd7cddfSDavid du Colombier cursornm->colour1 = (Pblack<<16)|(Pblack<<8)|Pblack;
2307dd7cddfSDavid du Colombier cursornm->colour2 = (Pwhite<<16)|(Pwhite<<8)|Pwhite;
2317dd7cddfSDavid du Colombier
2327dd7cddfSDavid du Colombier /*
2337dd7cddfSDavid du Colombier * Load, locate and enable the 64x64 cursor.
2347dd7cddfSDavid du Colombier */
2357dd7cddfSDavid du Colombier neomagiccurload(scr, &arrow);
2367dd7cddfSDavid du Colombier neomagiccurmove(scr, ZP);
2377dd7cddfSDavid du Colombier cursornm->enable = 1;
2387dd7cddfSDavid du Colombier }
2397dd7cddfSDavid du Colombier
2403ff48bf5SDavid du Colombier static int neomagicbltflags;
2413ff48bf5SDavid du Colombier
2423ff48bf5SDavid du Colombier /* registers */
2433ff48bf5SDavid du Colombier enum {
2443ff48bf5SDavid du Colombier BltStat = 0,
2453ff48bf5SDavid du Colombier BltCntl = 1,
2463ff48bf5SDavid du Colombier XPColor = 2,
2473ff48bf5SDavid du Colombier FGColor = 3,
2483ff48bf5SDavid du Colombier BGColor = 4,
2493ff48bf5SDavid du Colombier Pitch = 5,
2503ff48bf5SDavid du Colombier ClipLT = 6,
2513ff48bf5SDavid du Colombier ClipRB = 7,
2523ff48bf5SDavid du Colombier SrcBitOff = 8,
2533ff48bf5SDavid du Colombier SrcStartOff = 9,
2543ff48bf5SDavid du Colombier
2553ff48bf5SDavid du Colombier DstStartOff = 11,
2563ff48bf5SDavid du Colombier XYExt = 12,
2573ff48bf5SDavid du Colombier
2583ff48bf5SDavid du Colombier PageCntl = 20,
2593ff48bf5SDavid du Colombier PageBase,
2603ff48bf5SDavid du Colombier PostBase,
2613ff48bf5SDavid du Colombier PostPtr,
2623ff48bf5SDavid du Colombier DataPtr,
2633ff48bf5SDavid du Colombier };
2643ff48bf5SDavid du Colombier
2653ff48bf5SDavid du Colombier /* flags */
2663ff48bf5SDavid du Colombier enum {
2673ff48bf5SDavid du Colombier NEO_BS0_BLT_BUSY = 0x00000001,
2683ff48bf5SDavid du Colombier NEO_BS0_FIFO_AVAIL = 0x00000002,
2693ff48bf5SDavid du Colombier NEO_BS0_FIFO_PEND = 0x00000004,
2703ff48bf5SDavid du Colombier
2713ff48bf5SDavid du Colombier NEO_BC0_DST_Y_DEC = 0x00000001,
2723ff48bf5SDavid du Colombier NEO_BC0_X_DEC = 0x00000002,
2733ff48bf5SDavid du Colombier NEO_BC0_SRC_TRANS = 0x00000004,
2743ff48bf5SDavid du Colombier NEO_BC0_SRC_IS_FG = 0x00000008,
2753ff48bf5SDavid du Colombier NEO_BC0_SRC_Y_DEC = 0x00000010,
2763ff48bf5SDavid du Colombier NEO_BC0_FILL_PAT = 0x00000020,
2773ff48bf5SDavid du Colombier NEO_BC0_SRC_MONO = 0x00000040,
2783ff48bf5SDavid du Colombier NEO_BC0_SYS_TO_VID = 0x00000080,
2793ff48bf5SDavid du Colombier
2803ff48bf5SDavid du Colombier NEO_BC1_DEPTH8 = 0x00000100,
2813ff48bf5SDavid du Colombier NEO_BC1_DEPTH16 = 0x00000200,
2823ff48bf5SDavid du Colombier NEO_BC1_DEPTH24 = 0x00000300,
2833ff48bf5SDavid du Colombier NEO_BC1_X_320 = 0x00000400,
2843ff48bf5SDavid du Colombier NEO_BC1_X_640 = 0x00000800,
2853ff48bf5SDavid du Colombier NEO_BC1_X_800 = 0x00000c00,
2863ff48bf5SDavid du Colombier NEO_BC1_X_1024 = 0x00001000,
2873ff48bf5SDavid du Colombier NEO_BC1_X_1152 = 0x00001400,
2883ff48bf5SDavid du Colombier NEO_BC1_X_1280 = 0x00001800,
2893ff48bf5SDavid du Colombier NEO_BC1_X_1600 = 0x00001c00,
2903ff48bf5SDavid du Colombier NEO_BC1_DST_TRANS = 0x00002000,
2913ff48bf5SDavid du Colombier NEO_BC1_MSTR_BLT = 0x00004000,
2923ff48bf5SDavid du Colombier NEO_BC1_FILTER_Z = 0x00008000,
2933ff48bf5SDavid du Colombier
2943ff48bf5SDavid du Colombier NEO_BC2_WR_TR_DST = 0x00800000,
2953ff48bf5SDavid du Colombier
2963ff48bf5SDavid du Colombier NEO_BC3_SRC_XY_ADDR = 0x01000000,
2973ff48bf5SDavid du Colombier NEO_BC3_DST_XY_ADDR = 0x02000000,
2983ff48bf5SDavid du Colombier NEO_BC3_CLIP_ON = 0x04000000,
2993ff48bf5SDavid du Colombier NEO_BC3_FIFO_EN = 0x08000000,
3003ff48bf5SDavid du Colombier NEO_BC3_BLT_ON_ADDR = 0x10000000,
3013ff48bf5SDavid du Colombier NEO_BC3_SKIP_MAPPING = 0x80000000,
3023ff48bf5SDavid du Colombier
3033ff48bf5SDavid du Colombier NEO_MODE1_DEPTH8 = 0x0100,
3043ff48bf5SDavid du Colombier NEO_MODE1_DEPTH16 = 0x0200,
3053ff48bf5SDavid du Colombier NEO_MODE1_DEPTH24 = 0x0300,
3063ff48bf5SDavid du Colombier NEO_MODE1_X_320 = 0x0400,
3073ff48bf5SDavid du Colombier NEO_MODE1_X_640 = 0x0800,
3083ff48bf5SDavid du Colombier NEO_MODE1_X_800 = 0x0c00,
3093ff48bf5SDavid du Colombier NEO_MODE1_X_1024 = 0x1000,
3103ff48bf5SDavid du Colombier NEO_MODE1_X_1152 = 0x1400,
3113ff48bf5SDavid du Colombier NEO_MODE1_X_1280 = 0x1800,
3123ff48bf5SDavid du Colombier NEO_MODE1_X_1600 = 0x1c00,
3133ff48bf5SDavid du Colombier NEO_MODE1_BLT_ON_ADDR = 0x2000,
3143ff48bf5SDavid du Colombier };
3153ff48bf5SDavid du Colombier
3163ff48bf5SDavid du Colombier /* Raster Operations */
3173ff48bf5SDavid du Colombier enum {
3183ff48bf5SDavid du Colombier GXclear = 0x000000, /* 0x0000 */
3193ff48bf5SDavid du Colombier GXand = 0x080000, /* 0x1000 */
3203ff48bf5SDavid du Colombier GXandReverse = 0x040000, /* 0x0100 */
3213ff48bf5SDavid du Colombier GXcopy = 0x0c0000, /* 0x1100 */
3223ff48bf5SDavid du Colombier GXandInvert = 0x020000, /* 0x0010 */
3233ff48bf5SDavid du Colombier GXnoop = 0x0a0000, /* 0x1010 */
3243ff48bf5SDavid du Colombier GXxor = 0x060000, /* 0x0110 */
3253ff48bf5SDavid du Colombier GXor = 0x0e0000, /* 0x1110 */
3263ff48bf5SDavid du Colombier GXnor = 0x010000, /* 0x0001 */
3273ff48bf5SDavid du Colombier GXequiv = 0x090000, /* 0x1001 */
3283ff48bf5SDavid du Colombier GXinvert = 0x050000, /* 0x0101 */
3293ff48bf5SDavid du Colombier GXorReverse = 0x0d0000, /* 0x1101 */
3303ff48bf5SDavid du Colombier GXcopyInvert = 0x030000, /* 0x0011 */
3313ff48bf5SDavid du Colombier GXorInverted = 0x0b0000, /* 0x1011 */
3323ff48bf5SDavid du Colombier GXnand = 0x070000, /* 0x0111 */
3333ff48bf5SDavid du Colombier GXset = 0x0f0000, /* 0x1111 */
3343ff48bf5SDavid du Colombier };
3353ff48bf5SDavid du Colombier
3363ff48bf5SDavid du Colombier static void
waitforidle(VGAscr * scr)3373ff48bf5SDavid du Colombier waitforidle(VGAscr *scr)
3383ff48bf5SDavid du Colombier {
3393ff48bf5SDavid du Colombier ulong *mmio;
3403ff48bf5SDavid du Colombier long x;
3413ff48bf5SDavid du Colombier
3423ff48bf5SDavid du Colombier mmio = scr->mmio;
3433ff48bf5SDavid du Colombier x = 0;
3443ff48bf5SDavid du Colombier while((mmio[BltStat] & NEO_BS0_BLT_BUSY) && x++ < 1000000)
3453ff48bf5SDavid du Colombier ;
3463ff48bf5SDavid du Colombier //if(x >= 1000000)
347567483c8SDavid du Colombier // iprint("idle stat %lud scrmmio %#.8lux scr %#p pc %#p\n", mmio[BltStat], scr->mmio, scr, getcallerpc(&scr));
3483ff48bf5SDavid du Colombier }
3493ff48bf5SDavid du Colombier
3503ff48bf5SDavid du Colombier static void
waitforfifo(VGAscr * scr,int entries)3513ff48bf5SDavid du Colombier waitforfifo(VGAscr *scr, int entries)
3523ff48bf5SDavid du Colombier {
3533ff48bf5SDavid du Colombier ulong *mmio;
3543ff48bf5SDavid du Colombier long x;
3553ff48bf5SDavid du Colombier
3563ff48bf5SDavid du Colombier mmio = scr->mmio;
3573ff48bf5SDavid du Colombier x = 0;
3583ff48bf5SDavid du Colombier while(((mmio[BltStat]>>8) < entries) && x++ < 1000000)
3593ff48bf5SDavid du Colombier ;
3603ff48bf5SDavid du Colombier //if(x >= 1000000)
361567483c8SDavid du Colombier // iprint("fifo stat %d scrmmio %#.8lux scr %#p pc %#p\n", mmio[BltStat]>>8, scr->mmio, scr, getcallerpc(&scr));
3623ff48bf5SDavid du Colombier /* DirectFB says the above doesn't work. if so... */
3633ff48bf5SDavid du Colombier /* waitforidle(scr); */
3643ff48bf5SDavid du Colombier }
3653ff48bf5SDavid du Colombier
3663ff48bf5SDavid du Colombier static int
neomagichwfill(VGAscr * scr,Rectangle r,ulong sval)3673ff48bf5SDavid du Colombier neomagichwfill(VGAscr *scr, Rectangle r, ulong sval)
3683ff48bf5SDavid du Colombier {
3693ff48bf5SDavid du Colombier ulong *mmio;
3703ff48bf5SDavid du Colombier
3713ff48bf5SDavid du Colombier mmio = scr->mmio;
3723ff48bf5SDavid du Colombier
3733ff48bf5SDavid du Colombier waitforfifo(scr, 1);
3743ff48bf5SDavid du Colombier mmio[FGColor] = sval;
3753ff48bf5SDavid du Colombier waitforfifo(scr, 3);
3763ff48bf5SDavid du Colombier mmio[BltCntl] = neomagicbltflags
3773ff48bf5SDavid du Colombier | NEO_BC3_FIFO_EN
3783ff48bf5SDavid du Colombier | NEO_BC0_SRC_IS_FG
3793ff48bf5SDavid du Colombier | NEO_BC3_SKIP_MAPPING
3803ff48bf5SDavid du Colombier | GXcopy;
3814de34a7eSDavid du Colombier mmio[DstStartOff] = scr->paddr
3823ff48bf5SDavid du Colombier + r.min.y*scr->gscreen->width*BY2WD
3833ff48bf5SDavid du Colombier + r.min.x*scr->gscreen->depth/BI2BY;
3843ff48bf5SDavid du Colombier mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
3853ff48bf5SDavid du Colombier waitforidle(scr);
3863ff48bf5SDavid du Colombier return 1;
3873ff48bf5SDavid du Colombier }
3883ff48bf5SDavid du Colombier
3893ff48bf5SDavid du Colombier static int
neomagichwscroll(VGAscr * scr,Rectangle r,Rectangle sr)3903ff48bf5SDavid du Colombier neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
3913ff48bf5SDavid du Colombier {
3923ff48bf5SDavid du Colombier ulong *mmio;
3933ff48bf5SDavid du Colombier int pitch, pixel;
3943ff48bf5SDavid du Colombier
3953ff48bf5SDavid du Colombier mmio = scr->mmio;
3963ff48bf5SDavid du Colombier
3973ff48bf5SDavid du Colombier pitch = scr->gscreen->width*BY2WD;
3983ff48bf5SDavid du Colombier pixel = scr->gscreen->depth/BI2BY;
3993ff48bf5SDavid du Colombier
4003ff48bf5SDavid du Colombier waitforfifo(scr, 4);
4013ff48bf5SDavid du Colombier if (r.min.y < sr.min.y || (r.min.y == sr.min.y && r.min.x < sr.min.x)) {
4023ff48bf5SDavid du Colombier /* start from upper-left */
4033ff48bf5SDavid du Colombier mmio[BltCntl] = neomagicbltflags
4043ff48bf5SDavid du Colombier | NEO_BC3_FIFO_EN
4053ff48bf5SDavid du Colombier | NEO_BC3_SKIP_MAPPING
4063ff48bf5SDavid du Colombier | GXcopy;
4074de34a7eSDavid du Colombier mmio[SrcStartOff] = scr->paddr
4083ff48bf5SDavid du Colombier + sr.min.y*pitch + sr.min.x*pixel;
4094de34a7eSDavid du Colombier mmio[DstStartOff] = scr->paddr
4103ff48bf5SDavid du Colombier + r.min.y*pitch + r.min.x*pixel;
4113ff48bf5SDavid du Colombier } else {
4123ff48bf5SDavid du Colombier /* start from lower-right */
4133ff48bf5SDavid du Colombier mmio[BltCntl] = neomagicbltflags
4143ff48bf5SDavid du Colombier | NEO_BC0_X_DEC
4153ff48bf5SDavid du Colombier | NEO_BC0_DST_Y_DEC
4163ff48bf5SDavid du Colombier | NEO_BC0_SRC_Y_DEC
4173ff48bf5SDavid du Colombier | NEO_BC3_FIFO_EN
4183ff48bf5SDavid du Colombier | NEO_BC3_SKIP_MAPPING
4193ff48bf5SDavid du Colombier | GXcopy;
4204de34a7eSDavid du Colombier mmio[SrcStartOff] = scr->paddr
4213ff48bf5SDavid du Colombier + (sr.max.y-1)*pitch + (sr.max.x-1)*pixel;
4224de34a7eSDavid du Colombier mmio[DstStartOff] = scr->paddr
4233ff48bf5SDavid du Colombier + (r.max.y-1)*pitch + (r.max.x-1)*pixel;
4243ff48bf5SDavid du Colombier }
4253ff48bf5SDavid du Colombier mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
4263ff48bf5SDavid du Colombier waitforidle(scr);
4273ff48bf5SDavid du Colombier return 1;
4283ff48bf5SDavid du Colombier }
4293ff48bf5SDavid du Colombier
4303ff48bf5SDavid du Colombier static void
neomagicdrawinit(VGAscr * scr)4313ff48bf5SDavid du Colombier neomagicdrawinit(VGAscr *scr)
4323ff48bf5SDavid du Colombier {
4333ff48bf5SDavid du Colombier ulong *mmio;
4343ff48bf5SDavid du Colombier uint bltmode, pitch;
4353ff48bf5SDavid du Colombier
4363ff48bf5SDavid du Colombier mmio = scr->mmio;
4373ff48bf5SDavid du Colombier
4383ff48bf5SDavid du Colombier pitch = scr->gscreen->width*BY2WD;
4393ff48bf5SDavid du Colombier
4403ff48bf5SDavid du Colombier neomagicbltflags = bltmode = 0;
4413ff48bf5SDavid du Colombier
4423ff48bf5SDavid du Colombier switch(scr->gscreen->depth) {
4433ff48bf5SDavid du Colombier case 8:
4443ff48bf5SDavid du Colombier bltmode |= NEO_MODE1_DEPTH8;
4453ff48bf5SDavid du Colombier neomagicbltflags |= NEO_BC1_DEPTH8;
4463ff48bf5SDavid du Colombier break;
4473ff48bf5SDavid du Colombier case 16:
4483ff48bf5SDavid du Colombier bltmode |= NEO_MODE1_DEPTH16;
4493ff48bf5SDavid du Colombier neomagicbltflags |= NEO_BC1_DEPTH16;
4503ff48bf5SDavid du Colombier break;
4513ff48bf5SDavid du Colombier case 24: /* I can't get it to work, and XFree86 doesn't either. */
4523ff48bf5SDavid du Colombier default: /* give up */
4533ff48bf5SDavid du Colombier return;
4543ff48bf5SDavid du Colombier }
4553ff48bf5SDavid du Colombier
4563ff48bf5SDavid du Colombier switch(Dx(scr->gscreen->r)) {
4573ff48bf5SDavid du Colombier case 320:
4583ff48bf5SDavid du Colombier bltmode |= NEO_MODE1_X_320;
4593ff48bf5SDavid du Colombier neomagicbltflags |= NEO_BC1_X_320;
4603ff48bf5SDavid du Colombier break;
4613ff48bf5SDavid du Colombier case 640:
4623ff48bf5SDavid du Colombier bltmode |= NEO_MODE1_X_640;
4633ff48bf5SDavid du Colombier neomagicbltflags |= NEO_BC1_X_640;
4643ff48bf5SDavid du Colombier break;
4653ff48bf5SDavid du Colombier case 800:
4663ff48bf5SDavid du Colombier bltmode |= NEO_MODE1_X_800;
4673ff48bf5SDavid du Colombier neomagicbltflags |= NEO_BC1_X_800;
4683ff48bf5SDavid du Colombier break;
4693ff48bf5SDavid du Colombier case 1024:
4703ff48bf5SDavid du Colombier bltmode |= NEO_MODE1_X_1024;
4713ff48bf5SDavid du Colombier neomagicbltflags |= NEO_BC1_X_1024;
4723ff48bf5SDavid du Colombier break;
4733ff48bf5SDavid du Colombier case 1152:
4743ff48bf5SDavid du Colombier bltmode |= NEO_MODE1_X_1152;
4753ff48bf5SDavid du Colombier neomagicbltflags |= NEO_BC1_X_1152;
4763ff48bf5SDavid du Colombier break;
4773ff48bf5SDavid du Colombier case 1280:
4783ff48bf5SDavid du Colombier bltmode |= NEO_MODE1_X_1280;
4793ff48bf5SDavid du Colombier neomagicbltflags |= NEO_BC1_X_1280;
4803ff48bf5SDavid du Colombier break;
4813ff48bf5SDavid du Colombier case 1600:
4823ff48bf5SDavid du Colombier bltmode |= NEO_MODE1_X_1600;
4833ff48bf5SDavid du Colombier neomagicbltflags |= NEO_BC1_X_1600;
4843ff48bf5SDavid du Colombier break;
4853ff48bf5SDavid du Colombier default:
4863ff48bf5SDavid du Colombier /* don't worry about it */
4873ff48bf5SDavid du Colombier break;
4883ff48bf5SDavid du Colombier }
4893ff48bf5SDavid du Colombier
4903ff48bf5SDavid du Colombier waitforidle(scr);
4913ff48bf5SDavid du Colombier mmio[BltStat] = bltmode << 16;
4923ff48bf5SDavid du Colombier mmio[Pitch] = (pitch << 16) | (pitch & 0xffff);
4933ff48bf5SDavid du Colombier
4943ff48bf5SDavid du Colombier scr->fill = neomagichwfill;
4953ff48bf5SDavid du Colombier scr->scroll = neomagichwscroll;
4963ff48bf5SDavid du Colombier }
4973ff48bf5SDavid du Colombier
4987dd7cddfSDavid du Colombier VGAdev vganeomagicdev = {
4997dd7cddfSDavid du Colombier "neomagic",
5007dd7cddfSDavid du Colombier
5017dd7cddfSDavid du Colombier neomagicenable,
5027dd7cddfSDavid du Colombier nil,
5037dd7cddfSDavid du Colombier nil,
5044de34a7eSDavid du Colombier nil,
5053ff48bf5SDavid du Colombier neomagicdrawinit,
5067dd7cddfSDavid du Colombier };
5077dd7cddfSDavid du Colombier
5087dd7cddfSDavid du Colombier VGAcur vganeomagiccur = {
5097dd7cddfSDavid du Colombier "neomagichwgc",
5107dd7cddfSDavid du Colombier
5117dd7cddfSDavid du Colombier neomagiccurenable,
5127dd7cddfSDavid du Colombier neomagiccurdisable,
5137dd7cddfSDavid du Colombier neomagiccurload,
5147dd7cddfSDavid du Colombier neomagiccurmove,
5157dd7cddfSDavid du Colombier };
5163ff48bf5SDavid du Colombier
517