123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- #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",
- vmrd(vm,Rid)&0xFF);
- ctlr->flag |= Ulinear;
- if(strcmp(vm->chan, "unknown") == 0)
- error("couldn't translate color masks into channel");
- /* 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 */
- };
|