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