371 lines
5.9 KiB
C
371 lines
5.9 KiB
C
|
#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"
|
||
|
|
||
|
enum {
|
||
|
PCIVMWARE = 0x15AD, /* PCI VID */
|
||
|
|
||
|
VMWARE1 = 0x0710, /* PCI DID */
|
||
|
VMWARE2 = 0x0405,
|
||
|
};
|
||
|
|
||
|
enum {
|
||
|
Rid = 0,
|
||
|
Renable,
|
||
|
Rwidth,
|
||
|
Rheight,
|
||
|
Rmaxwidth,
|
||
|
|
||
|
Rmaxheight,
|
||
|
Rdepth,
|
||
|
Rbpp,
|
||
|
Rpseudocolor,
|
||
|
Rrmask,
|
||
|
|
||
|
Rgmask,
|
||
|
Rbmask,
|
||
|
Rbpl,
|
||
|
Rfbstart,
|
||
|
Rfboffset,
|
||
|
|
||
|
Rfbmaxsize,
|
||
|
Rfbsize,
|
||
|
Rcap,
|
||
|
Rmemstart,
|
||
|
Rmemsize,
|
||
|
|
||
|
Rconfigdone,
|
||
|
Rsync,
|
||
|
Rbusy,
|
||
|
Rguestid,
|
||
|
Rcursorid,
|
||
|
|
||
|
Rcursorx,
|
||
|
Rcursory,
|
||
|
Rcursoron,
|
||
|
Nreg,
|
||
|
|
||
|
Crectfill = 1<<0,
|
||
|
Crectcopy = 1<<1,
|
||
|
Crectpatfill = 1<<2,
|
||
|
Coffscreen = 1<<3,
|
||
|
Crasterop = 1<<4,
|
||
|
Ccursor = 1<<5,
|
||
|
Ccursorbypass = 1<<6,
|
||
|
Ccursorbypass2 = 1<<7,
|
||
|
C8bitemulation = 1<<8,
|
||
|
Calphacursor = 1<<9,
|
||
|
|
||
|
FifoMin = 0,
|
||
|
FifoMax = 1,
|
||
|
FifoNextCmd = 2,
|
||
|
FifoStop = 3,
|
||
|
FifoUser = 4,
|
||
|
|
||
|
Xupdate = 1,
|
||
|
Xrectfill = 2,
|
||
|
Xrectcopy = 3,
|
||
|
Xdefinebitmap = 4,
|
||
|
Xdefinebitmapscanline = 5,
|
||
|
Xdefinepixmap = 6,
|
||
|
Xdefinepixmapscanline = 7,
|
||
|
Xrectbitmapfill = 8,
|
||
|
Xrectpixmapfill = 9,
|
||
|
Xrectbitmapcopy = 10,
|
||
|
Xrectpixmapcopy = 11,
|
||
|
Xfreeobject = 12,
|
||
|
Xrectropfill = 13,
|
||
|
Xrectropcopy = 14,
|
||
|
Xrectropbitmapfill = 15,
|
||
|
Xrectroppixmapfill = 16,
|
||
|
Xrectropbitmapcopy = 17,
|
||
|
Xrectroppixmapcopy = 18,
|
||
|
Xdefinecursor = 19,
|
||
|
Xdisplaycursor = 20,
|
||
|
Xmovecursor = 21,
|
||
|
Xdefinealphacursor = 22,
|
||
|
Xcmdmax = 23,
|
||
|
|
||
|
CursorOnHide = 0,
|
||
|
CursorOnShow = 1,
|
||
|
CursorOnRemoveFromFb = 2,
|
||
|
CursorOnRestoreToFb = 3,
|
||
|
|
||
|
Rpalette = 1024,
|
||
|
};
|
||
|
|
||
|
typedef struct Vmware Vmware;
|
||
|
struct Vmware {
|
||
|
ulong fb;
|
||
|
|
||
|
ulong ra;
|
||
|
ulong rd;
|
||
|
|
||
|
ulong r[Nreg];
|
||
|
ulong *mmio;
|
||
|
ulong mmiosize;
|
||
|
|
||
|
char chan[32];
|
||
|
int depth;
|
||
|
};
|
||
|
|
||
|
Vmware xvm;
|
||
|
Vmware *vm=&xvm;
|
||
|
|
||
|
static ulong
|
||
|
vmrd(Vmware *vm, int i)
|
||
|
{
|
||
|
outl(vm->ra, i);
|
||
|
return inl(vm->rd);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
vmwr(Vmware *vm, int i, ulong v)
|
||
|
{
|
||
|
outl(vm->ra, i);
|
||
|
outl(vm->rd, v);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
vmwait(Vmware *vm)
|
||
|
{
|
||
|
vmwr(vm, Rsync, 1);
|
||
|
while(vmrd(vm, Rbusy))
|
||
|
;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
vmwarelinear(VGAscr* scr, int, int)
|
||
|
{
|
||
|
char err[64];
|
||
|
Pcidev *p;
|
||
|
|
||
|
err[0] = 0;
|
||
|
p = nil;
|
||
|
while((p = pcimatch(p, PCIVMWARE, 0)) != nil){
|
||
|
if(p->ccrb != Pcibcdisp)
|
||
|
continue;
|
||
|
switch(p->did){
|
||
|
default:
|
||
|
snprint(err, sizeof err, "unknown vmware pci did %.4ux",
|
||
|
p->did);
|
||
|
continue;
|
||
|
|
||
|
case VMWARE1:
|
||
|
vm->ra = 0x4560;
|
||
|
vm->rd = 0x4560 + 4;
|
||
|
break;
|
||
|
|
||
|
case VMWARE2:
|
||
|
vm->ra = p->mem[0].bar & ~3;
|
||
|
vm->rd = vm->ra + 1;
|
||
|
break;
|
||
|
}
|
||
|
break; /* found a card, p is set */
|
||
|
}
|
||
|
if(p == nil)
|
||
|
error(err[0]? err: "no vmware vga card found");
|
||
|
|
||
|
vgalinearaddr(scr, vmrd(vm, Rfbstart), vmrd(vm, Rfbsize));
|
||
|
if(scr->apsize)
|
||
|
addvgaseg("vmwarescreen", scr->paddr, scr->apsize);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
vmfifowr(Vmware *vm, ulong v)
|
||
|
{
|
||
|
ulong *mm;
|
||
|
|
||
|
mm = vm->mmio;
|
||
|
if(mm == nil){
|
||
|
iprint("!");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(mm[FifoNextCmd]+sizeof(ulong) == mm[FifoStop]
|
||
|
|| (mm[FifoNextCmd]+sizeof(ulong) == mm[FifoMax]
|
||
|
&& mm[FifoStop] == mm[FifoMin]))
|
||
|
vmwait(vm);
|
||
|
|
||
|
mm[mm[FifoNextCmd]/sizeof(ulong)] = v;
|
||
|
|
||
|
/* must do this way so mm[FifoNextCmd] is never mm[FifoMax] */
|
||
|
v = mm[FifoNextCmd] + sizeof(ulong);
|
||
|
if(v == mm[FifoMax])
|
||
|
v = mm[FifoMin];
|
||
|
mm[FifoNextCmd] = v;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
vmwareflush(VGAscr*, Rectangle r)
|
||
|
{
|
||
|
if(vm->mmio == nil)
|
||
|
return;
|
||
|
|
||
|
vmfifowr(vm, Xupdate);
|
||
|
vmfifowr(vm, r.min.x);
|
||
|
vmfifowr(vm, r.min.y);
|
||
|
vmfifowr(vm, r.max.x-r.min.x);
|
||
|
vmfifowr(vm, r.max.y-r.min.y);
|
||
|
vmwait(vm);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
vmwareload(VGAscr*, Cursor *c)
|
||
|
{
|
||
|
int i;
|
||
|
ulong clr, set;
|
||
|
ulong and[16];
|
||
|
ulong xor[16];
|
||
|
|
||
|
if(vm->mmio == nil)
|
||
|
return;
|
||
|
vmfifowr(vm, Xdefinecursor);
|
||
|
vmfifowr(vm, 1); /* cursor id */
|
||
|
vmfifowr(vm, -c->offset.x);
|
||
|
vmfifowr(vm, -c->offset.y);
|
||
|
|
||
|
vmfifowr(vm, 16); /* width */
|
||
|
vmfifowr(vm, 16); /* height */
|
||
|
vmfifowr(vm, 1); /* depth for and mask */
|
||
|
vmfifowr(vm, 1); /* depth for xor mask */
|
||
|
|
||
|
for(i=0; i<16; i++){
|
||
|
clr = (c->clr[i*2+1]<<8) | c->clr[i*2];
|
||
|
set = (c->set[i*2+1]<<8) | c->set[i*2];
|
||
|
and[i] = ~(clr|set); /* clr and set pixels => black */
|
||
|
xor[i] = clr&~set; /* clr pixels => white */
|
||
|
}
|
||
|
for(i=0; i<16; i++)
|
||
|
vmfifowr(vm, and[i]);
|
||
|
for(i=0; i<16; i++)
|
||
|
vmfifowr(vm, xor[i]);
|
||
|
|
||
|
vmwait(vm);
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
vmwaremove(VGAscr*, Point p)
|
||
|
{
|
||
|
vmwr(vm, Rcursorid, 1);
|
||
|
vmwr(vm, Rcursorx, p.x);
|
||
|
vmwr(vm, Rcursory, p.y);
|
||
|
vmwr(vm, Rcursoron, CursorOnShow);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
vmwaredisable(VGAscr*)
|
||
|
{
|
||
|
vmwr(vm, Rcursorid, 1);
|
||
|
vmwr(vm, Rcursoron, CursorOnHide);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
vmwareenable(VGAscr*)
|
||
|
{
|
||
|
vmwr(vm, Rcursorid, 1);
|
||
|
vmwr(vm, Rcursoron, CursorOnShow);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
vmwareblank(int)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
vmwarescroll(VGAscr*, Rectangle r, Rectangle sr)
|
||
|
{
|
||
|
if(vm->mmio == nil)
|
||
|
return 0;
|
||
|
vmfifowr(vm, Xrectcopy);
|
||
|
vmfifowr(vm, sr.min.x);
|
||
|
vmfifowr(vm, sr.min.y);
|
||
|
vmfifowr(vm, r.min.x);
|
||
|
vmfifowr(vm, r.min.y);
|
||
|
vmfifowr(vm, Dx(r));
|
||
|
vmfifowr(vm, Dy(r));
|
||
|
vmwait(vm);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
vmwarefill(VGAscr*, Rectangle r, ulong sval)
|
||
|
{
|
||
|
if(vm->mmio == nil)
|
||
|
return 0;
|
||
|
vmfifowr(vm, Xrectfill);
|
||
|
vmfifowr(vm, sval);
|
||
|
vmfifowr(vm, r.min.x);
|
||
|
vmfifowr(vm, r.min.y);
|
||
|
vmfifowr(vm, r.max.x-r.min.x);
|
||
|
vmfifowr(vm, r.max.y-r.min.y);
|
||
|
vmwait(vm);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
vmwaredrawinit(VGAscr *scr)
|
||
|
{
|
||
|
ulong offset;
|
||
|
ulong mmiobase, mmiosize;
|
||
|
|
||
|
if(scr->mmio==nil){
|
||
|
mmiobase = vmrd(vm, Rmemstart);
|
||
|
if(mmiobase == 0)
|
||
|
return;
|
||
|
mmiosize = vmrd(vm, Rmemsize);
|
||
|
scr->mmio = vmap(mmiobase, mmiosize);
|
||
|
if(scr->mmio == nil)
|
||
|
return;
|
||
|
vm->mmio = scr->mmio;
|
||
|
vm->mmiosize = mmiosize;
|
||
|
addvgaseg("vmwaremmio", mmiobase, mmiosize);
|
||
|
}
|
||
|
|
||
|
scr->mmio[FifoMin] = 4*sizeof(ulong);
|
||
|
scr->mmio[FifoMax] = vm->mmiosize;
|
||
|
scr->mmio[FifoNextCmd] = 4*sizeof(ulong);
|
||
|
scr->mmio[FifoStop] = 4*sizeof(ulong);
|
||
|
vmwr(vm, Rconfigdone, 1);
|
||
|
|
||
|
scr->scroll = vmwarescroll;
|
||
|
scr->fill = vmwarefill;
|
||
|
|
||
|
offset = vmrd(vm, Rfboffset);
|
||
|
scr->gscreendata->bdata += offset;
|
||
|
}
|
||
|
|
||
|
VGAdev vgavmwaredev = {
|
||
|
"vmware",
|
||
|
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
vmwarelinear,
|
||
|
vmwaredrawinit,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
vmwareflush,
|
||
|
};
|
||
|
|
||
|
VGAcur vgavmwarecur = {
|
||
|
"vmwarehwgc",
|
||
|
|
||
|
vmwareenable,
|
||
|
vmwaredisable,
|
||
|
vmwareload,
|
||
|
vmwaremove,
|
||
|
};
|