]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgavmware.c
kernel: cleanup the software mouse cursor mess
[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         Pcidev *p;
141
142         p = scr->pci;
143         if(p == nil || p->vid != PCIVMWARE)
144                 return;
145         switch(p->did){
146         default:
147                 return;
148         case VMWARE1:
149                 vm->ver = 1;
150                 vm->ra = 0x4560;
151                 vm->rd = 0x4560 + 4;
152                 break;
153         case VMWARE2:
154                 vm->ver = 2;
155                 vm->ra = p->mem[0].bar & ~3;
156                 vm->rd = vm->ra + 1;
157                 break;
158         }
159         // vm->fb = vmrd(vm, Rfbstart);
160         vm->fb = p->mem[1].bar & ~0xF;
161         vm->fb += vmrd(vm, Rfboffset);
162         vgalinearaddr(scr, vm->fb, vmrd(vm, Rfbmaxsize));
163         if(scr->apsize)
164                 addvgaseg("vmwarescreen", scr->paddr, scr->apsize);
165
166         if(scr->mmio==nil){
167                 ulong mmiobase, mmiosize;
168
169                 // mmiobase = vmrd(vm, Rmemstart);
170                 mmiobase = p->mem[2].bar & ~0xF;
171                 if(mmiobase == 0)
172                         return;
173                 mmiosize = vmrd(vm, Rmemsize);
174                 scr->mmio = vmap(mmiobase, mmiosize);
175                 if(scr->mmio == nil)
176                         return;
177                 vm->mmio = scr->mmio;
178                 vm->mmiosize = mmiosize;
179                 addvgaseg("vmwaremmio", mmiobase, mmiosize);
180         }
181         scr->mmio[FifoMin] = 4*sizeof(ulong);
182         scr->mmio[FifoMax] = vm->mmiosize;
183         scr->mmio[FifoNextCmd] = 4*sizeof(ulong);
184         scr->mmio[FifoStop] = 4*sizeof(ulong);
185         vmwr(vm, Rconfigdone, 1);
186 }
187
188 static void
189 vmfifowr(Vmware *vm, ulong v)
190 {
191         ulong *mm;
192
193         mm = vm->mmio;
194         if(mm[FifoNextCmd]+sizeof(ulong) == mm[FifoStop]
195         || (mm[FifoNextCmd]+sizeof(ulong) == mm[FifoMax]
196             && mm[FifoStop] == mm[FifoMin]))
197                 vmwait(vm);
198
199         mm[mm[FifoNextCmd]/sizeof(ulong)] = v;
200
201         /* must do this way so mm[FifoNextCmd] is never mm[FifoMax] */
202         v = mm[FifoNextCmd] + sizeof(ulong);
203         if(v == mm[FifoMax])
204                 v = mm[FifoMin];
205         mm[FifoNextCmd] = v;
206 }
207
208 static void
209 vmwareflush(VGAscr*, Rectangle r)
210 {
211         if(vm->mmio == nil)
212                 return;
213
214         vmfifowr(vm, Xupdate);
215         vmfifowr(vm, r.min.x);
216         vmfifowr(vm, r.min.y);
217         vmfifowr(vm, r.max.x-r.min.x);
218         vmfifowr(vm, r.max.y-r.min.y);
219         vmwait(vm);
220 }
221
222 static void
223 vmwareload(VGAscr*, Cursor *c)
224 {
225         int i;
226         ulong clr, set;
227         ulong and[16];
228         ulong xor[16];
229
230         if(vm->mmio == nil)
231                 return;
232
233         vmfifowr(vm, Xdefinecursor);
234         vmfifowr(vm, 1);        /* cursor id */
235         vmfifowr(vm, -c->offset.x);
236         vmfifowr(vm, -c->offset.y);
237
238         vmfifowr(vm, 16);       /* width */
239         vmfifowr(vm, 16);       /* height */
240         vmfifowr(vm, 1);        /* depth for and mask */
241         vmfifowr(vm, 1);        /* depth for xor mask */
242
243         for(i=0; i<16; i++){
244                 clr = (c->clr[i*2+1]<<8) | c->clr[i*2];
245                 set = (c->set[i*2+1]<<8) | c->set[i*2];
246                 and[i] = ~(clr|set);    /* clr and set pixels => black */
247                 xor[i] = clr&~set;              /* clr pixels => white */
248         }
249         for(i=0; i<16; i++)
250                 vmfifowr(vm, and[i]);
251         for(i=0; i<16; i++)
252                 vmfifowr(vm, xor[i]);
253
254         vmwait(vm);
255 }
256
257 static int
258 vmwaremove(VGAscr*, Point p)
259 {
260         if(vm->mmio == nil)
261                 return 1;
262         vmwr(vm, Rcursorid, 1);
263         vmwr(vm, Rcursorx, p.x);
264         vmwr(vm, Rcursory, p.y);
265         vmwr(vm, Rcursoron, CursorOnShow);
266         return 0;
267 }
268
269 static void
270 vmwaredisable(VGAscr*)
271 {
272         if(vm->mmio == nil)
273                 return;
274         vmwr(vm, Rcursorid, 1);
275         vmwr(vm, Rcursoron, CursorOnHide);
276 }
277
278 static void
279 vmwareenable(VGAscr*)
280 {
281         if(vm->mmio == nil)
282                 return;
283         vmwr(vm, Rcursorid, 1);
284         vmwr(vm, Rcursoron, CursorOnShow);
285 }
286
287 static int
288 vmwarescroll(VGAscr*, Rectangle r, Rectangle sr)
289 {
290         if(vm->mmio == nil)
291                 return 0;
292         vmfifowr(vm, Xrectcopy);
293         vmfifowr(vm, sr.min.x);
294         vmfifowr(vm, sr.min.y);
295         vmfifowr(vm, r.min.x);
296         vmfifowr(vm, r.min.y);
297         vmfifowr(vm, Dx(r));
298         vmfifowr(vm, Dy(r));
299         vmwait(vm);
300         return 1;
301 }
302
303 static int
304 vmwarefill(VGAscr*, Rectangle r, ulong sval)
305 {
306         if(vm->mmio == nil)
307                 return 0;
308         vmfifowr(vm, Xrectfill);
309         vmfifowr(vm, sval);
310         vmfifowr(vm, r.min.x);
311         vmfifowr(vm, r.min.y);
312         vmfifowr(vm, r.max.x-r.min.x);
313         vmfifowr(vm, r.max.y-r.min.y);
314         vmwait(vm);
315         return 1;
316 }
317
318 static void
319 vmwaredrawinit(VGAscr *scr)
320 {
321         scr->scroll = vmwarescroll;
322         if(vm->ver == 1)
323                 scr->fill = vmwarefill;
324 }
325
326 VGAdev vgavmwaredev = {
327         "vmware",
328         0,
329         0,
330         0,
331         vmwarelinear,
332         vmwaredrawinit,
333         0,
334         0,
335         0,
336         vmwareflush,
337 };
338
339 VGAcur vgavmwarecur = {
340         "vmwarehwgc",
341
342         vmwareenable,
343         vmwaredisable,
344         vmwareload,
345         vmwaremove,
346 };