vmware_bootstrap.c revision 3bfa90b6
1/* 2 * Copyright 2011 VMWare, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Author: Unknown at vmware 26 * Author: Thomas Hellstrom <thellstrom@vmware.com> 27 */ 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#include "xf86.h" 33#include "compiler.h" 34#include "xf86Pci.h" /* pci */ 35#include "vm_device_version.h" 36#include "vmware_bootstrap.h" 37 38#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 39#include "xf86Resources.h" 40#endif 41 42#ifndef XSERVER_LIBPCIACCESS 43#include "vm_basic_types.h" 44#include "svga_reg.h" 45#endif 46 47#ifndef HAVE_XORG_SERVER_1_5_0 48#include <xf86_ansic.h> 49#include <xf86_libc.h> 50#endif 51 52#ifdef HaveDriverFuncs 53#define VMWARE_DRIVER_FUNC HaveDriverFuncs 54#else 55#define VMWARE_DRIVER_FUNC 0 56#endif 57 58/* 59 * So that the file compiles unmodified when dropped in to a < 6.9 source tree. 60 */ 61#ifndef _X_EXPORT 62#define _X_EXPORT 63#endif 64/* 65 * So that the file compiles unmodified when dropped into an xfree source tree. 66 */ 67#ifndef XORG_VERSION_CURRENT 68#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT 69#endif 70 71/* 72 * This is the only way I know to turn a #define of an integer constant into 73 * a constant string. 74 */ 75#define VMW_INNERSTRINGIFY(s) #s 76#define VMW_STRING(str) VMW_INNERSTRINGIFY(str) 77 78#define VMWARE_NAME "vmware" 79#define VMWARE_DRIVER_NAME "vmware" 80#define VMWARE_DRIVER_VERSION \ 81 (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL) 82#define VMWARE_DRIVER_VERSION_STRING \ 83 VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \ 84 "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL) 85 86static const char VMWAREBuildStr[] = "VMware Guest X Server " 87 VMWARE_DRIVER_VERSION_STRING " - build=$Name: $\n"; 88 89/* 90 * Standard four digit version string expected by VMware Tools installer. 91 * As the driver's version is only {major, minor, patchlevel}, 92 * The fourth digit may describe the commit number relative to the 93 * last version tag as output from `git describe` 94 */ 95 96#ifdef __GNUC__ 97#ifdef VMW_SUBPATCH 98const char vmware_drv_modinfo[] 99__attribute__((section(".modinfo"),unused)) = 100 "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH); 101#else 102const char vmware_drv_modinfo[] 103__attribute__((section(".modinfo"),unused)) = 104 "version=" VMWARE_DRIVER_VERSION_STRING ".0"; 105#endif /*VMW_SUBPATCH*/ 106#endif 107 108#ifndef XSERVER_LIBPCIACCESS 109static resRange vmwareLegacyRes[] = { 110 { ResExcIoBlock, SVGA_LEGACY_BASE_PORT, 111 SVGA_LEGACY_BASE_PORT + SVGA_NUM_PORTS*sizeof(uint32)}, 112 _VGA_EXCLUSIVE, _END 113}; 114#else 115#define vmwareLegacyRes NULL 116#endif 117 118#if XSERVER_LIBPCIACCESS 119#define VENDOR_ID(p) (p)->vendor_id 120#define DEVICE_ID(p) (p)->device_id 121#define SUBVENDOR_ID(p) (p)->subvendor_id 122#define SUBSYS_ID(p) (p)->subdevice_id 123#define CHIP_REVISION(p) (p)->revision 124#else 125#define VENDOR_ID(p) (p)->vendor 126#define DEVICE_ID(p) (p)->chipType 127#define SUBVENDOR_ID(p) (p)->subsysVendor 128#define SUBSYS_ID(p) (p)->subsysCard 129#define CHIP_REVISION(p) (p)->chipRev 130#endif 131 132#if XSERVER_LIBPCIACCESS 133 134#define VMWARE_DEVICE_MATCH(d, i) \ 135 {PCI_VENDOR_ID_VMWARE, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) } 136 137static const struct pci_id_match VMwareDeviceMatch[] = { 138 VMWARE_DEVICE_MATCH (PCI_DEVICE_ID_VMWARE_SVGA2, 0 ), 139 VMWARE_DEVICE_MATCH (PCI_DEVICE_ID_VMWARE_SVGA, 0 ), 140 { 0, 0, 0 }, 141}; 142#endif 143 144/* 145 * Currently, even the PCI obedient 0405 chip still only obeys IOSE and 146 * MEMSE for the SVGA resources. Thus, RES_EXCLUSIVE_VGA is required. 147 * 148 * The 0710 chip also uses hardcoded IO ports that aren't disablable. 149 */ 150 151static PciChipsets VMWAREPciChipsets[] = { 152 { PCI_DEVICE_ID_VMWARE_SVGA2, PCI_DEVICE_ID_VMWARE_SVGA2, RES_EXCLUSIVE_VGA }, 153 { PCI_DEVICE_ID_VMWARE_SVGA, PCI_DEVICE_ID_VMWARE_SVGA, vmwareLegacyRes }, 154 { -1, -1, RES_UNDEFINED } 155}; 156 157static SymTabRec VMWAREChipsets[] = { 158 { PCI_DEVICE_ID_VMWARE_SVGA2, "vmware0405" }, 159 { PCI_DEVICE_ID_VMWARE_SVGA, "vmware0710" }, 160 { -1, NULL } 161}; 162 163#ifdef XFree86LOADER 164static XF86ModuleVersionInfo vmwareVersRec = { 165 VMWARE_DRIVER_NAME, 166 MODULEVENDORSTRING, 167 MODINFOSTRING1, 168 MODINFOSTRING2, 169 XORG_VERSION_CURRENT, 170 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, 171 ABI_CLASS_VIDEODRV, 172 ABI_VIDEODRV_VERSION, 173 MOD_CLASS_VIDEODRV, 174 { 0, 0, 0, 0} 175}; 176#endif /* XFree86LOADER */ 177 178static const OptionInfoRec VMWAREOptions[] = { 179 { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, 180 { OPTION_XINERAMA, "Xinerama", OPTV_BOOLEAN, {0}, FALSE }, 181 { OPTION_STATIC_XINERAMA, "StaticXinerama", OPTV_STRING, {0}, FALSE }, 182 { OPTION_GUI_LAYOUT, "GuiLayout", OPTV_STRING, {0}, FALSE }, 183 { OPTION_DEFAULT_MODE, "AddDefaultMode", OPTV_BOOLEAN, {0}, FALSE }, 184 { OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE}, 185 { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, 186 { OPTION_DIRECT_PRESENTS, "DirectPresents", OPTV_BOOLEAN, {0}, FALSE}, 187 { OPTION_HW_PRESENTS, "HWPresents", OPTV_BOOLEAN, {0}, FALSE}, 188 { OPTION_RENDERCHECK, "RenderCheck", OPTV_BOOLEAN, {0}, FALSE}, 189 { -1, NULL, OPTV_NONE, {0}, FALSE } 190}; 191 192OptionInfoPtr VMWARECopyOptions(void) 193{ 194 OptionInfoPtr options; 195 if (!(options = malloc(sizeof(VMWAREOptions)))) 196 return NULL; 197 198 memcpy(options, VMWAREOptions, sizeof(VMWAREOptions)); 199 return options; 200} 201 202static Bool 203VMwarePreinitStub(ScrnInfoPtr pScrn, int flags) 204{ 205#if XSERVER_LIBPCIACCESS 206 struct pci_device *pciInfo; 207#else 208 pciVideoPtr pciInfo; 209#endif /* XSERVER_LIBPCIACCESS */ 210 EntityInfoPtr pEnt; 211 212 pScrn->PreInit = pScrn->driverPrivate; 213 214#ifdef BUILD_VMWGFX 215 pScrn->driverPrivate = NULL; 216 217 /* 218 * Try vmwgfx path. 219 */ 220 if ((*pScrn->PreInit)(pScrn, flags)) 221 return TRUE; 222 223#else 224 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 225 "Driver was compiled without KMS- and 3D support.\n"); 226#endif /* defined(BUILD_VMWGFX) */ 227 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 228 "Disabling 3D support.\n"); 229 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 230 "Disabling Render Acceleration.\n"); 231 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 232 "Disabling RandR12+ support.\n"); 233 234 pScrn->driverPrivate = NULL; 235 vmwlegacy_hookup(pScrn); 236 237 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 238 if (pEnt->location.type != BUS_PCI) 239 return FALSE; 240 241 pciInfo = xf86GetPciInfoForEntity(pEnt->index); 242 if (pciInfo == NULL) 243 return FALSE; 244 245 pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets, 246 DEVICE_ID(pciInfo)); 247 248 return (*pScrn->PreInit)(pScrn, flags); 249}; 250 251#if XSERVER_LIBPCIACCESS 252static Bool 253VMwarePciProbe (DriverPtr drv, 254 int entity_num, 255 struct pci_device *device, 256 intptr_t match_data) 257{ 258 ScrnInfoPtr scrn = NULL; 259 EntityInfoPtr entity; 260 261 scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VMWAREPciChipsets, 262 NULL, NULL, NULL, NULL, NULL); 263 if (scrn != NULL) { 264 scrn->driverVersion = VMWARE_DRIVER_VERSION; 265 scrn->driverName = VMWARE_DRIVER_NAME; 266 scrn->name = VMWARE_NAME; 267 scrn->Probe = NULL; 268 } 269 270 entity = xf86GetEntityInfo(entity_num); 271 switch (DEVICE_ID(device)) { 272 case PCI_DEVICE_ID_VMWARE_SVGA2: 273 case PCI_DEVICE_ID_VMWARE_SVGA: 274 xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n"); 275 276#ifdef BUILD_VMWGFX 277 vmwgfx_hookup(scrn); 278#else 279 vmwlegacy_hookup(scrn); 280#endif /* defined(BUILD_VMWGFX) */ 281 282 scrn->driverPrivate = scrn->PreInit; 283 scrn->PreInit = VMwarePreinitStub; 284 break; 285 default: 286 xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Unknown device\n"); 287 } 288 return scrn != NULL; 289} 290#else 291 292/* 293 *---------------------------------------------------------------------- 294 * 295 * RewriteTagString -- 296 * 297 * Rewrites the given string, removing the $Name: $, and 298 * replacing it with the contents. The output string must 299 * have enough room, or else. 300 * 301 * Results: 302 * 303 * Output string updated. 304 * 305 * Side effects: 306 * None. 307 * 308 *---------------------------------------------------------------------- 309 */ 310 311static void 312RewriteTagString(const char *istr, char *ostr, int osize) 313{ 314 int chr; 315 Bool inTag = FALSE; 316 char *op = ostr; 317 318 do { 319 chr = *istr++; 320 if (chr == '$') { 321 if (inTag) { 322 inTag = FALSE; 323 for (; op > ostr && op[-1] == ' '; op--) { 324 } 325 continue; 326 } 327 if (strncmp(istr, "Name:", 5) == 0) { 328 istr += 5; 329 istr += strspn(istr, " "); 330 inTag = TRUE; 331 continue; 332 } 333 } 334 *op++ = chr; 335 } while (chr); 336} 337 338static Bool 339VMWAREProbe(DriverPtr drv, int flags) 340{ 341 int numDevSections, numUsed; 342 GDevPtr *devSections; 343 int *usedChips; 344 int i; 345 Bool foundScreen = FALSE; 346 char buildString[sizeof(VMWAREBuildStr)]; 347 348 RewriteTagString(VMWAREBuildStr, buildString, sizeof(VMWAREBuildStr)); 349 xf86MsgVerb(X_PROBED, 4, "%s", buildString); 350 351 numDevSections = xf86MatchDevice(VMWARE_DRIVER_NAME, &devSections); 352 if (numDevSections <= 0) { 353#ifdef DEBUG 354 xf86MsgVerb(X_ERROR, 0, "No vmware driver section\n"); 355#endif 356 return FALSE; 357 } 358 if (xf86GetPciVideoInfo()) { 359 VmwareLog(("Some PCI Video Info Exists\n")); 360 numUsed = xf86MatchPciInstances(VMWARE_NAME, PCI_VENDOR_ID_VMWARE, 361 VMWAREChipsets, VMWAREPciChipsets, devSections, 362 numDevSections, drv, &usedChips); 363 free(devSections); 364 if (numUsed <= 0) 365 return FALSE; 366 if (flags & PROBE_DETECT) 367 foundScreen = TRUE; 368 else 369 for (i = 0; i < numUsed; i++) { 370 ScrnInfoPtr pScrn = NULL; 371 372 VmwareLog(("Even some VMware SVGA PCI instances exists\n")); 373 pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i], 374 VMWAREPciChipsets, NULL, NULL, NULL, 375 NULL, NULL); 376 if (pScrn) { 377 VmwareLog(("And even configuration suceeded\n")); 378 pScrn->driverVersion = VMWARE_DRIVER_VERSION; 379 pScrn->driverName = VMWARE_DRIVER_NAME; 380 pScrn->name = VMWARE_NAME; 381 pScrn->Probe = VMWAREProbe; 382 383#ifdef BUILD_VMWGFX 384 vmwgfx_hookup(pScrn); 385#else 386 vmwlegacy_hookup(pScrn); 387#endif /* defined(BUILD_VMWGFX) */ 388 389 pScrn->driverPrivate = pScrn->PreInit; 390 pScrn->PreInit = VMwarePreinitStub; 391 foundScreen = TRUE; 392 } 393 } 394 free(usedChips); 395 } 396 return foundScreen; 397} 398#endif 399 400static void 401VMWAREIdentify(int flags) 402{ 403 xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets); 404} 405 406static const OptionInfoRec * 407VMWAREAvailableOptions(int chipid, int busid) 408{ 409 return VMWAREOptions; 410} 411 412#if VMWARE_DRIVER_FUNC 413static Bool 414VMWareDriverFunc(ScrnInfoPtr pScrn, 415 xorgDriverFuncOp op, 416 pointer data) 417{ 418 CARD32 *flag; 419 xorgRRModeMM *modemm; 420 421 switch (op) { 422 case GET_REQUIRED_HW_INTERFACES: 423 flag = (CARD32 *)data; 424 425 if (flag) { 426 *flag = HW_IO | HW_MMIO; 427 } 428 return TRUE; 429 case RR_GET_MODE_MM: 430 modemm = (xorgRRModeMM *)data; 431 432 /* 433 * Because changing the resolution of the guest is usually changing the size 434 * of a window on the host desktop, the real physical DPI will not change. To 435 * keep the guest in sync, we scale the 'physical' screen dimensions to 436 * keep the DPI constant. 437 */ 438 if (modemm && modemm->mode) { 439 modemm->mmWidth = (modemm->mode->HDisplay * VMWARE_INCHTOMM + 440 pScrn->xDpi / 2) / pScrn->xDpi; 441 modemm->mmHeight = (modemm->mode->VDisplay * VMWARE_INCHTOMM + 442 pScrn->yDpi / 2) / pScrn->yDpi; 443 } 444 return TRUE; 445 default: 446 return FALSE; 447 } 448} 449#endif 450 451 452_X_EXPORT DriverRec vmware = { 453 VMWARE_DRIVER_VERSION, 454 VMWARE_DRIVER_NAME, 455 VMWAREIdentify, 456#if XSERVER_LIBPCIACCESS 457 NULL, 458#else 459 VMWAREProbe, 460#endif 461 VMWAREAvailableOptions, 462 NULL, 463 0, 464#if VMWARE_DRIVER_FUNC 465 VMWareDriverFunc, 466#endif 467#if XSERVER_LIBPCIACCESS 468 VMwareDeviceMatch, 469 VMwarePciProbe, 470#endif 471}; 472 473 474#ifdef XFree86LOADER 475static MODULESETUPPROTO(vmwareSetup); 476 477_X_EXPORT XF86ModuleData vmwareModuleData = { 478 &vmwareVersRec, 479 vmwareSetup, 480 NULL 481}; 482 483static pointer 484vmwareSetup(pointer module, pointer opts, int *errmaj, int *errmin) 485{ 486 static Bool setupDone = FALSE; 487 488 if (!setupDone) { 489 setupDone = TRUE; 490 491 xf86AddDriver(&vmware, module, VMWARE_DRIVER_FUNC); 492 493 VMWARERefSymLists(); 494 495 return (pointer)1; 496 } 497 if (errmaj) { 498 *errmaj = LDR_ONCEONLY; 499 } 500 return NULL; 501} 502#endif /* XFree86LOADER */ 503