xref: /plan9/sys/src/cmd/aux/vga/vmware.c (revision 8cf6001e50e647a07ccf484b8e2f9940411befb9)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 
5 #include "pci.h"
6 #include "vga.h"
7 
8 enum {
9 	Rid = 0,
10 	Renable,
11 	Rwidth,
12 	Rheight,
13 	Rmaxwidth,
14 	Rmaxheight,
15 	Rdepth,
16 	Rbpp,
17 	Rpseudocolor,
18 	Rrmask,
19 	Rgmask,
20 	Rbmask,
21 	Rbpl,
22 	Rfbstart,
23 	Rfboffset,
24 	Rfbmaxsize,
25 	Rfbsize,
26 	Rcap,
27 	Rmemstart,
28 	Rmemsize,
29 	Rconfigdone,
30 	Rsync,
31 	Rbusy,
32 	Rguestid,
33 	Rcursorid,
34 	Rcursorx,
35 	Rcursory,
36 	Rcursoron,
37 	Rhostbpp,
38 	Nreg,
39 
40 	Crectfill = 1<<0,
41 	Crectcopy = 1<<1,
42 	Crectpatfill = 1<<2,
43 	Coffscreen = 1<<3,
44 	Crasterop = 1<<4,
45 	Ccursor = 1<<5,
46 	Ccursorbypass = 1<<6,
47 	Ccursorbypass2 = 1<<7,
48 	C8bitemulation = 1<<8,
49 	Calphacursor = 1<<9,
50 
51 	Rpalette = 1024,
52 };
53 
54 typedef struct Vmware	Vmware;
55 struct Vmware {
56 	ulong	mmio;
57 	ulong	fb;
58 
59 	ulong	ra;
60 	ulong	rd;
61 
62 	ulong	r[Nreg];
63 
64 	char	chan[32];
65 	int	depth;
66 };
67 
68 static char*
69 rname[Nreg] = {
70 	"ID",
71 	"Enable",
72 	"Width",
73 	"Height",
74 	"MaxWidth",
75 	"MaxHeight",
76 	"Depth",
77 	"Bpp",
78 	"PseudoColor",
79 	"RedMask",
80 	"GreenMask",
81 	"BlueMask",
82 	"Bpl",
83 	"FbStart",
84 	"FbOffset",
85 	"FbMaxSize",
86 	"FbSize",
87 	"Cap",
88 	"MemStart",
89 	"MemSize",
90 	"ConfigDone",
91 	"Sync",
92 	"Busy",
93 	"GuestID",
94 	"CursorID",
95 	"CursorX",
96 	"CursorY",
97 	"CursorOn",
98 	"HostBpp",
99 };
100 
101 static ulong
vmrd(Vmware * vm,int i)102 vmrd(Vmware *vm, int i)
103 {
104 	outportl(vm->ra, i);
105 	return inportl(vm->rd);
106 }
107 
108 static void
vmwr(Vmware * vm,int i,ulong v)109 vmwr(Vmware *vm, int i, ulong v)
110 {
111 	outportl(vm->ra, i);
112 	outportl(vm->rd, v);
113 }
114 
115 static uint
bits(ulong a)116 bits(ulong a)
117 {
118 	int b;
119 
120 	for(b=0; a; a>>=1)
121 		if(a&1)
122 			b++;
123 	return b;
124 }
125 
126 static void
snarf(Vga * vga,Ctlr * ctlr)127 snarf(Vga* vga, Ctlr* ctlr)
128 {
129 	int extra, i;
130 	Pcidev *p;
131 	Vmware *vm;
132 
133 	p = vga->pci;
134 	if(p == nil)
135 		error("%s: vga->pci not set\n", ctlr->name);
136 
137 	vm = alloc(sizeof(Vmware));
138 
139 	switch(p->did){
140 	case 0x710:	/* VMware video chipset #1 */
141 		vm->ra = 0x4560;
142 		vm->rd = 0x4560+4;
143 		break;
144 
145 	case 0x405:	/* VMware video chipset #2, untested */
146 		vm->ra = p->mem[0].bar&~3;
147 		vm->rd = vm->ra+1;
148 		break;
149 
150 	default:
151 		error("%s: unrecognized chipset %.4ux\n", ctlr->name, p->did);
152 	}
153 
154 	for(i=0; i<Nreg; i++)
155 		vm->r[i] = vmrd(vm, i);
156 
157 //vmwr(vm, Renable, 0);
158 	/*
159 	 * Figure out color channel.  Delay errors until init,
160 	 * which is after the register dump.
161 	 */
162 	vm->depth = vm->r[Rbpp];
163 	extra = vm->r[Rbpp] - vm->r[Rdepth];
164 	if(vm->r[Rrmask] > vm->r[Rgmask] && vm->r[Rgmask] > vm->r[Rbmask]){
165 		if(extra)
166 			sprint(vm->chan, "x%d", extra);
167 		else
168 			vm->chan[0] = '\0';
169 		sprint(vm->chan+strlen(vm->chan), "r%dg%db%d", bits(vm->r[Rrmask]),
170 			bits(vm->r[Rgmask]), bits(vm->r[Rbmask]));
171 	}else if(vm->r[Rbmask] > vm->r[Rgmask] && vm->r[Rgmask] > vm->r[Rrmask]){
172 		sprint(vm->chan, "b%dg%dr%d", bits(vm->r[Rbmask]),
173 			bits(vm->r[Rgmask]), bits(vm->r[Rrmask]));
174 		if(extra)
175 			sprint(vm->chan+strlen(vm->chan), "x%d", extra);
176 	}else
177 		sprint(vm->chan, "unknown");
178 
179 	/* Record the frame buffer start, size */
180 	vga->vmb = vm->r[Rfbstart];
181 	vga->apz = vm->r[Rfbmaxsize];
182 
183 	vga->private = vm;
184 	ctlr->flag |= Fsnarf;
185 }
186 
187 
188 static void
options(Vga *,Ctlr * ctlr)189 options(Vga*, Ctlr* ctlr)
190 {
191 	ctlr->flag |= Hlinear|Henhanced|Foptions;
192 }
193 
194 
195 static void
clock(Vga *,Ctlr *)196 clock(Vga*, Ctlr*)
197 {
198 	/* BEST CLOCK ROUTINE EVER! */
199 }
200 
201 static void
init(Vga * vga,Ctlr * ctlr)202 init(Vga* vga, Ctlr* ctlr)
203 {
204 	Vmware *vm;
205 
206 	vm = vga->private;
207 
208 	vmwr(vm, Rid, (0x900000<<8)|2);
209 	if(vmrd(vm, Rid)&0xFF != 2)
210 		error("old vmware svga version %lud; need version 2\n",
211 			vmrd(vm,Rid)&0xFF);
212 
213 	ctlr->flag |= Ulinear;
214 	if(strcmp(vm->chan, "unknown") == 0)
215 		error("couldn't translate color masks into channel\n");
216 
217 	/* Always use the screen depth, and clip the screen size */
218 	vga->mode->z = vm->r[Rbpp];
219 	if(vga->mode->x > vm->r[Rmaxwidth])
220 		vga->mode->x = vm->r[Rmaxwidth];
221 	if(vga->mode->y > vm->r[Rmaxheight])
222 		vga->mode->y = vm->r[Rmaxheight];
223 
224 	vm->r[Rwidth] = vga->mode->x;
225 	vm->r[Rheight] = vga->mode->y;
226 
227 	/* Figure out the channel string */
228 	strcpy(vga->mode->chan, vm->chan);
229 
230 	/* Record the bytes per line */
231 	ctlr->flag |= Finit;
232 }
233 
234 static void
load(Vga * vga,Ctlr * ctlr)235 load(Vga* vga, Ctlr *ctlr)
236 {
237 	char buf[64];
238 	int x;
239 	Vmware *vm;
240 
241 	vm = vga->private;
242 	vmwr(vm, Rwidth, vm->r[Rwidth]);
243 	vmwr(vm, Rheight, vm->r[Rheight]);
244 	vmwr(vm, Renable, 1);
245 	vmwr(vm, Rguestid, 0x5010);	/* OS type is "Other" */
246 
247 	x = vmrd(vm, Rbpl)/(vm->depth/8);
248 	if(x != vga->mode->x){
249 		vga->virtx = x;
250 		sprint(buf, "%ludx%ludx%d %s", vga->virtx, vga->virty,
251 			vga->mode->z, vga->mode->chan);
252 		vgactlw("size", buf);
253 	}
254 	ctlr->flag |= Fload;
255 }
256 
257 static void
dump(Vga * vga,Ctlr * ctlr)258 dump(Vga* vga, Ctlr* ctlr)
259 {
260 	int i;
261 	Vmware *vm;
262 
263 	vm = vga->private;
264 
265 	for(i=0; i<Nreg; i++){
266 		printitem(ctlr->name, rname[i]);
267 		Bprint(&stdout, " %.8lux\n", vm->r[i]);
268 	}
269 
270 	printitem(ctlr->name, "chan");
271 	Bprint(&stdout, " %s\n", vm->chan);
272 	printitem(ctlr->name, "depth");
273 	Bprint(&stdout, " %d\n", vm->depth);
274 	printitem(ctlr->name, "linear");
275 
276 }
277 
278 Ctlr vmware = {
279 	"vmware",			/* name */
280 	snarf,				/* snarf */
281 	options,			/* options */
282 	init,				/* init */
283 	load,				/* load */
284 	dump,				/* dump */
285 };
286 
287 Ctlr vmwarehwgc = {
288 	"vmwarehwgc",			/* name */
289 	0,				/* snarf */
290 	0,				/* options */
291 	0,				/* init */
292 	0,				/* load */
293 	0,				/* dump */
294 };
295 
296