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