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