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