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