vmware.c 5.2 KB

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