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