diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aux/vga/vmware.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/vga/vmware.c')
-rwxr-xr-x | sys/src/cmd/aux/vga/vmware.c | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/vga/vmware.c b/sys/src/cmd/aux/vga/vmware.c new file mode 100755 index 000000000..15e0589fb --- /dev/null +++ b/sys/src/cmd/aux/vga/vmware.c @@ -0,0 +1,295 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> + +#include "pci.h" +#include "vga.h" + +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, + Rhostbpp, + 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, + + Rpalette = 1024, +}; + +typedef struct Vmware Vmware; +struct Vmware { + ulong mmio; + ulong fb; + + ulong ra; + ulong rd; + + ulong r[Nreg]; + + char chan[32]; + int depth; +}; + +static char* +rname[Nreg] = { + "ID", + "Enable", + "Width", + "Height", + "MaxWidth", + "MaxHeight", + "Depth", + "Bpp", + "PseudoColor", + "RedMask", + "GreenMask", + "BlueMask", + "Bpl", + "FbStart", + "FbOffset", + "FbMaxSize", + "FbSize", + "Cap", + "MemStart", + "MemSize", + "ConfigDone", + "Sync", + "Busy", + "GuestID", + "CursorID", + "CursorX", + "CursorY", + "CursorOn", + "HostBpp", +}; + +static ulong +vmrd(Vmware *vm, int i) +{ + outportl(vm->ra, i); + return inportl(vm->rd); +} + +static void +vmwr(Vmware *vm, int i, ulong v) +{ + outportl(vm->ra, i); + outportl(vm->rd, v); +} + +static uint +bits(ulong a) +{ + int b; + + for(b=0; a; a>>=1) + if(a&1) + b++; + return b; +} + +static void +snarf(Vga* vga, Ctlr* ctlr) +{ + int extra, i; + Pcidev *p; + Vmware *vm; + + p = vga->pci; + if(p == nil) + error("%s: vga->pci not set\n", ctlr->name); + + vm = alloc(sizeof(Vmware)); + + switch(p->did){ + case 0x710: /* VMware video chipset #1 */ + vm->ra = 0x4560; + vm->rd = 0x4560+4; + break; + + case 0x405: /* VMware video chipset #2, untested */ + vm->ra = p->mem[0].bar&~3; + vm->rd = vm->ra+1; + break; + + default: + error("%s: unrecognized chipset %.4ux\n", ctlr->name, p->did); + } + + for(i=0; i<Nreg; i++) + vm->r[i] = vmrd(vm, i); + +//vmwr(vm, Renable, 0); + /* + * Figure out color channel. Delay errors until init, + * which is after the register dump. + */ + vm->depth = vm->r[Rbpp]; + extra = vm->r[Rbpp] - vm->r[Rdepth]; + if(vm->r[Rrmask] > vm->r[Rgmask] && vm->r[Rgmask] > vm->r[Rbmask]){ + if(extra) + sprint(vm->chan, "x%d", extra); + else + vm->chan[0] = '\0'; + sprint(vm->chan+strlen(vm->chan), "r%dg%db%d", bits(vm->r[Rrmask]), + bits(vm->r[Rgmask]), bits(vm->r[Rbmask])); + }else if(vm->r[Rbmask] > vm->r[Rgmask] && vm->r[Rgmask] > vm->r[Rrmask]){ + sprint(vm->chan, "b%dg%dr%d", bits(vm->r[Rbmask]), + bits(vm->r[Rgmask]), bits(vm->r[Rrmask])); + if(extra) + sprint(vm->chan+strlen(vm->chan), "x%d", extra); + }else + sprint(vm->chan, "unknown"); + + /* Record the frame buffer start, size */ + vga->vmb = vm->r[Rfbstart]; + vga->apz = vm->r[Rfbmaxsize]; + + vga->private = vm; + ctlr->flag |= Fsnarf; +} + + +static void +options(Vga*, Ctlr* ctlr) +{ + ctlr->flag |= Hlinear|Henhanced|Foptions; +} + + +static void +clock(Vga*, Ctlr*) +{ + /* BEST CLOCK ROUTINE EVER! */ +} + +static void +init(Vga* vga, Ctlr* ctlr) +{ + Vmware *vm; + + vm = vga->private; + + vmwr(vm, Rid, (0x900000<<8)|2); + if(vmrd(vm, Rid)&0xFF != 2) + error("old vmware svga version %lud; need version 2\n", + vmrd(vm,Rid)&0xFF); + + ctlr->flag |= Ulinear; + if(strcmp(vm->chan, "unknown") == 0) + error("couldn't translate color masks into channel\n"); + + /* Always use the screen depth, and clip the screen size */ + vga->mode->z = vm->r[Rbpp]; + if(vga->mode->x > vm->r[Rmaxwidth]) + vga->mode->x = vm->r[Rmaxwidth]; + if(vga->mode->y > vm->r[Rmaxheight]) + vga->mode->y = vm->r[Rmaxheight]; + + vm->r[Rwidth] = vga->mode->x; + vm->r[Rheight] = vga->mode->y; + + /* Figure out the channel string */ + strcpy(vga->mode->chan, vm->chan); + + /* Record the bytes per line */ + ctlr->flag |= Finit; +} + +static void +load(Vga* vga, Ctlr *ctlr) +{ + char buf[64]; + int x; + Vmware *vm; + + vm = vga->private; + vmwr(vm, Rwidth, vm->r[Rwidth]); + vmwr(vm, Rheight, vm->r[Rheight]); + vmwr(vm, Renable, 1); + vmwr(vm, Rguestid, 0x5010); /* OS type is "Other" */ + + x = vmrd(vm, Rbpl)/(vm->depth/8); + if(x != vga->mode->x){ + vga->virtx = x; + sprint(buf, "%ludx%ludx%d %s", vga->virtx, vga->virty, + vga->mode->z, vga->mode->chan); + vgactlw("size", buf); + } + ctlr->flag |= Fload; +} + +static void +dump(Vga* vga, Ctlr* ctlr) +{ + int i; + Vmware *vm; + + vm = vga->private; + + for(i=0; i<Nreg; i++){ + printitem(ctlr->name, rname[i]); + Bprint(&stdout, " %.8lux\n", vm->r[i]); + } + + printitem(ctlr->name, "chan"); + Bprint(&stdout, " %s\n", vm->chan); + printitem(ctlr->name, "depth"); + Bprint(&stdout, " %d\n", vm->depth); + printitem(ctlr->name, "linear"); + +} + +Ctlr vmware = { + "vmware", /* name */ + snarf, /* snarf */ + options, /* options */ + init, /* init */ + load, /* load */ + dump, /* dump */ +}; + +Ctlr vmwarehwgc = { + "vmwarehwgc", /* name */ + 0, /* snarf */ + 0, /* options */ + 0, /* init */ + 0, /* load */ + 0, /* dump */ +}; + |