]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgavmware.c
vgavmware: fix hardware acceleration (fill is not available with SVGA2)
[plan9front.git] / sys / src / 9 / pc / vgavmware.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "../port/error.h"
8
9 #define Image   IMAGE
10 #include <draw.h>
11 #include <memdraw.h>
12 #include <cursor.h>
13 #include "screen.h"
14
15 enum {
16         PCIVMWARE       = 0x15AD,       /* PCI VID */
17
18         VMWARE1         = 0x0710,       /* PCI DID */
19         VMWARE2         = 0x0405,
20 };
21
22 enum {
23         Rid = 0,
24         Renable,
25         Rwidth,
26         Rheight,
27         Rmaxwidth,
28
29         Rmaxheight,
30         Rdepth,
31         Rbpp,
32         Rpseudocolor,
33         Rrmask,
34
35         Rgmask,
36         Rbmask,
37         Rbpl,
38         Rfbstart,       /* deprecated */
39         Rfboffset,
40
41         Rfbmaxsize,
42         Rfbsize,
43         Rcap,
44         Rmemstart,      /* deprecated */
45         Rmemsize,
46
47         Rconfigdone,
48         Rsync,
49         Rbusy,
50         Rguestid,
51         Rcursorid,
52
53         Rcursorx,
54         Rcursory,
55         Rcursoron,
56         Nreg,
57
58         FifoMin = 0,
59         FifoMax = 1,
60         FifoNextCmd = 2,
61         FifoStop = 3,
62         FifoUser = 4,
63
64         Xupdate = 1,
65         Xrectfill = 2,
66         Xrectcopy = 3,
67         Xdefinebitmap = 4,
68         Xdefinebitmapscanline = 5,
69         Xdefinepixmap = 6,
70         Xdefinepixmapscanline = 7,
71         Xrectbitmapfill = 8,
72         Xrectpixmapfill = 9,
73         Xrectbitmapcopy = 10,
74         Xrectpixmapcopy = 11,
75         Xfreeobject = 12,
76         Xrectropfill = 13,
77         Xrectropcopy = 14,
78         Xrectropbitmapfill = 15,
79         Xrectroppixmapfill = 16,
80         Xrectropbitmapcopy = 17,
81         Xrectroppixmapcopy = 18,
82         Xdefinecursor = 19,
83         Xdisplaycursor = 20,
84         Xmovecursor = 21,
85         Xdefinealphacursor = 22,
86         Xcmdmax = 23,
87
88         CursorOnHide = 0,
89         CursorOnShow = 1,
90         CursorOnRemoveFromFb = 2,
91         CursorOnRestoreToFb = 3,
92
93         Rpalette = 1024,
94 };
95
96 typedef struct Vmware   Vmware;
97 struct Vmware {
98         ulong   fb;
99
100         ulong   ra;
101         ulong   rd;
102
103         ulong   r[Nreg];
104         ulong   *mmio;
105         ulong   mmiosize;
106
107         char    chan[32];
108         int     depth;
109         int     ver;
110 };
111
112 Vmware xvm;
113 Vmware *vm=&xvm;
114
115 static ulong
116 vmrd(Vmware *vm, int i)
117 {
118         outl(vm->ra, i);
119         return inl(vm->rd);
120 }
121
122 static void
123 vmwr(Vmware *vm, int i, ulong v)
124 {
125         outl(vm->ra, i);
126         outl(vm->rd, v);
127 }
128
129 static void
130 vmwait(Vmware *vm)
131 {
132         vmwr(vm, Rsync, 1);
133         while(vmrd(vm, Rbusy))
134                 ;
135 }
136
137 static void
138 vmwarelinear(VGAscr* scr, int, int)
139 {
140         char err[64];
141         Pcidev *p;
142
143         err[0] = 0;
144         p = nil;
145         while((p = pcimatch(p, PCIVMWARE, 0)) != nil){
146                 if(p->ccrb != Pcibcdisp)
147                         continue;
148                 switch(p->did){
149                 default:
150                         snprint(err, sizeof err, "unknown vmware pci did %.4ux",
151                                 p->did);
152                         continue;
153                 case VMWARE1:
154                         vm->ver = 1;
155                         vm->ra = 0x4560;
156                         vm->rd = 0x4560 + 4;
157                         break;
158                 case VMWARE2:
159                         vm->ver = 2;
160                         vm->ra = p->mem[0].bar & ~3;
161                         vm->rd = vm->ra + 1;
162                         break;
163                 }
164                 break;                  /* found a card, p is set */
165         }
166         if(p == nil)
167                 error(err[0]? err: "no vmware vga card found");
168         // vm->fb = vmrd(vm, Rfbstart);
169         vm->fb = p->mem[1].bar & ~0xF;
170         vm->fb += vmrd(vm, Rfboffset);
171         vgalinearaddr(scr, vm->fb, vmrd(vm, Rfbmaxsize));
172         if(scr->apsize)
173                 addvgaseg("vmwarescreen", scr->paddr, scr->apsize);
174
175         if(scr->mmio==nil){
176                 ulong mmiobase, mmiosize;
177
178                 // mmiobase = vmrd(vm, Rmemstart);
179                 mmiobase = p->mem[2].bar & ~0xF;
180                 if(mmiobase == 0)
181                         return;
182                 mmiosize = vmrd(vm, Rmemsize);
183                 scr->mmio = vmap(mmiobase, mmiosize);
184                 if(scr->mmio == nil)
185                         return;
186                 vm->mmio = scr->mmio;
187                 vm->mmiosize = mmiosize;
188                 addvgaseg("vmwaremmio", mmiobase, mmiosize);
189         }
190         scr->mmio[FifoMin] = 4*sizeof(ulong);
191         scr->mmio[FifoMax] = vm->mmiosize;
192         scr->mmio[FifoNextCmd] = 4*sizeof(ulong);
193         scr->mmio[FifoStop] = 4*sizeof(ulong);
194         vmwr(vm, Rconfigdone, 1);
195 }
196
197 static void
198 vmfifowr(Vmware *vm, ulong v)
199 {
200         ulong *mm;
201
202         mm = vm->mmio;
203         if(mm[FifoNextCmd]+sizeof(ulong) == mm[FifoStop]
204         || (mm[FifoNextCmd]+sizeof(ulong) == mm[FifoMax]
205             && mm[FifoStop] == mm[FifoMin]))
206                 vmwait(vm);
207
208         mm[mm[FifoNextCmd]/sizeof(ulong)] = v;
209
210         /* must do this way so mm[FifoNextCmd] is never mm[FifoMax] */
211         v = mm[FifoNextCmd] + sizeof(ulong);
212         if(v == mm[FifoMax])
213                 v = mm[FifoMin];
214         mm[FifoNextCmd] = v;
215 }
216
217 static void
218 vmwareflush(VGAscr*, Rectangle r)
219 {
220         if(vm->mmio == nil)
221                 return;
222
223         vmfifowr(vm, Xupdate);
224         vmfifowr(vm, r.min.x);
225         vmfifowr(vm, r.min.y);
226         vmfifowr(vm, r.max.x-r.min.x);
227         vmfifowr(vm, r.max.y-r.min.y);
228         vmwait(vm);
229 }
230
231 static void
232 vmwareload(VGAscr*, Cursor *c)
233 {
234         int i;
235         ulong clr, set;
236         ulong and[16];
237         ulong xor[16];
238
239         if(vm->mmio == nil)
240                 return;
241
242         vmfifowr(vm, Xdefinecursor);
243         vmfifowr(vm, 1);        /* cursor id */
244         vmfifowr(vm, -c->offset.x);
245         vmfifowr(vm, -c->offset.y);
246
247         vmfifowr(vm, 16);       /* width */
248         vmfifowr(vm, 16);       /* height */
249         vmfifowr(vm, 1);        /* depth for and mask */
250         vmfifowr(vm, 1);        /* depth for xor mask */
251
252         for(i=0; i<16; i++){
253                 clr = (c->clr[i*2+1]<<8) | c->clr[i*2];
254                 set = (c->set[i*2+1]<<8) | c->set[i*2];
255                 and[i] = ~(clr|set);    /* clr and set pixels => black */
256                 xor[i] = clr&~set;              /* clr pixels => white */
257         }
258         for(i=0; i<16; i++)
259                 vmfifowr(vm, and[i]);
260         for(i=0; i<16; i++)
261                 vmfifowr(vm, xor[i]);
262
263         vmwait(vm);
264 }
265
266 static int
267 vmwaremove(VGAscr*, Point p)
268 {
269         if(vm->mmio == nil)
270                 return 1;
271         vmwr(vm, Rcursorid, 1);
272         vmwr(vm, Rcursorx, p.x);
273         vmwr(vm, Rcursory, p.y);
274         vmwr(vm, Rcursoron, CursorOnShow);
275         return 0;
276 }
277
278 static void
279 vmwaredisable(VGAscr*)
280 {
281         if(vm->mmio == nil)
282                 return;
283         vmwr(vm, Rcursorid, 1);
284         vmwr(vm, Rcursoron, CursorOnHide);
285 }
286
287 static void
288 vmwareenable(VGAscr*)
289 {
290         if(vm->mmio == nil)
291                 return;
292         vmwr(vm, Rcursorid, 1);
293         vmwr(vm, Rcursoron, CursorOnShow);
294 }
295
296 static int
297 vmwarescroll(VGAscr*, Rectangle r, Rectangle sr)
298 {
299         if(vm->mmio == nil)
300                 return 0;
301         vmfifowr(vm, Xrectcopy);
302         vmfifowr(vm, sr.min.x);
303         vmfifowr(vm, sr.min.y);
304         vmfifowr(vm, r.min.x);
305         vmfifowr(vm, r.min.y);
306         vmfifowr(vm, Dx(r));
307         vmfifowr(vm, Dy(r));
308         vmwait(vm);
309         return 1;
310 }
311
312 static int
313 vmwarefill(VGAscr*, Rectangle r, ulong sval)
314 {
315         if(vm->mmio == nil)
316                 return 0;
317         vmfifowr(vm, Xrectfill);
318         vmfifowr(vm, sval);
319         vmfifowr(vm, r.min.x);
320         vmfifowr(vm, r.min.y);
321         vmfifowr(vm, r.max.x-r.min.x);
322         vmfifowr(vm, r.max.y-r.min.y);
323         vmwait(vm);
324         return 1;
325 }
326
327 static void
328 vmwaredrawinit(VGAscr *scr)
329 {
330         scr->scroll = vmwarescroll;
331         if(vm->ver == 1)
332                 scr->fill = vmwarefill;
333 }
334
335 VGAdev vgavmwaredev = {
336         "vmware",
337         0,
338         0,
339         0,
340         vmwarelinear,
341         vmwaredrawinit,
342         0,
343         0,
344         0,
345         vmwareflush,
346 };
347
348 VGAcur vgavmwarecur = {
349         "vmwarehwgc",
350
351         vmwareenable,
352         vmwaredisable,
353         vmwareload,
354         vmwaremove,
355 };