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