vmware.c revision 6df26cac
1/* ********************************************************** 2 * Copyright (C) 1998-2001 VMware, Inc. 3 * All Rights Reserved 4 * **********************************************************/ 5#ifdef VMX86_DEVEL 6char rcsId_vmware[] = 7 "Id: vmware.c,v 1.11 2001/02/23 02:10:39 yoel Exp $"; 8#endif 9/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/vmware.c,v 1.18 2003/09/24 02:43:31 dawes Exp $ */ 10 11#ifdef HAVE_CONFIG_H 12#include "config.h" 13#endif 14 15/* 16 * TODO: support the vmware linux kernel fb driver (Option "UseFBDev"). 17 */ 18 19#include "xf86.h" 20#include "xf86_OSproc.h" 21#include "xf86Resources.h" 22 23#include "compiler.h" /* inb/outb */ 24 25#include "xf86PciInfo.h" /* pci vendor id */ 26#include "xf86Pci.h" /* pci */ 27 28#include "mipointer.h" /* sw cursor */ 29#include "mibstore.h" /* backing store */ 30#include "micmap.h" /* mi color map */ 31#include "vgaHW.h" /* VGA hardware */ 32#include "fb.h" 33#include "shadowfb.h" /* ShadowFB wrappers */ 34 35#include "xf86cmap.h" /* xf86HandleColormaps */ 36 37#include "vmware.h" 38#include "guest_os.h" 39#include "vm_device_version.h" 40#include "svga_modes.h" 41 42#ifdef HaveDriverFuncs 43#define VMWARE_DRIVER_FUNC HaveDriverFuncs 44#else 45#define VMWARE_DRIVER_FUNC 0 46#endif 47 48/* 49 * So that the file compiles unmodified when dropped in to a < 6.9 source tree. 50 */ 51#ifndef _X_EXPORT 52#define _X_EXPORT 53#endif 54/* 55 * So that the file compiles unmodified when dropped into an xfree source tree. 56 */ 57#ifndef XORG_VERSION_CURRENT 58#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT 59#endif 60 61/* 62 * Sanity check that xf86PciInfo.h has the correct values (which come from 63 * the VMware source tree in vm_device_version.h. 64 */ 65#if PCI_CHIP_VMWARE0405 != PCI_DEVICE_ID_VMWARE_SVGA2 66#error "PCI_CHIP_VMWARE0405 is wrong, update it from vm_device_version.h" 67#endif 68#if PCI_CHIP_VMWARE0710 != PCI_DEVICE_ID_VMWARE_SVGA 69#error "PCI_CHIP_VMWARE0710 is wrong, update it from vm_device_version.h" 70#endif 71#if PCI_VENDOR_VMWARE != PCI_VENDOR_ID_VMWARE 72#error "PCI_VENDOR_VMWARE is wrong, update it from vm_device_version.h" 73#endif 74 75/* 76 * This is the only way I know to turn a #define of an integer constant into 77 * a constant string. 78 */ 79#define VMW_INNERSTRINGIFY(s) #s 80#define VMW_STRING(str) VMW_INNERSTRINGIFY(str) 81 82#define VMWARE_NAME "VMWARE" 83#define VMWARE_DRIVER_NAME "vmware" 84#define VMWARE_MAJOR_VERSION 10 85#define VMWARE_MINOR_VERSION 16 86#define VMWARE_PATCHLEVEL 1 87#define VMWARE_DRIVER_VERSION \ 88 (VMWARE_MAJOR_VERSION * 65536 + VMWARE_MINOR_VERSION * 256 + VMWARE_PATCHLEVEL) 89#define VMWARE_DRIVER_VERSION_STRING \ 90 VMW_STRING(VMWARE_MAJOR_VERSION) "." VMW_STRING(VMWARE_MINOR_VERSION) \ 91 "." VMW_STRING(VMWARE_PATCHLEVEL) 92 93static const char VMWAREBuildStr[] = "VMware Guest X Server " 94 VMWARE_DRIVER_VERSION_STRING " - build=$Name: $\n"; 95 96/* 97 * Standard four digit version string expected by VMware Tools installer. 98 * As the driver's version is only {major, minor, patchlevel}, simply append an 99 * extra zero for the fourth digit. 100 */ 101#ifdef __GNUC__ 102const char vm_svga_version[] __attribute__((section(".modinfo"),unused)) = 103 "version=" VMWARE_DRIVER_VERSION_STRING ".0"; 104#endif 105 106static SymTabRec VMWAREChipsets[] = { 107 { PCI_CHIP_VMWARE0405, "vmware0405" }, 108 { PCI_CHIP_VMWARE0710, "vmware0710" }, 109 { -1, NULL } 110}; 111 112static resRange vmwareLegacyRes[] = { 113 { ResExcIoBlock, SVGA_LEGACY_BASE_PORT, 114 SVGA_LEGACY_BASE_PORT + SVGA_NUM_PORTS*sizeof(uint32)}, 115 _VGA_EXCLUSIVE, _END 116}; 117 118#if XSERVER_LIBPCIACCESS 119 120#define VMWARE_DEVICE_MATCH(d, i) \ 121 {PCI_VENDOR_VMWARE, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) } 122 123static const struct pci_id_match VMwareDeviceMatch[] = { 124 VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0405, 0 ), 125 VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0710, 0 ), 126 { 0, 0, 0 }, 127}; 128#endif 129 130/* 131 * Currently, even the PCI obedient 0405 chip still only obeys IOSE and 132 * MEMSE for the SVGA resources. Thus, RES_EXCLUSIVE_VGA is required. 133 * 134 * The 0710 chip also uses hardcoded IO ports that aren't disablable. 135 */ 136 137static PciChipsets VMWAREPciChipsets[] = { 138 { PCI_CHIP_VMWARE0405, PCI_CHIP_VMWARE0405, RES_EXCLUSIVE_VGA }, 139 { PCI_CHIP_VMWARE0710, PCI_CHIP_VMWARE0710, vmwareLegacyRes }, 140 { -1, -1, RES_UNDEFINED } 141}; 142 143static const char *vgahwSymbols[] = { 144 "vgaHWGetHWRec", 145 "vgaHWGetIOBase", 146 "vgaHWGetIndex", 147 "vgaHWInit", 148 "vgaHWProtect", 149 "vgaHWRestore", 150 "vgaHWSave", 151 "vgaHWSaveScreen", 152 "vgaHWUnlock", 153 NULL 154}; 155 156static const char *fbSymbols[] = { 157 "fbCreateDefColormap", 158 "fbPictureInit", 159 "fbScreenInit", 160 NULL 161}; 162 163static const char *ramdacSymbols[] = { 164 "xf86CreateCursorInfoRec", 165 "xf86DestroyCursorInfoRec", 166 "xf86InitCursor", 167 NULL 168}; 169 170static const char *shadowfbSymbols[] = { 171 "ShadowFBInit2", 172 NULL 173}; 174 175#ifdef XFree86LOADER 176static XF86ModuleVersionInfo vmwareVersRec = { 177 "vmware", 178 MODULEVENDORSTRING, 179 MODINFOSTRING1, 180 MODINFOSTRING2, 181 XORG_VERSION_CURRENT, 182 VMWARE_MAJOR_VERSION, VMWARE_MINOR_VERSION, VMWARE_PATCHLEVEL, 183 ABI_CLASS_VIDEODRV, 184 ABI_VIDEODRV_VERSION, 185 MOD_CLASS_VIDEODRV, 186 { 0, 0, 0, 0} 187}; 188#endif /* XFree86LOADER */ 189 190typedef enum { 191 OPTION_HW_CURSOR, 192 OPTION_XINERAMA, 193 OPTION_STATIC_XINERAMA 194} VMWAREOpts; 195 196static const OptionInfoRec VMWAREOptions[] = { 197 { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, 198 { OPTION_XINERAMA, "Xinerama", OPTV_BOOLEAN, {0}, FALSE }, 199 { OPTION_STATIC_XINERAMA, "StaticXinerama", OPTV_STRING, {0}, FALSE }, 200 { -1, NULL, OPTV_NONE, {0}, FALSE } 201}; 202 203/* Table of default modes to always add to the mode list. */ 204 205typedef struct { 206 int width; 207 int height; 208} VMWAREDefaultMode; 209 210#define SVGA_DEFAULT_MODE(width, height) { width, height, }, 211 212static const VMWAREDefaultMode VMWAREDefaultModes[] = { 213 SVGA_DEFAULT_MODES 214}; 215 216#undef SVGA_DEFAULT_MODE 217 218static void VMWAREStopFIFO(ScrnInfoPtr pScrn); 219static void VMWARESave(ScrnInfoPtr pScrn); 220 221static Bool 222VMWAREGetRec(ScrnInfoPtr pScrn) 223{ 224 if (pScrn->driverPrivate != NULL) { 225 return TRUE; 226 } 227 pScrn->driverPrivate = xnfcalloc(sizeof(VMWARERec), 1); 228 /* FIXME: Initialize driverPrivate... */ 229 return TRUE; 230} 231 232static void 233VMWAREFreeRec(ScrnInfoPtr pScrn) 234{ 235 if (pScrn->driverPrivate) { 236 xfree(pScrn->driverPrivate); 237 pScrn->driverPrivate = NULL; 238 } 239} 240 241CARD32 242vmwareReadReg(VMWAREPtr pVMWARE, int index) 243{ 244 /* 245 * Block SIGIO for the duration, so we don't get interrupted after the 246 * outl but before the inl by a mouse move (which write to our registers). 247 */ 248 int oldsigio, ret; 249 oldsigio = xf86BlockSIGIO(); 250 outl(pVMWARE->indexReg, index); 251 ret = inl(pVMWARE->valueReg); 252 xf86UnblockSIGIO(oldsigio); 253 return ret; 254} 255 256void 257vmwareWriteReg(VMWAREPtr pVMWARE, int index, CARD32 value) 258{ 259 /* 260 * Block SIGIO for the duration, so we don't get interrupted in between 261 * the outls by a mouse move (which write to our registers). 262 */ 263 int oldsigio; 264 oldsigio = xf86BlockSIGIO(); 265 outl(pVMWARE->indexReg, index); 266 outl(pVMWARE->valueReg, value); 267 xf86UnblockSIGIO(oldsigio); 268} 269 270void 271vmwareWriteWordToFIFO(VMWAREPtr pVMWARE, CARD32 value) 272{ 273 CARD32* vmwareFIFO = pVMWARE->vmwareFIFO; 274 275 /* Need to sync? */ 276 if ((vmwareFIFO[SVGA_FIFO_NEXT_CMD] + sizeof(CARD32) == vmwareFIFO[SVGA_FIFO_STOP]) 277 || (vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - sizeof(CARD32) && 278 vmwareFIFO[SVGA_FIFO_STOP] == vmwareFIFO[SVGA_FIFO_MIN])) { 279 VmwareLog(("Syncing because of full fifo\n")); 280 vmwareWaitForFB(pVMWARE); 281 } 282 283 vmwareFIFO[vmwareFIFO[SVGA_FIFO_NEXT_CMD] / sizeof(CARD32)] = value; 284 if(vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - 285 sizeof(CARD32)) { 286 vmwareFIFO[SVGA_FIFO_NEXT_CMD] = vmwareFIFO[SVGA_FIFO_MIN]; 287 } else { 288 vmwareFIFO[SVGA_FIFO_NEXT_CMD] += sizeof(CARD32); 289 } 290} 291 292void 293vmwareWaitForFB(VMWAREPtr pVMWARE) 294{ 295 vmwareWriteReg(pVMWARE, SVGA_REG_SYNC, 1); 296 while (vmwareReadReg(pVMWARE, SVGA_REG_BUSY)); 297} 298 299void 300vmwareSendSVGACmdUpdate(VMWAREPtr pVMWARE, BoxPtr pBB) 301{ 302 vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_UPDATE); 303 vmwareWriteWordToFIFO(pVMWARE, pBB->x1); 304 vmwareWriteWordToFIFO(pVMWARE, pBB->y1); 305 vmwareWriteWordToFIFO(pVMWARE, pBB->x2 - pBB->x1); 306 vmwareWriteWordToFIFO(pVMWARE, pBB->y2 - pBB->y1); 307} 308 309static void 310vmwareSendSVGACmdUpdateFullScreen(VMWAREPtr pVMWARE) 311{ 312 BoxRec BB; 313 314 BB.x1 = 0; 315 BB.y1 = 0; 316 BB.x2 = pVMWARE->ModeReg.svga_reg_width; 317 BB.y2 = pVMWARE->ModeReg.svga_reg_height; 318 vmwareSendSVGACmdUpdate(pVMWARE, &BB); 319} 320 321static CARD32 322vmwareCalculateWeight(CARD32 mask) 323{ 324 CARD32 weight; 325 326 for (weight = 0; mask; mask >>= 1) { 327 if (mask & 1) { 328 weight++; 329 } 330 } 331 return weight; 332} 333 334/* 335 *----------------------------------------------------------------------------- 336 * 337 * VMXGetVMwareSvgaId -- 338 * 339 * Retrieve the SVGA_ID of the VMware SVGA adapter. 340 * This function should hide any backward compatibility mess. 341 * 342 * Results: 343 * The SVGA_ID_* of the present VMware adapter. 344 * 345 * Side effects: 346 * ins/outs 347 * 348 *----------------------------------------------------------------------------- 349 */ 350 351static uint32 352VMXGetVMwareSvgaId(VMWAREPtr pVMWARE) 353{ 354 uint32 vmware_svga_id; 355 356 /* Any version with any SVGA_ID_* support will initialize SVGA_REG_ID 357 * to SVGA_ID_0 to support versions of this driver with SVGA_ID_0. 358 * 359 * Versions of SVGA_ID_0 ignore writes to the SVGA_REG_ID register. 360 * 361 * Versions of SVGA_ID_1 will allow us to overwrite the content 362 * of the SVGA_REG_ID register only with the values SVGA_ID_0 or SVGA_ID_1. 363 * 364 * Versions of SVGA_ID_2 will allow us to overwrite the content 365 * of the SVGA_REG_ID register only with the values SVGA_ID_0 or SVGA_ID_1 366 * or SVGA_ID_2. 367 */ 368 369 vmwareWriteReg(pVMWARE, SVGA_REG_ID, SVGA_ID_2); 370 vmware_svga_id = vmwareReadReg(pVMWARE, SVGA_REG_ID); 371 if (vmware_svga_id == SVGA_ID_2) { 372 return SVGA_ID_2; 373 } 374 375 vmwareWriteReg(pVMWARE, SVGA_REG_ID, SVGA_ID_1); 376 vmware_svga_id = vmwareReadReg(pVMWARE, SVGA_REG_ID); 377 if (vmware_svga_id == SVGA_ID_1) { 378 return SVGA_ID_1; 379 } 380 381 if (vmware_svga_id == SVGA_ID_0) { 382 return SVGA_ID_0; 383 } 384 385 /* No supported VMware SVGA devices found */ 386 return SVGA_ID_INVALID; 387} 388 389#ifndef XSERVER_LIBPCIACCESS 390/* 391 *---------------------------------------------------------------------- 392 * 393 * RewriteTagString -- 394 * 395 * Rewrites the given string, removing the $Name: $, and 396 * replacing it with the contents. The output string must 397 * have enough room, or else. 398 * 399 * Results: 400 * 401 * Output string updated. 402 * 403 * Side effects: 404 * None. 405 * 406 *---------------------------------------------------------------------- 407 */ 408 409static void 410RewriteTagString(const char *istr, char *ostr, int osize) 411{ 412 int chr; 413 Bool inTag = FALSE; 414 char *op = ostr; 415 416 do { 417 chr = *istr++; 418 if (chr == '$') { 419 if (inTag) { 420 inTag = FALSE; 421 for (; op > ostr && op[-1] == ' '; op--) { 422 } 423 continue; 424 } 425 if (strncmp(istr, "Name:", 5) == 0) { 426 istr += 5; 427 istr += strspn(istr, " "); 428 inTag = TRUE; 429 continue; 430 } 431 } 432 *op++ = chr; 433 } while (chr); 434} 435#endif 436 437static void 438VMWAREIdentify(int flags) 439{ 440 xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets); 441} 442 443static const OptionInfoRec * 444VMWAREAvailableOptions(int chipid, int busid) 445{ 446 return VMWAREOptions; 447} 448 449static int 450VMWAREParseTopologyElement(ScrnInfoPtr pScrn, 451 unsigned int output, 452 const char *elementName, 453 const char *element, 454 const char *expectedTerminators, 455 Bool needTerminator, 456 unsigned int *outValue) 457{ 458 char buf[10] = {0, }; 459 size_t i = 0; 460 int retVal = -1; 461 const char *str = element; 462 463 for (i = 0; str[i] >= '0' && str[i] <= '9'; i++); 464 if (i == 0) { 465 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: unable to parse %s.\n", 466 output, elementName); 467 goto exit; 468 } 469 470 strncpy(buf, str, i); 471 *outValue = atoi(buf); 472 473 if (*outValue > (unsigned short)-1) { 474 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %s must be less than %hu.\n", 475 output, elementName, (unsigned short)-1); 476 goto exit; 477 } 478 479 str += i; 480 481 if (needTerminator || str[0] != '\0') { 482 Bool unexpected = TRUE; 483 484 for (i = 0; i < strlen(expectedTerminators); i++) { 485 if (str[0] == expectedTerminators[i]) { 486 unexpected = FALSE; 487 } 488 } 489 490 if (unexpected) { 491 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 492 "Output %u: unexpected character '%c' after %s.\n", 493 output, str[0], elementName); 494 goto exit; 495 } else { 496 str++; 497 } 498 } 499 500 retVal = str - element; 501 502 exit: 503 return retVal; 504} 505 506static xXineramaScreenInfo * 507VMWAREParseTopologyString(ScrnInfoPtr pScrn, 508 const char *topology, 509 unsigned int *retNumOutputs) 510{ 511 xXineramaScreenInfo *extents = NULL; 512 unsigned int numOutputs = 0; 513 const char *str = topology; 514 515 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Starting...\n"); 516 517 do { 518 unsigned int x, y, width, height; 519 int i; 520 521 i = VMWAREParseTopologyElement(pScrn, numOutputs, "width", str, "xX", TRUE, &width); 522 if (i == -1) { 523 goto error; 524 } 525 str += i; 526 527 i = VMWAREParseTopologyElement(pScrn, numOutputs, "height", str, "+", TRUE, &height); 528 if (i == -1) { 529 goto error; 530 } 531 str += i; 532 533 i= VMWAREParseTopologyElement(pScrn, numOutputs, "X offset", str, "+", TRUE, &x); 534 if (i == -1) { 535 goto error; 536 } 537 str += i; 538 539 i = VMWAREParseTopologyElement(pScrn, numOutputs, "Y offset", str, ";", FALSE, &y); 540 if (i == -1) { 541 goto error; 542 } 543 str += i; 544 545 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %ux%u+%u+%u\n", 546 numOutputs, width, height, x, y); 547 548 numOutputs++; 549 extents = xrealloc(extents, numOutputs * sizeof (xXineramaScreenInfo)); 550 extents[numOutputs - 1].x_org = x; 551 extents[numOutputs - 1].y_org = y; 552 extents[numOutputs - 1].width = width; 553 extents[numOutputs - 1].height = height; 554 } while (*str != 0); 555 556 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Succeeded.\n"); 557 goto exit; 558 559 error: 560 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Failed.\n"); 561 562 xfree(extents); 563 extents = NULL; 564 numOutputs = 0; 565 566 exit: 567 *retNumOutputs = numOutputs; 568 return extents; 569} 570 571 572static Bool 573VMWAREPreInit(ScrnInfoPtr pScrn, int flags) 574{ 575 MessageType from; 576 VMWAREPtr pVMWARE; 577 OptionInfoPtr options; 578 int bpp24flags; 579 uint32 id; 580 int i; 581 ClockRange* clockRanges; 582 IOADDRESS domainIOBase = 0; 583 Bool useXinerama = TRUE; 584 585#ifndef BUILD_FOR_420 586 domainIOBase = pScrn->domainIOBase; 587#endif 588 589 if (flags & PROBE_DETECT) { 590 return FALSE; 591 } 592 593 if (pScrn->numEntities != 1) { 594 return FALSE; 595 } 596 597 if (!VMWAREGetRec(pScrn)) { 598 return FALSE; 599 } 600 pVMWARE = VMWAREPTR(pScrn); 601 602 pVMWARE->pvtSema = &pScrn->vtSema; 603 604 pVMWARE->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 605 if (pVMWARE->pEnt->location.type != BUS_PCI) { 606 return FALSE; 607 } 608 pVMWARE->PciInfo = xf86GetPciInfoForEntity(pVMWARE->pEnt->index); 609 if (pVMWARE->PciInfo == NULL) { 610 return FALSE; 611 } 612 613 if (DEVICE_ID(pVMWARE->PciInfo) == PCI_CHIP_VMWARE0710) { 614 pVMWARE->indexReg = domainIOBase + 615 SVGA_LEGACY_BASE_PORT + SVGA_INDEX_PORT*sizeof(uint32); 616 pVMWARE->valueReg = domainIOBase + 617 SVGA_LEGACY_BASE_PORT + SVGA_VALUE_PORT*sizeof(uint32); 618 } else { 619 /* Note: This setting of valueReg causes unaligned I/O */ 620#if XSERVER_LIBPCIACCESS 621 pVMWARE->portIOBase = pVMWARE->PciInfo->regions[0].base_addr; 622#else 623 pVMWARE->portIOBase = pVMWARE->PciInfo->ioBase[0]; 624#endif 625 pVMWARE->indexReg = domainIOBase + 626 pVMWARE->portIOBase + SVGA_INDEX_PORT; 627 pVMWARE->valueReg = domainIOBase + 628 pVMWARE->portIOBase + SVGA_VALUE_PORT; 629 } 630 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 631 "VMware SVGA regs at (0x%04lx, 0x%04lx)\n", 632 pVMWARE->indexReg, pVMWARE->valueReg); 633 634 if (!xf86LoadSubModule(pScrn, "vgahw")) { 635 return FALSE; 636 } 637 638 xf86LoaderReqSymLists(vgahwSymbols, NULL); 639 640 if (!vgaHWGetHWRec(pScrn)) { 641 return FALSE; 642 } 643 644 /* 645 * Save the current video state. Do it here before VMXGetVMwareSvgaId 646 * writes to any registers. 647 */ 648 VMWARESave(pScrn); 649 650 id = VMXGetVMwareSvgaId(pVMWARE); 651 if (id == SVGA_ID_0 || id == SVGA_ID_INVALID) { 652 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 653 "No supported VMware SVGA found (read ID 0x%08x).\n", id); 654 return FALSE; 655 } 656 657#if !XSERVER_LIBPCIACCESS 658 pVMWARE->PciTag = pciTag(pVMWARE->PciInfo->bus, pVMWARE->PciInfo->device, 659 pVMWARE->PciInfo->func); 660#endif 661 pVMWARE->Primary = xf86IsPrimaryPci(pVMWARE->PciInfo); 662 663 pScrn->monitor = pScrn->confScreen->monitor; 664 665#ifdef ACCELERATE_OPS 666 pVMWARE->vmwareCapability = vmwareReadReg(pVMWARE, SVGA_REG_CAPABILITIES); 667#else 668 pVMWARE->vmwareCapability = 0; 669#endif 670 671 pVMWARE->bitsPerPixel = vmwareReadReg(pVMWARE, 672 SVGA_REG_HOST_BITS_PER_PIXEL); 673 if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { 674 vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, pVMWARE->bitsPerPixel); 675 } 676 677 pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH); 678 pVMWARE->videoRam = vmwareReadReg(pVMWARE, SVGA_REG_VRAM_SIZE); 679 pVMWARE->memPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_FB_START); 680 pVMWARE->maxWidth = vmwareReadReg(pVMWARE, SVGA_REG_MAX_WIDTH); 681 pVMWARE->maxHeight = vmwareReadReg(pVMWARE, SVGA_REG_MAX_HEIGHT); 682 pVMWARE->cursorDefined = FALSE; 683 pVMWARE->cursorShouldBeHidden = FALSE; 684 685 if (pVMWARE->vmwareCapability & SVGA_CAP_CURSOR_BYPASS_2) { 686 pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_REMOVE_FROM_FB; 687 pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_RESTORE_TO_FB; 688 } else { 689 pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_HIDE; 690 pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_SHOW; 691 } 692 693 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "caps: 0x%08X\n", pVMWARE->vmwareCapability); 694 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "depth: %d\n", pVMWARE->depth); 695 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "bpp: %d\n", pVMWARE->bitsPerPixel); 696 697 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "vram: %d\n", pVMWARE->videoRam); 698 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "pbase: 0x%08lx\n", pVMWARE->memPhysBase); 699 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mwidt: %d\n", pVMWARE->maxWidth); 700 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mheig: %d\n", pVMWARE->maxHeight); 701 702 if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { 703 bpp24flags = Support24bppFb | Support32bppFb; 704 } else { 705 switch (pVMWARE->depth) { 706 case 16: 707 /* 708 * In certain cases, the Windows host appears to 709 * report 16 bpp and 16 depth but 555 weight. Just 710 * silently convert it to depth of 15. 711 */ 712 if (pVMWARE->bitsPerPixel == 16 && 713 pVMWARE->weight.green == 5) 714 pVMWARE->depth = 15; 715 case 8: 716 case 15: 717 bpp24flags = NoDepth24Support; 718 break; 719 case 32: 720 /* 721 * There is no 32 bit depth, apparently it can get 722 * reported this way sometimes on the Windows host. 723 */ 724 if (pVMWARE->bitsPerPixel == 32) 725 pVMWARE->depth = 24; 726 case 24: 727 if (pVMWARE->bitsPerPixel == 24) 728 bpp24flags = Support24bppFb; 729 else 730 bpp24flags = Support32bppFb; 731 break; 732 default: 733 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 734 "Adapter is using an unsupported depth (%d).\n", 735 pVMWARE->depth); 736 return FALSE; 737 } 738 } 739 740 if (!xf86SetDepthBpp(pScrn, pVMWARE->depth, pVMWARE->bitsPerPixel, 741 pVMWARE->bitsPerPixel, bpp24flags)) { 742 return FALSE; 743 } 744 745 /* Check that the returned depth is one we support */ 746 switch (pScrn->depth) { 747 case 8: 748 case 15: 749 case 16: 750 case 24: 751 /* OK */ 752 break; 753 default: 754 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 755 "Given depth (%d) is not supported by this driver\n", 756 pScrn->depth); 757 return FALSE; 758 } 759 760 if (pScrn->bitsPerPixel != pVMWARE->bitsPerPixel) { 761 if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { 762 vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, 763 pScrn->bitsPerPixel); 764 pVMWARE->bitsPerPixel = 765 vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL); 766 pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH); 767 } else { 768 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 769 "Currently unavailable depth/bpp of %d/%d requested.\n" 770 "\tThe guest X server must run at the same depth and bpp as the host\n" 771 "\t(which are currently %d/%d). This is automatically detected. Please\n" 772 "\tdo not specify a depth on the command line or via the config file.\n", 773 pScrn->depth, pScrn->bitsPerPixel, 774 pVMWARE->depth, pVMWARE->bitsPerPixel); 775 return FALSE; 776 } 777 } 778 779 /* 780 * Defer reading the colour registers until here in case we changed 781 * bpp above. 782 */ 783 784 pVMWARE->weight.red = 785 vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_RED_MASK)); 786 pVMWARE->weight.green = 787 vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_GREEN_MASK)); 788 pVMWARE->weight.blue = 789 vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_BLUE_MASK)); 790 pVMWARE->offset.blue = 0; 791 pVMWARE->offset.green = pVMWARE->weight.blue; 792 pVMWARE->offset.red = pVMWARE->weight.green + pVMWARE->offset.green; 793 pVMWARE->defaultVisual = vmwareReadReg(pVMWARE, SVGA_REG_PSEUDOCOLOR) ? 794 PseudoColor : TrueColor; 795 796 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 797 2, "depth: %d\n", pVMWARE->depth); 798 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 799 2, "bpp: %d\n", pVMWARE->bitsPerPixel); 800 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 801 2, "w.red: %d\n", (int)pVMWARE->weight.red); 802 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 803 2, "w.grn: %d\n", (int)pVMWARE->weight.green); 804 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 805 2, "w.blu: %d\n", (int)pVMWARE->weight.blue); 806 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 807 2, "vis: %d\n", pVMWARE->defaultVisual); 808 809 if (pScrn->depth != pVMWARE->depth) { 810 if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { 811 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 812 "Currently unavailable depth of %d requested.\n" 813 "\tIf the guest X server's BPP matches the host's " 814 "BPP, then\n\tthe guest X server's depth must also " 815 "match the\n\thost's depth (currently %d).\n", 816 pScrn->depth, pVMWARE->depth); 817 } else { 818 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 819 "Currently unavailable depth of %d requested.\n" 820 "\tThe guest X server must run at the same depth as " 821 "the host (which\n\tis currently %d). This is " 822 "automatically detected. Please do not\n\tspecify " 823 "a depth on the command line or via the config file.\n", 824 pScrn->depth, pVMWARE->depth); 825 } 826 return FALSE; 827 } 828 xf86PrintDepthBpp(pScrn); 829 830#if 0 831 if (pScrn->depth == 24 && pix24bpp == 0) { 832 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 833 } 834#endif 835 836 if (pScrn->depth > 8) { 837 rgb zeros = { 0, 0, 0 }; 838 839 if (!xf86SetWeight(pScrn, pVMWARE->weight, zeros)) { 840 return FALSE; 841 } 842 /* FIXME check returned weight */ 843 } 844 if (!xf86SetDefaultVisual(pScrn, pVMWARE->defaultVisual)) { 845 return FALSE; 846 } 847 if (pScrn->defaultVisual != pVMWARE->defaultVisual) { 848 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 849 "Given visual (%d) is not supported by this driver (%d is required)\n", 850 pScrn->defaultVisual, pVMWARE->defaultVisual); 851 return FALSE; 852 } 853#if 0 854 bytesPerPixel = pScrn->bitsPerPixel / 8; 855#endif 856 pScrn->progClock = TRUE; 857 858#if 0 /* MGA does not do this */ 859 if (pScrn->visual != 0) { /* FIXME */ 860 /* print error message */ 861 return FALSE; 862 } 863#endif 864 865 xf86CollectOptions(pScrn, NULL); 866 if (!(options = xalloc(sizeof(VMWAREOptions)))) 867 return FALSE; 868 memcpy(options, VMWAREOptions, sizeof(VMWAREOptions)); 869 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); 870 871 if (pScrn->depth <= 8) { 872 pScrn->rgbBits = 8; 873 } 874 875 from = X_PROBED; 876 pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets, DEVICE_ID(pVMWARE->PciInfo)); 877 878 if (!pScrn->chipset) { 879 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04x is not recognised\n", DEVICE_ID(pVMWARE->PciInfo)); 880 return FALSE; 881 } 882 883 from = X_DEFAULT; 884 pVMWARE->hwCursor = TRUE; 885 if (xf86GetOptValBool(options, OPTION_HW_CURSOR, &pVMWARE->hwCursor)) { 886 from = X_CONFIG; 887 } 888 if (pVMWARE->hwCursor && !(pVMWARE->vmwareCapability & SVGA_CAP_CURSOR)) { 889 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW cursor is not supported in this configuration\n"); 890 from = X_PROBED; 891 pVMWARE->hwCursor = FALSE; 892 } 893 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 894 pVMWARE->hwCursor ? "HW" : "SW"); 895 pScrn->videoRam = pVMWARE->videoRam / 1024; 896 pScrn->memPhysBase = pVMWARE->memPhysBase; 897 898 /* 899 * Init xinerama preferences. 900 */ 901 useXinerama = xf86ReturnOptValBool(options, OPTION_XINERAMA, 902 pVMWARE->vmwareCapability & SVGA_CAP_MULTIMON); 903 if (useXinerama && !(pVMWARE->vmwareCapability & SVGA_CAP_MULTIMON)) { 904 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 905 "Xinerama is not safely supported by the current virtual hardware. " 906 "Do not request resolutions that require > 16MB of framebuffer.\n"); 907 } 908 909 910 if (useXinerama && xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) { 911 char *topology = xf86GetOptValString(options, OPTION_STATIC_XINERAMA); 912 if (topology) { 913 pVMWARE->xineramaState = 914 VMWAREParseTopologyString(pScrn, topology, &pVMWARE->xineramaNumOutputs); 915 916 pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL; 917 918 xfree(topology); 919 } 920 } 921 922 xfree(options); 923 924 { 925 Gamma zeros = { 0.0, 0.0, 0.0 }; 926 if (!xf86SetGamma(pScrn, zeros)) { 927 return FALSE; 928 } 929 } 930#if 0 931 if ((i = xf86GetPciInfoForScreen(pScrn->scrnIndex, &pciList, NULL)) != 1) { 932 /* print error message */ 933 VMWAREFreeRec(pScrn); 934 if (i > 0) { 935 xfree(pciList); 936 } 937 return FALSE; 938 } 939#endif 940 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 941 clockRanges->next = NULL; 942 clockRanges->minClock = 1; 943 clockRanges->maxClock = 400000000; 944 clockRanges->clockIndex = -1; 945 clockRanges->interlaceAllowed = FALSE; 946 clockRanges->doubleScanAllowed = FALSE; 947 clockRanges->ClockMulFactor = 1; 948 clockRanges->ClockDivFactor = 1; 949 950 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, 951 clockRanges, NULL, 256, pVMWARE->maxWidth, 32 * 32, 952 128, pVMWARE->maxHeight, 953 pScrn->display->virtualX, pScrn->display->virtualY, 954 pVMWARE->videoRam, 955 LOOKUP_BEST_REFRESH); 956 if (i == -1) { 957 VMWAREFreeRec(pScrn); 958 return FALSE; 959 } 960 xf86PruneDriverModes(pScrn); 961 if (i == 0 || pScrn->modes == NULL) { 962 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 963 VMWAREFreeRec(pScrn); 964 return FALSE; 965 } 966 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 967 pScrn->currentMode = pScrn->modes; 968 xf86PrintModes(pScrn); 969 xf86SetDpi(pScrn, 0, 0); 970 if (!xf86LoadSubModule(pScrn, "fb") || 971 !xf86LoadSubModule(pScrn, "shadowfb")) { 972 VMWAREFreeRec(pScrn); 973 return FALSE; 974 } 975 xf86LoaderReqSymLists(fbSymbols, shadowfbSymbols, NULL); 976 977 /* Need ramdac for hwcursor */ 978 if (pVMWARE->hwCursor) { 979 if (!xf86LoadSubModule(pScrn, "ramdac")) { 980 VMWAREFreeRec(pScrn); 981 return FALSE; 982 } 983 xf86LoaderReqSymLists(ramdacSymbols, NULL); 984 } 985 986 /* Initialise VMWARE_CTRL extension. */ 987 VMwareCtrl_ExtInit(pScrn); 988 989 /* Initialise Xinerama extension. */ 990 if (useXinerama) { 991 VMwareXinerama_ExtInit(pScrn); 992 } 993 994 if (pVMWARE->xinerama && pVMWARE->xineramaStatic) { 995 xf86DrvMsg(pScrn->scrnIndex, X_INFO, pVMWARE->xineramaState ? 996 "Using static Xinerama.\n" : 997 "Failed to configure static Xinerama.\n"); 998 } 999 1000 return TRUE; 1001} 1002 1003static Bool 1004VMWAREMapMem(ScrnInfoPtr pScrn) 1005{ 1006 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1007#if XSERVER_LIBPCIACCESS 1008 int err; 1009 struct pci_device *const device = pVMWARE->PciInfo; 1010#endif 1011 1012#if XSERVER_LIBPCIACCESS 1013 err = pci_device_map_range(device, 1014 pVMWARE->memPhysBase, 1015 pVMWARE->videoRam, 1016 PCI_DEV_MAP_FLAG_WRITABLE | 1017 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 1018 (void **) &pVMWARE->FbBase); 1019 if (err) { 1020 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1021 "Unable to map frame buffer BAR. %s (%d)\n", 1022 strerror (err), err); 1023 return FALSE; 1024 } 1025 1026#else 1027 pVMWARE->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 1028 pVMWARE->PciTag, 1029 pVMWARE->memPhysBase, 1030 pVMWARE->videoRam); 1031#endif 1032 if (!pVMWARE->FbBase) 1033 return FALSE; 1034 1035 VmwareLog(("FB Mapped: %p/%u -> %p/%u\n", 1036 pVMWARE->memPhysBase, pVMWARE->videoRam, 1037 pVMWARE->FbBase, pVMWARE->videoRam)); 1038 return TRUE; 1039} 1040 1041static Bool 1042VMWAREUnmapMem(ScrnInfoPtr pScrn) 1043{ 1044 VMWAREPtr pVMWARE; 1045 1046 pVMWARE = VMWAREPTR(pScrn); 1047 1048 VmwareLog(("Unmapped: %p/%u\n", pVMWARE->FbBase, pVMWARE->videoRam)); 1049 1050#if XSERVER_LIBPCIACCESS 1051 pci_device_unmap_range(pVMWARE->PciInfo, pVMWARE->FbBase, pVMWARE->videoRam); 1052#else 1053 xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->FbBase, pVMWARE->videoRam); 1054#endif 1055 pVMWARE->FbBase = NULL; 1056 return TRUE; 1057} 1058 1059static void 1060VMWARESave(ScrnInfoPtr pScrn) 1061{ 1062 vgaHWPtr hwp = VGAHWPTR(pScrn); 1063 vgaRegPtr vgaReg = &hwp->SavedReg; 1064 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1065 VMWARERegPtr vmwareReg = &pVMWARE->SavedReg; 1066 1067 vgaHWSave(pScrn, vgaReg, VGA_SR_ALL); 1068 1069 vmwareReg->svga_reg_enable = vmwareReadReg(pVMWARE, SVGA_REG_ENABLE); 1070 vmwareReg->svga_reg_width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH); 1071 vmwareReg->svga_reg_height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT); 1072 vmwareReg->svga_reg_bits_per_pixel = 1073 vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL); 1074 vmwareReg->svga_reg_id = vmwareReadReg(pVMWARE, SVGA_REG_ID); 1075 1076 /* XXX this should be based on the cap bit, not hwCursor... */ 1077 if (pVMWARE->hwCursor) { 1078 vmwareReg->svga_reg_cursor_on = 1079 vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ON); 1080 vmwareReg->svga_reg_cursor_x = 1081 vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_X); 1082 vmwareReg->svga_reg_cursor_y = 1083 vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_Y); 1084 vmwareReg->svga_reg_cursor_id = 1085 vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ID); 1086 } 1087 1088 vmwareReg->svga_fifo_enabled = vmwareReadReg(pVMWARE, SVGA_REG_CONFIG_DONE); 1089} 1090 1091static void 1092VMWARERestoreRegs(ScrnInfoPtr pScrn, VMWARERegPtr vmwareReg) 1093{ 1094 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1095 VmwareLog(("VMWARERestoreRegs: W: %d, H: %d, BPP: %d, Enable: %d\n", 1096 vmwareReg->svga_reg_width, vmwareReg->svga_reg_height, 1097 vmwareReg->svga_reg_bits_per_pixel, vmwareReg->svga_reg_enable)); 1098 if (vmwareReg->svga_reg_enable) { 1099 vmwareWriteReg(pVMWARE, SVGA_REG_ID, vmwareReg->svga_reg_id); 1100 vmwareWriteReg(pVMWARE, SVGA_REG_WIDTH, vmwareReg->svga_reg_width); 1101 vmwareWriteReg(pVMWARE, SVGA_REG_HEIGHT, vmwareReg->svga_reg_height); 1102 vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, 1103 vmwareReg->svga_reg_bits_per_pixel); 1104 vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable); 1105 vmwareWriteReg(pVMWARE, SVGA_REG_GUEST_ID, GUEST_OS_LINUX); 1106 if (pVMWARE->hwCursor) { 1107 vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ID, 1108 vmwareReg->svga_reg_cursor_id); 1109 vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_X, 1110 vmwareReg->svga_reg_cursor_x); 1111 vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_Y, 1112 vmwareReg->svga_reg_cursor_y); 1113 vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ON, 1114 vmwareReg->svga_reg_cursor_on); 1115 } 1116 } else { 1117 vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable); 1118 } 1119} 1120 1121static void 1122VMWARERestore(ScrnInfoPtr pScrn) 1123{ 1124 vgaHWPtr hwp = VGAHWPTR(pScrn); 1125 vgaRegPtr vgaReg = &hwp->SavedReg; 1126 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1127 VMWARERegPtr vmwareReg = &pVMWARE->SavedReg; 1128 1129 vmwareWaitForFB(pVMWARE); 1130 if (!vmwareReg->svga_fifo_enabled) { 1131 VMWAREStopFIFO(pScrn); 1132 } 1133 1134 vgaHWProtect(pScrn, TRUE); 1135 VMWARERestoreRegs(pScrn, vmwareReg); 1136 vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); 1137 vgaHWProtect(pScrn, FALSE); 1138} 1139 1140static Bool 1141VMWAREModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool rebuildPixmap) 1142{ 1143 vgaHWPtr hwp = VGAHWPTR(pScrn); 1144 vgaRegPtr vgaReg = &hwp->ModeReg; 1145 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1146 VMWARERegPtr vmwareReg = &pVMWARE->ModeReg; 1147 1148 vgaHWUnlock(hwp); 1149 if (!vgaHWInit(pScrn, mode)) 1150 return FALSE; 1151 pScrn->vtSema = TRUE; 1152 1153 vmwareReg->svga_reg_enable = 1; 1154 vmwareReg->svga_reg_width = max(mode->HDisplay, pScrn->virtualX); 1155 vmwareReg->svga_reg_height = max(mode->VDisplay, pScrn->virtualY); 1156 vmwareReg->svga_reg_bits_per_pixel = pVMWARE->bitsPerPixel; 1157 1158 vgaHWProtect(pScrn, TRUE); 1159 1160 vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); 1161 VMWARERestoreRegs(pScrn, vmwareReg); 1162 1163 if (pVMWARE->hwCursor) { 1164 vmwareCursorModeInit(pScrn, mode); 1165 } 1166 1167 VmwareLog(("Required mode: %ux%u\n", mode->HDisplay, mode->VDisplay)); 1168 VmwareLog(("Virtual: %ux%u\n", pScrn->virtualX, pScrn->virtualY)); 1169 VmwareLog(("dispWidth: %u\n", pScrn->displayWidth)); 1170 pVMWARE->fbOffset = vmwareReadReg(pVMWARE, SVGA_REG_FB_OFFSET); 1171 pVMWARE->fbPitch = vmwareReadReg(pVMWARE, SVGA_REG_BYTES_PER_LINE); 1172 pVMWARE->FbSize = vmwareReadReg(pVMWARE, SVGA_REG_FB_SIZE); 1173 1174 pScrn->displayWidth = (pVMWARE->fbPitch * 8) / ((pScrn->bitsPerPixel + 7) & ~7); 1175 VmwareLog(("fbOffset: %u\n", pVMWARE->fbOffset)); 1176 VmwareLog(("fbPitch: %u\n", pVMWARE->fbPitch)); 1177 VmwareLog(("fbSize: %u\n", pVMWARE->FbSize)); 1178 VmwareLog(("New dispWidth: %u\n", pScrn->displayWidth)); 1179 1180 vmwareCheckVideoSanity(pScrn); 1181 1182 if (rebuildPixmap) { 1183 pScrn->pScreen->ModifyPixmapHeader((*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen), 1184 pScrn->pScreen->width, 1185 pScrn->pScreen->height, 1186 pScrn->pScreen->rootDepth, 1187 pScrn->bitsPerPixel, 1188 PixmapBytePad(pScrn->displayWidth, 1189 pScrn->pScreen->rootDepth), 1190 (pointer)(pVMWARE->FbBase + pScrn->fbOffset)); 1191 1192 (*pScrn->EnableDisableFBAccess)(pScrn->pScreen->myNum, FALSE); 1193 (*pScrn->EnableDisableFBAccess)(pScrn->pScreen->myNum, TRUE); 1194 } 1195 1196 vgaHWProtect(pScrn, FALSE); 1197 1198 /* 1199 * XXX -- If we want to check that we got the mode we asked for, this 1200 * would be a good place. 1201 */ 1202 1203 /* 1204 * Update Xinerama info appropriately. 1205 */ 1206 if (pVMWARE->xinerama && !pVMWARE->xineramaStatic) { 1207 if (pVMWARE->xineramaNextState) { 1208 xfree(pVMWARE->xineramaState); 1209 pVMWARE->xineramaState = pVMWARE->xineramaNextState; 1210 pVMWARE->xineramaNumOutputs = pVMWARE->xineramaNextNumOutputs; 1211 1212 pVMWARE->xineramaNextState = NULL; 1213 pVMWARE->xineramaNextNumOutputs = 0; 1214 } else { 1215 VMWAREXineramaPtr basicState = 1216 (VMWAREXineramaPtr)xcalloc(1, sizeof (VMWAREXineramaRec)); 1217 if (basicState) { 1218 basicState->x_org = 0; 1219 basicState->y_org = 0; 1220 basicState->width = vmwareReg->svga_reg_width; 1221 basicState->height = vmwareReg->svga_reg_height; 1222 1223 xfree(pVMWARE->xineramaState); 1224 pVMWARE->xineramaState = basicState; 1225 pVMWARE->xineramaNumOutputs = 1; 1226 } 1227 } 1228 } 1229 1230 /* 1231 * Update host's view of guest topology. 1232 */ 1233 if (pVMWARE->vmwareCapability & SVGA_CAP_DISPLAY_TOPOLOGY) { 1234 if (pVMWARE->xinerama) { 1235 int i = 0; 1236 VMWAREXineramaPtr xineramaState = pVMWARE->xineramaState; 1237 vmwareWriteReg(pVMWARE, SVGA_REG_NUM_GUEST_DISPLAYS, 1238 pVMWARE->xineramaNumOutputs); 1239 1240 for (i = 0; i < pVMWARE->xineramaNumOutputs; i++) { 1241 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, i); 1242 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_IS_PRIMARY, TRUE); 1243 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_X, 1244 xineramaState[i].x_org); 1245 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_Y, 1246 xineramaState[i].y_org); 1247 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_WIDTH, 1248 xineramaState[i].width); 1249 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_HEIGHT, 1250 xineramaState[i].height); 1251 } 1252 } else { 1253 vmwareWriteReg(pVMWARE, SVGA_REG_NUM_GUEST_DISPLAYS, 1); 1254 1255 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, 0); 1256 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_IS_PRIMARY, TRUE); 1257 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_X, 0); 1258 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_Y, 0); 1259 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_WIDTH, mode->HDisplay); 1260 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_HEIGHT, mode->VDisplay); 1261 } 1262 1263 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, SVGA_INVALID_DISPLAY_ID); 1264 } 1265 1266 return TRUE; 1267} 1268 1269static void 1270VMWAREAdjustFrame(int scrnIndex, int x, int y, int flags) 1271{ 1272 /* FIXME */ 1273} 1274 1275static void 1276VMWAREInitFIFO(ScrnInfoPtr pScrn) 1277{ 1278 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1279#if XSERVER_LIBPCIACCESS 1280 struct pci_device *const device = pVMWARE->PciInfo; 1281 int err; 1282#endif 1283 CARD32* vmwareFIFO; 1284 Bool extendedFifo; 1285 int min; 1286 1287 TRACEPOINT 1288 1289 pVMWARE->mmioPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_MEM_START); 1290 pVMWARE->mmioSize = vmwareReadReg(pVMWARE, SVGA_REG_MEM_SIZE) & ~3; 1291#if XSERVER_LIBPCIACCESS 1292 err = pci_device_map_range(device, pVMWARE->mmioPhysBase, 1293 pVMWARE->mmioSize, 1294 PCI_DEV_MAP_FLAG_WRITABLE, 1295 (void **) &pVMWARE->mmioVirtBase); 1296 if (err) { 1297 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1298 "Unable to map mmio BAR. %s (%d)\n", 1299 strerror (err), err); 1300 return; 1301 } 1302#else 1303 pVMWARE->mmioVirtBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 1304 pVMWARE->PciTag, 1305 pVMWARE->mmioPhysBase, 1306 pVMWARE->mmioSize); 1307#endif 1308 vmwareFIFO = pVMWARE->vmwareFIFO = (CARD32*)pVMWARE->mmioVirtBase; 1309 1310 extendedFifo = pVMWARE->vmwareCapability & SVGA_CAP_EXTENDED_FIFO; 1311 min = extendedFifo ? vmwareReadReg(pVMWARE, SVGA_REG_MEM_REGS) : 4; 1312 1313 vmwareFIFO[SVGA_FIFO_MIN] = min * sizeof(CARD32); 1314 vmwareFIFO[SVGA_FIFO_MAX] = pVMWARE->mmioSize; 1315 vmwareFIFO[SVGA_FIFO_NEXT_CMD] = min * sizeof(CARD32); 1316 vmwareFIFO[SVGA_FIFO_STOP] = min * sizeof(CARD32); 1317 vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 1); 1318} 1319 1320static void 1321VMWAREStopFIFO(ScrnInfoPtr pScrn) 1322{ 1323 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1324 1325 TRACEPOINT 1326 1327 vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 0); 1328#if XSERVER_LIBPCIACCESS 1329 pci_device_unmap_range(pVMWARE->PciInfo, pVMWARE->mmioVirtBase, pVMWARE->mmioSize); 1330#else 1331 xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->mmioVirtBase, pVMWARE->mmioSize); 1332#endif 1333} 1334 1335static Bool 1336VMWARECloseScreen(int scrnIndex, ScreenPtr pScreen) 1337{ 1338 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1339 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1340 ScreenPtr save = &pVMWARE->ScrnFuncs; 1341 1342 VmwareLog(("cursorSema: %d\n", pVMWARE->cursorSema)); 1343 1344 if (*pVMWARE->pvtSema) { 1345 if (pVMWARE->videoStreams) { 1346 vmwareVideoEnd(pScreen); 1347 } 1348 1349 if (pVMWARE->CursorInfoRec) { 1350 vmwareCursorCloseScreen(pScreen); 1351 } 1352 1353 VMWARERestore(pScrn); 1354 VMWAREUnmapMem(pScrn); 1355 1356 pScrn->vtSema = FALSE; 1357 } 1358 1359 pScreen->CloseScreen = save->CloseScreen; 1360 pScreen->SaveScreen = save->SaveScreen; 1361 1362#if VMWARE_DRIVER_FUNC 1363 pScrn->DriverFunc = NULL; 1364#endif 1365 1366 return (*pScreen->CloseScreen)(scrnIndex, pScreen); 1367} 1368 1369static Bool 1370VMWARESaveScreen(ScreenPtr pScreen, int mode) 1371{ 1372 VmwareLog(("VMWareSaveScreen() mode = %d\n", mode)); 1373 1374 /* 1375 * This thoroughly fails to do anything useful to svga mode. I doubt 1376 * we care; who wants to idle-blank their VM's screen anyway? 1377 */ 1378 return vgaHWSaveScreen(pScreen, mode); 1379} 1380 1381/* disabled by default to reduce spew in DEBUG_LOGGING mode. */ 1382/*#define DEBUG_LOG_UPDATES*/ 1383 1384static void 1385VMWAREPreDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr) 1386{ 1387 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1388 1389#ifdef DEBUG_LOG_UPDATES 1390 { 1391 int i; 1392 for (i = 0; i < nboxes; i++) { 1393 VmwareLog(("PreUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes - i, 1394 boxPtr[i].x1, boxPtr[i].y1, 1395 boxPtr[i].x2 - boxPtr[i].x1, 1396 boxPtr[i].y2 - boxPtr[i].y1)); 1397 } 1398 } 1399#endif 1400 1401 /* 1402 * We only register this callback if we have a HW cursor. 1403 */ 1404 while (nboxes--) { 1405 if (BOX_INTERSECT(*boxPtr, pVMWARE->hwcur.box)) { 1406 if (!pVMWARE->cursorExcludedForUpdate) { 1407 PRE_OP_HIDE_CURSOR(); 1408 pVMWARE->cursorExcludedForUpdate = TRUE; 1409 } 1410 break; 1411 } 1412 boxPtr++; 1413 } 1414} 1415 1416static void 1417VMWAREPostDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr) 1418{ 1419 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1420 while (nboxes--) { 1421#ifdef DEBUG_LOG_UPDATES 1422 VmwareLog(("PostUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes, 1423 boxPtr->x1, boxPtr->y1, 1424 boxPtr->x2 - boxPtr->x1, boxPtr->y2 - boxPtr->y1)); 1425#endif 1426 1427 /* Clip off (y only) for offscreen memory */ 1428 if (boxPtr->y2 >= pVMWARE->ModeReg.svga_reg_height) 1429 boxPtr->y2 = pVMWARE->ModeReg.svga_reg_height; 1430 if (boxPtr->y1 >= pVMWARE->ModeReg.svga_reg_height) 1431 boxPtr->y1 = pVMWARE->ModeReg.svga_reg_height; 1432 if (boxPtr->y1 == boxPtr->y2) { 1433 boxPtr++; 1434 continue; 1435 } 1436 1437 vmwareSendSVGACmdUpdate(pVMWARE, boxPtr++); 1438 } 1439 1440 if (pVMWARE->hwCursor && pVMWARE->cursorExcludedForUpdate) { 1441 POST_OP_SHOW_CURSOR(); 1442 pVMWARE->cursorExcludedForUpdate = FALSE; 1443 } 1444} 1445 1446static void 1447VMWARELoadPalette(ScrnInfoPtr pScrn, int numColors, int* indices, 1448 LOCO* colors, VisualPtr pVisual) 1449{ 1450 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1451 int i; 1452 1453 for (i = 0; i < numColors; i++) { 1454 vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 0, colors[*indices].red); 1455 vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 1, colors[*indices].green); 1456 vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 2, colors[*indices].blue); 1457 indices++; 1458 } 1459 VmwareLog(("Palette loading done\n")); 1460} 1461 1462 1463DisplayModeRec * 1464VMWAREAddDisplayMode(ScrnInfoPtr pScrn, 1465 const char *name, 1466 int width, 1467 int height) 1468{ 1469 DisplayModeRec *mode; 1470 1471 mode = xalloc(sizeof(DisplayModeRec)); 1472 1473 mode->name = xalloc(strlen(name) + 1); 1474 strcpy(mode->name, name); 1475 mode->status = MODE_OK; 1476 mode->type = M_T_DEFAULT; 1477 mode->HDisplay = width; 1478 mode->VDisplay = height; 1479 1480 mode->next = pScrn->modes; 1481 mode->prev = pScrn->modes->prev; 1482 pScrn->modes->prev->next = mode; 1483 pScrn->modes->prev = mode; 1484 1485 return mode; 1486} 1487 1488 1489#if VMWARE_DRIVER_FUNC 1490static Bool 1491VMWareDriverFunc(ScrnInfoPtr pScrn, 1492 xorgDriverFuncOp op, 1493 pointer data) 1494{ 1495 CARD32 *flag; 1496 xorgRRModeMM *modemm; 1497 1498 switch (op) { 1499 case GET_REQUIRED_HW_INTERFACES: 1500 flag = (CARD32 *)data; 1501 1502 if (flag) { 1503 *flag = HW_IO | HW_MMIO; 1504 } 1505 return TRUE; 1506 case RR_GET_MODE_MM: 1507 modemm = (xorgRRModeMM *)data; 1508 1509 /* 1510 * Because changing the resolution of the guest is usually changing the size 1511 * of a window on the host desktop, the real physical DPI will not change. To 1512 * keep the guest in sync, we scale the 'physical' screen dimensions to 1513 * keep the DPI constant. 1514 */ 1515 if (modemm && modemm->mode) { 1516 modemm->mmWidth *= modemm->mode->HDisplay / (double)(modemm->virtX); 1517 modemm->mmHeight *= modemm->mode->VDisplay / (double)(modemm->virtY); 1518 } 1519 return TRUE; 1520 default: 1521 return FALSE; 1522 } 1523} 1524#endif 1525 1526 1527static Bool 1528VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 1529{ 1530 ScrnInfoPtr pScrn; 1531 vgaHWPtr hwp; 1532 VMWAREPtr pVMWARE; 1533 1534 /* Get the ScrnInfoRec */ 1535 pScrn = xf86Screens[pScreen->myNum]; 1536 pVMWARE = VMWAREPTR(pScrn); 1537 1538 /* 1539 * If using the vgahw module, its data structures and related 1540 * things are typically initialised/mapped here. 1541 */ 1542 1543 hwp = VGAHWPTR(pScrn); 1544 vgaHWGetIOBase(hwp); 1545 1546 VMWAREInitFIFO(pScrn); 1547 1548 /* Initialise the first mode */ 1549 VMWAREModeInit(pScrn, pScrn->currentMode, FALSE); 1550 1551 /* Set the viewport if supported */ 1552 VMWAREAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 1553 1554 /* 1555 * Setup the screen's visuals, and initialise the framebuffer 1556 * code. 1557 */ 1558 VMWAREMapMem(pScrn); 1559 1560 /* 1561 * Clear the framebuffer (and any black-border mode areas). 1562 */ 1563 memset(pVMWARE->FbBase, 0, pVMWARE->FbSize); 1564 vmwareSendSVGACmdUpdateFullScreen(pVMWARE); 1565 1566 /* Reset the visual list */ 1567 miClearVisualTypes(); 1568 1569 /* 1570 * Setup the visuals supported. This driver only supports 1571 * TrueColor for bpp > 8, so the default set of visuals isn't 1572 * acceptable. To deal with this, call miSetVisualTypes with 1573 * the appropriate visual mask. 1574 */ 1575 1576 if (pScrn->bitsPerPixel > 8) { 1577 if (!miSetVisualTypes(pScrn->depth, TrueColorMask, 1578 pScrn->rgbBits, pScrn->defaultVisual)) { 1579 return FALSE; 1580 } 1581 } else { 1582 if (!miSetVisualTypes(pScrn->depth, 1583 miGetDefaultVisualMask(pScrn->depth), 1584 pScrn->rgbBits, pScrn->defaultVisual)) { 1585 return FALSE; 1586 } 1587 } 1588 1589 miSetPixmapDepths(); 1590 1591 /* 1592 * Initialise the framebuffer. 1593 */ 1594 if (!fbScreenInit(pScreen, pVMWARE->FbBase + pVMWARE->fbOffset, 1595 pScrn->virtualX, pScrn->virtualY, 1596 pScrn->xDpi, pScrn->yDpi, 1597 pScrn->displayWidth, 1598 pScrn->bitsPerPixel)) { 1599 return FALSE; 1600 } 1601 1602 /* Override the default mask/offset settings */ 1603 if (pScrn->bitsPerPixel > 8) { 1604 int i; 1605 VisualPtr visual; 1606 1607 for (i = 0, visual = pScreen->visuals; 1608 i < pScreen->numVisuals; i++, visual++) { 1609 if ((visual->class | DynamicClass) == DirectColor) { 1610 visual->offsetRed = pScrn->offset.red; 1611 visual->offsetGreen = pScrn->offset.green; 1612 visual->offsetBlue = pScrn->offset.blue; 1613 visual->redMask = pScrn->mask.red; 1614 visual->greenMask = pScrn->mask.green; 1615 visual->blueMask = pScrn->mask.blue; 1616 } 1617 } 1618 } 1619 1620 /* must be after RGB ordering fixed */ 1621 fbPictureInit (pScreen, 0, 0); 1622 1623 /* 1624 * Save the old screen vector, then wrap CloseScreen and 1625 * set SaveScreen. 1626 */ 1627 pVMWARE->ScrnFuncs = *pScreen; 1628 pScreen->CloseScreen = VMWARECloseScreen; 1629 pScreen->SaveScreen = VMWARESaveScreen; 1630 1631 /* 1632 * Set initial black & white colourmap indices. 1633 */ 1634 xf86SetBlackWhitePixels(pScreen); 1635 1636 /* 1637 * Initialize shadowfb to notify us of dirty rectangles. We only 1638 * need preFB access callbacks if we're using the hw cursor. 1639 */ 1640 if (!ShadowFBInit2(pScreen, 1641 pVMWARE->hwCursor ? VMWAREPreDirtyBBUpdate : NULL, 1642 VMWAREPostDirtyBBUpdate)) { 1643 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1644 "ShadowFB initialization failed\n"); 1645 return FALSE; 1646 } 1647 1648 /* 1649 * If we have a hw cursor, we need to hook functions that might 1650 * read from the framebuffer. 1651 */ 1652 if (pVMWARE->hwCursor) { 1653 vmwareCursorHookWrappers(pScreen); 1654 } 1655 1656 /* 1657 * If backing store is to be supported (as is usually the case), 1658 * initialise it. 1659 */ 1660 miInitializeBackingStore(pScreen); 1661 xf86SetBackingStore(pScreen); 1662 xf86SetSilkenMouse(pScreen); 1663 1664 /* 1665 * Initialize software cursor. 1666 */ 1667 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1668 1669 /* 1670 * Initialize hardware cursor. 1671 */ 1672 if (pVMWARE->hwCursor) { 1673 if (!vmwareCursorInit(pScreen)) { 1674 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1675 "Hardware cursor initialization failed\n"); 1676 pVMWARE->hwCursor = FALSE; 1677 } 1678 } 1679 1680 /* 1681 * Install colourmap functions. If using the vgahw module, 1682 * vgaHandleColormaps would usually be called here. 1683 */ 1684 1685 if (!fbCreateDefColormap(pScreen)) 1686 return FALSE; 1687 1688 if (!xf86HandleColormaps(pScreen, 256, 8, 1689 VMWARELoadPalette, NULL, 1690 CMAP_PALETTED_TRUECOLOR | 1691 CMAP_RELOAD_ON_MODE_SWITCH)) { 1692 return FALSE; 1693 } 1694 1695 /* 1696 * We explictly add a set of default modes because the X server will 1697 * not include modes larger than the initial one. 1698 */ 1699 { 1700 unsigned int i; 1701 unsigned int numModes = sizeof (VMWAREDefaultModes) / sizeof *(VMWAREDefaultModes); 1702 char name[10]; 1703 for (i = 0; i < numModes; i++) { 1704 const VMWAREDefaultMode *mode = &VMWAREDefaultModes[i]; 1705 1706 /* Only modes that fit the hardware maximums should be added. */ 1707 if (mode->width <= pVMWARE->maxWidth && mode->height <= pVMWARE->maxHeight) { 1708 snprintf(name, 10, "%dx%d", mode->width, mode->height); 1709 VMWAREAddDisplayMode(pScrn, name, mode->width, mode->height); 1710 } 1711 } 1712 1713 /* Add the hardware maximums as a mode. */ 1714 snprintf(name, 10, "%dx%d", pVMWARE->maxWidth, pVMWARE->maxHeight); 1715 VMWAREAddDisplayMode(pScrn, name, pVMWARE->maxWidth, pVMWARE->maxHeight); 1716 } 1717 1718 /* 1719 * We will lazily add the dynamic modes as the are needed when new 1720 * modes are requested through the control extension. 1721 */ 1722 pVMWARE->dynMode1 = NULL; 1723 pVMWARE->dynMode2 = NULL; 1724 1725#if VMWARE_DRIVER_FUNC 1726 pScrn->DriverFunc = VMWareDriverFunc; 1727#endif 1728 1729 /* Report any unused options (only for the first generation) */ 1730 if (serverGeneration == 1) { 1731 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1732 } 1733 1734 /* Initialize Xv extension */ 1735 pVMWARE->videoStreams = NULL; 1736 if (vmwareVideoEnabled(pVMWARE)) { 1737 if (!vmwareVideoInit(pScreen)) { 1738 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Xv initialization failed\n"); 1739 } 1740 } 1741 1742 1743 /* Done */ 1744 return TRUE; 1745} 1746 1747static Bool 1748VMWARESwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 1749{ 1750 return VMWAREModeInit(xf86Screens[scrnIndex], mode, TRUE); 1751} 1752 1753static Bool 1754VMWAREEnterVT(int scrnIndex, int flags) 1755{ 1756 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1757 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1758 1759 if (!pVMWARE->SavedReg.svga_fifo_enabled) { 1760 VMWAREInitFIFO(pScrn); 1761 } 1762 1763 return VMWAREModeInit(pScrn, pScrn->currentMode, TRUE); 1764} 1765 1766static void 1767VMWARELeaveVT(int scrnIndex, int flags) 1768{ 1769 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1770 VMWARERestore(pScrn); 1771} 1772 1773static void 1774VMWAREFreeScreen(int scrnIndex, int flags) 1775{ 1776 /* 1777 * If the vgahw module is used vgaHWFreeHWRec() would be called 1778 * here. 1779 */ 1780 VMWAREFreeRec(xf86Screens[scrnIndex]); 1781} 1782 1783static ModeStatus 1784VMWAREValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) 1785{ 1786 return MODE_OK; 1787} 1788 1789#if XSERVER_LIBPCIACCESS 1790static Bool 1791VMwarePciProbe (DriverPtr drv, 1792 int entity_num, 1793 struct pci_device *device, 1794 intptr_t match_data) 1795{ 1796 ScrnInfoPtr scrn = NULL; 1797 EntityInfoPtr entity; 1798 1799 scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VMWAREPciChipsets, 1800 NULL, NULL, NULL, NULL, NULL); 1801 if (scrn != NULL) { 1802 scrn->driverVersion = VMWARE_DRIVER_VERSION; 1803 scrn->driverName = VMWARE_DRIVER_NAME; 1804 scrn->name = VMWARE_NAME; 1805 scrn->Probe = NULL; 1806 } 1807 1808 entity = xf86GetEntityInfo(entity_num); 1809 switch (DEVICE_ID(device)) { 1810 case PCI_CHIP_VMWARE0405: 1811 case PCI_CHIP_VMWARE0710: 1812 xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n"); 1813 scrn->PreInit = VMWAREPreInit; 1814 scrn->ScreenInit = VMWAREScreenInit; 1815 scrn->SwitchMode = VMWARESwitchMode; 1816 scrn->EnterVT = VMWAREEnterVT; 1817 scrn->LeaveVT = VMWARELeaveVT; 1818 scrn->FreeScreen = VMWAREFreeScreen; 1819 scrn->ValidMode = VMWAREValidMode; 1820 break; 1821 default: 1822 xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Unknown device\n"); 1823 } 1824 return scrn != NULL; 1825} 1826#else 1827 1828static Bool 1829VMWAREProbe(DriverPtr drv, int flags) 1830{ 1831 int numDevSections, numUsed; 1832 GDevPtr *devSections; 1833 int *usedChips; 1834 int i; 1835 Bool foundScreen = FALSE; 1836 char buildString[sizeof(VMWAREBuildStr)]; 1837 1838 RewriteTagString(VMWAREBuildStr, buildString, sizeof(VMWAREBuildStr)); 1839 xf86MsgVerb(X_PROBED, 4, "%s", buildString); 1840 1841 numDevSections = xf86MatchDevice(VMWARE_DRIVER_NAME, &devSections); 1842 if (numDevSections <= 0) { 1843#ifdef DEBUG 1844 xf86MsgVerb(X_ERROR, 0, "No vmware driver section\n"); 1845#endif 1846 return FALSE; 1847 } 1848 if (xf86GetPciVideoInfo()) { 1849 VmwareLog(("Some PCI Video Info Exists\n")); 1850 numUsed = xf86MatchPciInstances(VMWARE_NAME, PCI_VENDOR_VMWARE, 1851 VMWAREChipsets, VMWAREPciChipsets, devSections, 1852 numDevSections, drv, &usedChips); 1853 xfree(devSections); 1854 if (numUsed <= 0) 1855 return FALSE; 1856 if (flags & PROBE_DETECT) 1857 foundScreen = TRUE; 1858 else 1859 for (i = 0; i < numUsed; i++) { 1860 ScrnInfoPtr pScrn = NULL; 1861 1862 VmwareLog(("Even some VMware SVGA PCI instances exists\n")); 1863 pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i], 1864 VMWAREPciChipsets, NULL, NULL, NULL, 1865 NULL, NULL); 1866 if (pScrn) { 1867 VmwareLog(("And even configuration suceeded\n")); 1868 pScrn->driverVersion = VMWARE_DRIVER_VERSION; 1869 pScrn->driverName = VMWARE_DRIVER_NAME; 1870 pScrn->name = VMWARE_NAME; 1871 pScrn->Probe = VMWAREProbe; 1872 pScrn->PreInit = VMWAREPreInit; 1873 pScrn->ScreenInit = VMWAREScreenInit; 1874 pScrn->SwitchMode = VMWARESwitchMode; 1875 pScrn->AdjustFrame = VMWAREAdjustFrame; 1876 pScrn->EnterVT = VMWAREEnterVT; 1877 pScrn->LeaveVT = VMWARELeaveVT; 1878 pScrn->FreeScreen = VMWAREFreeScreen; 1879 pScrn->ValidMode = VMWAREValidMode; 1880 foundScreen = TRUE; 1881 } 1882 } 1883 xfree(usedChips); 1884 } 1885 return foundScreen; 1886} 1887#endif 1888 1889 1890_X_EXPORT DriverRec VMWARE = { 1891 VMWARE_DRIVER_VERSION, 1892 VMWARE_DRIVER_NAME, 1893 VMWAREIdentify, 1894#if XSERVER_LIBPCIACCESS 1895 NULL, 1896#else 1897 VMWAREProbe, 1898#endif 1899 VMWAREAvailableOptions, 1900 NULL, 1901 0, 1902#if VMWARE_DRIVER_FUNC 1903 VMWareDriverFunc, 1904#endif 1905#if XSERVER_LIBPCIACCESS 1906 VMwareDeviceMatch, 1907 VMwarePciProbe, 1908#endif 1909}; 1910 1911#ifdef XFree86LOADER 1912static MODULESETUPPROTO(vmwareSetup); 1913 1914_X_EXPORT XF86ModuleData vmwareModuleData = { 1915 &vmwareVersRec, 1916 vmwareSetup, 1917 NULL 1918}; 1919 1920static pointer 1921vmwareSetup(pointer module, pointer opts, int *errmaj, int *errmin) 1922{ 1923 static Bool setupDone = FALSE; 1924 1925 if (!setupDone) { 1926 setupDone = TRUE; 1927 xf86AddDriver(&VMWARE, module, VMWARE_DRIVER_FUNC); 1928 1929 LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols, 1930 shadowfbSymbols, NULL); 1931 1932 return (pointer)1; 1933 } 1934 if (errmaj) { 1935 *errmaj = LDR_ONCEONLY; 1936 } 1937 return NULL; 1938} 1939#endif /* XFree86LOADER */ 1940