vmware.c revision 16fd1166
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	6
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
309static void
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
656#if !XSERVER_LIBPCIACCESS
657    pVMWARE->PciTag = pciTag(pVMWARE->PciInfo->bus, pVMWARE->PciInfo->device,
658                             pVMWARE->PciInfo->func);
659#endif
660    pVMWARE->Primary = xf86IsPrimaryPci(pVMWARE->PciInfo);
661
662    pScrn->monitor = pScrn->confScreen->monitor;
663
664#ifdef ACCELERATE_OPS
665    pVMWARE->vmwareCapability = vmwareReadReg(pVMWARE, SVGA_REG_CAPABILITIES);
666#else
667    pVMWARE->vmwareCapability = 0;
668#endif
669
670    pVMWARE->bitsPerPixel = vmwareReadReg(pVMWARE,
671                                          SVGA_REG_HOST_BITS_PER_PIXEL);
672    if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) {
673       vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, pVMWARE->bitsPerPixel);
674    }
675
676    pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH);
677    pVMWARE->videoRam = vmwareReadReg(pVMWARE, SVGA_REG_VRAM_SIZE);
678    pVMWARE->memPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_FB_START);
679    pVMWARE->maxWidth = vmwareReadReg(pVMWARE, SVGA_REG_MAX_WIDTH);
680    pVMWARE->maxHeight = vmwareReadReg(pVMWARE, SVGA_REG_MAX_HEIGHT);
681    pVMWARE->cursorDefined = FALSE;
682    pVMWARE->cursorShouldBeHidden = FALSE;
683
684    if (pVMWARE->vmwareCapability & SVGA_CAP_CURSOR_BYPASS_2) {
685        pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_REMOVE_FROM_FB;
686        pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_RESTORE_TO_FB;
687    } else {
688        pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_HIDE;
689        pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_SHOW;
690    }
691
692    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "caps:  0x%08X\n", pVMWARE->vmwareCapability);
693    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "depth: %d\n", pVMWARE->depth);
694    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "bpp:   %d\n", pVMWARE->bitsPerPixel);
695
696    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "vram:  %d\n", pVMWARE->videoRam);
697    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "pbase: 0x%08lx\n", pVMWARE->memPhysBase);
698    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mwidt: %d\n", pVMWARE->maxWidth);
699    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mheig: %d\n", pVMWARE->maxHeight);
700
701    if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) {
702        bpp24flags = Support24bppFb | Support32bppFb;
703    } else {
704        switch (pVMWARE->depth) {
705        case 16:
706            /*
707             * In certain cases, the Windows host appears to
708             * report 16 bpp and 16 depth but 555 weight.  Just
709             * silently convert it to depth of 15.
710             */
711            if (pVMWARE->bitsPerPixel == 16 &&
712                pVMWARE->weight.green == 5)
713                pVMWARE->depth = 15;
714        case 8:
715        case 15:
716            bpp24flags = NoDepth24Support;
717         break;
718        case 32:
719            /*
720             * There is no 32 bit depth, apparently it can get
721             * reported this way sometimes on the Windows host.
722             */
723            if (pVMWARE->bitsPerPixel == 32)
724                pVMWARE->depth = 24;
725        case 24:
726            if (pVMWARE->bitsPerPixel == 24)
727                bpp24flags = Support24bppFb;
728            else
729                bpp24flags = Support32bppFb;
730            break;
731       default:
732            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
733                       "Adapter is using an unsupported depth (%d).\n",
734                       pVMWARE->depth);
735            return FALSE;
736       }
737    }
738
739    if (!xf86SetDepthBpp(pScrn, pVMWARE->depth, pVMWARE->bitsPerPixel,
740                         pVMWARE->bitsPerPixel, bpp24flags)) {
741        return FALSE;
742    }
743
744    /* Check that the returned depth is one we support */
745    switch (pScrn->depth) {
746    case 8:
747    case 15:
748    case 16:
749    case 24:
750        /* OK */
751        break;
752    default:
753        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
754                   "Given depth (%d) is not supported by this driver\n",
755                   pScrn->depth);
756        return FALSE;
757    }
758
759    if (pScrn->bitsPerPixel != pVMWARE->bitsPerPixel) {
760        if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) {
761            vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL,
762                           pScrn->bitsPerPixel);
763            pVMWARE->bitsPerPixel =
764               vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL);
765            pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH);
766        } else {
767            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
768                       "Currently unavailable depth/bpp of %d/%d requested.\n"
769                       "\tThe guest X server must run at the same depth and bpp as the host\n"
770                       "\t(which are currently %d/%d).  This is automatically detected.  Please\n"
771                       "\tdo not specify a depth on the command line or via the config file.\n",
772                       pScrn->depth, pScrn->bitsPerPixel,
773                       pVMWARE->depth, pVMWARE->bitsPerPixel);
774            return FALSE;
775        }
776    }
777
778    /*
779     * Defer reading the colour registers until here in case we changed
780     * bpp above.
781     */
782
783    pVMWARE->weight.red =
784       vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_RED_MASK));
785    pVMWARE->weight.green =
786       vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_GREEN_MASK));
787    pVMWARE->weight.blue =
788       vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_BLUE_MASK));
789    pVMWARE->offset.blue = 0;
790    pVMWARE->offset.green = pVMWARE->weight.blue;
791    pVMWARE->offset.red = pVMWARE->weight.green + pVMWARE->offset.green;
792    pVMWARE->defaultVisual = vmwareReadReg(pVMWARE, SVGA_REG_PSEUDOCOLOR) ?
793       PseudoColor : TrueColor;
794
795    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
796                   2, "depth: %d\n", pVMWARE->depth);
797    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
798                   2, "bpp:   %d\n", pVMWARE->bitsPerPixel);
799    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
800                   2, "w.red: %d\n", (int)pVMWARE->weight.red);
801    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
802                   2, "w.grn: %d\n", (int)pVMWARE->weight.green);
803    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
804                   2, "w.blu: %d\n", (int)pVMWARE->weight.blue);
805    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
806                   2, "vis:   %d\n", pVMWARE->defaultVisual);
807
808    if (pScrn->depth != pVMWARE->depth) {
809        if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) {
810            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
811                       "Currently unavailable depth of %d requested.\n"
812                       "\tIf the guest X server's BPP matches the host's "
813                       "BPP, then\n\tthe guest X server's depth must also "
814                       "match the\n\thost's depth (currently %d).\n",
815                       pScrn->depth, pVMWARE->depth);
816        } else {
817            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
818                       "Currently unavailable depth of %d requested.\n"
819                       "\tThe guest X server must run at the same depth as "
820                       "the host (which\n\tis currently %d).  This is "
821                       "automatically detected.  Please do not\n\tspecify "
822                       "a depth on the command line or via the config file.\n",
823                       pScrn->depth, pVMWARE->depth);
824        }
825           return FALSE;
826    }
827    xf86PrintDepthBpp(pScrn);
828
829#if 0
830    if (pScrn->depth == 24 && pix24bpp == 0) {
831        pix24bpp = xf86GetBppFromDepth(pScrn, 24);
832    }
833#endif
834
835    if (pScrn->depth > 8) {
836        rgb zeros = { 0, 0, 0 };
837
838        if (!xf86SetWeight(pScrn, pVMWARE->weight, zeros)) {
839            return FALSE;
840        }
841        /* FIXME check returned weight */
842    }
843    if (!xf86SetDefaultVisual(pScrn, pVMWARE->defaultVisual)) {
844        return FALSE;
845    }
846    if (pScrn->defaultVisual != pVMWARE->defaultVisual) {
847        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
848                   "Given visual (%d) is not supported by this driver (%d is required)\n",
849                   pScrn->defaultVisual, pVMWARE->defaultVisual);
850        return FALSE;
851    }
852#if 0
853    bytesPerPixel = pScrn->bitsPerPixel / 8;
854#endif
855    pScrn->progClock = TRUE;
856
857#if 0 /* MGA does not do this */
858    if (pScrn->visual != 0) {	/* FIXME */
859        /* print error message */
860        return FALSE;
861    }
862#endif
863
864    xf86CollectOptions(pScrn, NULL);
865    if (!(options = xalloc(sizeof(VMWAREOptions))))
866        return FALSE;
867    memcpy(options, VMWAREOptions, sizeof(VMWAREOptions));
868    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
869
870    if (pScrn->depth <= 8) {
871        pScrn->rgbBits = 8;
872    }
873
874    from = X_PROBED;
875    pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets, DEVICE_ID(pVMWARE->PciInfo));
876
877    if (!pScrn->chipset) {
878        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04x is not recognised\n", DEVICE_ID(pVMWARE->PciInfo));
879        return FALSE;
880    }
881
882    from = X_DEFAULT;
883    pVMWARE->hwCursor = TRUE;
884    if (xf86GetOptValBool(options, OPTION_HW_CURSOR, &pVMWARE->hwCursor)) {
885        from = X_CONFIG;
886    }
887    if (pVMWARE->hwCursor && !(pVMWARE->vmwareCapability & SVGA_CAP_CURSOR)) {
888        xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW cursor is not supported in this configuration\n");
889        from = X_PROBED;
890        pVMWARE->hwCursor = FALSE;
891    }
892    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
893               pVMWARE->hwCursor ? "HW" : "SW");
894    pScrn->videoRam = pVMWARE->videoRam / 1024;
895    pScrn->memPhysBase = pVMWARE->memPhysBase;
896
897    xfree(options);
898
899    {
900        Gamma zeros = { 0.0, 0.0, 0.0 };
901        if (!xf86SetGamma(pScrn, zeros)) {
902            return FALSE;
903        }
904    }
905#if 0
906    if ((i = xf86GetPciInfoForScreen(pScrn->scrnIndex, &pciList, NULL)) != 1) {
907        /* print error message */
908        VMWAREFreeRec(pScrn);
909        if (i > 0) {
910            xfree(pciList);
911        }
912        return FALSE;
913    }
914#endif
915    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
916    clockRanges->next = NULL;
917    clockRanges->minClock = 1;
918    clockRanges->maxClock = 400000000;
919    clockRanges->clockIndex = -1;
920    clockRanges->interlaceAllowed = FALSE;
921    clockRanges->doubleScanAllowed = FALSE;
922    clockRanges->ClockMulFactor = 1;
923    clockRanges->ClockDivFactor = 1;
924
925    /*
926     * Get the default supported modelines
927     */
928    vmwareGetSupportedModelines(&pScrn->monitor->Modes);
929
930    i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes,
931                          clockRanges, NULL, 256, pVMWARE->maxWidth, 32 * 32,
932                          128, pVMWARE->maxHeight,
933                          pScrn->display->virtualX, pScrn->display->virtualY,
934                          pVMWARE->videoRam,
935                          LOOKUP_BEST_REFRESH);
936    if (i == -1) {
937        VMWAREFreeRec(pScrn);
938        return FALSE;
939    }
940    xf86PruneDriverModes(pScrn);
941    if (i == 0 || pScrn->modes == NULL) {
942        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
943        VMWAREFreeRec(pScrn);
944        return FALSE;
945    }
946    xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
947    pScrn->currentMode = pScrn->modes;
948    xf86PrintModes(pScrn);
949    xf86SetDpi(pScrn, 0, 0);
950    if (!xf86LoadSubModule(pScrn, "fb") ||
951        !xf86LoadSubModule(pScrn, "shadowfb")) {
952        VMWAREFreeRec(pScrn);
953        return FALSE;
954    }
955    xf86LoaderReqSymLists(fbSymbols, shadowfbSymbols, NULL);
956
957    /* Need ramdac for hwcursor */
958    if (pVMWARE->hwCursor) {
959        if (!xf86LoadSubModule(pScrn, "ramdac")) {
960            VMWAREFreeRec(pScrn);
961            return FALSE;
962        }
963        xf86LoaderReqSymLists(ramdacSymbols, NULL);
964    }
965
966    return TRUE;
967}
968
969static Bool
970VMWAREMapMem(ScrnInfoPtr pScrn)
971{
972    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
973#if XSERVER_LIBPCIACCESS
974    int err;
975    struct pci_device *const device = pVMWARE->PciInfo;
976#endif
977
978#if XSERVER_LIBPCIACCESS
979   err = pci_device_map_range(device,
980                              pVMWARE->memPhysBase,
981                              pVMWARE->videoRam,
982                              PCI_DEV_MAP_FLAG_WRITABLE |
983                              PCI_DEV_MAP_FLAG_WRITE_COMBINE,
984                              (void **) &pVMWARE->FbBase);
985   if (err) {
986       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
987                  "Unable to map frame buffer BAR. %s (%d)\n",
988                  strerror (err), err);
989       return FALSE;
990   }
991
992#else
993    pVMWARE->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
994                                    pVMWARE->PciTag,
995                                    pVMWARE->memPhysBase,
996                                    pVMWARE->videoRam);
997#endif
998    if (!pVMWARE->FbBase)
999        return FALSE;
1000
1001    VmwareLog(("FB Mapped: %p/%u -> %p/%u\n",
1002               pVMWARE->memPhysBase, pVMWARE->videoRam,
1003               pVMWARE->FbBase, pVMWARE->videoRam));
1004    return TRUE;
1005}
1006
1007static Bool
1008VMWAREUnmapMem(ScrnInfoPtr pScrn)
1009{
1010    VMWAREPtr pVMWARE;
1011
1012    pVMWARE = VMWAREPTR(pScrn);
1013
1014    VmwareLog(("Unmapped: %p/%u\n", pVMWARE->FbBase, pVMWARE->videoRam));
1015
1016#if XSERVER_LIBPCIACCESS
1017    pci_device_unmap_range(pVMWARE->PciInfo, pVMWARE->FbBase, pVMWARE->videoRam);
1018#else
1019    xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->FbBase, pVMWARE->videoRam);
1020#endif
1021    pVMWARE->FbBase = NULL;
1022    return TRUE;
1023}
1024
1025static void
1026VMWARESave(ScrnInfoPtr pScrn)
1027{
1028    vgaHWPtr hwp = VGAHWPTR(pScrn);
1029    vgaRegPtr vgaReg = &hwp->SavedReg;
1030    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1031    VMWARERegPtr vmwareReg = &pVMWARE->SavedReg;
1032
1033    vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
1034
1035    vmwareReg->svga_reg_enable = vmwareReadReg(pVMWARE, SVGA_REG_ENABLE);
1036    vmwareReg->svga_reg_width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH);
1037    vmwareReg->svga_reg_height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT);
1038    vmwareReg->svga_reg_bits_per_pixel =
1039       vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL);
1040    vmwareReg->svga_reg_id = vmwareReadReg(pVMWARE, SVGA_REG_ID);
1041
1042    /* XXX this should be based on the cap bit, not hwCursor... */
1043    if (pVMWARE->hwCursor) {
1044       vmwareReg->svga_reg_cursor_on =
1045          vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ON);
1046       vmwareReg->svga_reg_cursor_x =
1047          vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_X);
1048       vmwareReg->svga_reg_cursor_y =
1049          vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_Y);
1050       vmwareReg->svga_reg_cursor_id =
1051          vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ID);
1052    }
1053
1054    vmwareReg->svga_fifo_enabled = vmwareReadReg(pVMWARE, SVGA_REG_CONFIG_DONE);
1055}
1056
1057static void
1058VMWARERestoreRegs(ScrnInfoPtr pScrn, VMWARERegPtr vmwareReg)
1059{
1060    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1061    VmwareLog(("VMWARERestoreRegs: W: %d, H: %d, BPP: %d, Enable: %d\n",
1062	       vmwareReg->svga_reg_width, vmwareReg->svga_reg_height,
1063	       vmwareReg->svga_reg_bits_per_pixel, vmwareReg->svga_reg_enable));
1064    if (vmwareReg->svga_reg_enable) {
1065        vmwareWriteReg(pVMWARE, SVGA_REG_ID, vmwareReg->svga_reg_id);
1066        vmwareWriteReg(pVMWARE, SVGA_REG_WIDTH, vmwareReg->svga_reg_width);
1067        vmwareWriteReg(pVMWARE, SVGA_REG_HEIGHT, vmwareReg->svga_reg_height);
1068        vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL,
1069                       vmwareReg->svga_reg_bits_per_pixel);
1070        vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable);
1071        vmwareWriteReg(pVMWARE, SVGA_REG_GUEST_ID, GUEST_OS_LINUX);
1072        if (pVMWARE->hwCursor) {
1073            vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ID,
1074                           vmwareReg->svga_reg_cursor_id);
1075            vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_X,
1076                           vmwareReg->svga_reg_cursor_x);
1077            vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_Y,
1078                           vmwareReg->svga_reg_cursor_y);
1079            vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ON,
1080                           vmwareReg->svga_reg_cursor_on);
1081        }
1082    } else {
1083        vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable);
1084    }
1085}
1086
1087static void
1088VMWARERestore(ScrnInfoPtr pScrn)
1089{
1090    vgaHWPtr hwp = VGAHWPTR(pScrn);
1091    vgaRegPtr vgaReg = &hwp->SavedReg;
1092    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1093    VMWARERegPtr vmwareReg = &pVMWARE->SavedReg;
1094
1095    vmwareWaitForFB(pVMWARE);
1096    if (!vmwareReg->svga_fifo_enabled) {
1097        VMWAREStopFIFO(pScrn);
1098    }
1099
1100    vgaHWProtect(pScrn, TRUE);
1101    VMWARERestoreRegs(pScrn, vmwareReg);
1102    vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
1103    vgaHWProtect(pScrn, FALSE);
1104}
1105
1106static Bool
1107VMWAREModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool rebuildPixmap)
1108{
1109    vgaHWPtr hwp = VGAHWPTR(pScrn);
1110    vgaRegPtr vgaReg = &hwp->ModeReg;
1111    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1112    VMWARERegPtr vmwareReg = &pVMWARE->ModeReg;
1113
1114    vgaHWUnlock(hwp);
1115    if (!vgaHWInit(pScrn, mode))
1116        return FALSE;
1117    pScrn->vtSema = TRUE;
1118
1119    vmwareReg->svga_reg_enable = 1;
1120    vmwareReg->svga_reg_width = max(mode->HDisplay, pScrn->virtualX);
1121    vmwareReg->svga_reg_height = max(mode->VDisplay, pScrn->virtualY);
1122    vmwareReg->svga_reg_bits_per_pixel = pVMWARE->bitsPerPixel;
1123
1124    vgaHWProtect(pScrn, TRUE);
1125
1126    vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
1127    VMWARERestoreRegs(pScrn, vmwareReg);
1128
1129    if (pVMWARE->hwCursor) {
1130        vmwareCursorModeInit(pScrn, mode);
1131    }
1132
1133    VmwareLog(("Required mode: %ux%u\n", mode->HDisplay, mode->VDisplay));
1134    VmwareLog(("Virtual:       %ux%u\n", pScrn->virtualX, pScrn->virtualY));
1135    VmwareLog(("dispWidth:     %u\n", pScrn->displayWidth));
1136    pVMWARE->fbOffset = vmwareReadReg(pVMWARE, SVGA_REG_FB_OFFSET);
1137    pVMWARE->fbPitch = vmwareReadReg(pVMWARE, SVGA_REG_BYTES_PER_LINE);
1138    pVMWARE->FbSize = vmwareReadReg(pVMWARE, SVGA_REG_FB_SIZE);
1139
1140    pScrn->displayWidth = (pVMWARE->fbPitch * 8) / ((pScrn->bitsPerPixel + 7) & ~7);
1141    VmwareLog(("fbOffset:      %u\n", pVMWARE->fbOffset));
1142    VmwareLog(("fbPitch:       %u\n", pVMWARE->fbPitch));
1143    VmwareLog(("fbSize:        %u\n", pVMWARE->FbSize));
1144    VmwareLog(("New dispWidth: %u\n", pScrn->displayWidth));
1145
1146    vmwareCheckVideoSanity(pScrn);
1147
1148    if (rebuildPixmap) {
1149        pScrn->pScreen->ModifyPixmapHeader((*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen),
1150                                           pScrn->pScreen->width,
1151                                           pScrn->pScreen->height,
1152                                           pScrn->pScreen->rootDepth,
1153                                           pScrn->bitsPerPixel,
1154                                           PixmapBytePad(pScrn->displayWidth,
1155                                                         pScrn->pScreen->rootDepth),
1156                                           (pointer)(pVMWARE->FbBase + pScrn->fbOffset));
1157
1158        (*pScrn->EnableDisableFBAccess)(pScrn->pScreen->myNum, FALSE);
1159        (*pScrn->EnableDisableFBAccess)(pScrn->pScreen->myNum, TRUE);
1160    }
1161
1162    vgaHWProtect(pScrn, FALSE);
1163
1164    /*
1165     * XXX -- If we want to check that we got the mode we asked for, this
1166     * would be a good place.
1167     */
1168
1169    /*
1170     * Update Xinerama info appropriately.
1171     */
1172    if (pVMWARE->xinerama && !pVMWARE->xineramaStatic) {
1173       if (pVMWARE->xineramaNextState) {
1174          xfree(pVMWARE->xineramaState);
1175          pVMWARE->xineramaState = pVMWARE->xineramaNextState;
1176          pVMWARE->xineramaNumOutputs = pVMWARE->xineramaNextNumOutputs;
1177
1178          pVMWARE->xineramaNextState = NULL;
1179          pVMWARE->xineramaNextNumOutputs = 0;
1180       } else {
1181          VMWAREXineramaPtr basicState =
1182             (VMWAREXineramaPtr)xcalloc(1, sizeof (VMWAREXineramaRec));
1183          if (basicState) {
1184             basicState->x_org = 0;
1185             basicState->y_org = 0;
1186             basicState->width = vmwareReg->svga_reg_width;
1187             basicState->height = vmwareReg->svga_reg_height;
1188
1189             xfree(pVMWARE->xineramaState);
1190             pVMWARE->xineramaState = basicState;
1191             pVMWARE->xineramaNumOutputs = 1;
1192          }
1193       }
1194    }
1195
1196    /*
1197     * Update host's view of guest topology.
1198     */
1199    if (pVMWARE->vmwareCapability & SVGA_CAP_DISPLAY_TOPOLOGY) {
1200        if (pVMWARE->xinerama) {
1201            int i = 0;
1202            VMWAREXineramaPtr xineramaState = pVMWARE->xineramaState;
1203            vmwareWriteReg(pVMWARE, SVGA_REG_NUM_GUEST_DISPLAYS,
1204                           pVMWARE->xineramaNumOutputs);
1205
1206            for (i = 0; i < pVMWARE->xineramaNumOutputs; i++) {
1207                vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, i);
1208                vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_IS_PRIMARY, TRUE);
1209                vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_X,
1210                               xineramaState[i].x_org);
1211                vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_Y,
1212                               xineramaState[i].y_org);
1213                vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_WIDTH,
1214                               xineramaState[i].width);
1215                vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_HEIGHT,
1216                               xineramaState[i].height);
1217            }
1218        } else {
1219            vmwareWriteReg(pVMWARE, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
1220
1221            vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, 0);
1222            vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_IS_PRIMARY, TRUE);
1223            vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_X, 0);
1224            vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_Y, 0);
1225            vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_WIDTH, mode->HDisplay);
1226            vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_HEIGHT, mode->VDisplay);
1227        }
1228
1229        vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, SVGA_INVALID_DISPLAY_ID);
1230    }
1231
1232    return TRUE;
1233}
1234
1235static void
1236VMWAREAdjustFrame(int scrnIndex, int x, int y, int flags)
1237{
1238    /* FIXME */
1239}
1240
1241static void
1242VMWAREInitFIFO(ScrnInfoPtr pScrn)
1243{
1244    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1245#if XSERVER_LIBPCIACCESS
1246    struct pci_device *const device = pVMWARE->PciInfo;
1247    int err;
1248#endif
1249    CARD32* vmwareFIFO;
1250    Bool extendedFifo;
1251    int min;
1252
1253    TRACEPOINT
1254
1255    pVMWARE->mmioPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_MEM_START);
1256    pVMWARE->mmioSize = vmwareReadReg(pVMWARE, SVGA_REG_MEM_SIZE) & ~3;
1257#if XSERVER_LIBPCIACCESS
1258    err = pci_device_map_range(device, pVMWARE->mmioPhysBase,
1259                               pVMWARE->mmioSize,
1260                               PCI_DEV_MAP_FLAG_WRITABLE,
1261                               (void **) &pVMWARE->mmioVirtBase);
1262    if (err) {
1263        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1264                   "Unable to map mmio BAR. %s (%d)\n",
1265                   strerror (err), err);
1266        return;
1267    }
1268#else
1269    pVMWARE->mmioVirtBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
1270                                          pVMWARE->PciTag,
1271                                          pVMWARE->mmioPhysBase,
1272                                          pVMWARE->mmioSize);
1273#endif
1274    vmwareFIFO = pVMWARE->vmwareFIFO = (CARD32*)pVMWARE->mmioVirtBase;
1275
1276    extendedFifo = pVMWARE->vmwareCapability & SVGA_CAP_EXTENDED_FIFO;
1277    min = extendedFifo ? vmwareReadReg(pVMWARE, SVGA_REG_MEM_REGS) : 4;
1278
1279    vmwareFIFO[SVGA_FIFO_MIN] = min * sizeof(CARD32);
1280    vmwareFIFO[SVGA_FIFO_MAX] = pVMWARE->mmioSize;
1281    vmwareFIFO[SVGA_FIFO_NEXT_CMD] = min * sizeof(CARD32);
1282    vmwareFIFO[SVGA_FIFO_STOP] = min * sizeof(CARD32);
1283    vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 1);
1284}
1285
1286static void
1287VMWAREStopFIFO(ScrnInfoPtr pScrn)
1288{
1289    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1290
1291    TRACEPOINT
1292
1293    vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 0);
1294#if XSERVER_LIBPCIACCESS
1295    pci_device_unmap_range(pVMWARE->PciInfo, pVMWARE->mmioVirtBase, pVMWARE->mmioSize);
1296#else
1297    xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->mmioVirtBase, pVMWARE->mmioSize);
1298#endif
1299}
1300
1301static Bool
1302VMWARECloseScreen(int scrnIndex, ScreenPtr pScreen)
1303{
1304    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1305    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1306    ScreenPtr save = &pVMWARE->ScrnFuncs;
1307
1308    VmwareLog(("cursorSema: %d\n", pVMWARE->cursorSema));
1309
1310    if (*pVMWARE->pvtSema) {
1311        if (pVMWARE->videoStreams) {
1312            vmwareVideoEnd(pScreen);
1313        }
1314
1315        if (pVMWARE->CursorInfoRec) {
1316            vmwareCursorCloseScreen(pScreen);
1317        }
1318
1319        VMWARERestore(pScrn);
1320        VMWAREUnmapMem(pScrn);
1321
1322        pScrn->vtSema = FALSE;
1323    }
1324
1325    pScreen->CloseScreen = save->CloseScreen;
1326    pScreen->SaveScreen = save->SaveScreen;
1327
1328#if VMWARE_DRIVER_FUNC
1329    pScrn->DriverFunc = NULL;
1330#endif
1331
1332    return (*pScreen->CloseScreen)(scrnIndex, pScreen);
1333}
1334
1335static Bool
1336VMWARESaveScreen(ScreenPtr pScreen, int mode)
1337{
1338    VmwareLog(("VMWareSaveScreen() mode = %d\n", mode));
1339
1340    /*
1341     * This thoroughly fails to do anything useful to svga mode.  I doubt
1342     * we care; who wants to idle-blank their VM's screen anyway?
1343     */
1344    return vgaHWSaveScreen(pScreen, mode);
1345}
1346
1347/* disabled by default to reduce spew in DEBUG_LOGGING mode. */
1348/*#define DEBUG_LOG_UPDATES*/
1349
1350static void
1351VMWAREPreDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr)
1352{
1353    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1354
1355#ifdef DEBUG_LOG_UPDATES
1356    {
1357        int i;
1358        for (i = 0; i < nboxes; i++) {
1359            VmwareLog(("PreUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes - i,
1360                       boxPtr[i].x1, boxPtr[i].y1,
1361                       boxPtr[i].x2 - boxPtr[i].x1,
1362                       boxPtr[i].y2 - boxPtr[i].y1));
1363        }
1364    }
1365#endif
1366
1367    /*
1368     * We only register this callback if we have a HW cursor.
1369     */
1370    while (nboxes--) {
1371        if (BOX_INTERSECT(*boxPtr, pVMWARE->hwcur.box)) {
1372            if (!pVMWARE->cursorExcludedForUpdate) {
1373                PRE_OP_HIDE_CURSOR();
1374                pVMWARE->cursorExcludedForUpdate = TRUE;
1375            }
1376	    break;
1377        }
1378        boxPtr++;
1379    }
1380}
1381
1382static void
1383VMWAREPostDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr)
1384{
1385    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1386    while (nboxes--) {
1387#ifdef DEBUG_LOG_UPDATES
1388        VmwareLog(("PostUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes,
1389                   boxPtr->x1, boxPtr->y1,
1390                   boxPtr->x2 - boxPtr->x1, boxPtr->y2 - boxPtr->y1));
1391#endif
1392
1393        /* Clip off (y only) for offscreen memory */
1394        if (boxPtr->y2 >= pVMWARE->ModeReg.svga_reg_height)
1395            boxPtr->y2 = pVMWARE->ModeReg.svga_reg_height;
1396        if (boxPtr->y1 >= pVMWARE->ModeReg.svga_reg_height)
1397            boxPtr->y1 = pVMWARE->ModeReg.svga_reg_height;
1398        if (boxPtr->y1 == boxPtr->y2) {
1399            boxPtr++;
1400            continue;
1401        }
1402
1403        vmwareSendSVGACmdUpdate(pVMWARE, boxPtr++);
1404    }
1405
1406    if (pVMWARE->hwCursor && pVMWARE->cursorExcludedForUpdate) {
1407        POST_OP_SHOW_CURSOR();
1408        pVMWARE->cursorExcludedForUpdate = FALSE;
1409    }
1410}
1411
1412static void
1413VMWARELoadPalette(ScrnInfoPtr pScrn, int numColors, int* indices,
1414                  LOCO* colors, VisualPtr pVisual)
1415{
1416    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1417    int i;
1418
1419    for (i = 0; i < numColors; i++) {
1420        vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 0, colors[*indices].red);
1421        vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 1, colors[*indices].green);
1422        vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 2, colors[*indices].blue);
1423        indices++;
1424    }
1425    VmwareLog(("Palette loading done\n"));
1426}
1427
1428
1429DisplayModeRec *
1430VMWAREAddDisplayMode(ScrnInfoPtr pScrn,
1431                     const char *name,
1432                     int width,
1433                     int height)
1434{
1435   DisplayModeRec *mode;
1436
1437   mode = xalloc(sizeof(DisplayModeRec));
1438
1439   mode->name = xalloc(strlen(name) + 1);
1440   strcpy(mode->name, name);
1441   mode->status = MODE_OK;
1442   mode->type = M_T_DEFAULT;
1443   mode->HDisplay = width;
1444   mode->VDisplay = height;
1445
1446   mode->next = pScrn->modes;
1447   mode->prev = pScrn->modes->prev;
1448   pScrn->modes->prev->next = mode;
1449   pScrn->modes->prev = mode;
1450
1451   return mode;
1452}
1453
1454
1455/*
1456 *-----------------------------------------------------------------------------
1457 *
1458 * vmwareIsRegionEqual --
1459 *
1460 *    This function implements REGION_EQUAL because older versions of
1461 *    regionstr.h don't define it.
1462 *    It is a slightly modified version of miRegionEqual from $Xorg: miregion.c
1463 *
1464 * Results:
1465 *    TRUE if regions are equal; FALSE otherwise
1466 *
1467 * Side effects:
1468 *    None.
1469 *
1470 *-----------------------------------------------------------------------------
1471 */
1472
1473Bool
1474vmwareIsRegionEqual(const RegionPtr reg1,
1475                    const RegionPtr reg2)
1476{
1477    int i, num;
1478    BoxPtr rects1, rects2;
1479
1480    if ((reg1->extents.x1 != reg2->extents.x1) ||
1481        (reg1->extents.x2 != reg2->extents.x2) ||
1482        (reg1->extents.y1 != reg2->extents.y1) ||
1483        (reg1->extents.y2 != reg2->extents.y2)) {
1484        return FALSE;
1485    }
1486
1487    num = REGION_NUM_RECTS(reg1);
1488    if (num != REGION_NUM_RECTS(reg2)) {
1489        return FALSE;
1490    }
1491
1492    rects1 = REGION_RECTS(reg1);
1493    rects2 = REGION_RECTS(reg2);
1494
1495    for (i = 0; i < num; i++) {
1496        if ((rects1[i].x1 != rects2[i].x1) ||
1497            (rects1[i].x2 != rects2[i].x2) ||
1498            (rects1[i].y1 != rects2[i].y1) ||
1499            (rects1[i].y2 != rects2[i].y2)) {
1500            return FALSE;
1501        }
1502    }
1503
1504    return TRUE;
1505}
1506
1507
1508#if VMWARE_DRIVER_FUNC
1509static Bool
1510VMWareDriverFunc(ScrnInfoPtr pScrn,
1511                 xorgDriverFuncOp op,
1512                 pointer data)
1513{
1514   CARD32 *flag;
1515   xorgRRModeMM *modemm;
1516
1517   switch (op) {
1518   case GET_REQUIRED_HW_INTERFACES:
1519      flag = (CARD32 *)data;
1520
1521      if (flag) {
1522         *flag = HW_IO | HW_MMIO;
1523      }
1524      return TRUE;
1525   case RR_GET_MODE_MM:
1526      modemm = (xorgRRModeMM *)data;
1527
1528      /*
1529       * Because changing the resolution of the guest is usually changing the size
1530       * of a window on the host desktop, the real physical DPI will not change. To
1531       * keep the guest in sync, we scale the 'physical' screen dimensions to
1532       * keep the DPI constant.
1533       */
1534      if (modemm && modemm->mode) {
1535         modemm->mmWidth *= modemm->mode->HDisplay / (double)(modemm->virtX);
1536         modemm->mmHeight *= modemm->mode->VDisplay / (double)(modemm->virtY);
1537      }
1538      return TRUE;
1539   default:
1540      return FALSE;
1541   }
1542}
1543#endif
1544
1545
1546static Bool
1547VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
1548{
1549    ScrnInfoPtr pScrn;
1550    vgaHWPtr hwp;
1551    VMWAREPtr pVMWARE;
1552    OptionInfoPtr options;
1553    Bool useXinerama = TRUE;
1554
1555    /* Get the ScrnInfoRec */
1556    pScrn = xf86Screens[pScreen->myNum];
1557    pVMWARE = VMWAREPTR(pScrn);
1558
1559
1560    xf86CollectOptions(pScrn, NULL);
1561    if (!(options = xalloc(sizeof(VMWAREOptions))))
1562        return FALSE;
1563    memcpy(options, VMWAREOptions, sizeof(VMWAREOptions));
1564    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
1565
1566    /*
1567     * Init xinerama preferences.
1568     */
1569    useXinerama = xf86ReturnOptValBool(options, OPTION_XINERAMA,
1570                                       pVMWARE->vmwareCapability & SVGA_CAP_MULTIMON);
1571    if (useXinerama && !(pVMWARE->vmwareCapability & SVGA_CAP_MULTIMON)) {
1572       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1573                  "Xinerama is not safely supported by the current virtual hardware. "
1574                  "Do not request resolutions that require > 16MB of framebuffer.\n");
1575    }
1576
1577
1578    if (useXinerama && xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) {
1579       char *topology = xf86GetOptValString(options, OPTION_STATIC_XINERAMA);
1580       if (topology) {
1581          pVMWARE->xineramaState =
1582             VMWAREParseTopologyString(pScrn, topology, &pVMWARE->xineramaNumOutputs);
1583
1584         pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL;
1585
1586         xfree(topology);
1587       }
1588    }
1589
1590    xfree(options);
1591
1592    /* Initialise VMWARE_CTRL extension. */
1593    VMwareCtrl_ExtInit(pScrn);
1594
1595    /* Initialise Xinerama extension. */
1596    if (useXinerama) {
1597       VMwareXinerama_ExtInit(pScrn);
1598    }
1599
1600    if (pVMWARE->xinerama && pVMWARE->xineramaStatic) {
1601       xf86DrvMsg(pScrn->scrnIndex, X_INFO, pVMWARE->xineramaState ?
1602                                            "Using static Xinerama.\n" :
1603                                            "Failed to configure static Xinerama.\n");
1604    }
1605
1606    /*
1607     * If using the vgahw module, its data structures and related
1608     * things are typically initialised/mapped here.
1609     */
1610    hwp = VGAHWPTR(pScrn);
1611    vgaHWGetIOBase(hwp);
1612
1613    VMWAREInitFIFO(pScrn);
1614
1615    /* Initialise the first mode */
1616    VMWAREModeInit(pScrn, pScrn->currentMode, FALSE);
1617
1618    /* Set the viewport if supported */
1619    VMWAREAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
1620
1621    /*
1622     * Setup the screen's visuals, and initialise the framebuffer
1623     * code.
1624     */
1625    VMWAREMapMem(pScrn);
1626
1627    /*
1628     * Clear the framebuffer (and any black-border mode areas).
1629     */
1630    memset(pVMWARE->FbBase, 0, pVMWARE->FbSize);
1631    vmwareSendSVGACmdUpdateFullScreen(pVMWARE);
1632
1633    /* Reset the visual list */
1634    miClearVisualTypes();
1635
1636    /*
1637     * Setup the visuals supported.  This driver only supports
1638     * TrueColor for bpp > 8, so the default set of visuals isn't
1639     * acceptable.  To deal with this, call miSetVisualTypes with
1640     * the appropriate visual mask.
1641     */
1642    if (pScrn->bitsPerPixel > 8) {
1643        if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
1644                              pScrn->rgbBits, pScrn->defaultVisual)) {
1645            return FALSE;
1646        }
1647    } else {
1648        if (!miSetVisualTypes(pScrn->depth,
1649                              miGetDefaultVisualMask(pScrn->depth),
1650                              pScrn->rgbBits, pScrn->defaultVisual)) {
1651            return FALSE;
1652        }
1653    }
1654
1655    miSetPixmapDepths();
1656
1657    /*
1658     * Initialise the framebuffer.
1659     */
1660    if (!fbScreenInit(pScreen, pVMWARE->FbBase + pVMWARE->fbOffset,
1661                      pScrn->virtualX, pScrn->virtualY,
1662                      pScrn->xDpi, pScrn->yDpi,
1663                      pScrn->displayWidth,
1664                      pScrn->bitsPerPixel)) {
1665        return FALSE;
1666    }
1667
1668    /* Override the default mask/offset settings */
1669    if (pScrn->bitsPerPixel > 8) {
1670        int i;
1671        VisualPtr visual;
1672
1673        for (i = 0, visual = pScreen->visuals;
1674             i < pScreen->numVisuals; i++, visual++) {
1675            if ((visual->class | DynamicClass) == DirectColor) {
1676                visual->offsetRed = pScrn->offset.red;
1677                visual->offsetGreen = pScrn->offset.green;
1678                visual->offsetBlue = pScrn->offset.blue;
1679                visual->redMask = pScrn->mask.red;
1680                visual->greenMask = pScrn->mask.green;
1681                visual->blueMask = pScrn->mask.blue;
1682            }
1683        }
1684    }
1685
1686    /* must be after RGB ordering fixed */
1687    fbPictureInit (pScreen, 0, 0);
1688
1689    /*
1690     * Save the old screen vector, then wrap CloseScreen and
1691     * set SaveScreen.
1692     */
1693    pVMWARE->ScrnFuncs = *pScreen;
1694    pScreen->CloseScreen = VMWARECloseScreen;
1695    pScreen->SaveScreen = VMWARESaveScreen;
1696
1697    /*
1698     * Set initial black & white colourmap indices.
1699     */
1700    xf86SetBlackWhitePixels(pScreen);
1701
1702    /*
1703     * Initialize shadowfb to notify us of dirty rectangles.  We only
1704     * need preFB access callbacks if we're using the hw cursor.
1705     */
1706    if (!ShadowFBInit2(pScreen,
1707                       pVMWARE->hwCursor ? VMWAREPreDirtyBBUpdate : NULL,
1708                       VMWAREPostDirtyBBUpdate)) {
1709        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1710                   "ShadowFB initialization failed\n");
1711        return FALSE;
1712    }
1713
1714    /*
1715     * If we have a hw cursor, we need to hook functions that might
1716     * read from the framebuffer.
1717     */
1718    if (pVMWARE->hwCursor) {
1719        vmwareCursorHookWrappers(pScreen);
1720    }
1721
1722    /*
1723     * If backing store is to be supported (as is usually the case),
1724     * initialise it.
1725     */
1726    miInitializeBackingStore(pScreen);
1727    xf86SetBackingStore(pScreen);
1728    xf86SetSilkenMouse(pScreen);
1729
1730    /*
1731     * Initialize software cursor.
1732     */
1733    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1734
1735    /*
1736     * Initialize hardware cursor.
1737     */
1738    if (pVMWARE->hwCursor) {
1739        if (!vmwareCursorInit(pScreen)) {
1740            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1741                       "Hardware cursor initialization failed\n");
1742            pVMWARE->hwCursor = FALSE;
1743        }
1744    }
1745
1746    /*
1747     * Install colourmap functions.  If using the vgahw module,
1748     * vgaHandleColormaps would usually be called here.
1749     */
1750    if (!fbCreateDefColormap(pScreen))
1751        return FALSE;
1752
1753    if (!xf86HandleColormaps(pScreen, 256, 8,
1754                             VMWARELoadPalette, NULL,
1755                             CMAP_PALETTED_TRUECOLOR |
1756                             CMAP_RELOAD_ON_MODE_SWITCH)) {
1757        return FALSE;
1758    }
1759
1760    /*
1761     * We explictly add a set of default modes because the X server will
1762     * not include modes larger than the initial one.
1763     */
1764   {
1765      unsigned int i;
1766      unsigned int numModes = sizeof (VMWAREDefaultModes) / sizeof *(VMWAREDefaultModes);
1767      char name[10];
1768      for (i = 0; i < numModes; i++) {
1769         const VMWAREDefaultMode *mode = &VMWAREDefaultModes[i];
1770
1771         /* Only modes that fit the hardware maximums should be added. */
1772         if (mode->width <= pVMWARE->maxWidth && mode->height <= pVMWARE->maxHeight) {
1773            snprintf(name, 10, "%dx%d", mode->width, mode->height);
1774            VMWAREAddDisplayMode(pScrn, name, mode->width, mode->height);
1775         }
1776      }
1777
1778      /* Add the hardware maximums as a mode. */
1779      snprintf(name, 10, "%dx%d", pVMWARE->maxWidth, pVMWARE->maxHeight);
1780      VMWAREAddDisplayMode(pScrn, name, pVMWARE->maxWidth, pVMWARE->maxHeight);
1781   }
1782
1783    /*
1784     * We will lazily add the dynamic modes as the are needed when new
1785     * modes are requested through the control extension.
1786     */
1787    memset(&pVMWARE->dynModes, 0, sizeof pVMWARE->dynModes);
1788
1789#if VMWARE_DRIVER_FUNC
1790    pScrn->DriverFunc = VMWareDriverFunc;
1791#endif
1792
1793    /* Report any unused options (only for the first generation) */
1794    if (serverGeneration == 1) {
1795        xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1796    }
1797
1798    /* Initialize Xv extension */
1799    pVMWARE->videoStreams = NULL;
1800    if (vmwareVideoEnabled(pVMWARE)) {
1801        if (!vmwareVideoInit(pScreen)) {
1802            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Xv initialization failed\n");
1803        }
1804    }
1805
1806
1807    /* Done */
1808    return TRUE;
1809}
1810
1811static Bool
1812VMWARESwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
1813{
1814    return VMWAREModeInit(xf86Screens[scrnIndex], mode, TRUE);
1815}
1816
1817static Bool
1818VMWAREEnterVT(int scrnIndex, int flags)
1819{
1820    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1821    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1822
1823    if (!pVMWARE->SavedReg.svga_fifo_enabled) {
1824        VMWAREInitFIFO(pScrn);
1825    }
1826
1827    return VMWAREModeInit(pScrn, pScrn->currentMode, TRUE);
1828}
1829
1830static void
1831VMWARELeaveVT(int scrnIndex, int flags)
1832{
1833    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1834    VMWARERestore(pScrn);
1835}
1836
1837static void
1838VMWAREFreeScreen(int scrnIndex, int flags)
1839{
1840    /*
1841     * If the vgahw module is used vgaHWFreeHWRec() would be called
1842     * here.
1843     */
1844   VMWAREFreeRec(xf86Screens[scrnIndex]);
1845}
1846
1847static ModeStatus
1848VMWAREValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
1849{
1850    return MODE_OK;
1851}
1852
1853#if XSERVER_LIBPCIACCESS
1854static Bool
1855VMwarePciProbe (DriverPtr           drv,
1856                int                 entity_num,
1857                struct pci_device   *device,
1858                intptr_t            match_data)
1859{
1860    ScrnInfoPtr     scrn = NULL;
1861    EntityInfoPtr   entity;
1862
1863    scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VMWAREPciChipsets,
1864                               NULL, NULL, NULL, NULL, NULL);
1865    if (scrn != NULL) {
1866        scrn->driverVersion = VMWARE_DRIVER_VERSION;
1867        scrn->driverName = VMWARE_DRIVER_NAME;
1868        scrn->name = VMWARE_NAME;
1869        scrn->Probe = NULL;
1870    }
1871
1872    entity = xf86GetEntityInfo(entity_num);
1873    switch (DEVICE_ID(device)) {
1874    case PCI_CHIP_VMWARE0405:
1875    case PCI_CHIP_VMWARE0710:
1876        xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n");
1877        scrn->PreInit = VMWAREPreInit;
1878        scrn->ScreenInit = VMWAREScreenInit;
1879        scrn->SwitchMode = VMWARESwitchMode;
1880        scrn->EnterVT = VMWAREEnterVT;
1881        scrn->LeaveVT = VMWARELeaveVT;
1882        scrn->FreeScreen = VMWAREFreeScreen;
1883        scrn->ValidMode = VMWAREValidMode;
1884        break;
1885    default:
1886        xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Unknown device\n");
1887    }
1888    return scrn != NULL;
1889}
1890#else
1891
1892static Bool
1893VMWAREProbe(DriverPtr drv, int flags)
1894{
1895    int numDevSections, numUsed;
1896    GDevPtr *devSections;
1897    int *usedChips;
1898    int i;
1899    Bool foundScreen = FALSE;
1900    char buildString[sizeof(VMWAREBuildStr)];
1901
1902    RewriteTagString(VMWAREBuildStr, buildString, sizeof(VMWAREBuildStr));
1903    xf86MsgVerb(X_PROBED, 4, "%s", buildString);
1904
1905    numDevSections = xf86MatchDevice(VMWARE_DRIVER_NAME, &devSections);
1906    if (numDevSections <= 0) {
1907#ifdef DEBUG
1908        xf86MsgVerb(X_ERROR, 0, "No vmware driver section\n");
1909#endif
1910        return FALSE;
1911    }
1912    if (xf86GetPciVideoInfo()) {
1913        VmwareLog(("Some PCI Video Info Exists\n"));
1914        numUsed = xf86MatchPciInstances(VMWARE_NAME, PCI_VENDOR_VMWARE,
1915                                        VMWAREChipsets, VMWAREPciChipsets, devSections,
1916                                        numDevSections, drv, &usedChips);
1917        xfree(devSections);
1918        if (numUsed <= 0)
1919            return FALSE;
1920        if (flags & PROBE_DETECT)
1921            foundScreen = TRUE;
1922        else
1923            for (i = 0; i < numUsed; i++) {
1924                ScrnInfoPtr pScrn = NULL;
1925
1926                VmwareLog(("Even some VMware SVGA PCI instances exists\n"));
1927                pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i],
1928                                            VMWAREPciChipsets, NULL, NULL, NULL,
1929                                            NULL, NULL);
1930                if (pScrn) {
1931                    VmwareLog(("And even configuration suceeded\n"));
1932                    pScrn->driverVersion = VMWARE_DRIVER_VERSION;
1933                    pScrn->driverName = VMWARE_DRIVER_NAME;
1934                    pScrn->name = VMWARE_NAME;
1935                    pScrn->Probe = VMWAREProbe;
1936                    pScrn->PreInit = VMWAREPreInit;
1937                    pScrn->ScreenInit = VMWAREScreenInit;
1938                    pScrn->SwitchMode = VMWARESwitchMode;
1939                    pScrn->AdjustFrame = VMWAREAdjustFrame;
1940                    pScrn->EnterVT = VMWAREEnterVT;
1941                    pScrn->LeaveVT = VMWARELeaveVT;
1942                    pScrn->FreeScreen = VMWAREFreeScreen;
1943                    pScrn->ValidMode = VMWAREValidMode;
1944                    foundScreen = TRUE;
1945                }
1946            }
1947        xfree(usedChips);
1948    }
1949    return foundScreen;
1950}
1951#endif
1952
1953
1954_X_EXPORT DriverRec VMWARE = {
1955    VMWARE_DRIVER_VERSION,
1956    VMWARE_DRIVER_NAME,
1957    VMWAREIdentify,
1958#if XSERVER_LIBPCIACCESS
1959    NULL,
1960#else
1961    VMWAREProbe,
1962#endif
1963    VMWAREAvailableOptions,
1964    NULL,
1965    0,
1966#if VMWARE_DRIVER_FUNC
1967    VMWareDriverFunc,
1968#endif
1969#if XSERVER_LIBPCIACCESS
1970    VMwareDeviceMatch,
1971    VMwarePciProbe,
1972#endif
1973};
1974
1975#ifdef XFree86LOADER
1976static MODULESETUPPROTO(vmwareSetup);
1977
1978_X_EXPORT XF86ModuleData vmwareModuleData = {
1979    &vmwareVersRec,
1980    vmwareSetup,
1981    NULL
1982};
1983
1984static pointer
1985vmwareSetup(pointer module, pointer opts, int *errmaj, int *errmin)
1986{
1987    static Bool setupDone = FALSE;
1988
1989    if (!setupDone) {
1990        setupDone = TRUE;
1991        xf86AddDriver(&VMWARE, module, VMWARE_DRIVER_FUNC);
1992
1993        LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols,
1994                          shadowfbSymbols, NULL);
1995
1996        return (pointer)1;
1997    }
1998    if (errmaj) {
1999        *errmaj = LDR_ONCEONLY;
2000    }
2001    return NULL;
2002}
2003#endif	/* XFree86LOADER */
2004