19a747e4fSDavid du Colombier #include "u.h"
29a747e4fSDavid du Colombier #include "../port/lib.h"
39a747e4fSDavid du Colombier #include "mem.h"
49a747e4fSDavid du Colombier #include "dat.h"
59a747e4fSDavid du Colombier #include "fns.h"
69a747e4fSDavid du Colombier #include "io.h"
79a747e4fSDavid du Colombier #include "../port/error.h"
89a747e4fSDavid du Colombier
99a747e4fSDavid du Colombier #define Image IMAGE
109a747e4fSDavid du Colombier #include <draw.h>
119a747e4fSDavid du Colombier #include <memdraw.h>
129a747e4fSDavid du Colombier #include <cursor.h>
139a747e4fSDavid du Colombier #include "screen.h"
149a747e4fSDavid du Colombier
159a747e4fSDavid du Colombier enum {
169a747e4fSDavid du Colombier PCIVMWARE = 0x15AD, /* PCI VID */
179a747e4fSDavid du Colombier
189a747e4fSDavid du Colombier VMWARE1 = 0x0710, /* PCI DID */
199a747e4fSDavid du Colombier VMWARE2 = 0x0405,
209a747e4fSDavid du Colombier };
219a747e4fSDavid du Colombier
229a747e4fSDavid du Colombier enum {
239a747e4fSDavid du Colombier Rid = 0,
249a747e4fSDavid du Colombier Renable,
259a747e4fSDavid du Colombier Rwidth,
269a747e4fSDavid du Colombier Rheight,
279a747e4fSDavid du Colombier Rmaxwidth,
289a747e4fSDavid du Colombier
299a747e4fSDavid du Colombier Rmaxheight,
309a747e4fSDavid du Colombier Rdepth,
319a747e4fSDavid du Colombier Rbpp,
329a747e4fSDavid du Colombier Rpseudocolor,
339a747e4fSDavid du Colombier Rrmask,
349a747e4fSDavid du Colombier
359a747e4fSDavid du Colombier Rgmask,
369a747e4fSDavid du Colombier Rbmask,
379a747e4fSDavid du Colombier Rbpl,
389a747e4fSDavid du Colombier Rfbstart,
399a747e4fSDavid du Colombier Rfboffset,
409a747e4fSDavid du Colombier
419a747e4fSDavid du Colombier Rfbmaxsize,
429a747e4fSDavid du Colombier Rfbsize,
439a747e4fSDavid du Colombier Rcap,
449a747e4fSDavid du Colombier Rmemstart,
459a747e4fSDavid du Colombier Rmemsize,
469a747e4fSDavid du Colombier
479a747e4fSDavid du Colombier Rconfigdone,
489a747e4fSDavid du Colombier Rsync,
499a747e4fSDavid du Colombier Rbusy,
509a747e4fSDavid du Colombier Rguestid,
519a747e4fSDavid du Colombier Rcursorid,
529a747e4fSDavid du Colombier
539a747e4fSDavid du Colombier Rcursorx,
549a747e4fSDavid du Colombier Rcursory,
559a747e4fSDavid du Colombier Rcursoron,
569a747e4fSDavid du Colombier Nreg,
579a747e4fSDavid du Colombier
589a747e4fSDavid du Colombier Crectfill = 1<<0,
599a747e4fSDavid du Colombier Crectcopy = 1<<1,
609a747e4fSDavid du Colombier Crectpatfill = 1<<2,
619a747e4fSDavid du Colombier Coffscreen = 1<<3,
629a747e4fSDavid du Colombier Crasterop = 1<<4,
639a747e4fSDavid du Colombier Ccursor = 1<<5,
649a747e4fSDavid du Colombier Ccursorbypass = 1<<6,
659a747e4fSDavid du Colombier Ccursorbypass2 = 1<<7,
669a747e4fSDavid du Colombier C8bitemulation = 1<<8,
679a747e4fSDavid du Colombier Calphacursor = 1<<9,
689a747e4fSDavid du Colombier
699a747e4fSDavid du Colombier FifoMin = 0,
709a747e4fSDavid du Colombier FifoMax = 1,
719a747e4fSDavid du Colombier FifoNextCmd = 2,
729a747e4fSDavid du Colombier FifoStop = 3,
739a747e4fSDavid du Colombier FifoUser = 4,
749a747e4fSDavid du Colombier
759a747e4fSDavid du Colombier Xupdate = 1,
769a747e4fSDavid du Colombier Xrectfill = 2,
779a747e4fSDavid du Colombier Xrectcopy = 3,
789a747e4fSDavid du Colombier Xdefinebitmap = 4,
799a747e4fSDavid du Colombier Xdefinebitmapscanline = 5,
809a747e4fSDavid du Colombier Xdefinepixmap = 6,
819a747e4fSDavid du Colombier Xdefinepixmapscanline = 7,
829a747e4fSDavid du Colombier Xrectbitmapfill = 8,
839a747e4fSDavid du Colombier Xrectpixmapfill = 9,
849a747e4fSDavid du Colombier Xrectbitmapcopy = 10,
859a747e4fSDavid du Colombier Xrectpixmapcopy = 11,
869a747e4fSDavid du Colombier Xfreeobject = 12,
879a747e4fSDavid du Colombier Xrectropfill = 13,
889a747e4fSDavid du Colombier Xrectropcopy = 14,
899a747e4fSDavid du Colombier Xrectropbitmapfill = 15,
909a747e4fSDavid du Colombier Xrectroppixmapfill = 16,
919a747e4fSDavid du Colombier Xrectropbitmapcopy = 17,
929a747e4fSDavid du Colombier Xrectroppixmapcopy = 18,
939a747e4fSDavid du Colombier Xdefinecursor = 19,
949a747e4fSDavid du Colombier Xdisplaycursor = 20,
959a747e4fSDavid du Colombier Xmovecursor = 21,
969a747e4fSDavid du Colombier Xdefinealphacursor = 22,
979a747e4fSDavid du Colombier Xcmdmax = 23,
989a747e4fSDavid du Colombier
999a747e4fSDavid du Colombier CursorOnHide = 0,
1009a747e4fSDavid du Colombier CursorOnShow = 1,
1019a747e4fSDavid du Colombier CursorOnRemoveFromFb = 2,
1029a747e4fSDavid du Colombier CursorOnRestoreToFb = 3,
1039a747e4fSDavid du Colombier
1049a747e4fSDavid du Colombier Rpalette = 1024,
1059a747e4fSDavid du Colombier };
1069a747e4fSDavid du Colombier
1079a747e4fSDavid du Colombier typedef struct Vmware Vmware;
1089a747e4fSDavid du Colombier struct Vmware {
1099a747e4fSDavid du Colombier ulong fb;
1109a747e4fSDavid du Colombier
1119a747e4fSDavid du Colombier ulong ra;
1129a747e4fSDavid du Colombier ulong rd;
1139a747e4fSDavid du Colombier
1149a747e4fSDavid du Colombier ulong r[Nreg];
1159a747e4fSDavid du Colombier ulong *mmio;
1169a747e4fSDavid du Colombier ulong mmiosize;
1179a747e4fSDavid du Colombier
1189a747e4fSDavid du Colombier char chan[32];
1199a747e4fSDavid du Colombier int depth;
1209a747e4fSDavid du Colombier };
1219a747e4fSDavid du Colombier
1229a747e4fSDavid du Colombier Vmware xvm;
1239a747e4fSDavid du Colombier Vmware *vm=&xvm;
1249a747e4fSDavid du Colombier
1259a747e4fSDavid du Colombier static ulong
vmrd(Vmware * vm,int i)1269a747e4fSDavid du Colombier vmrd(Vmware *vm, int i)
1279a747e4fSDavid du Colombier {
1289a747e4fSDavid du Colombier outl(vm->ra, i);
1299a747e4fSDavid du Colombier return inl(vm->rd);
1309a747e4fSDavid du Colombier }
1319a747e4fSDavid du Colombier
1329a747e4fSDavid du Colombier static void
vmwr(Vmware * vm,int i,ulong v)1339a747e4fSDavid du Colombier vmwr(Vmware *vm, int i, ulong v)
1349a747e4fSDavid du Colombier {
1359a747e4fSDavid du Colombier outl(vm->ra, i);
1369a747e4fSDavid du Colombier outl(vm->rd, v);
1379a747e4fSDavid du Colombier }
1389a747e4fSDavid du Colombier
1399a747e4fSDavid du Colombier static void
vmwait(Vmware * vm)1409a747e4fSDavid du Colombier vmwait(Vmware *vm)
1419a747e4fSDavid du Colombier {
1429a747e4fSDavid du Colombier vmwr(vm, Rsync, 1);
1439a747e4fSDavid du Colombier while(vmrd(vm, Rbusy))
1449a747e4fSDavid du Colombier ;
1459a747e4fSDavid du Colombier }
1469a747e4fSDavid du Colombier
1474de34a7eSDavid du Colombier static void
vmwarelinear(VGAscr * scr,int,int)1484de34a7eSDavid du Colombier vmwarelinear(VGAscr* scr, int, int)
1499a747e4fSDavid du Colombier {
1509a747e4fSDavid du Colombier char err[64];
1519a747e4fSDavid du Colombier Pcidev *p;
1529a747e4fSDavid du Colombier
1536aadf539SDavid du Colombier err[0] = 0;
1546aadf539SDavid du Colombier p = nil;
1556aadf539SDavid du Colombier while((p = pcimatch(p, PCIVMWARE, 0)) != nil){
1566aadf539SDavid du Colombier if(p->ccrb != Pcibcdisp)
1576aadf539SDavid du Colombier continue;
1589a747e4fSDavid du Colombier switch(p->did){
1599a747e4fSDavid du Colombier default:
1606aadf539SDavid du Colombier snprint(err, sizeof err, "unknown vmware pci did %.4ux",
1616aadf539SDavid du Colombier p->did);
1626aadf539SDavid du Colombier continue;
1639a747e4fSDavid du Colombier
1649a747e4fSDavid du Colombier case VMWARE1:
1659a747e4fSDavid du Colombier vm->ra = 0x4560;
1669a747e4fSDavid du Colombier vm->rd = 0x4560 + 4;
1679a747e4fSDavid du Colombier break;
1689a747e4fSDavid du Colombier
1699a747e4fSDavid du Colombier case VMWARE2:
1709a747e4fSDavid du Colombier vm->ra = p->mem[0].bar & ~3;
1719a747e4fSDavid du Colombier vm->rd = vm->ra + 1;
1726aadf539SDavid du Colombier break;
1739a747e4fSDavid du Colombier }
1746aadf539SDavid du Colombier break; /* found a card, p is set */
1756aadf539SDavid du Colombier }
1766aadf539SDavid du Colombier if(p == nil)
1776aadf539SDavid du Colombier error(err[0]? err: "no vmware vga card found");
1789a747e4fSDavid du Colombier
179*27acba7cSDavid du Colombier /*
180*27acba7cSDavid du Colombier * empirically, 2*fbsize enables 1280x1024x32, not just 1024x768x32.
181*27acba7cSDavid du Colombier * is fbsize in bytes or pixels?
182*27acba7cSDavid du Colombier */
183*27acba7cSDavid du Colombier vgalinearaddr(scr, vmrd(vm, Rfbstart), 2*vmrd(vm, Rfbsize));
1844de34a7eSDavid du Colombier if(scr->apsize)
1854de34a7eSDavid du Colombier addvgaseg("vmwarescreen", scr->paddr, scr->apsize);
1869a747e4fSDavid du Colombier }
1879a747e4fSDavid du Colombier
1889a747e4fSDavid du Colombier static void
vmfifowr(Vmware * vm,ulong v)1899a747e4fSDavid du Colombier vmfifowr(Vmware *vm, ulong v)
1909a747e4fSDavid du Colombier {
1919a747e4fSDavid du Colombier ulong *mm;
1929a747e4fSDavid du Colombier
1939a747e4fSDavid du Colombier mm = vm->mmio;
1949a747e4fSDavid du Colombier if(mm == nil){
1959a747e4fSDavid du Colombier iprint("!");
1969a747e4fSDavid du Colombier return;
1979a747e4fSDavid du Colombier }
1989a747e4fSDavid du Colombier
1999a747e4fSDavid du Colombier if(mm[FifoNextCmd]+sizeof(ulong) == mm[FifoStop]
2009a747e4fSDavid du Colombier || (mm[FifoNextCmd]+sizeof(ulong) == mm[FifoMax]
2019a747e4fSDavid du Colombier && mm[FifoStop] == mm[FifoMin]))
2029a747e4fSDavid du Colombier vmwait(vm);
2039a747e4fSDavid du Colombier
2049a747e4fSDavid du Colombier mm[mm[FifoNextCmd]/sizeof(ulong)] = v;
20567031067SDavid du Colombier
20667031067SDavid du Colombier /* must do this way so mm[FifoNextCmd] is never mm[FifoMax] */
20767031067SDavid du Colombier v = mm[FifoNextCmd] + sizeof(ulong);
20867031067SDavid du Colombier if(v == mm[FifoMax])
20967031067SDavid du Colombier v = mm[FifoMin];
21067031067SDavid du Colombier mm[FifoNextCmd] = v;
2119a747e4fSDavid du Colombier }
2129a747e4fSDavid du Colombier
2139a747e4fSDavid du Colombier static void
vmwareflush(VGAscr *,Rectangle r)2149a747e4fSDavid du Colombier vmwareflush(VGAscr*, Rectangle r)
2159a747e4fSDavid du Colombier {
2169a747e4fSDavid du Colombier if(vm->mmio == nil)
2179a747e4fSDavid du Colombier return;
2189a747e4fSDavid du Colombier
2199a747e4fSDavid du Colombier vmfifowr(vm, Xupdate);
2209a747e4fSDavid du Colombier vmfifowr(vm, r.min.x);
2219a747e4fSDavid du Colombier vmfifowr(vm, r.min.y);
2229a747e4fSDavid du Colombier vmfifowr(vm, r.max.x-r.min.x);
2239a747e4fSDavid du Colombier vmfifowr(vm, r.max.y-r.min.y);
2249a747e4fSDavid du Colombier vmwait(vm);
2259a747e4fSDavid du Colombier }
2269a747e4fSDavid du Colombier
2279a747e4fSDavid du Colombier static void
vmwareload(VGAscr *,Cursor * c)2289a747e4fSDavid du Colombier vmwareload(VGAscr*, Cursor *c)
2299a747e4fSDavid du Colombier {
2309a747e4fSDavid du Colombier int i;
2319a747e4fSDavid du Colombier ulong clr, set;
2329a747e4fSDavid du Colombier ulong and[16];
2339a747e4fSDavid du Colombier ulong xor[16];
2349a747e4fSDavid du Colombier
2359a747e4fSDavid du Colombier if(vm->mmio == nil)
2369a747e4fSDavid du Colombier return;
2379a747e4fSDavid du Colombier vmfifowr(vm, Xdefinecursor);
2389a747e4fSDavid du Colombier vmfifowr(vm, 1); /* cursor id */
2399a747e4fSDavid du Colombier vmfifowr(vm, -c->offset.x);
2409a747e4fSDavid du Colombier vmfifowr(vm, -c->offset.y);
2419a747e4fSDavid du Colombier
2429a747e4fSDavid du Colombier vmfifowr(vm, 16); /* width */
2439a747e4fSDavid du Colombier vmfifowr(vm, 16); /* height */
2449a747e4fSDavid du Colombier vmfifowr(vm, 1); /* depth for and mask */
2459a747e4fSDavid du Colombier vmfifowr(vm, 1); /* depth for xor mask */
2469a747e4fSDavid du Colombier
2479a747e4fSDavid du Colombier for(i=0; i<16; i++){
2489a747e4fSDavid du Colombier clr = (c->clr[i*2+1]<<8) | c->clr[i*2];
2499a747e4fSDavid du Colombier set = (c->set[i*2+1]<<8) | c->set[i*2];
2509a747e4fSDavid du Colombier and[i] = ~(clr|set); /* clr and set pixels => black */
2519a747e4fSDavid du Colombier xor[i] = clr&~set; /* clr pixels => white */
2529a747e4fSDavid du Colombier }
2539a747e4fSDavid du Colombier for(i=0; i<16; i++)
2549a747e4fSDavid du Colombier vmfifowr(vm, and[i]);
2559a747e4fSDavid du Colombier for(i=0; i<16; i++)
2569a747e4fSDavid du Colombier vmfifowr(vm, xor[i]);
2579a747e4fSDavid du Colombier
2589a747e4fSDavid du Colombier vmwait(vm);
2599a747e4fSDavid du Colombier }
2609a747e4fSDavid du Colombier
2619a747e4fSDavid du Colombier static int
vmwaremove(VGAscr *,Point p)2629a747e4fSDavid du Colombier vmwaremove(VGAscr*, Point p)
2639a747e4fSDavid du Colombier {
2649a747e4fSDavid du Colombier vmwr(vm, Rcursorid, 1);
2659a747e4fSDavid du Colombier vmwr(vm, Rcursorx, p.x);
2669a747e4fSDavid du Colombier vmwr(vm, Rcursory, p.y);
2679a747e4fSDavid du Colombier vmwr(vm, Rcursoron, CursorOnShow);
2689a747e4fSDavid du Colombier return 0;
2699a747e4fSDavid du Colombier }
2709a747e4fSDavid du Colombier
2719a747e4fSDavid du Colombier static void
vmwaredisable(VGAscr *)2729a747e4fSDavid du Colombier vmwaredisable(VGAscr*)
2739a747e4fSDavid du Colombier {
2749a747e4fSDavid du Colombier vmwr(vm, Rcursorid, 1);
2759a747e4fSDavid du Colombier vmwr(vm, Rcursoron, CursorOnHide);
2769a747e4fSDavid du Colombier }
2779a747e4fSDavid du Colombier
2789a747e4fSDavid du Colombier static void
vmwareenable(VGAscr *)2799a747e4fSDavid du Colombier vmwareenable(VGAscr*)
2809a747e4fSDavid du Colombier {
2819a747e4fSDavid du Colombier vmwr(vm, Rcursorid, 1);
2829a747e4fSDavid du Colombier vmwr(vm, Rcursoron, CursorOnShow);
2839a747e4fSDavid du Colombier }
2849a747e4fSDavid du Colombier
2859a747e4fSDavid du Colombier static void
vmwareblank(int)2869a747e4fSDavid du Colombier vmwareblank(int)
2879a747e4fSDavid du Colombier {
2889a747e4fSDavid du Colombier }
2899a747e4fSDavid du Colombier
2909a747e4fSDavid du Colombier static int
vmwarescroll(VGAscr *,Rectangle r,Rectangle sr)2919a747e4fSDavid du Colombier vmwarescroll(VGAscr*, Rectangle r, Rectangle sr)
2929a747e4fSDavid du Colombier {
2939a747e4fSDavid du Colombier if(vm->mmio == nil)
2949a747e4fSDavid du Colombier return 0;
2959a747e4fSDavid du Colombier vmfifowr(vm, Xrectcopy);
2969a747e4fSDavid du Colombier vmfifowr(vm, sr.min.x);
2979a747e4fSDavid du Colombier vmfifowr(vm, sr.min.y);
2989a747e4fSDavid du Colombier vmfifowr(vm, r.min.x);
2999a747e4fSDavid du Colombier vmfifowr(vm, r.min.y);
3009a747e4fSDavid du Colombier vmfifowr(vm, Dx(r));
3019a747e4fSDavid du Colombier vmfifowr(vm, Dy(r));
3029a747e4fSDavid du Colombier vmwait(vm);
3039a747e4fSDavid du Colombier return 1;
3049a747e4fSDavid du Colombier }
3059a747e4fSDavid du Colombier
3069a747e4fSDavid du Colombier static int
vmwarefill(VGAscr *,Rectangle r,ulong sval)3079a747e4fSDavid du Colombier vmwarefill(VGAscr*, Rectangle r, ulong sval)
3089a747e4fSDavid du Colombier {
3099a747e4fSDavid du Colombier if(vm->mmio == nil)
3109a747e4fSDavid du Colombier return 0;
3119a747e4fSDavid du Colombier vmfifowr(vm, Xrectfill);
3129a747e4fSDavid du Colombier vmfifowr(vm, sval);
3139a747e4fSDavid du Colombier vmfifowr(vm, r.min.x);
3149a747e4fSDavid du Colombier vmfifowr(vm, r.min.y);
3159a747e4fSDavid du Colombier vmfifowr(vm, r.max.x-r.min.x);
3169a747e4fSDavid du Colombier vmfifowr(vm, r.max.y-r.min.y);
3179a747e4fSDavid du Colombier vmwait(vm);
3189a747e4fSDavid du Colombier return 1;
3199a747e4fSDavid du Colombier }
3209a747e4fSDavid du Colombier
3219a747e4fSDavid du Colombier static void
vmwaredrawinit(VGAscr * scr)3229a747e4fSDavid du Colombier vmwaredrawinit(VGAscr *scr)
3239a747e4fSDavid du Colombier {
324b7b24591SDavid du Colombier ulong offset;
3259a747e4fSDavid du Colombier ulong mmiobase, mmiosize;
3269a747e4fSDavid du Colombier
3279a747e4fSDavid du Colombier if(scr->mmio==nil){
3289a747e4fSDavid du Colombier mmiobase = vmrd(vm, Rmemstart);
3299a747e4fSDavid du Colombier if(mmiobase == 0)
3309a747e4fSDavid du Colombier return;
3319a747e4fSDavid du Colombier mmiosize = vmrd(vm, Rmemsize);
3324de34a7eSDavid du Colombier scr->mmio = vmap(mmiobase, mmiosize);
3339a747e4fSDavid du Colombier if(scr->mmio == nil)
3349a747e4fSDavid du Colombier return;
3354de34a7eSDavid du Colombier vm->mmio = scr->mmio;
3364de34a7eSDavid du Colombier vm->mmiosize = mmiosize;
3379a747e4fSDavid du Colombier addvgaseg("vmwaremmio", mmiobase, mmiosize);
3389a747e4fSDavid du Colombier }
3399a747e4fSDavid du Colombier
3409a747e4fSDavid du Colombier scr->mmio[FifoMin] = 4*sizeof(ulong);
3419a747e4fSDavid du Colombier scr->mmio[FifoMax] = vm->mmiosize;
3429a747e4fSDavid du Colombier scr->mmio[FifoNextCmd] = 4*sizeof(ulong);
3439a747e4fSDavid du Colombier scr->mmio[FifoStop] = 4*sizeof(ulong);
3449a747e4fSDavid du Colombier vmwr(vm, Rconfigdone, 1);
3459a747e4fSDavid du Colombier
3469a747e4fSDavid du Colombier scr->scroll = vmwarescroll;
3479a747e4fSDavid du Colombier scr->fill = vmwarefill;
348b7b24591SDavid du Colombier
349b7b24591SDavid du Colombier offset = vmrd(vm, Rfboffset);
350b7b24591SDavid du Colombier scr->gscreendata->bdata += offset;
3519a747e4fSDavid du Colombier }
3529a747e4fSDavid du Colombier
3539a747e4fSDavid du Colombier VGAdev vgavmwaredev = {
3549a747e4fSDavid du Colombier "vmware",
3559a747e4fSDavid du Colombier
3569a747e4fSDavid du Colombier 0,
3579a747e4fSDavid du Colombier 0,
3589a747e4fSDavid du Colombier 0,
3599a747e4fSDavid du Colombier vmwarelinear,
3609a747e4fSDavid du Colombier vmwaredrawinit,
3619a747e4fSDavid du Colombier 0,
3629a747e4fSDavid du Colombier 0,
3639a747e4fSDavid du Colombier 0,
3649a747e4fSDavid du Colombier vmwareflush,
3659a747e4fSDavid du Colombier };
3669a747e4fSDavid du Colombier
3679a747e4fSDavid du Colombier VGAcur vgavmwarecur = {
3689a747e4fSDavid du Colombier "vmwarehwgc",
3699a747e4fSDavid du Colombier
3709a747e4fSDavid du Colombier vmwareenable,
3719a747e4fSDavid du Colombier vmwaredisable,
3729a747e4fSDavid du Colombier vmwareload,
3739a747e4fSDavid du Colombier vmwaremove,
3749a747e4fSDavid du Colombier };
375