2 #include "../port/lib.h"
7 #include "../port/error.h"
15 typedef struct CursorNM CursorNM;
26 neomagicenable(VGAscr* scr)
34 * scr->mmio holds the virtual address of the cursor registers
35 * in the MMIO space. This may need to change for older chips
36 * which have the MMIO space offset in the framebuffer region.
38 * scr->io holds the offset into mmio of the CursorNM struct.
43 if(p == nil || p->vid != 0x10C8)
46 case 0x0003: /* MagicGraph 128ZV */
49 ioaddr = (p->mem[0].bar & ~0x0F) + 0x200000;
52 case 0x0083: /* MagicGraph 128ZV+ */
55 ioaddr = p->mem[1].bar & ~0x0F;
56 iosize = p->mem[1].size;
58 case 0x0004: /* MagicGraph 128XD */
61 ioaddr = p->mem[1].bar & ~0x0F;
62 iosize = p->mem[1].size;
64 case 0x0005: /* MagicMedia 256AV */
67 ioaddr = p->mem[1].bar & ~0x0F;
68 iosize = p->mem[1].size;
70 case 0x0006: /* MagicMedia 256ZX */
73 ioaddr = p->mem[1].bar & ~0x0F;
74 iosize = p->mem[1].size;
76 case 0x0016: /* MagicMedia 256XL+ */
78 /* Vaio VESA BIOS says 6080, but then hwgc doesn't work */
80 ioaddr = p->mem[1].bar & ~0x0F;
81 iosize = p->mem[1].size;
87 scr->mmio = vmap(ioaddr, iosize);
90 addvgaseg("neomagicmmio", ioaddr, iosize);
93 * Find a place for the cursor data in display memory.
94 * 2 cursor images might be needed, 1KB each so use the
95 * last 2KB of the framebuffer.
97 scr->storage = vmsize-2*1024;
101 addvgaseg("neomagicscreen", scr->paddr, scr->apsize);
105 neomagiccurdisable(VGAscr* scr)
111 cursornm = (void*)((char*)scr->mmio + scr->io);
112 cursornm->enable = 0;
116 neomagicinitcursor(VGAscr* scr, int xo, int yo, int index)
122 p = (uchar*)scr->vaddr;
123 p += scr->storage + index*1024;
125 for(y = yo; y < 16; y++){
127 p1 = scr->set[2*y+1];
129 p0 = (p0<<xo)|(p1>>(8-xo));
135 for(x = 16; x < 64; x += 8)
138 p0 = scr->clr[2*y]|scr->set[2*y];
139 p1 = scr->clr[2*y+1]|scr->set[2*y+1];
141 p0 = (p0<<xo)|(p1>>(8-xo));
147 for(x = 16; x < 64; x += 8)
151 for(x = 0; x < 64; x += 8){
160 neomagiccurload(VGAscr* scr, Cursor* curs)
166 cursornm = (void*)((char*)scr->mmio + scr->io);
168 cursornm->enable = 0;
169 memmove(&scr->Cursor, curs, sizeof(Cursor));
170 neomagicinitcursor(scr, 0, 0, 0);
171 cursornm->enable = 1;
175 neomagiccurmove(VGAscr* scr, Point p)
178 int addr, index, x, xo, y, yo;
182 cursornm = (void*)((char*)scr->mmio + scr->io);
185 if((x = p.x+scr->offset.x) < 0){
191 if((y = p.y+scr->offset.y) < 0){
200 neomagicinitcursor(scr, xo, yo, index);
202 addr = ((scr->storage+(1024*index))>>10) & 0xFFF;
203 addr = ((addr & 0x00F)<<8)|((addr>>4) & 0xFF);
204 if(cursornm->addr != addr)
205 cursornm->addr = addr;
214 neomagiccurenable(VGAscr* scr)
221 cursornm = (void*)((char*)scr->mmio + scr->io);
222 cursornm->enable = 0;
227 cursornm->colour1 = (Pblack<<16)|(Pblack<<8)|Pblack;
228 cursornm->colour2 = (Pwhite<<16)|(Pwhite<<8)|Pwhite;
231 * Load, locate and enable the 64x64 cursor.
233 neomagiccurload(scr, &arrow);
234 neomagiccurmove(scr, ZP);
235 cursornm->enable = 1;
238 static int neomagicbltflags;
265 NEO_BS0_BLT_BUSY = 0x00000001,
266 NEO_BS0_FIFO_AVAIL = 0x00000002,
267 NEO_BS0_FIFO_PEND = 0x00000004,
269 NEO_BC0_DST_Y_DEC = 0x00000001,
270 NEO_BC0_X_DEC = 0x00000002,
271 NEO_BC0_SRC_TRANS = 0x00000004,
272 NEO_BC0_SRC_IS_FG = 0x00000008,
273 NEO_BC0_SRC_Y_DEC = 0x00000010,
274 NEO_BC0_FILL_PAT = 0x00000020,
275 NEO_BC0_SRC_MONO = 0x00000040,
276 NEO_BC0_SYS_TO_VID = 0x00000080,
278 NEO_BC1_DEPTH8 = 0x00000100,
279 NEO_BC1_DEPTH16 = 0x00000200,
280 NEO_BC1_DEPTH24 = 0x00000300,
281 NEO_BC1_X_320 = 0x00000400,
282 NEO_BC1_X_640 = 0x00000800,
283 NEO_BC1_X_800 = 0x00000c00,
284 NEO_BC1_X_1024 = 0x00001000,
285 NEO_BC1_X_1152 = 0x00001400,
286 NEO_BC1_X_1280 = 0x00001800,
287 NEO_BC1_X_1600 = 0x00001c00,
288 NEO_BC1_DST_TRANS = 0x00002000,
289 NEO_BC1_MSTR_BLT = 0x00004000,
290 NEO_BC1_FILTER_Z = 0x00008000,
292 NEO_BC2_WR_TR_DST = 0x00800000,
294 NEO_BC3_SRC_XY_ADDR = 0x01000000,
295 NEO_BC3_DST_XY_ADDR = 0x02000000,
296 NEO_BC3_CLIP_ON = 0x04000000,
297 NEO_BC3_FIFO_EN = 0x08000000,
298 NEO_BC3_BLT_ON_ADDR = 0x10000000,
299 NEO_BC3_SKIP_MAPPING = 0x80000000,
301 NEO_MODE1_DEPTH8 = 0x0100,
302 NEO_MODE1_DEPTH16 = 0x0200,
303 NEO_MODE1_DEPTH24 = 0x0300,
304 NEO_MODE1_X_320 = 0x0400,
305 NEO_MODE1_X_640 = 0x0800,
306 NEO_MODE1_X_800 = 0x0c00,
307 NEO_MODE1_X_1024 = 0x1000,
308 NEO_MODE1_X_1152 = 0x1400,
309 NEO_MODE1_X_1280 = 0x1800,
310 NEO_MODE1_X_1600 = 0x1c00,
311 NEO_MODE1_BLT_ON_ADDR = 0x2000,
314 /* Raster Operations */
316 GXclear = 0x000000, /* 0x0000 */
317 GXand = 0x080000, /* 0x1000 */
318 GXandReverse = 0x040000, /* 0x0100 */
319 GXcopy = 0x0c0000, /* 0x1100 */
320 GXandInvert = 0x020000, /* 0x0010 */
321 GXnoop = 0x0a0000, /* 0x1010 */
322 GXxor = 0x060000, /* 0x0110 */
323 GXor = 0x0e0000, /* 0x1110 */
324 GXnor = 0x010000, /* 0x0001 */
325 GXequiv = 0x090000, /* 0x1001 */
326 GXinvert = 0x050000, /* 0x0101 */
327 GXorReverse = 0x0d0000, /* 0x1101 */
328 GXcopyInvert = 0x030000, /* 0x0011 */
329 GXorInverted = 0x0b0000, /* 0x1011 */
330 GXnand = 0x070000, /* 0x0111 */
331 GXset = 0x0f0000, /* 0x1111 */
335 waitforidle(VGAscr *scr)
342 while((mmio[BltStat] & NEO_BS0_BLT_BUSY) && x++ < 1000000)
345 // iprint("idle stat %lud scrmmio %#.8lux scr %#p pc %#p\n", mmio[BltStat], scr->mmio, scr, getcallerpc(&scr));
349 waitforfifo(VGAscr *scr, int entries)
356 while(((mmio[BltStat]>>8) < entries) && x++ < 1000000)
359 // iprint("fifo stat %d scrmmio %#.8lux scr %#p pc %#p\n", mmio[BltStat]>>8, scr->mmio, scr, getcallerpc(&scr));
360 /* DirectFB says the above doesn't work. if so... */
361 /* waitforidle(scr); */
365 neomagichwfill(VGAscr *scr, Rectangle r, ulong sval)
372 mmio[FGColor] = sval;
374 mmio[BltCntl] = neomagicbltflags
377 | NEO_BC3_SKIP_MAPPING
379 mmio[DstStartOff] = scr->paddr
380 + r.min.y*scr->gscreen->width*BY2WD
381 + r.min.x*scr->gscreen->depth/BI2BY;
382 mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
388 neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
395 pitch = scr->gscreen->width*BY2WD;
396 pixel = scr->gscreen->depth/BI2BY;
399 if (r.min.y < sr.min.y || (r.min.y == sr.min.y && r.min.x < sr.min.x)) {
400 /* start from upper-left */
401 mmio[BltCntl] = neomagicbltflags
403 | NEO_BC3_SKIP_MAPPING
405 mmio[SrcStartOff] = scr->paddr
406 + sr.min.y*pitch + sr.min.x*pixel;
407 mmio[DstStartOff] = scr->paddr
408 + r.min.y*pitch + r.min.x*pixel;
410 /* start from lower-right */
411 mmio[BltCntl] = neomagicbltflags
416 | NEO_BC3_SKIP_MAPPING
418 mmio[SrcStartOff] = scr->paddr
419 + (sr.max.y-1)*pitch + (sr.max.x-1)*pixel;
420 mmio[DstStartOff] = scr->paddr
421 + (r.max.y-1)*pitch + (r.max.x-1)*pixel;
423 mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
429 neomagicdrawinit(VGAscr *scr)
436 pitch = scr->gscreen->width*BY2WD;
438 neomagicbltflags = bltmode = 0;
440 switch(scr->gscreen->depth) {
442 bltmode |= NEO_MODE1_DEPTH8;
443 neomagicbltflags |= NEO_BC1_DEPTH8;
446 bltmode |= NEO_MODE1_DEPTH16;
447 neomagicbltflags |= NEO_BC1_DEPTH16;
449 case 24: /* I can't get it to work, and XFree86 doesn't either. */
450 default: /* give up */
454 switch(Dx(scr->gscreen->r)) {
456 bltmode |= NEO_MODE1_X_320;
457 neomagicbltflags |= NEO_BC1_X_320;
460 bltmode |= NEO_MODE1_X_640;
461 neomagicbltflags |= NEO_BC1_X_640;
464 bltmode |= NEO_MODE1_X_800;
465 neomagicbltflags |= NEO_BC1_X_800;
468 bltmode |= NEO_MODE1_X_1024;
469 neomagicbltflags |= NEO_BC1_X_1024;
472 bltmode |= NEO_MODE1_X_1152;
473 neomagicbltflags |= NEO_BC1_X_1152;
476 bltmode |= NEO_MODE1_X_1280;
477 neomagicbltflags |= NEO_BC1_X_1280;
480 bltmode |= NEO_MODE1_X_1600;
481 neomagicbltflags |= NEO_BC1_X_1600;
484 /* don't worry about it */
489 mmio[BltStat] = bltmode << 16;
490 mmio[Pitch] = (pitch << 16) | (pitch & 0xffff);
492 scr->fill = neomagichwfill;
493 scr->scroll = neomagichwscroll;
496 VGAdev vganeomagicdev = {
506 VGAcur vganeomagiccur = {