xref: /plan9-contrib/sys/src/9/pc/vgavmware.c (revision 27acba7cf6d37c65abba4ecf8ad572a5980447ad)
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