vmware.c 4.8 KB

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