## diffname pc/vganeomagic.c 2000/0209
## diff -e /dev/null /n/emeliedump/2000/0209/sys/src/9/pc/vganeomagic.c
0a
#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 {
int enable;
int x;
int y;
int colour1;
int colour2;
int addr;
} CursorNM;
enum {
CursorMMIO = 0x1000, /* MagicMedia 256AV */
};
static ulong
neomagiclinear(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, 0x10C8, 0)){
switch(p->did){
case 0x0005: /* MagicMedia 256AV */
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
neomagicenable(VGAscr* scr)
{
Pcidev *p;
Physseg seg;
int size, align, asize;
ulong aperture;
/*
* Only once, can't be disabled for now.
* scr->io holds the virtual address of
* the MMIO registers.
*/
if(scr->io)
return;
if(p = pcimatch(nil, 0x10C8, 0)){
switch(p->did){
case 0x0005: /* MagicMedia 256AV */
asize = 2560*1024;
break;
default:
return;
}
}
else
return;
scr->io = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0);
if(scr->io == 0)
return;
memset(&seg, 0, sizeof(seg));
seg.attr = SG_PHYSICAL;
seg.name = smalloc(NAMELEN);
snprint(seg.name, NAMELEN, "neomagicmmio");
seg.pa = scr->io;
seg.size = p->mem[1].size;
addphysseg(&seg);
scr->io = (ulong)KADDR(scr->io);
size = p->mem[0].size;
align = 0;
aperture = neomagiclinear(scr, &size, &align);
if(aperture) {
scr->aperture = aperture;
scr->apsize = asize;
memset(&seg, 0, sizeof(seg));
seg.attr = SG_PHYSICAL;
seg.name = smalloc(NAMELEN);
snprint(seg.name, NAMELEN, "neomagicscreen");
seg.pa = aperture;
seg.size = size;
addphysseg(&seg);
}
}
static void
neomagiccurdisable(VGAscr* scr)
{
CursorNM *cursornm;
if(scr->io == 0)
return;
cursornm = KADDR(scr->io+CursorMMIO);
cursornm->enable = 0;
}
static void
neomagicinitcursor(VGAscr* scr, int xo, int yo, int index)
{
int x, y;
uchar *p;
uint p0, p1;
p = KADDR(scr->aperture);
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->io == 0)
return;
cursornm = KADDR(scr->io+CursorMMIO);
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->io == 0)
return 1;
cursornm = KADDR(scr->io+CursorMMIO);
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->io == 0)
return;
cursornm = KADDR(scr->io+CursorMMIO);
cursornm->enable = 0;
/*
* Cursor colours.
*/
cursornm->colour1 = (Pblack<<16)|(Pblack<<8)|Pblack;
cursornm->colour2 = (Pwhite<<16)|(Pwhite<<8)|Pwhite;
/*
* 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 and initialise them to be
* transparent.
*/
scr->storage = /*scr->apsize*/2560*1024-2*1024;
/*
* Load, locate and enable the 64x64 cursor.
*/
neomagiccurload(scr, &arrow);
neomagiccurmove(scr, ZP);
cursornm->enable = 1;
}
VGAdev vganeomagicdev = {
"neomagic",
neomagicenable,
nil,
nil,
neomagiclinear,
};
VGAcur vganeomagiccur = {
"neomagichwgc",
neomagiccurenable,
neomagiccurdisable,
neomagiccurload,
neomagiccurmove,
};
.
## diffname pc/vganeomagic.c 2000/0211
## diff -e /n/emeliedump/2000/0209/sys/src/9/pc/vganeomagic.c /n/emeliedump/2000/0211/sys/src/9/pc/vganeomagic.c
260c
scr->storage = scr->apsize-2*1024;
.
245c
cursornm = KADDR(scr->io);
.
206c
cursornm = KADDR(scr->io);
.
190c
cursornm = KADDR(scr->io);
.
144a
int x, y;
.
142d
135c
cursornm = KADDR(scr->io);
.
117c
scr->apsize = vmsize;
.
110c
scr->io += curoff;
.
90c
curoff = 0x1000;
vmsize = 2560*1024;
.
88a
case 0x0004: /* MagicGraph 128XD */
curoff = 0x100;
vmsize = 2048*1024;
break;
.
82,83c
* scr->io holds the physical 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.
.
77c
int align, curoff, size, vmsize;
.
41a
case 0x0004: /* MagicGraph 128XD */
.
24,27d
## diffname pc/vganeomagic.c 2000/0212
## diff -e /n/emeliedump/2000/0211/sys/src/9/pc/vganeomagic.c /n/emeliedump/2000/0212/sys/src/9/pc/vganeomagic.c
256,263d
120c
scr->apsize = size;
.
112a
/*
* 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;
.
68a
.
## diffname pc/vganeomagic.c 2000/0608
## diff -e /n/emeliedump/2000/0212/sys/src/9/pc/vganeomagic.c /n/emeliedump/2000/0608/sys/src/9/pc/vganeomagic.c
94a
break;
case 0x0006: /* MagicMedia 256ZX */
curoff = 0x1000;
vmsize = 4096*1024;
.
39a
case 0x0006: /* MagicMedia 256ZX */
.
## diffname pc/vganeomagic.c 2001/0527
## diff -e /n/emeliedump/2000/0608/sys/src/9/pc/vganeomagic.c /n/emeliedump/2001/0527/sys/src/9/pc/vganeomagic.c
135,136c
kstrdup(&seg.name, "neomagicscreen");
.
113,114c
kstrdup(&seg.name, "neomagicmmio");
.
## diffname pc/vganeomagic.c 2001/0908
## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/vganeomagic.c /n/emeliedump/2001/0908/sys/src/9/pc/vganeomagic.c
132,137c
addvgaseg("neomagicscreen", aperture, size);
.
111,117d
109a
addvgaseg("neomagicmmio", scr->io, p->mem[1].size);
.
75d
## diffname pc/vganeomagic.c 2002/0919
## diff -e /n/emeliedump/2001/0908/sys/src/9/pc/vganeomagic.c /n/emeliedump/2002/0919/sys/src/9/pc/vganeomagic.c
279a
.
269a
neomagicdrawinit,
.
262a
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->aperture
+ 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->aperture
+ sr.min.y*pitch + sr.min.x*pixel;
mmio[DstStartOff] = scr->aperture
+ 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->aperture
+ (sr.max.y-1)*pitch + (sr.max.x-1)*pixel;
mmio[DstStartOff] = scr->aperture
+ (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;
}
.
109a
scr->mmio = KADDR(scr->io);
.
|