vmware.c revision 3bfa90b6
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 if (pVMWARE->pEnt->location.type != BUS_PCI) { 314 return FALSE; 315 } 316 pVMWARE->PciInfo = xf86GetPciInfoForEntity(pVMWARE->pEnt->index); 317 if (pVMWARE->PciInfo == NULL) { 318 return FALSE; 319 } 320 321 if (DEVICE_ID(pVMWARE->PciInfo) == PCI_DEVICE_ID_VMWARE_SVGA) { 322 pVMWARE->indexReg = domainIOBase + 323 SVGA_LEGACY_BASE_PORT + SVGA_INDEX_PORT*sizeof(uint32); 324 pVMWARE->valueReg = domainIOBase + 325 SVGA_LEGACY_BASE_PORT + SVGA_VALUE_PORT*sizeof(uint32); 326 } else { 327 /* Note: This setting of valueReg causes unaligned I/O */ 328#if XSERVER_LIBPCIACCESS 329 pVMWARE->portIOBase = pVMWARE->PciInfo->regions[0].base_addr; 330#else 331 pVMWARE->portIOBase = pVMWARE->PciInfo->ioBase[0]; 332#endif 333 pVMWARE->indexReg = domainIOBase + 334 pVMWARE->portIOBase + SVGA_INDEX_PORT; 335 pVMWARE->valueReg = domainIOBase + 336 pVMWARE->portIOBase + SVGA_VALUE_PORT; 337 } 338 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 339 "VMware SVGA regs at (0x%04lx, 0x%04lx)\n", 340 pVMWARE->indexReg, pVMWARE->valueReg); 341 342 if (!xf86LoadSubModule(pScrn, "vgahw")) { 343 return FALSE; 344 } 345 346 xf86LoaderReqSymLists(vgahwSymbols, NULL); 347 348 if (!vgaHWGetHWRec(pScrn)) { 349 return FALSE; 350 } 351 352#ifdef HAVE_XORG_SERVER_1_12_0 353 vgaHWSetStdFuncs(VGAHWPTR(pScrn)); 354#endif 355 356 /* 357 * Save the current video state. Do it here before VMXGetVMwareSvgaId 358 * writes to any registers. 359 */ 360 VMWARESave(pScrn); 361 362 id = VMXGetVMwareSvgaId(pVMWARE); 363 if (id == SVGA_ID_0 || id == SVGA_ID_INVALID) { 364 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 365 "No supported VMware SVGA found (read ID 0x%08x).\n", id); 366 return FALSE; 367 } 368 pVMWARE->suspensionSavedRegId = id; 369 370#if !XSERVER_LIBPCIACCESS 371 pVMWARE->PciTag = pciTag(pVMWARE->PciInfo->bus, pVMWARE->PciInfo->device, 372 pVMWARE->PciInfo->func); 373#endif 374 pVMWARE->Primary = xf86IsPrimaryPci(pVMWARE->PciInfo); 375 376 pScrn->monitor = pScrn->confScreen->monitor; 377 378#ifdef ACCELERATE_OPS 379 pVMWARE->vmwareCapability = vmwareReadReg(pVMWARE, SVGA_REG_CAPABILITIES); 380#else 381 pVMWARE->vmwareCapability = 0; 382#endif 383 384 pVMWARE->bitsPerPixel = vmwareReadReg(pVMWARE, 385 SVGA_REG_HOST_BITS_PER_PIXEL); 386 if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { 387 vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, pVMWARE->bitsPerPixel); 388 } 389 390 pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH); 391 pVMWARE->videoRam = vmwareReadReg(pVMWARE, SVGA_REG_VRAM_SIZE); 392 pVMWARE->memPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_FB_START); 393 pVMWARE->maxWidth = vmwareReadReg(pVMWARE, SVGA_REG_MAX_WIDTH); 394 pVMWARE->maxHeight = vmwareReadReg(pVMWARE, SVGA_REG_MAX_HEIGHT); 395 pVMWARE->cursorDefined = FALSE; 396 pVMWARE->cursorShouldBeHidden = FALSE; 397 398 if (pVMWARE->vmwareCapability & SVGA_CAP_CURSOR_BYPASS_2) { 399 pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_REMOVE_FROM_FB; 400 pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_RESTORE_TO_FB; 401 } else { 402 pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_HIDE; 403 pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_SHOW; 404 } 405 406 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "caps: 0x%08X\n", pVMWARE->vmwareCapability); 407 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "depth: %d\n", pVMWARE->depth); 408 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "bpp: %d\n", pVMWARE->bitsPerPixel); 409 410 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "vram: %d\n", pVMWARE->videoRam); 411 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "pbase: 0x%08lx\n", pVMWARE->memPhysBase); 412 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mwidt: %d\n", pVMWARE->maxWidth); 413 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mheig: %d\n", pVMWARE->maxHeight); 414 415 if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { 416 bpp24flags = Support24bppFb | Support32bppFb; 417 } else { 418 switch (pVMWARE->depth) { 419 case 16: 420 /* 421 * In certain cases, the Windows host appears to 422 * report 16 bpp and 16 depth but 555 weight. Just 423 * silently convert it to depth of 15. 424 */ 425 if (pVMWARE->bitsPerPixel == 16 && 426 pVMWARE->weight.green == 5) 427 pVMWARE->depth = 15; 428 case 8: 429 case 15: 430 bpp24flags = NoDepth24Support; 431 break; 432 case 32: 433 /* 434 * There is no 32 bit depth, apparently it can get 435 * reported this way sometimes on the Windows host. 436 */ 437 if (pVMWARE->bitsPerPixel == 32) 438 pVMWARE->depth = 24; 439 case 24: 440 if (pVMWARE->bitsPerPixel == 24) 441 bpp24flags = Support24bppFb; 442 else 443 bpp24flags = Support32bppFb; 444 break; 445 default: 446 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 447 "Adapter is using an unsupported depth (%d).\n", 448 pVMWARE->depth); 449 return FALSE; 450 } 451 } 452 453 if (!xf86SetDepthBpp(pScrn, pVMWARE->depth, pVMWARE->bitsPerPixel, 454 pVMWARE->bitsPerPixel, bpp24flags)) { 455 return FALSE; 456 } 457 458 /* Check that the returned depth is one we support */ 459 switch (pScrn->depth) { 460 case 8: 461 case 15: 462 case 16: 463 case 24: 464 /* OK */ 465 break; 466 default: 467 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 468 "Given depth (%d) is not supported by this driver\n", 469 pScrn->depth); 470 return FALSE; 471 } 472 473 if (pScrn->bitsPerPixel != pVMWARE->bitsPerPixel) { 474 if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { 475 vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, 476 pScrn->bitsPerPixel); 477 pVMWARE->bitsPerPixel = 478 vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL); 479 pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH); 480 } else { 481 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 482 "Currently unavailable depth/bpp of %d/%d requested.\n" 483 "\tThe guest X server must run at the same depth and bpp as the host\n" 484 "\t(which are currently %d/%d). This is automatically detected. Please\n" 485 "\tdo not specify a depth on the command line or via the config file.\n", 486 pScrn->depth, pScrn->bitsPerPixel, 487 pVMWARE->depth, pVMWARE->bitsPerPixel); 488 return FALSE; 489 } 490 } 491 492 /* 493 * Defer reading the colour registers until here in case we changed 494 * bpp above. 495 */ 496 497 pVMWARE->weight.red = 498 vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_RED_MASK)); 499 pVMWARE->weight.green = 500 vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_GREEN_MASK)); 501 pVMWARE->weight.blue = 502 vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_BLUE_MASK)); 503 pVMWARE->offset.blue = 0; 504 pVMWARE->offset.green = pVMWARE->weight.blue; 505 pVMWARE->offset.red = pVMWARE->weight.green + pVMWARE->offset.green; 506 pVMWARE->defaultVisual = vmwareReadReg(pVMWARE, SVGA_REG_PSEUDOCOLOR) ? 507 PseudoColor : TrueColor; 508 509 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 510 2, "depth: %d\n", pVMWARE->depth); 511 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 512 2, "bpp: %d\n", pVMWARE->bitsPerPixel); 513 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 514 2, "w.red: %d\n", (int)pVMWARE->weight.red); 515 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 516 2, "w.grn: %d\n", (int)pVMWARE->weight.green); 517 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 518 2, "w.blu: %d\n", (int)pVMWARE->weight.blue); 519 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 520 2, "vis: %d\n", pVMWARE->defaultVisual); 521 522 if (pScrn->depth != pVMWARE->depth) { 523 if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { 524 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 525 "Currently unavailable depth of %d requested.\n" 526 "\tIf the guest X server's BPP matches the host's " 527 "BPP, then\n\tthe guest X server's depth must also " 528 "match the\n\thost's depth (currently %d).\n", 529 pScrn->depth, pVMWARE->depth); 530 } else { 531 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 532 "Currently unavailable depth of %d requested.\n" 533 "\tThe guest X server must run at the same depth as " 534 "the host (which\n\tis currently %d). This is " 535 "automatically detected. Please do not\n\tspecify " 536 "a depth on the command line or via the config file.\n", 537 pScrn->depth, pVMWARE->depth); 538 } 539 return FALSE; 540 } 541 xf86PrintDepthBpp(pScrn); 542 543#if 0 544 if (pScrn->depth == 24 && pix24bpp == 0) { 545 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 546 } 547#endif 548 549 if (pScrn->depth > 8) { 550 rgb zeros = { 0, 0, 0 }; 551 552 if (!xf86SetWeight(pScrn, pVMWARE->weight, zeros)) { 553 return FALSE; 554 } 555 /* FIXME check returned weight */ 556 } 557 if (!xf86SetDefaultVisual(pScrn, pVMWARE->defaultVisual)) { 558 return FALSE; 559 } 560 if (pScrn->defaultVisual != pVMWARE->defaultVisual) { 561 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 562 "Given visual (%d) is not supported by this driver (%d is required)\n", 563 pScrn->defaultVisual, pVMWARE->defaultVisual); 564 return FALSE; 565 } 566#if 0 567 bytesPerPixel = pScrn->bitsPerPixel / 8; 568#endif 569 pScrn->progClock = TRUE; 570 571#if 0 /* MGA does not do this */ 572 if (pScrn->visual != 0) { /* FIXME */ 573 /* print error message */ 574 return FALSE; 575 } 576#endif 577 578 xf86CollectOptions(pScrn, NULL); 579 if (!(options = VMWARECopyOptions())) 580 return FALSE; 581 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); 582 583 if (pScrn->depth <= 8) { 584 pScrn->rgbBits = 8; 585 } 586 587 if (!pScrn->chipset) { 588 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04x is not recognised\n", DEVICE_ID(pVMWARE->PciInfo)); 589 return FALSE; 590 } 591 592 from = X_DEFAULT; 593 pVMWARE->hwCursor = TRUE; 594 if (xf86GetOptValBool(options, OPTION_HW_CURSOR, &pVMWARE->hwCursor)) { 595 from = X_CONFIG; 596 } 597 if (pVMWARE->hwCursor && !(pVMWARE->vmwareCapability & SVGA_CAP_CURSOR)) { 598 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW cursor is not supported in this configuration\n"); 599 from = X_PROBED; 600 pVMWARE->hwCursor = FALSE; 601 } 602 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 603 pVMWARE->hwCursor ? "HW" : "SW"); 604 pScrn->videoRam = pVMWARE->videoRam / 1024; 605 pScrn->memPhysBase = pVMWARE->memPhysBase; 606 607 from = X_DEFAULT; 608 defaultMode = TRUE; 609 if (xf86GetOptValBool(options, OPTION_DEFAULT_MODE, &defaultMode)) { 610 from = X_CONFIG; 611 } 612 613 width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH); 614 height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT); 615 width = MAX(width, VMW_MIN_INITIAL_WIDTH); 616 height = MAX(height, VMW_MIN_INITIAL_HEIGHT); 617 618 if (width > pVMWARE->maxWidth || height > pVMWARE->maxHeight) { 619 /* 620 * This is an error condition and shouldn't happen. 621 * revert to MIN_INITIAL_ values 622 */ 623 width = VMW_MIN_INITIAL_WIDTH; 624 height = VMW_MIN_INITIAL_HEIGHT; 625 } 626 627 xf86DrvMsg(pScrn->scrnIndex, from, 628 "Will %sset up a driver mode with dimensions %dx%d.\n", 629 defaultMode ? "" : "not ", width, height); 630 631 free(options); 632 633 { 634 Gamma zeros = { 0.0, 0.0, 0.0 }; 635 if (!xf86SetGamma(pScrn, zeros)) { 636 return FALSE; 637 } 638 } 639#if 0 640 if ((i = xf86GetPciInfoForScreen(pScrn->scrnIndex, &pciList, NULL)) != 1) { 641 /* print error message */ 642 VMWAREFreeRec(pScrn); 643 if (i > 0) { 644 free(pciList); 645 } 646 return FALSE; 647 } 648#endif 649 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 650 clockRanges->next = NULL; 651 clockRanges->minClock = 1; 652 clockRanges->maxClock = 400000000; 653 clockRanges->clockIndex = -1; 654 clockRanges->interlaceAllowed = FALSE; 655 clockRanges->doubleScanAllowed = FALSE; 656 clockRanges->ClockMulFactor = 1; 657 clockRanges->ClockDivFactor = 1; 658 659 if (defaultMode) { 660 vmwareAddDefaultMode(pScrn, width, height); 661 } 662 663 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, 664 clockRanges, NULL, 256, pVMWARE->maxWidth, 665 pVMWARE->bitsPerPixel * 1, 666 128, pVMWARE->maxHeight, 667 pScrn->display->virtualX, pScrn->display->virtualY, 668 pVMWARE->videoRam, 669 LOOKUP_BEST_REFRESH | LOOKUP_OPTIONAL_TOLERANCES); 670 671 if (i == -1) { 672 VMWAREFreeRec(pScrn); 673 return FALSE; 674 } 675 xf86PruneDriverModes(pScrn); 676 if (i == 0 || pScrn->modes == NULL) { 677 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 678 VMWAREFreeRec(pScrn); 679 return FALSE; 680 } 681 682 pScrn->currentMode = pScrn->modes; 683 pScrn->virtualX = pScrn->modes->HDisplay; 684 pScrn->virtualY = pScrn->modes->VDisplay; 685 686 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 687 688 xf86PrintModes(pScrn); 689 xf86SetDpi(pScrn, 0, 0); 690 if (!xf86LoadSubModule(pScrn, "fb") || 691 !xf86LoadSubModule(pScrn, "shadowfb")) { 692 VMWAREFreeRec(pScrn); 693 return FALSE; 694 } 695 xf86LoaderReqSymLists(fbSymbols, shadowfbSymbols, NULL); 696 697 /* Need ramdac for hwcursor */ 698 if (pVMWARE->hwCursor) { 699 if (!xf86LoadSubModule(pScrn, "ramdac")) { 700 VMWAREFreeRec(pScrn); 701 return FALSE; 702 } 703 xf86LoaderReqSymLists(ramdacSymbols, NULL); 704 } 705 706 return TRUE; 707} 708 709static Bool 710VMWAREMapMem(ScrnInfoPtr pScrn) 711{ 712 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 713#if XSERVER_LIBPCIACCESS 714 int err; 715 struct pci_device *const device = pVMWARE->PciInfo; 716 void *fbBase; 717#endif 718 719#if XSERVER_LIBPCIACCESS 720 err = pci_device_map_range(device, 721 pVMWARE->memPhysBase, 722 pVMWARE->videoRam, 723 PCI_DEV_MAP_FLAG_WRITABLE, 724 &fbBase); 725 if (err) { 726 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 727 "Unable to map frame buffer BAR. %s (%d)\n", 728 strerror (err), err); 729 return FALSE; 730 } 731 pVMWARE->FbBase = fbBase; 732#else 733 pVMWARE->FbBase = xf86MapPciMem(pScrn->scrnIndex, 0, 734 pVMWARE->PciTag, 735 pVMWARE->memPhysBase, 736 pVMWARE->videoRam); 737#endif 738 if (!pVMWARE->FbBase) 739 return FALSE; 740 741 VmwareLog(("FB Mapped: %p/%u -> %p/%u\n", 742 pVMWARE->memPhysBase, pVMWARE->videoRam, 743 pVMWARE->FbBase, pVMWARE->videoRam)); 744 return TRUE; 745} 746 747static Bool 748VMWAREUnmapMem(ScrnInfoPtr pScrn) 749{ 750 VMWAREPtr pVMWARE; 751 752 pVMWARE = VMWAREPTR(pScrn); 753 754 VmwareLog(("Unmapped: %p/%u\n", pVMWARE->FbBase, pVMWARE->videoRam)); 755 756#if XSERVER_LIBPCIACCESS 757 pci_device_unmap_range(pVMWARE->PciInfo, pVMWARE->FbBase, pVMWARE->videoRam); 758#else 759 xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->FbBase, pVMWARE->videoRam); 760#endif 761 pVMWARE->FbBase = NULL; 762 return TRUE; 763} 764 765static void 766VMWARESave(ScrnInfoPtr pScrn) 767{ 768 vgaHWPtr hwp = VGAHWPTR(pScrn); 769 vgaRegPtr vgaReg = &hwp->SavedReg; 770 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 771 VMWARERegPtr vmwareReg = &pVMWARE->SavedReg; 772 773 vgaHWSave(pScrn, vgaReg, VGA_SR_ALL); 774 775 vmwareReg->svga_reg_enable = vmwareReadReg(pVMWARE, SVGA_REG_ENABLE); 776 vmwareReg->svga_reg_width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH); 777 vmwareReg->svga_reg_height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT); 778 vmwareReg->svga_reg_bits_per_pixel = 779 vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL); 780 vmwareReg->svga_reg_id = vmwareReadReg(pVMWARE, SVGA_REG_ID); 781 782 /* XXX this should be based on the cap bit, not hwCursor... */ 783 if (pVMWARE->hwCursor) { 784 vmwareReg->svga_reg_cursor_on = 785 vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ON); 786 vmwareReg->svga_reg_cursor_x = 787 vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_X); 788 vmwareReg->svga_reg_cursor_y = 789 vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_Y); 790 vmwareReg->svga_reg_cursor_id = 791 vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ID); 792 } 793 794 vmwareReg->svga_fifo_enabled = vmwareReadReg(pVMWARE, SVGA_REG_CONFIG_DONE); 795} 796 797static void 798VMWARERestoreRegs(ScrnInfoPtr pScrn, VMWARERegPtr vmwareReg) 799{ 800 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 801 VmwareLog(("VMWARERestoreRegs: W: %d, H: %d, BPP: %d, Enable: %d\n", 802 vmwareReg->svga_reg_width, vmwareReg->svga_reg_height, 803 vmwareReg->svga_reg_bits_per_pixel, vmwareReg->svga_reg_enable)); 804 if (vmwareReg->svga_reg_enable) { 805 vmwareWriteReg(pVMWARE, SVGA_REG_ID, vmwareReg->svga_reg_id); 806 vmwareWriteReg(pVMWARE, SVGA_REG_WIDTH, vmwareReg->svga_reg_width); 807 vmwareWriteReg(pVMWARE, SVGA_REG_HEIGHT, vmwareReg->svga_reg_height); 808 vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, 809 vmwareReg->svga_reg_bits_per_pixel); 810 vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable); 811 vmwareWriteReg(pVMWARE, SVGA_REG_GUEST_ID, GUEST_OS_LINUX); 812 if (pVMWARE->hwCursor) { 813 vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ID, 814 vmwareReg->svga_reg_cursor_id); 815 vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_X, 816 vmwareReg->svga_reg_cursor_x); 817 vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_Y, 818 vmwareReg->svga_reg_cursor_y); 819 vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ON, 820 vmwareReg->svga_reg_cursor_on); 821 } 822 } else { 823 vmwareWriteReg(pVMWARE, SVGA_REG_ID, vmwareReg->svga_reg_id); 824 vmwareWriteReg(pVMWARE, SVGA_REG_WIDTH, vmwareReg->svga_reg_width); 825 vmwareWriteReg(pVMWARE, SVGA_REG_HEIGHT, vmwareReg->svga_reg_height); 826 vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, 827 vmwareReg->svga_reg_bits_per_pixel); 828 vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable); 829 } 830} 831 832static void 833VMWARERestore(ScrnInfoPtr pScrn) 834{ 835 vgaHWPtr hwp = VGAHWPTR(pScrn); 836 vgaRegPtr vgaReg = &hwp->SavedReg; 837 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 838 VMWARERegPtr vmwareReg = &pVMWARE->SavedReg; 839 840 vmwareWaitForFB(pVMWARE); 841 if (!vmwareReg->svga_fifo_enabled) { 842 VMWAREStopFIFO(pScrn); 843 } 844 845 vgaHWProtect(pScrn, TRUE); 846 VMWARERestoreRegs(pScrn, vmwareReg); 847 vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); 848 vgaHWProtect(pScrn, FALSE); 849} 850 851static Bool 852VMWAREModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool rebuildPixmap) 853{ 854 vgaHWPtr hwp = VGAHWPTR(pScrn); 855 vgaRegPtr vgaReg = &hwp->ModeReg; 856 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 857 VMWARERegPtr vmwareReg = &pVMWARE->ModeReg; 858 859 vgaHWUnlock(hwp); 860 if (!vgaHWInit(pScrn, mode)) 861 return FALSE; 862 pScrn->vtSema = TRUE; 863 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 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 free(topology); 1336 } 1337 } else if (useXinerama && 1338 xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) { 1339 char *topology = xf86GetOptValString(options, OPTION_STATIC_XINERAMA); 1340 if (topology) { 1341 pVMWARE->xineramaState = 1342 VMWAREParseTopologyString(pScrn, topology, 1343 &pVMWARE->xineramaNumOutputs, 1344 "static Xinerama"); 1345 1346 pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL; 1347 1348 free(topology); 1349 } 1350 } 1351 1352 free(options); 1353 1354 /* Initialise VMWARE_CTRL extension. */ 1355 VMwareCtrl_ExtInit(pScrn); 1356 1357 /* Initialise Xinerama extension. */ 1358 if (useXinerama) { 1359 VMwareXinerama_ExtInit(pScrn); 1360 } 1361 1362 if (pVMWARE->xinerama && pVMWARE->xineramaStatic) { 1363 xf86DrvMsg(pScrn->scrnIndex, X_INFO, pVMWARE->xineramaState ? 1364 "Using static Xinerama.\n" : 1365 "Failed to configure static Xinerama.\n"); 1366 } 1367 1368 /* 1369 * If using the vgahw module, its data structures and related 1370 * things are typically initialised/mapped here. 1371 */ 1372 hwp = VGAHWPTR(pScrn); 1373 vgaHWGetIOBase(hwp); 1374 1375 VMWAREInitFIFO(pScrn); 1376 1377 /* Initialise the first mode */ 1378 VMWAREModeInit(pScrn, pScrn->currentMode, FALSE); 1379 1380 /* Set the viewport if supported */ 1381 VMWAREAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 1382 1383 /* 1384 * Setup the screen's visuals, and initialise the framebuffer 1385 * code. 1386 */ 1387 VMWAREMapMem(pScrn); 1388 1389 /* 1390 * Clear the framebuffer (and any black-border mode areas). 1391 */ 1392 memset(pVMWARE->FbBase, 0, pVMWARE->FbSize); 1393 vmwareSendSVGACmdUpdateFullScreen(pVMWARE); 1394 1395 /* Reset the visual list */ 1396 miClearVisualTypes(); 1397 1398 /* 1399 * Setup the visuals supported. This driver only supports 1400 * TrueColor for bpp > 8, so the default set of visuals isn't 1401 * acceptable. To deal with this, call miSetVisualTypes with 1402 * the appropriate visual mask. 1403 */ 1404 if (pScrn->bitsPerPixel > 8) { 1405 if (!miSetVisualTypes(pScrn->depth, TrueColorMask, 1406 pScrn->rgbBits, pScrn->defaultVisual)) { 1407 return FALSE; 1408 } 1409 } else { 1410 if (!miSetVisualTypes(pScrn->depth, 1411 miGetDefaultVisualMask(pScrn->depth), 1412 pScrn->rgbBits, pScrn->defaultVisual)) { 1413 return FALSE; 1414 } 1415 } 1416 1417 miSetPixmapDepths(); 1418 1419 /* 1420 * Initialise the framebuffer. 1421 */ 1422 if (!fbScreenInit(pScreen, pVMWARE->FbBase + pVMWARE->fbOffset, 1423 pScrn->virtualX, pScrn->virtualY, 1424 pScrn->xDpi, pScrn->yDpi, 1425 pScrn->displayWidth, 1426 pScrn->bitsPerPixel)) { 1427 return FALSE; 1428 } 1429 1430 /* Override the default mask/offset settings */ 1431 if (pScrn->bitsPerPixel > 8) { 1432 int i; 1433 VisualPtr visual; 1434 1435 for (i = 0, visual = pScreen->visuals; 1436 i < pScreen->numVisuals; i++, visual++) { 1437 if ((visual->class | DynamicClass) == DirectColor) { 1438 visual->offsetRed = pScrn->offset.red; 1439 visual->offsetGreen = pScrn->offset.green; 1440 visual->offsetBlue = pScrn->offset.blue; 1441 visual->redMask = pScrn->mask.red; 1442 visual->greenMask = pScrn->mask.green; 1443 visual->blueMask = pScrn->mask.blue; 1444 } 1445 } 1446 } 1447 1448 /* must be after RGB ordering fixed */ 1449 fbPictureInit (pScreen, 0, 0); 1450 1451 /* 1452 * Save the old screen vector. 1453 */ 1454 pVMWARE->ScrnFuncs = *pScreen; 1455 1456 /* 1457 * Set initial black & white colourmap indices. 1458 */ 1459 xf86SetBlackWhitePixels(pScreen); 1460 1461 /* 1462 * Initialize shadowfb to notify us of dirty rectangles. We only 1463 * need preFB access callbacks if we're using the hw cursor. 1464 */ 1465 if (!ShadowFBInit2(pScreen, 1466 pVMWARE->hwCursor ? VMWAREPreDirtyBBUpdate : NULL, 1467 VMWAREPostDirtyBBUpdate)) { 1468 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1469 "ShadowFB initialization failed\n"); 1470 return FALSE; 1471 } 1472 1473 /* 1474 * If we have a hw cursor, we need to hook functions that might 1475 * read from the framebuffer. 1476 */ 1477 if (pVMWARE->hwCursor) { 1478 vmwareCursorHookWrappers(pScreen); 1479 } 1480 1481 /* 1482 * If backing store is to be supported (as is usually the case), 1483 * initialise it. 1484 */ 1485 xf86SetBackingStore(pScreen); 1486 xf86SetSilkenMouse(pScreen); 1487 1488 /* 1489 * Initialize software cursor. 1490 */ 1491 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1492 1493 /* 1494 * Initialize hardware cursor. 1495 */ 1496 if (pVMWARE->hwCursor) { 1497 if (!vmwareCursorInit(pScreen)) { 1498 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1499 "Hardware cursor initialization failed\n"); 1500 pVMWARE->hwCursor = FALSE; 1501 } 1502 } 1503 1504 /* 1505 * Install colourmap functions. If using the vgahw module, 1506 * vgaHandleColormaps would usually be called here. 1507 */ 1508 if (!fbCreateDefColormap(pScreen)) 1509 return FALSE; 1510 1511 if (!xf86HandleColormaps(pScreen, 256, 8, 1512 VMWARELoadPalette, NULL, 1513 CMAP_PALETTED_TRUECOLOR | 1514 CMAP_RELOAD_ON_MODE_SWITCH)) { 1515 return FALSE; 1516 } 1517 1518 /* 1519 * We explictly add a set of default modes because the X server will 1520 * not include modes larger than the initial one. 1521 */ 1522 { 1523 unsigned int i; 1524 unsigned int numModes = sizeof (VMWAREDefaultModes) / sizeof *(VMWAREDefaultModes); 1525 char name[10]; 1526 for (i = 0; i < numModes; i++) { 1527 const VMWAREDefaultMode *mode = &VMWAREDefaultModes[i]; 1528 1529 /* Only modes that fit the hardware maximums should be added. */ 1530 if (mode->width <= pVMWARE->maxWidth && mode->height <= pVMWARE->maxHeight) { 1531 snprintf(name, 10, "%dx%d", mode->width, mode->height); 1532 VMWAREAddDisplayMode(pScrn, name, mode->width, mode->height); 1533 } 1534 } 1535 1536 /* Add the hardware maximums as a mode. */ 1537 snprintf(name, 10, "%dx%d", pVMWARE->maxWidth, pVMWARE->maxHeight); 1538 VMWAREAddDisplayMode(pScrn, name, pVMWARE->maxWidth, pVMWARE->maxHeight); 1539 } 1540 1541 /* 1542 * We will lazily add the dynamic modes as the are needed when new 1543 * modes are requested through the control extension. 1544 */ 1545 memset(&pVMWARE->dynModes, 0, sizeof pVMWARE->dynModes); 1546 1547#if VMWARE_DRIVER_FUNC 1548 pScrn->DriverFunc = VMWareDriverFunc; 1549#endif 1550 1551 /* Report any unused options (only for the first generation) */ 1552 if (serverGeneration == 1) { 1553 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1554 } 1555 1556 /* Initialize Xv extension */ 1557 pVMWARE->videoStreams = NULL; 1558 if (vmwareVideoEnabled(pVMWARE)) { 1559 if (!vmwareVideoInit(pScreen)) { 1560 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Xv initialization failed\n"); 1561 } 1562 } 1563 1564 /** 1565 * Wrap CloseScreen and SaveScreen. Do this late since we 1566 * want to be first in the callchain, to avoid using resources 1567 * already taken down in CloseScreen. 1568 */ 1569 1570 pVMWARE->ScrnFuncs.CloseScreen = pScreen->CloseScreen; 1571 pVMWARE->ScrnFuncs.SaveScreen = pScreen->SaveScreen; 1572 1573 pScreen->CloseScreen = VMWARECloseScreen; 1574 pScreen->SaveScreen = VMWARESaveScreen; 1575 1576 /* Done */ 1577 return TRUE; 1578} 1579 1580static Bool 1581VMWARESwitchMode(SWITCH_MODE_ARGS_DECL) 1582{ 1583 SCRN_INFO_PTR(arg); 1584 ScreenPtr pScreen = pScrn->pScreen; 1585 1586 pScreen->mmWidth = (pScreen->width * VMWARE_INCHTOMM + 1587 pScrn->xDpi / 2) / pScrn->xDpi; 1588 pScreen->mmHeight = (pScreen->height * VMWARE_INCHTOMM + 1589 pScrn->yDpi / 2) / pScrn->yDpi; 1590 1591 return VMWAREModeInit(pScrn, mode, TRUE); 1592} 1593 1594static Bool 1595VMWAREEnterVT(VT_FUNC_ARGS_DECL) 1596{ 1597 SCRN_INFO_PTR(arg); 1598 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1599 1600 /* 1601 * After system resumes from hiberation, EnterVT will be called and this 1602 * is a good place to restore the SVGA ID register. 1603 */ 1604 vmwareWriteReg(pVMWARE, SVGA_REG_ID, pVMWARE->suspensionSavedRegId); 1605 1606 if (!pVMWARE->SavedReg.svga_fifo_enabled) { 1607 VMWAREInitFIFO(pScrn); 1608 } 1609 1610 return VMWAREModeInit(pScrn, pScrn->currentMode, TRUE); 1611} 1612 1613static void 1614VMWARELeaveVT(VT_FUNC_ARGS_DECL) 1615{ 1616 SCRN_INFO_PTR(arg); 1617 VMWAREPtr pVMWARE = VMWAREPTR(pScrn); 1618 1619 /* 1620 * Before shutting down system for hibneration, LeaveVT will be called, 1621 * we save the ID register value here and later restore it in EnterVT. 1622 */ 1623 pVMWARE->suspensionSavedRegId = vmwareReadReg(pVMWARE, SVGA_REG_ID); 1624 1625 VMWARERestore(pScrn); 1626} 1627 1628static void 1629VMWAREFreeScreen(FREE_SCREEN_ARGS_DECL) 1630{ 1631 SCRN_INFO_PTR(arg); 1632 /* 1633 * If the vgahw module is used vgaHWFreeHWRec() would be called 1634 * here. 1635 */ 1636 VMWAREFreeRec(pScrn); 1637} 1638 1639static ModeStatus 1640VMWAREValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 1641{ 1642 return MODE_OK; 1643} 1644 1645void 1646vmwlegacy_hookup(ScrnInfoPtr pScrn) 1647{ 1648 pScrn->PreInit = VMWAREPreInit; 1649 pScrn->ScreenInit = VMWAREScreenInit; 1650 pScrn->SwitchMode = VMWARESwitchMode; 1651 pScrn->EnterVT = VMWAREEnterVT; 1652 pScrn->LeaveVT = VMWARELeaveVT; 1653 pScrn->FreeScreen = VMWAREFreeScreen; 1654 pScrn->ValidMode = VMWAREValidMode; 1655} 1656 1657#ifdef XFree86LOADER 1658void 1659VMWARERefSymLists(void) 1660{ 1661 LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols, 1662 shadowfbSymbols, NULL); 1663} 1664#endif /* XFree86LOADER */ 1665