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