]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/vga/vmware.c
Import sources from 2011-03-30 iso image
[plan9front.git] / sys / src / cmd / aux / vga / vmware.c
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
102 vmrd(Vmware *vm, int i)
103 {
104         outportl(vm->ra, i);
105         return inportl(vm->rd);
106 }
107
108 static void
109 vmwr(Vmware *vm, int i, ulong v)
110 {
111         outportl(vm->ra, i);
112         outportl(vm->rd, v);
113 }
114
115 static uint
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
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
189 options(Vga*, Ctlr* ctlr)
190 {
191         ctlr->flag |= Hlinear|Henhanced|Foptions;
192 }
193
194
195 static void
196 clock(Vga*, Ctlr*)
197 {
198         /* BEST CLOCK ROUTINE EVER! */
199 }
200
201 static void
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
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
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