vmware.c revision 0b7217d9
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 10#ifdef HAVE_CONFIG_H 11#include "config.h" 12#endif 13 14/* 15 * TODO: support the vmware linux kernel fb driver (Option "UseFBDev"). 16 */ 17 18#include "xf86.h" 19#include "xf86_OSproc.h" 20 21#include "compiler.h" /* inb/outb */ 22 23#include "xf86Pci.h" /* pci */ 24 25#include "mipointer.h" /* sw cursor */ 26#include "micmap.h" /* mi color map */ 27#include "vgaHW.h" /* VGA hardware */ 28#include "fb.h" 29#include "shadowfb.h" /* ShadowFB wrappers */ 30 31#include "xf86cmap.h" /* xf86HandleColormaps */ 32 33#include "vmware.h" 34#include "guest_os.h" 35#include "vm_device_version.h" 36#include "svga_modes.h" 37#include "vmware_bootstrap.h" 38#include "vmware_common.h" 39#include "common_compat.h" 40 41#ifndef HAVE_XORG_SERVER_1_5_0 42#include <xf86_ansic.h> 43#include <xf86_libc.h> 44#endif 45 46#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5) 47 48#define xf86LoaderReqSymLists(...) do {} while (0) 49#define LoaderRefSymLists(...) do {} while (0) 50 51#else 52 53const char *vgahwSymbols[] = { 54 "vgaHWGetHWRec", 55 "vgaHWGetIOBase", 56 "vgaHWGetIndex", 57 "vgaHWInit", 58 "vgaHWProtect", 59 "vgaHWRestore", 60 "vgaHWSave", 61 "vgaHWSaveScreen", 62 "vgaHWUnlock", 63 NULL 64}; 65 66static const char *fbSymbols[] = { 67 "fbCreateDefColormap", 68 "fbPictureInit", 69 "fbScreenInit", 70 NULL 71}; 72 73static const char *ramdacSymbols[] = { 74 "xf86CreateCursorInfoRec", 75 "xf86DestroyCursorInfoRec", 76 "xf86InitCursor", 77 NULL 78}; 79 80static const char *shadowfbSymbols[] = { 81 "ShadowFBInit2", 82 NULL 83}; 84#endif 85 86/* Table of default modes to always add to the mode list. */ 87 88typedef struct { 89 int width; 90 int height; 91} VMWAREDefaultMode; 92 93#define VMW_MIN_INITIAL_WIDTH 800 94#define VMW_MIN_INITIAL_HEIGHT 600 95 96#define SVGA_DEFAULT_MODE(width, height) { width, height, }, 97 98static const VMWAREDefaultMode VMWAREDefaultModes[] = { 99 SVGA_DEFAULT_MODES 100}; 101 102#undef SVGA_DEFAULT_MODE 103 104static void VMWAREStopFIFO(ScrnInfoPtr pScrn); 105static void VMWARESave(ScrnInfoPtr pScrn); 106 107static Bool 108VMWAREGetRec(ScrnInfoPtr pScrn) 109{ 110 if (pScrn->driverPrivate != NULL) { 111 return TRUE; 112 } 113 pScrn->driverPrivate = xnfcalloc(sizeof(VMWARERec), 1); 114 /* FIXME: Initialize driverPrivate... */ 115 return TRUE; 116} 117 118static void 119VMWAREFreeRec(ScrnInfoPtr pScrn) 120{ 121 if (pScrn->driverPrivate) { 122 free(pScrn->driverPrivate); 123 pScrn->driverPrivate = NULL; 124 } 125} 126 127CARD32 128vmwareReadReg(VMWAREPtr pVMWARE, int rIndex) 129{ 130 /* 131 * Block SIGIO for the duration, so we don't get interrupted after the 132 * outl but before the inl by a mouse move (which write to our registers). 133 */ 134 int ret; 135#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 22) 136 int oldsigio; 137 138 oldsigio = xf86BlockSIGIO(); 139#else 140 input_lock(); 141#endif 142 outl(pVMWARE->indexReg, rIndex); 143 ret = inl(pVMWARE->valueReg); 144#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 22) 145 xf86UnblockSIGIO(oldsigio); 146#else 147 input_unlock(); 148#endif 149 return ret; 150} 151 152void 153vmwareWriteReg(VMWAREPtr pVMWARE, int wIndex, CARD32 value) 154{ 155 /* 156 * Block SIGIO for the duration, so we don't get interrupted in between 157 * the outls by a mouse move (which write to our registers). 158 */ 159#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 22) 160 int oldsigio; 161 oldsigio = xf86BlockSIGIO(); 162#else 163 input_lock(); 164#endif 165 outl(pVMWARE->indexReg, wIndex); 166 outl(pVMWARE->valueReg, value); 167#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 22) 168 xf86UnblockSIGIO(oldsigio); 169#else 170 input_unlock(); 171#endif 172} 173 174void 175vmwareWriteWordToFIFO(VMWAREPtr pVMWARE, CARD32 value) 176{ 177 volatile CARD32* vmwareFIFO = pVMWARE->vmwareFIFO; 178 179 /* Need to sync? */ 180 if ((vmwareFIFO[SVGA_FIFO_NEXT_CMD] + sizeof(CARD32) == vmwareFIFO[SVGA_FIFO_STOP]) 181 || (vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - sizeof(CARD32) && 182 vmwareFIFO[SVGA_FIFO_STOP] == vmwareFIFO[SVGA_FIFO_MIN])) { 183 VmwareLog(("Syncing because of full fifo\n")); 184 vmwareWaitForFB(pVMWARE); 185 } 186 187 vmwareFIFO[vmwareFIFO[SVGA_FIFO_NEXT_CMD] / sizeof(CARD32)] = value; 188 189 write_mem_barrier(); 190 191 if(vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - 192 sizeof(CARD32)) { 193 vmwareFIFO[SVGA_FIFO_NEXT_CMD] = vmwareFIFO[SVGA_FIFO_MIN]; 194 } else { 195 vmwareFIFO[SVGA_FIFO_NEXT_CMD] += sizeof(CARD32); 196 } 197} 198 199void 200vmwareWaitForFB(VMWAREPtr pVMWARE) 201{ 202 vmwareWriteReg(pVMWARE, SVGA_REG_SYNC, 1); 203 while (vmwareReadReg(pVMWARE, SVGA_REG_BUSY)); 204} 205 206void 207vmwareSendSVGACmdUpdate(VMWAREPtr pVMWARE, BoxPtr pBB) 208{ 209 vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_UPDATE); 210 vmwareWriteWordToFIFO(pVMWARE, pBB->x1); 211 vmwareWriteWordToFIFO(pVMWARE, pBB->y1); 212 vmwareWriteWordToFIFO(pVMWARE, pBB->x2 - pBB->x1); 213 vmwareWriteWordToFIFO(pVMWARE, pBB->y2 - pBB->y1); 214} 215 216void 217vmwareSendSVGACmdUpdateFullScreen(VMWAREPtr pVMWARE) 218{ 219 BoxRec BB; 220 221 BB.x1 = 0; 222 BB.y1 = 0; 223 BB.x2 = pVMWARE->ModeReg.svga_reg_width; 224 BB.y2 = pVMWARE->ModeReg.svga_reg_height; 225 vmwareSendSVGACmdUpdate(pVMWARE, &BB); 226} 227 228static CARD32 229vmwareCalculateWeight(CARD32 mask) 230{ 231 CARD32 weight; 232 233 for (weight = 0; mask; mask >>= 1) { 234 if (mask & 1) { 235 weight++; 236 } 237 } 238 return weight; 239} 240 241/* 242 *----------------------------------------------------------------------------- 243 * 244 * VMXGetVMwareSvgaId -- 245 * 246 * Retrieve the SVGA_ID of the VMware SVGA adapter. 247 * This function should hide any backward compatibility mess. 248 * 249 * Results: 250 * The SVGA_ID_* of the present VMware adapter. 251 * 252 * Side effects: 253 * ins/outs 254 * 255 *----------------------------------------------------------------------------- 256 */ 257 258static uint32 259VMXGetVMwareSvgaId(VMWAREPtr pVMWARE) 260{ 261 uint32 vmware_svga_id; 262 263 /* Any version with any SVGA_ID_* support will initialize SVGA_REG_ID 264 * to SVGA_ID_0 to support versions of this driver with SVGA_ID_0. 265 * 266 * Versions of SVGA_ID_0 ignore writes to the SVGA_REG_ID register. 267 * 268 * Versions of SVGA_ID_1 will allow us to overwrite the content 269 * of the SVGA_REG_ID register only with the values SVGA_ID_0 or SVGA_ID_1. 270 * 271 * Versions of SVGA_ID_2 will allow us to overwrite the content 272 * of the SVGA_REG_ID register only with the values SVGA_ID_0 or SVGA_ID_1 273 * or SVGA_ID_2. 274 */ 275 276 vmwareWriteReg(pVMWARE, SVGA_REG_ID, SVGA_ID_2); 277 vmware_svga_id = vmwareReadReg(pVMWARE, SVGA_REG_ID); 278 if (vmware_svga_id == SVGA_ID_2) { 279 return SVGA_ID_2; 280 } 281 282 vmwareWriteReg(pVMWARE, SVGA_REG_ID, SVGA_ID_1); 283 vmware_svga_id = vmwareReadReg(pVMWARE, SVGA_REG_ID); 284 if (vmware_svga_id == SVGA_ID_1) { 285 return SVGA_ID_1; 286 } 287 288 if (vmware_svga_id == SVGA_ID_0) { 289 return SVGA_ID_0; 290 } 291 292 /* No supported VMware SVGA devices found */ 293 return SVGA_ID_INVALID; 294} 295 296static Bool 297VMWAREPreInit(ScrnInfoPtr pScrn, int flags) 298{ 299 MessageType from; 300 VMWAREPtr pVMWARE; 301 OptionInfoPtr options; 302 int bpp24flags; 303 uint32 id; 304 int i; 305 ClockRange* clockRanges; 306 unsigned long domainIOBase = 0; 307 uint32 width = 0, height = 0; 308 Bool defaultMode; 309 310#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 311#ifndef BUILD_FOR_420 312 domainIOBase = pScrn->domainIOBase; 313#endif 314#endif 315 316 if (flags & PROBE_DETECT) { 317 return FALSE; 318 } 319 320 if (pScrn->numEntities != 1) { 321 return FALSE; 322 } 323 324 if (!VMWAREGetRec(pScrn)) { 325 return FALSE; 326 } 327 pVMWARE = VMWAREPTR(pScrn); 328 329 pVMWARE->pvtSema = &pScrn->vtSema; 330 331 pVMWARE->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 332 pVMWARE->PciInfo = xf86GetPciInfoForEntity(pVMWARE->pEnt->index); 333 if (pVMWARE->PciInfo == NULL) { 334 return FALSE; 335 } 336 337 if (DEVICE_ID(pVMWARE->PciInfo) == PCI_DEVICE_ID_VMWARE_SVGA) { 338 pVMWARE->indexReg = domainIOBase + 339 SVGA_LEGACY_BASE_PORT + SVGA_INDEX_PORT*sizeof(uint32); 340 pVMWARE->valueReg = domainIOBase + 341 SVGA_LEGACY_BASE_PORT + SVGA_VALUE_PORT*sizeof(uint32); 342 } else { 343 /* Note: This setting of valueReg causes unaligned I/O */ 344#if XSERVER_LIBPCIACCESS 345 pVMWARE->portIOBase = pVMWARE->PciInfo->regions[0].base_addr; 346#else 347 pVMWARE->portIOBase = pVMWARE->PciInfo->ioBase[0]; 348#endif 349 pVMWARE->indexReg = domainIOBase + 350 pVMWARE->portIOBase + SVGA_INDEX_PORT; 351 pVMWARE->valueReg = domainIOBase + 352 pVMWARE->portIOBase + SVGA_VALUE_PORT; 353 } 354 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 355 "VMware SVGA regs at (0x%04lx, 0x%04lx)\n", 356 pVMWARE->indexReg, pVMWARE->valueReg); 357 358 if (!xf86LoadSubModule(pScrn, "vgahw")) { 359 return FALSE; 360 } 361 362 xf86LoaderReqSymLists(vgahwSymbols, NULL); 363 364 if (!vgaHWGetHWRec(pScrn)) { 365 return FALSE; 366 } 367 368#ifdef HAVE_XORG_SERVER_1_12_0 369 vgaHWSetStdFuncs(VGAHWPTR(pScrn)); 370#endif 371 372 /* 373 * Save the current video state. Do it here before VMXGetVMwareSvgaId 374 * writes to any registers. 375 */ 376 VMWARESave(pScrn); 377 378 id = VMXGetVMwareSvgaId(pVMWARE); 379 if (id == SVGA_ID_0 || id == SVGA_ID_INVALID) { 380 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 381 "No supported VMware SVGA found (read ID 0x%08x).\n", id); 382 return FALSE; 383 } 384 pVMWARE->suspensionSavedRegId = id; 385 386#if !XSERVER_LIBPCIACCESS 387 pVMWARE->PciTag = pciTag(pVMWARE->PciInfo->bus, pVMWARE->PciInfo->device, 388 pVMWARE->PciInfo->func); 389#endif 390 pVMWARE->Primary = xf86IsPrimaryPci(pVMWARE->PciInfo); 391 392 pScrn->monitor = pScrn->confScreen->monitor; 393 394#ifdef ACCELERATE_OPS 395 pVMWARE->vmwareCapability = vmwareReadReg(pVMWARE, SVGA_REG_CAPABILITIES); 396#else 397 pVMWARE->vmwareCapability = vmwareReadReg(pVMWARE, SVGA_REG_CAPABILITIES) & 398 SVGA_CAP_PITCHLOCK; 399#endif 400 401 pVMWARE->bitsPerPixel = vmwareReadReg(pVMWARE, 402 SVGA_REG_HOST_BITS_PER_PIXEL); 403 if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { 404 vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, pVMWARE->bitsPerPixel); 405 } 406 407 pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH); 408 pVMWARE->videoRam = vmwareReadReg(pVMWARE, SVGA_REG_VRAM_SIZE); 409 pVMWARE->memPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_FB_START); 410 pVMWARE->maxWidth = vmwareReadReg(pVMWARE, SVGA_REG_MAX_WIDTH); 411 pVMWARE->maxHeight = vmwareReadReg(pVMWARE, SVGA_REG_MAX_HEIGHT); 412 pVMWARE->cursorDefined = FALSE; 413 pVMWARE->cursorShouldBeHidden = FALSE; 414 415 if (pVMWARE->vmwareCapability & SVGA_CAP_CURSOR_BYPASS_2) { 416 pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_REMOVE_FROM_FB; 417 pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_RESTORE_TO_FB; 418 } else { 419 pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_HIDE; 420 pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_SHOW; 421 } 422 423 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "caps: 0x%08X\n", pVMWARE->vmwareCapability); 424 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "depth: %d\n", pVMWARE->depth); 425 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "bpp: %d\n", pVMWARE->bitsPerPixel); 426 427 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "vram: %d\n", pVMWARE->videoRam); 428 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "pbase: 0x%08lx\n", pVMWARE->memPhysBase); 429 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mwidt: %d\n", pVMWARE->maxWidth); 430 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mheig: %d\n", pVMWARE->maxHeight); 431 432 if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { 433 bpp24flags = Support24bppFb | Support32bppFb; 434 } else { 435 switch (pVMWARE->depth) { 436 case 16: 437 /* 438 * In certain cases, the Windows host appears to 439 * report 16 bpp and 16 depth but 555 weight. Just 440 * silently convert it to depth of 15. 441 */ 442 if (pVMWARE->bitsPerPixel == 16 && 443 pVMWARE->weight.green == 5) 444 pVMWARE->depth = 15; 445 case 8: 446 case 15: 447 bpp24flags = NoDepth24Support; 448 break; 449 case 32: 450 /* 451 * There is no 32 bit depth, apparently it can get 452 * reported this way sometimes on the Windows host. 453 */ 454 if (pVMWARE->bitsPerPixel == 32) 455 pVMWARE->depth = 24; 456 case 24: 457 if (pVMWARE->bitsPerPixel == 24) 458 bpp24flags = Support24bppFb; 459 else 460 bpp24flags = Support32bppFb; 461 break; 462 default: 463 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 464 "Adapter is using an unsupported depth (%d).\n", 465 pVMWARE->depth); 466 return FALSE; 467 } 468 } 469 470 if (!xf86SetDepthBpp(pScrn, pVMWARE->depth, pVMWARE->bitsPerPixel, 471 pVMWARE->bitsPerPixel, bpp24flags)) { 472 return FALSE; 473 } 474 475 /* Check that the returned depth is one we support */ 476 switch (pScrn->depth) { 477 case 8: 478 case 15: 479 case 16: 480 case 24: 481 /* OK */ 482 break; 483 default: 484 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 485 "Given depth (%d) is not supported by this driver\n", 486 pScrn->depth); 487 return FALSE; 488 } 489 490 if (pScrn->bitsPerPixel != pVMWARE->bitsPerPixel) { 491 if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { 492 vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, 493 pScrn->bitsPerPixel); 494 pVMWARE->bitsPerPixel = 495 vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL); 496 pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH); 497 } else { 498 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 499 "Currently unavailable depth/bpp of %d/%d requested.\n" 500 "\tThe guest X server must run at the same depth and bpp as the host\n" 501 "\t(which are currently %d/%d). This is automatically detected. Please\n" 502 "\tdo not specify a depth on the command line or via the config file.\n", 503 pScrn->depth, pScrn->bitsPerPixel, 504 pVMWARE->depth, pVMWARE->bitsPerPixel); 505 return FALSE; 506 } 507 } 508 509 /* 510 * Defer reading the colour registers until here in case we changed 511 * bpp above. 512 */ 513 514 pVMWARE->weight.red = 515 vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_RED_MASK)); 516 pVMWARE->weight.green = 517 vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_GREEN_MASK)); 518 pVMWARE->weight.blue = 519 vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_BLUE_MASK)); 520 pVMWARE->offset.blue = 0; 521 pVMWARE->offset.green = pVMWARE->weight.blue; 522 pVMWARE->offset.red = pVMWARE->weight.green + pVMWARE->offset.green; 523 pVMWARE->defaultVisual = vmwareReadReg(pVMWARE, SVGA_REG_PSEUDOCOLOR) ? 524 PseudoColor : TrueColor; 525 526 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 527 2, "depth: %d\n", pVMWARE->depth); 528 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 529 2, "bpp: %d\n", pVMWARE->bitsPerPixel); 530 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 531 2, "w.red: %d\n", (int)pVMWARE->weight.red); 532 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 533 2, "w.grn: %d\n", (int)pVMWARE->weight.green); 534 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 535 2, "w.blu: %d\n", (int)pVMWARE->weight.blue); 536 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 537 2, "vis: %d\n", pVMWARE->defaultVisual); 538 539 if (pScrn->depth != pVMWARE->depth) { 540 if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { 541 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 542 "Currently unavailable depth of %d requested.\n" 543 "\tIf the guest X server's BPP matches the host's " 544 "BPP, then\n\tthe guest X server's depth must also " 545 "match the\n\thost's depth (currently %d).\n", 546 pScrn->depth, pVMWARE->depth); 547 } else { 548 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 549 "Currently unavailable depth of %d requested.\n" 550 "\tThe guest X server must run at the same depth as " 551 "the host (which\n\tis currently %d). This is " 552 "automatically detected. Please do not\n\tspecify " 553 "a depth on the command line or via the config file.\n", 554 pScrn->depth, pVMWARE->depth); 555 } 556 return FALSE; 557 } 558 xf86PrintDepthBpp(pScrn); 559 560#if 0 561 if (pScrn->depth == 24 && pix24bpp == 0) { 562 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 563 } 564#endif 565 566 if (pScrn->depth > 8) { 567 rgb zeros = { 0, 0, 0 }; 568 569 if (!xf86SetWeight(pScrn, pVMWARE->weight, zeros)) { 570 return FALSE; 571 } 572 /* FIXME check returned weight */ 573 } 574 if (!xf86SetDefaultVisual(pScrn, pVMWARE->defaultVisual)) { 575 return FALSE; 576 } 577 if (pScrn->defaultVisual != pVMWARE->defaultVisual) { 578 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 579 "Given visual (%d) is not supported by this driver (%d is required)\n", 580 pScrn->defaultVisual, pVMWARE->defaultVisual); 581 return FALSE; 582 } 583#if 0 584 bytesPerPixel = pScrn->bitsPerPixel / 8; 585#endif 586 pScrn->progClock = TRUE; 587 588#if 0 /* MGA does not do this */ 589 if (pScrn->visual != 0) { /* FIXME */ 590 /* print error message */ 591 return FALSE; 592 } 593#endif 594 595 xf86CollectOptions(pScrn, NULL); 596 if (!(options = VMWARECopyOptions())) 597 return FALSE; 598 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); 599 600 if (pScrn->depth <= 8) { 601 pScrn->rgbBits = 8; 602 } 603 604 if (!pScrn->chipset) { 605 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04x is not recognised\n", DEVICE_ID(pVMWARE->PciInfo)); 606 return FALSE; 607 } 608 609 from = X_DEFAULT; 610 pVMWARE->hwCursor = TRUE; 611 if (xf86GetOptValBool(options, OPTION_HW_CURSOR, &pVMWARE->hwCursor)) { 612 from = X_CONFIG; 613 } 614 if (pVMWARE->hwCursor && !(pVMWARE->vmwareCapability & SVGA_CAP_CURSOR)) { 615 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW cursor is not supported in this configuration\n"); 616 from = X_PROBED; 617 pVMWARE->hwCursor = FALSE; 618 } 619 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 620 pVMWARE->hwCursor ? "HW" : "SW"); 621 pScrn->videoRam = pVMWARE->videoRam / 1024; 622 pScrn->memPhysBase = pVMWARE->memPhysBase; 623 624 from = X_DEFAULT; 625 defaultMode = TRUE; 626 if (xf86GetOptValBool(options, OPTION_DEFAULT_MODE, &defaultMode)) { 627 from = X_CONFIG; 628 } 629 630 width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH); 631 height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT); 632 width = MAX(width, VMW_MIN_INITIAL_WIDTH); 633 height = MAX(height, VMW_MIN_INITIAL_HEIGHT); 634 635 if (width > pVMWARE->maxWidth || height > pVMWARE->maxHeight) { 636 /* 637 * This is an error condition and shouldn't happen. 638 * revert to MIN_INITIAL_ values 639 */ 640 width = VMW_MIN_INITIAL_WIDTH; 641 height = VMW_MIN_INITIAL_HEIGHT; 642 } 643 644 xf86DrvMsg(pScrn->scrnIndex, from, 645 "Will %sset up a driver mode with dimensions %dx%d.\n", 646 defaultMode ? "" : "not ", width, height); 647 648 free(options); 649 650 { 651 Gamma zeros = { 0.0, 0.0, 0.0 }; 652 if (!xf86SetGamma(pScrn, zeros)) { 653 return FALSE; 654 } 655 } 656#if 0 657 if ((i = xf86GetPciInfoForScreen(pScrn->scrnIndex, &pciList, NULL)) != 1) { 658 /* print error message */ 659 VMWAREFreeRec(pScrn); 660 if (i > 0) { 661 free(pciList); 662 } 663 return FALSE; 664 } 665#endif 666 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 667 clockRanges->next = NULL; 668 clockRanges->minClock = 1; 669 clockRanges->maxClock = 400000000; 670 clockRanges->clockIndex = -1; 671 clockRanges->interlaceAllowed = FALSE; 672 clockRanges->doubleScanAllowed = FALSE; 673 clockRanges->ClockMulFactor = 1; 674 clockRanges->ClockDivFactor = 1; 675 676 if (defaultMode) { 677 vmwareAddDefaultMode(pScrn, width, height); 678 } 679 680 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, 681 clockRanges, NULL, 256, pVMWARE->maxWidth, 682 pVMWARE->bitsPerPixel * 1, 683 128, pVMWARE->maxHeight, 684 pScrn->display->virtualX, pScrn->display->virtualY, 685 pVMWARE->videoRam, 686 LOOKUP_BEST_REFRESH | LOOKUP_OPTIONAL_TOLERANCES); 687 688 if (i == -1) { 689 VMWAREFreeRec(pScrn); 690 return FALSE; 691 } 692 xf86PruneDriverModes(pScrn); 693 if (i == 0 || pScrn->modes == NULL) { 694 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 695 VMWAREFreeRec(pScrn); 696 return FALSE; 697 } 698 699 pScrn->currentMode = pScrn->modes; 700 pScrn->virtualX = pScrn->modes->HDisplay; 701 pScrn->virtualY = pScrn->modes->VDisplay; 702 703 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 704 705 xf86PrintModes(pScrn); 706 xf86SetDpi(pScrn, 0, 0); 707 if (!xf86LoadSubModule(pScrn, "fb") || 708 !xf86LoadSubModule(pScrn, "shadowfb")) { 709 VMWAREFreeRec(pScrn); 710 return FALSE; 711 } 712 xf86LoaderReqSymLists(fbSymbols, shadowfbSymbols, NULL); 713 714 /* Need ramdac for hwcursor */ 715 if (pVMWARE->hwCursor) { 716 if (!xf86LoadSubModule(pScrn, "ramdac")) { 717 VMWAREFreeRec(pScrn); 718 return FALSE; 719 } 720 xf86LoaderReqSymLists(ramdacSymbols, NULL); 721 } 722 723 return TRUE; 724} 725 726static Bool 727VMWAREMapMem(ScrnInfoPtr pScrn) 728{ 729 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 730#if XSERVER_LIBPCIACCESS 731 int err; 732 struct pci_device *const device = pVMWARE->PciInfo; 733 void *fbBase; 734#endif 735 736#if XSERVER_LIBPCIACCESS 737 err = pci_device_map_range(device, 738 pVMWARE->memPhysBase, 739 pVMWARE->videoRam, 740 PCI_DEV_MAP_FLAG_WRITABLE, 741 &fbBase); 742 if (err) { 743 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 744 "Unable to map frame buffer BAR. %s (%d)\n", 745 strerror (err), err); 746 return FALSE; 747 } 748 pVMWARE->FbBase = fbBase; 749#else 750 pVMWARE->FbBase = xf86MapPciMem(pScrn->scrnIndex, 0, 751 pVMWARE->PciTag, 752 pVMWARE->memPhysBase, 753 pVMWARE->videoRam); 754#endif 755 if (!pVMWARE->FbBase) 756 return FALSE; 757 758 VmwareLog(("FB Mapped: %p/%u -> %p/%u\n", 759 pVMWARE->memPhysBase, pVMWARE->videoRam, 760 pVMWARE->FbBase, pVMWARE->videoRam)); 761 return TRUE; 762} 763 764static Bool 765VMWAREUnmapMem(ScrnInfoPtr pScrn) 766{ 767 VMWAREPtr pVMWARE; 768 769 pVMWARE = VMWAREPTR(pScrn); 770 771 VmwareLog(("Unmapped: %p/%u\n", pVMWARE->FbBase, pVMWARE->videoRam)); 772 773#if XSERVER_LIBPCIACCESS 774 pci_device_unmap_range(pVMWARE->PciInfo, pVMWARE->FbBase, pVMWARE->videoRam); 775#else 776 xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->FbBase, pVMWARE->videoRam); 777#endif 778 pVMWARE->FbBase = NULL; 779 return TRUE; 780} 781 782static void 783VMWARESave(ScrnInfoPtr pScrn) 784{ 785 vgaHWPtr hwp = VGAHWPTR(pScrn); 786 vgaRegPtr vgaReg = &hwp->SavedReg; 787 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 788 VMWARERegPtr vmwareReg = &pVMWARE->SavedReg; 789 790 vgaHWSave(pScrn, vgaReg, VGA_SR_ALL); 791 792 vmwareReg->svga_reg_enable = vmwareReadReg(pVMWARE, SVGA_REG_ENABLE); 793 vmwareReg->svga_reg_width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH); 794 vmwareReg->svga_reg_height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT); 795 vmwareReg->svga_reg_bits_per_pixel = 796 vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL); 797 vmwareReg->svga_reg_id = vmwareReadReg(pVMWARE, SVGA_REG_ID); 798 799 /* XXX this should be based on the cap bit, not hwCursor... */ 800 if (pVMWARE->hwCursor) { 801 vmwareReg->svga_reg_cursor_on = 802 vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ON); 803 vmwareReg->svga_reg_cursor_x = 804 vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_X); 805 vmwareReg->svga_reg_cursor_y = 806 vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_Y); 807 vmwareReg->svga_reg_cursor_id = 808 vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ID); 809 } 810 811 vmwareReg->svga_fifo_enabled = vmwareReadReg(pVMWARE, SVGA_REG_CONFIG_DONE); 812} 813 814static void 815VMWARERestoreRegs(ScrnInfoPtr pScrn, VMWARERegPtr vmwareReg) 816{ 817 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 818 VmwareLog(("VMWARERestoreRegs: W: %d, H: %d, BPP: %d, Enable: %d\n", 819 vmwareReg->svga_reg_width, vmwareReg->svga_reg_height, 820 vmwareReg->svga_reg_bits_per_pixel, vmwareReg->svga_reg_enable)); 821 if (vmwareReg->svga_reg_enable) { 822 vmwareWriteReg(pVMWARE, SVGA_REG_ID, vmwareReg->svga_reg_id); 823 vmwareWriteReg(pVMWARE, SVGA_REG_WIDTH, vmwareReg->svga_reg_width); 824 vmwareWriteReg(pVMWARE, SVGA_REG_HEIGHT, vmwareReg->svga_reg_height); 825 vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, 826 vmwareReg->svga_reg_bits_per_pixel); 827 vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable); 828 vmwareWriteReg(pVMWARE, SVGA_REG_GUEST_ID, GUEST_OS_LINUX); 829 if (pVMWARE->hwCursor) { 830 vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ID, 831 vmwareReg->svga_reg_cursor_id); 832 vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_X, 833 vmwareReg->svga_reg_cursor_x); 834 vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_Y, 835 vmwareReg->svga_reg_cursor_y); 836 vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ON, 837 vmwareReg->svga_reg_cursor_on); 838 } 839 } else { 840 vmwareWriteReg(pVMWARE, SVGA_REG_ID, vmwareReg->svga_reg_id); 841 vmwareWriteReg(pVMWARE, SVGA_REG_WIDTH, vmwareReg->svga_reg_width); 842 vmwareWriteReg(pVMWARE, SVGA_REG_HEIGHT, vmwareReg->svga_reg_height); 843 vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, 844 vmwareReg->svga_reg_bits_per_pixel); 845 vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable); 846 } 847} 848 849static void 850VMWARERestore(ScrnInfoPtr pScrn) 851{ 852 vgaHWPtr hwp = VGAHWPTR(pScrn); 853 vgaRegPtr vgaReg = &hwp->SavedReg; 854 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 855 VMWARERegPtr vmwareReg = &pVMWARE->SavedReg; 856 857 vmwareWaitForFB(pVMWARE); 858 if (!vmwareReg->svga_fifo_enabled) { 859 VMWAREStopFIFO(pScrn); 860 } 861 862 vgaHWProtect(pScrn, TRUE); 863 VMWARERestoreRegs(pScrn, vmwareReg); 864 vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); 865 vgaHWProtect(pScrn, FALSE); 866} 867 868static Bool 869VMWAREModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool rebuildPixmap) 870{ 871 vgaHWPtr hwp = VGAHWPTR(pScrn); 872 vgaRegPtr vgaReg = &hwp->ModeReg; 873 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 874 VMWARERegPtr vmwareReg = &pVMWARE->ModeReg; 875 876 vgaHWUnlock(hwp); 877 if (!vgaHWInit(pScrn, mode)) 878 return FALSE; 879 pScrn->vtSema = TRUE; 880 881 if (pVMWARE->vmwareCapability & SVGA_CAP_PITCHLOCK) 882 vmwareWriteReg(pVMWARE, SVGA_REG_PITCHLOCK, 0); 883 vmwareReg->svga_reg_enable = 1; 884 vmwareReg->svga_reg_width = max(mode->HDisplay, pScrn->virtualX); 885 vmwareReg->svga_reg_height = max(mode->VDisplay, pScrn->virtualY); 886 vmwareReg->svga_reg_bits_per_pixel = pVMWARE->bitsPerPixel; 887 888 vgaHWProtect(pScrn, TRUE); 889 890 vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); 891 VMWARERestoreRegs(pScrn, vmwareReg); 892 893 if (pVMWARE->hwCursor) { 894 vmwareCursorModeInit(pScrn, mode); 895 } 896 897 VmwareLog(("Required mode: %ux%u\n", mode->HDisplay, mode->VDisplay)); 898 VmwareLog(("Virtual: %ux%u\n", pScrn->virtualX, pScrn->virtualY)); 899 VmwareLog(("dispWidth: %u\n", pScrn->displayWidth)); 900 pVMWARE->fbOffset = vmwareReadReg(pVMWARE, SVGA_REG_FB_OFFSET); 901 pVMWARE->fbPitch = vmwareReadReg(pVMWARE, SVGA_REG_BYTES_PER_LINE); 902 pVMWARE->FbSize = vmwareReadReg(pVMWARE, SVGA_REG_FB_SIZE); 903 904 pScrn->displayWidth = (pVMWARE->fbPitch * 8) / ((pScrn->bitsPerPixel + 7) & ~7); 905 VmwareLog(("fbOffset: %u\n", pVMWARE->fbOffset)); 906 VmwareLog(("fbPitch: %u\n", pVMWARE->fbPitch)); 907 VmwareLog(("fbSize: %u\n", pVMWARE->FbSize)); 908 VmwareLog(("New dispWidth: %u\n", pScrn->displayWidth)); 909 910 vmwareCheckVideoSanity(pScrn); 911 912 if (rebuildPixmap) { 913 pScrn->pScreen->ModifyPixmapHeader((*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen), 914 pScrn->pScreen->width, 915 pScrn->pScreen->height, 916 pScrn->pScreen->rootDepth, 917 pScrn->bitsPerPixel, 918 PixmapBytePad(pScrn->displayWidth, 919 pScrn->pScreen->rootDepth), 920 (pointer)(pVMWARE->FbBase + pScrn->fbOffset)); 921 922 (*pScrn->EnableDisableFBAccess)(XF86_SCRN_ARG(pScrn), FALSE); 923 (*pScrn->EnableDisableFBAccess)(XF86_SCRN_ARG(pScrn), TRUE); 924 } 925 926 vgaHWProtect(pScrn, FALSE); 927 928 /* 929 * Push the new Xinerama state to X clients and the hardware, 930 * synchronously with the mode change. Note that this must happen 931 * AFTER we write the new width and height to the hardware 932 * registers, since updating the WIDTH and HEIGHT registers will 933 * reset the device's multimon topology. 934 */ 935 vmwareNextXineramaState(pVMWARE); 936 937 return TRUE; 938} 939 940void 941vmwareNextXineramaState(VMWAREPtr pVMWARE) 942{ 943 VMWARERegPtr vmwareReg = &pVMWARE->ModeReg; 944 945 /* 946 * Switch to the next Xinerama state (from pVMWARE->xineramaNextState). 947 * 948 * This new state will be available to X clients via the Xinerama 949 * extension, and we push the new state to the virtual hardware, 950 * in order to configure a number of virtual monitors within the 951 * device's framebuffer. 952 * 953 * This function can be called at any time, but it should usually be 954 * called just after a mode switch. This is for two reasons: 955 * 956 * 1) We don't want X clients to see a Xinerama topology and a video 957 * mode that are inconsistent with each other, so we'd like to switch 958 * both at the same time. 959 * 960 * 2) We must set the host's display topology registers after setting 961 * the new video mode, since writes to WIDTH/HEIGHT will reset the 962 * hardware display topology. 963 */ 964 965 /* 966 * Update Xinerama info appropriately. 967 */ 968 if (pVMWARE->xinerama && !pVMWARE->xineramaStatic) { 969 if (pVMWARE->xineramaNextState) { 970 free(pVMWARE->xineramaState); 971 pVMWARE->xineramaState = pVMWARE->xineramaNextState; 972 pVMWARE->xineramaNumOutputs = pVMWARE->xineramaNextNumOutputs; 973 974 pVMWARE->xineramaNextState = NULL; 975 pVMWARE->xineramaNextNumOutputs = 0; 976 977 } else { 978 /* 979 * There is no next state pending. Switch back to 980 * single-monitor mode. This is necessary for resetting the 981 * Xinerama state if we get a mode change which doesn't 982 * follow a VMwareCtrlDoSetTopology call. 983 */ 984 VMWAREXineramaPtr basicState = 985 (VMWAREXineramaPtr)calloc(1, sizeof (VMWAREXineramaRec)); 986 if (basicState) { 987 basicState->x_org = 0; 988 basicState->y_org = 0; 989 basicState->width = vmwareReg->svga_reg_width; 990 basicState->height = vmwareReg->svga_reg_height; 991 992 free(pVMWARE->xineramaState); 993 pVMWARE->xineramaState = basicState; 994 pVMWARE->xineramaNumOutputs = 1; 995 } 996 } 997 } 998 999 /* 1000 * Update host's view of guest topology. This tells the device 1001 * how we're carving up its framebuffer into virtual screens. 1002 */ 1003 if (pVMWARE->vmwareCapability & SVGA_CAP_DISPLAY_TOPOLOGY) { 1004 if (pVMWARE->xinerama) { 1005 int i = 0; 1006 VMWAREXineramaPtr xineramaState = pVMWARE->xineramaState; 1007 vmwareWriteReg(pVMWARE, SVGA_REG_NUM_GUEST_DISPLAYS, 1008 pVMWARE->xineramaNumOutputs); 1009 1010 for (i = 0; i < pVMWARE->xineramaNumOutputs; i++) { 1011 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, i); 1012 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_IS_PRIMARY, i == 0); 1013 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_X, 1014 xineramaState[i].x_org); 1015 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_Y, 1016 xineramaState[i].y_org); 1017 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_WIDTH, 1018 xineramaState[i].width); 1019 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_HEIGHT, 1020 xineramaState[i].height); 1021 } 1022 } else { 1023 vmwareWriteReg(pVMWARE, SVGA_REG_NUM_GUEST_DISPLAYS, 1); 1024 1025 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, 0); 1026 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_IS_PRIMARY, TRUE); 1027 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_X, 0); 1028 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_Y, 0); 1029 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_WIDTH, vmwareReg->svga_reg_width); 1030 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_HEIGHT, vmwareReg->svga_reg_height); 1031 } 1032 1033 /* Done. */ 1034 vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, SVGA_INVALID_DISPLAY_ID); 1035 } 1036} 1037 1038static void 1039VMWAREAdjustFrame(ADJUST_FRAME_ARGS_DECL) 1040{ 1041 /* FIXME */ 1042} 1043 1044static void 1045VMWAREInitFIFO(ScrnInfoPtr pScrn) 1046{ 1047 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1048#if XSERVER_LIBPCIACCESS 1049 struct pci_device *const device = pVMWARE->PciInfo; 1050 int err; 1051 void *mmioVirtBase; 1052#endif 1053 volatile CARD32* vmwareFIFO; 1054 Bool extendedFifo; 1055 int min; 1056 1057 TRACEPOINT 1058 1059 pVMWARE->mmioPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_MEM_START); 1060 pVMWARE->mmioSize = vmwareReadReg(pVMWARE, SVGA_REG_MEM_SIZE) & ~3; 1061#if XSERVER_LIBPCIACCESS 1062 err = pci_device_map_range(device, pVMWARE->mmioPhysBase, 1063 pVMWARE->mmioSize, 1064 PCI_DEV_MAP_FLAG_WRITABLE, 1065 &mmioVirtBase); 1066 if (err) { 1067 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1068 "Unable to map mmio BAR. %s (%d)\n", 1069 strerror (err), err); 1070 return; 1071 } 1072 pVMWARE->mmioVirtBase = mmioVirtBase; 1073#else 1074 pVMWARE->mmioVirtBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 1075 pVMWARE->PciTag, 1076 pVMWARE->mmioPhysBase, 1077 pVMWARE->mmioSize); 1078#endif 1079 vmwareFIFO = pVMWARE->vmwareFIFO = (CARD32*)pVMWARE->mmioVirtBase; 1080 1081 extendedFifo = pVMWARE->vmwareCapability & SVGA_CAP_EXTENDED_FIFO; 1082 min = extendedFifo ? vmwareReadReg(pVMWARE, SVGA_REG_MEM_REGS) : 4; 1083 1084 vmwareWaitForFB(pVMWARE); 1085 vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 0); 1086 1087 vmwareFIFO[SVGA_FIFO_MIN] = min * sizeof(CARD32); 1088 vmwareFIFO[SVGA_FIFO_MAX] = pVMWARE->mmioSize; 1089 vmwareFIFO[SVGA_FIFO_NEXT_CMD] = min * sizeof(CARD32); 1090 vmwareFIFO[SVGA_FIFO_STOP] = min * sizeof(CARD32); 1091 vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 1); 1092} 1093 1094static void 1095VMWAREStopFIFO(ScrnInfoPtr pScrn) 1096{ 1097 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1098 1099 TRACEPOINT 1100 1101 vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 0); 1102#if XSERVER_LIBPCIACCESS 1103 pci_device_unmap_range(pVMWARE->PciInfo, pVMWARE->mmioVirtBase, pVMWARE->mmioSize); 1104#else 1105 xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->mmioVirtBase, pVMWARE->mmioSize); 1106#endif 1107} 1108 1109static Bool 1110VMWARECloseScreen(CLOSE_SCREEN_ARGS_DECL) 1111{ 1112 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1113 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1114 ScreenPtr save = &pVMWARE->ScrnFuncs; 1115 1116 VmwareLog(("cursorSema: %d\n", pVMWARE->cursorSema)); 1117 1118 if (*pVMWARE->pvtSema) { 1119 if (pVMWARE->videoStreams) { 1120 vmwareVideoEnd(pScreen); 1121 } 1122 1123 if (pVMWARE->CursorInfoRec) { 1124 vmwareCursorCloseScreen(pScreen); 1125 } 1126 1127 VMWARERestore(pScrn); 1128 VMWAREUnmapMem(pScrn); 1129 1130 pScrn->vtSema = FALSE; 1131 } 1132 1133 pScreen->CloseScreen = save->CloseScreen; 1134 pScreen->SaveScreen = save->SaveScreen; 1135 1136#if VMWARE_DRIVER_FUNC 1137 pScrn->DriverFunc = NULL; 1138#endif 1139 1140 return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 1141} 1142 1143static Bool 1144VMWARESaveScreen(ScreenPtr pScreen, int mode) 1145{ 1146 VmwareLog(("VMWareSaveScreen() mode = %d\n", mode)); 1147 1148 /* 1149 * This thoroughly fails to do anything useful to svga mode. I doubt 1150 * we care; who wants to idle-blank their VM's screen anyway? 1151 */ 1152 return vgaHWSaveScreen(pScreen, mode); 1153} 1154 1155/* disabled by default to reduce spew in DEBUG_LOGGING mode. */ 1156/*#define DEBUG_LOG_UPDATES*/ 1157 1158static void 1159VMWAREPreDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr) 1160{ 1161 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1162 1163#ifdef DEBUG_LOG_UPDATES 1164 { 1165 int i; 1166 for (i = 0; i < nboxes; i++) { 1167 VmwareLog(("PreUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes - i, 1168 boxPtr[i].x1, boxPtr[i].y1, 1169 boxPtr[i].x2 - boxPtr[i].x1, 1170 boxPtr[i].y2 - boxPtr[i].y1)); 1171 } 1172 } 1173#endif 1174 1175 /* 1176 * We only register this callback if we have a HW cursor. 1177 */ 1178 while (nboxes--) { 1179 if (BOX_INTERSECT(*boxPtr, pVMWARE->hwcur.box)) { 1180 if (!pVMWARE->cursorExcludedForUpdate) { 1181 PRE_OP_HIDE_CURSOR(); 1182 pVMWARE->cursorExcludedForUpdate = TRUE; 1183 } 1184 break; 1185 } 1186 boxPtr++; 1187 } 1188} 1189 1190static void 1191VMWAREPostDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr) 1192{ 1193 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1194 while (nboxes--) { 1195#ifdef DEBUG_LOG_UPDATES 1196 VmwareLog(("PostUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes, 1197 boxPtr->x1, boxPtr->y1, 1198 boxPtr->x2 - boxPtr->x1, boxPtr->y2 - boxPtr->y1)); 1199#endif 1200 1201 /* Clip off (y only) for offscreen memory */ 1202 if (boxPtr->y2 >= pVMWARE->ModeReg.svga_reg_height) 1203 boxPtr->y2 = pVMWARE->ModeReg.svga_reg_height; 1204 if (boxPtr->y1 >= pVMWARE->ModeReg.svga_reg_height) 1205 boxPtr->y1 = pVMWARE->ModeReg.svga_reg_height; 1206 if (boxPtr->y1 == boxPtr->y2) { 1207 boxPtr++; 1208 continue; 1209 } 1210 1211 vmwareSendSVGACmdUpdate(pVMWARE, boxPtr++); 1212 } 1213 1214 if (pVMWARE->hwCursor && pVMWARE->cursorExcludedForUpdate) { 1215 POST_OP_SHOW_CURSOR(); 1216 pVMWARE->cursorExcludedForUpdate = FALSE; 1217 } 1218} 1219 1220static void 1221VMWARELoadPalette(ScrnInfoPtr pScrn, int numColors, int* indices, 1222 LOCO* colors, VisualPtr pVisual) 1223{ 1224 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1225 int i; 1226 1227 for (i = 0; i < numColors; i++) { 1228 vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 0, colors[*indices].red); 1229 vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 1, colors[*indices].green); 1230 vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 2, colors[*indices].blue); 1231 indices++; 1232 } 1233 VmwareLog(("Palette loading done\n")); 1234} 1235 1236 1237DisplayModeRec * 1238VMWAREAddDisplayMode(ScrnInfoPtr pScrn, 1239 const char *name, 1240 int width, 1241 int height) 1242{ 1243 DisplayModeRec *mode; 1244 char * modeName; 1245 1246 mode = malloc(sizeof(DisplayModeRec)); 1247 memset(mode, 0, sizeof *mode); 1248 1249 modeName = malloc(strlen(name) + 1); 1250 strcpy(modeName, name); 1251 mode->name = modeName; 1252 mode->status = MODE_OK; 1253 mode->type = M_T_DEFAULT; 1254 mode->HDisplay = width; 1255 mode->VDisplay = height; 1256 1257 mode->next = pScrn->modes; 1258 mode->prev = pScrn->modes->prev; 1259 pScrn->modes->prev->next = mode; 1260 pScrn->modes->prev = mode; 1261 1262 return mode; 1263} 1264 1265 1266/* 1267 *----------------------------------------------------------------------------- 1268 * 1269 * vmwareIsRegionEqual -- 1270 * 1271 * This function implements REGION_EQUAL because older versions of 1272 * regionstr.h don't define it. 1273 * It is a slightly modified version of miRegionEqual from $Xorg: miregion.c 1274 * 1275 * Results: 1276 * TRUE if regions are equal; FALSE otherwise 1277 * 1278 * Side effects: 1279 * None. 1280 * 1281 *----------------------------------------------------------------------------- 1282 */ 1283 1284Bool 1285vmwareIsRegionEqual(const RegionPtr reg1, 1286 const RegionPtr reg2) 1287{ 1288 int i, num; 1289 BoxPtr rects1, rects2; 1290 1291 if ((reg1->extents.x1 != reg2->extents.x1) || 1292 (reg1->extents.x2 != reg2->extents.x2) || 1293 (reg1->extents.y1 != reg2->extents.y1) || 1294 (reg1->extents.y2 != reg2->extents.y2)) { 1295 return FALSE; 1296 } 1297 1298 num = REGION_NUM_RECTS(reg1); 1299 if (num != REGION_NUM_RECTS(reg2)) { 1300 return FALSE; 1301 } 1302 1303 rects1 = REGION_RECTS(reg1); 1304 rects2 = REGION_RECTS(reg2); 1305 1306 for (i = 0; i < num; i++) { 1307 if ((rects1[i].x1 != rects2[i].x1) || 1308 (rects1[i].x2 != rects2[i].x2) || 1309 (rects1[i].y1 != rects2[i].y1) || 1310 (rects1[i].y2 != rects2[i].y2)) { 1311 return FALSE; 1312 } 1313 } 1314 1315 return TRUE; 1316} 1317 1318static Bool 1319VMWAREScreenInit(SCREEN_INIT_ARGS_DECL) 1320{ 1321 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1322 vgaHWPtr hwp; 1323 VMWAREPtr pVMWARE; 1324 OptionInfoPtr options; 1325 Bool useXinerama = TRUE; 1326 1327 pVMWARE = VMWAREPTR(pScrn); 1328 1329 1330 xf86CollectOptions(pScrn, NULL); 1331 if (!(options = VMWARECopyOptions())) 1332 return FALSE; 1333 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); 1334 1335 /* 1336 * Init xinerama preferences. 1337 */ 1338 useXinerama = xf86ReturnOptValBool(options, OPTION_XINERAMA, 1339 pVMWARE->vmwareCapability & SVGA_CAP_MULTIMON); 1340 if (useXinerama && !(pVMWARE->vmwareCapability & SVGA_CAP_MULTIMON)) { 1341 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1342 "Xinerama is not safely supported by the current virtual hardware. " 1343 "Do not request resolutions that require > 16MB of framebuffer.\n"); 1344 } 1345 1346 1347 if (useXinerama && xf86IsOptionSet(options, OPTION_GUI_LAYOUT)) { 1348 CONST_ABI_18_0 char *topology = xf86GetOptValString(options, OPTION_GUI_LAYOUT); 1349 if (topology) { 1350 pVMWARE->xineramaState = 1351 VMWAREParseTopologyString(pScrn, topology, 1352 &pVMWARE->xineramaNumOutputs, "gui"); 1353 1354 pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL; 1355 1356 free((void *)topology); 1357 } 1358 } else if (useXinerama && 1359 xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) { 1360 CONST_ABI_18_0 char *topology = xf86GetOptValString(options, OPTION_STATIC_XINERAMA); 1361 if (topology) { 1362 pVMWARE->xineramaState = 1363 VMWAREParseTopologyString(pScrn, topology, 1364 &pVMWARE->xineramaNumOutputs, 1365 "static Xinerama"); 1366 1367 pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL; 1368 1369 free((void *)topology); 1370 } 1371 } 1372 1373 free(options); 1374 1375 /* Initialise VMWARE_CTRL extension. */ 1376 VMwareCtrl_ExtInit(pScrn); 1377 1378 /* Initialise Xinerama extension. */ 1379 if (useXinerama) { 1380 VMwareXinerama_ExtInit(pScrn); 1381 } 1382 1383 if (pVMWARE->xinerama && pVMWARE->xineramaStatic) { 1384 xf86DrvMsg(pScrn->scrnIndex, X_INFO, pVMWARE->xineramaState ? 1385 "Using static Xinerama.\n" : 1386 "Failed to configure static Xinerama.\n"); 1387 } 1388 1389 /* 1390 * If using the vgahw module, its data structures and related 1391 * things are typically initialised/mapped here. 1392 */ 1393 hwp = VGAHWPTR(pScrn); 1394 vgaHWGetIOBase(hwp); 1395 1396 VMWAREInitFIFO(pScrn); 1397 1398 /* Initialise the first mode */ 1399 VMWAREModeInit(pScrn, pScrn->currentMode, FALSE); 1400 1401 /* Set the viewport if supported */ 1402 VMWAREAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 1403 1404 /* 1405 * Setup the screen's visuals, and initialise the framebuffer 1406 * code. 1407 */ 1408 VMWAREMapMem(pScrn); 1409 1410 /* 1411 * Clear the framebuffer (and any black-border mode areas). 1412 */ 1413 memset(pVMWARE->FbBase, 0, pVMWARE->FbSize); 1414 vmwareSendSVGACmdUpdateFullScreen(pVMWARE); 1415 1416 /* Reset the visual list */ 1417 miClearVisualTypes(); 1418 1419 /* 1420 * Setup the visuals supported. This driver only supports 1421 * TrueColor for bpp > 8, so the default set of visuals isn't 1422 * acceptable. To deal with this, call miSetVisualTypes with 1423 * the appropriate visual mask. 1424 */ 1425 if (pScrn->bitsPerPixel > 8) { 1426 if (!miSetVisualTypes(pScrn->depth, TrueColorMask, 1427 pScrn->rgbBits, pScrn->defaultVisual)) { 1428 return FALSE; 1429 } 1430 } else { 1431 if (!miSetVisualTypes(pScrn->depth, 1432 miGetDefaultVisualMask(pScrn->depth), 1433 pScrn->rgbBits, pScrn->defaultVisual)) { 1434 return FALSE; 1435 } 1436 } 1437 1438 miSetPixmapDepths(); 1439 1440 /* 1441 * Initialise the framebuffer. 1442 */ 1443 if (!fbScreenInit(pScreen, pVMWARE->FbBase + pVMWARE->fbOffset, 1444 pScrn->virtualX, pScrn->virtualY, 1445 pScrn->xDpi, pScrn->yDpi, 1446 pScrn->displayWidth, 1447 pScrn->bitsPerPixel)) { 1448 return FALSE; 1449 } 1450 1451 /* Override the default mask/offset settings */ 1452 if (pScrn->bitsPerPixel > 8) { 1453 int i; 1454 VisualPtr visual; 1455 1456 for (i = 0, visual = pScreen->visuals; 1457 i < pScreen->numVisuals; i++, visual++) { 1458 if ((visual->class | DynamicClass) == DirectColor) { 1459 visual->offsetRed = pScrn->offset.red; 1460 visual->offsetGreen = pScrn->offset.green; 1461 visual->offsetBlue = pScrn->offset.blue; 1462 visual->redMask = pScrn->mask.red; 1463 visual->greenMask = pScrn->mask.green; 1464 visual->blueMask = pScrn->mask.blue; 1465 } 1466 } 1467 } 1468 1469 /* must be after RGB ordering fixed */ 1470 fbPictureInit (pScreen, 0, 0); 1471 1472 /* 1473 * Save the old screen vector. 1474 */ 1475 pVMWARE->ScrnFuncs = *pScreen; 1476 1477 /* 1478 * Set initial black & white colourmap indices. 1479 */ 1480 xf86SetBlackWhitePixels(pScreen); 1481 1482 /* 1483 * Initialize shadowfb to notify us of dirty rectangles. We only 1484 * need preFB access callbacks if we're using the hw cursor. 1485 */ 1486 if (!ShadowFBInit2(pScreen, 1487 pVMWARE->hwCursor ? VMWAREPreDirtyBBUpdate : NULL, 1488 VMWAREPostDirtyBBUpdate)) { 1489 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1490 "ShadowFB initialization failed\n"); 1491 return FALSE; 1492 } 1493 1494 /* 1495 * If we have a hw cursor, we need to hook functions that might 1496 * read from the framebuffer. 1497 */ 1498 if (pVMWARE->hwCursor) { 1499 vmwareCursorHookWrappers(pScreen); 1500 } 1501 1502 /* 1503 * If backing store is to be supported (as is usually the case), 1504 * initialise it. 1505 */ 1506 xf86SetBackingStore(pScreen); 1507 xf86SetSilkenMouse(pScreen); 1508 1509 /* 1510 * Initialize software cursor. 1511 */ 1512 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1513 1514 /* 1515 * Initialize hardware cursor. 1516 */ 1517 if (pVMWARE->hwCursor) { 1518 if (!vmwareCursorInit(pScreen)) { 1519 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1520 "Hardware cursor initialization failed\n"); 1521 pVMWARE->hwCursor = FALSE; 1522 } 1523 } 1524 1525 /* 1526 * Install colourmap functions. If using the vgahw module, 1527 * vgaHandleColormaps would usually be called here. 1528 */ 1529 if (!fbCreateDefColormap(pScreen)) 1530 return FALSE; 1531 1532 if (!xf86HandleColormaps(pScreen, 256, 8, 1533 VMWARELoadPalette, NULL, 1534 CMAP_PALETTED_TRUECOLOR | 1535 CMAP_RELOAD_ON_MODE_SWITCH)) { 1536 return FALSE; 1537 } 1538 1539 /* 1540 * We explicitly add a set of default modes because the X server will 1541 * not include modes larger than the initial one. 1542 */ 1543 { 1544 unsigned int i; 1545 unsigned int numModes = sizeof (VMWAREDefaultModes) / sizeof *(VMWAREDefaultModes); 1546 char name[10]; 1547 for (i = 0; i < numModes; i++) { 1548 const VMWAREDefaultMode *mode = &VMWAREDefaultModes[i]; 1549 1550 /* Only modes that fit the hardware maximums should be added. */ 1551 if (mode->width <= pVMWARE->maxWidth && mode->height <= pVMWARE->maxHeight) { 1552 snprintf(name, 10, "%dx%d", mode->width, mode->height); 1553 VMWAREAddDisplayMode(pScrn, name, mode->width, mode->height); 1554 } 1555 } 1556 1557 /* Add the hardware maximums as a mode. */ 1558 snprintf(name, 10, "%dx%d", pVMWARE->maxWidth, pVMWARE->maxHeight); 1559 VMWAREAddDisplayMode(pScrn, name, pVMWARE->maxWidth, pVMWARE->maxHeight); 1560 } 1561 1562 /* 1563 * We will lazily add the dynamic modes as the are needed when new 1564 * modes are requested through the control extension. 1565 */ 1566 memset(&pVMWARE->dynModes, 0, sizeof pVMWARE->dynModes); 1567 1568#if VMWARE_DRIVER_FUNC 1569 pScrn->DriverFunc = VMWareDriverFunc; 1570#endif 1571 1572 /* Report any unused options (only for the first generation) */ 1573 if (serverGeneration == 1) { 1574 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1575 } 1576 1577 /* Initialize Xv extension */ 1578 pVMWARE->videoStreams = NULL; 1579 if (vmwareVideoEnabled(pVMWARE)) { 1580 if (!vmwareVideoInit(pScreen)) { 1581 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Xv initialization failed\n"); 1582 } 1583 } 1584 1585 /** 1586 * Wrap CloseScreen and SaveScreen. Do this late since we 1587 * want to be first in the callchain, to avoid using resources 1588 * already taken down in CloseScreen. 1589 */ 1590 1591 pVMWARE->ScrnFuncs.CloseScreen = pScreen->CloseScreen; 1592 pVMWARE->ScrnFuncs.SaveScreen = pScreen->SaveScreen; 1593 1594 pScreen->CloseScreen = VMWARECloseScreen; 1595 pScreen->SaveScreen = VMWARESaveScreen; 1596 1597 /* Done */ 1598 return TRUE; 1599} 1600 1601static Bool 1602VMWARESwitchMode(SWITCH_MODE_ARGS_DECL) 1603{ 1604 SCRN_INFO_PTR(arg); 1605 ScreenPtr pScreen = pScrn->pScreen; 1606 1607 pScreen->mmWidth = (pScreen->width * VMWARE_INCHTOMM + 1608 pScrn->xDpi / 2) / pScrn->xDpi; 1609 pScreen->mmHeight = (pScreen->height * VMWARE_INCHTOMM + 1610 pScrn->yDpi / 2) / pScrn->yDpi; 1611 1612 return VMWAREModeInit(pScrn, mode, TRUE); 1613} 1614 1615static Bool 1616VMWAREEnterVT(VT_FUNC_ARGS_DECL) 1617{ 1618 SCRN_INFO_PTR(arg); 1619 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1620 1621 /* 1622 * After system resumes from hiberation, EnterVT will be called and this 1623 * is a good place to restore the SVGA ID register. 1624 */ 1625 vmwareWriteReg(pVMWARE, SVGA_REG_ID, pVMWARE->suspensionSavedRegId); 1626 1627 if (!pVMWARE->SavedReg.svga_fifo_enabled) { 1628 VMWAREInitFIFO(pScrn); 1629 } 1630 1631 return VMWAREModeInit(pScrn, pScrn->currentMode, TRUE); 1632} 1633 1634static void 1635VMWARELeaveVT(VT_FUNC_ARGS_DECL) 1636{ 1637 SCRN_INFO_PTR(arg); 1638 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1639 1640 /* 1641 * Before shutting down system for hibneration, LeaveVT will be called, 1642 * we save the ID register value here and later restore it in EnterVT. 1643 */ 1644 pVMWARE->suspensionSavedRegId = vmwareReadReg(pVMWARE, SVGA_REG_ID); 1645 1646 VMWARERestore(pScrn); 1647} 1648 1649static void 1650VMWAREFreeScreen(FREE_SCREEN_ARGS_DECL) 1651{ 1652 SCRN_INFO_PTR(arg); 1653 /* 1654 * If the vgahw module is used vgaHWFreeHWRec() would be called 1655 * here. 1656 */ 1657 VMWAREFreeRec(pScrn); 1658} 1659 1660static ModeStatus 1661VMWAREValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 1662{ 1663 return MODE_OK; 1664} 1665 1666void 1667vmwlegacy_hookup(ScrnInfoPtr pScrn) 1668{ 1669 pScrn->PreInit = VMWAREPreInit; 1670 pScrn->ScreenInit = VMWAREScreenInit; 1671 pScrn->SwitchMode = VMWARESwitchMode; 1672 pScrn->EnterVT = VMWAREEnterVT; 1673 pScrn->LeaveVT = VMWARELeaveVT; 1674 pScrn->FreeScreen = VMWAREFreeScreen; 1675 pScrn->ValidMode = VMWAREValidMode; 1676} 1677 1678#ifdef XFree86LOADER 1679void 1680VMWARERefSymLists(void) 1681{ 1682 LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols, 1683 shadowfbSymbols, NULL); 1684} 1685#endif /* XFree86LOADER */ 1686