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