/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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 ulongvmrd(Vmware *vm, int i){ outl(vm->ra, i); return inl(vm->rd);} static voidvmwr(Vmware *vm, int i, ulong v){ outl(vm->ra, i); outl(vm->rd, v);} static voidvmwait(Vmware *vm){ vmwr(vm, Rsync, 1); while(vmrd(vm, Rbusy)) ;} static voidvmwarelinear(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"); /* * empirically, 2*fbsize enables 1280x1024x32, not just 1024x768x32. * is fbsize in bytes or pixels? */ vgalinearaddr(scr, vmrd(vm, Rfbstart), 2*vmrd(vm, Rfbsize)); if(scr->apsize) addvgaseg("vmwarescreen", scr->paddr, scr->apsize);} static voidvmfifowr(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 voidvmwareflush(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 voidvmwareload(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 intvmwaremove(VGAscr*, Point p){ vmwr(vm, Rcursorid, 1); vmwr(vm, Rcursorx, p.x); vmwr(vm, Rcursory, p.y); vmwr(vm, Rcursoron, CursorOnShow); return 0;} static voidvmwaredisable(VGAscr*){ vmwr(vm, Rcursorid, 1); vmwr(vm, Rcursoron, CursorOnHide);} static voidvmwareenable(VGAscr*){ vmwr(vm, Rcursorid, 1); vmwr(vm, Rcursoron, CursorOnShow);} static voidvmwareblank(int){} static intvmwarescroll(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 intvmwarefill(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 voidvmwaredrawinit(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,};
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#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");
/*
* empirically, 2*fbsize enables 1280x1024x32, not just 1024x768x32.
* is fbsize in bytes or pixels?
*/
vgalinearaddr(scr, vmrd(vm, Rfbstart), 2*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,
};