vmware.c revision 0b7217d9
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
10#ifdef HAVE_CONFIG_H
11#include "config.h"
12#endif
13
14/*
15 * TODO: support the vmware linux kernel fb driver (Option "UseFBDev").
16 */
17
18#include "xf86.h"
19#include "xf86_OSproc.h"
20
21#include "compiler.h"	/* inb/outb */
22
23#include "xf86Pci.h"		/* pci */
24
25#include "mipointer.h"		/* sw cursor */
26#include "micmap.h"		/* mi color map */
27#include "vgaHW.h"		/* VGA hardware */
28#include "fb.h"
29#include "shadowfb.h"           /* ShadowFB wrappers */
30
31#include "xf86cmap.h"		/* xf86HandleColormaps */
32
33#include "vmware.h"
34#include "guest_os.h"
35#include "vm_device_version.h"
36#include "svga_modes.h"
37#include "vmware_bootstrap.h"
38#include "vmware_common.h"
39#include "common_compat.h"
40
41#ifndef HAVE_XORG_SERVER_1_5_0
42#include <xf86_ansic.h>
43#include <xf86_libc.h>
44#endif
45
46#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5)
47
48#define xf86LoaderReqSymLists(...) do {} while (0)
49#define LoaderRefSymLists(...) do {} while (0)
50
51#else
52
53const char *vgahwSymbols[] = {
54    "vgaHWGetHWRec",
55    "vgaHWGetIOBase",
56    "vgaHWGetIndex",
57    "vgaHWInit",
58    "vgaHWProtect",
59    "vgaHWRestore",
60    "vgaHWSave",
61    "vgaHWSaveScreen",
62    "vgaHWUnlock",
63    NULL
64};
65
66static const char *fbSymbols[] = {
67    "fbCreateDefColormap",
68    "fbPictureInit",
69    "fbScreenInit",
70    NULL
71};
72
73static const char *ramdacSymbols[] = {
74    "xf86CreateCursorInfoRec",
75    "xf86DestroyCursorInfoRec",
76    "xf86InitCursor",
77    NULL
78};
79
80static const char *shadowfbSymbols[] = {
81    "ShadowFBInit2",
82    NULL
83};
84#endif
85
86/* Table of default modes to always add to the mode list. */
87
88typedef struct {
89   int width;
90   int height;
91} VMWAREDefaultMode;
92
93#define VMW_MIN_INITIAL_WIDTH 800
94#define VMW_MIN_INITIAL_HEIGHT 600
95
96#define SVGA_DEFAULT_MODE(width, height) { width, height, },
97
98static const VMWAREDefaultMode VMWAREDefaultModes[] = {
99   SVGA_DEFAULT_MODES
100};
101
102#undef SVGA_DEFAULT_MODE
103
104static void VMWAREStopFIFO(ScrnInfoPtr pScrn);
105static void VMWARESave(ScrnInfoPtr pScrn);
106
107static Bool
108VMWAREGetRec(ScrnInfoPtr pScrn)
109{
110    if (pScrn->driverPrivate != NULL) {
111        return TRUE;
112    }
113    pScrn->driverPrivate = xnfcalloc(sizeof(VMWARERec), 1);
114    /* FIXME: Initialize driverPrivate... */
115    return TRUE;
116}
117
118static void
119VMWAREFreeRec(ScrnInfoPtr pScrn)
120{
121    if (pScrn->driverPrivate) {
122        free(pScrn->driverPrivate);
123        pScrn->driverPrivate = NULL;
124    }
125}
126
127CARD32
128vmwareReadReg(VMWAREPtr pVMWARE, int rIndex)
129{
130    /*
131     * Block SIGIO for the duration, so we don't get interrupted after the
132     * outl but before the inl by a mouse move (which write to our registers).
133     */
134    int ret;
135#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 22)
136    int oldsigio;
137
138    oldsigio = xf86BlockSIGIO();
139#else
140    input_lock();
141#endif
142    outl(pVMWARE->indexReg, rIndex);
143    ret = inl(pVMWARE->valueReg);
144#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 22)
145    xf86UnblockSIGIO(oldsigio);
146#else
147    input_unlock();
148#endif
149    return ret;
150}
151
152void
153vmwareWriteReg(VMWAREPtr pVMWARE, int wIndex, CARD32 value)
154{
155    /*
156     * Block SIGIO for the duration, so we don't get interrupted in between
157     * the outls by a mouse move (which write to our registers).
158     */
159#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 22)
160    int oldsigio;
161    oldsigio = xf86BlockSIGIO();
162#else
163    input_lock();
164#endif
165    outl(pVMWARE->indexReg, wIndex);
166    outl(pVMWARE->valueReg, value);
167#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 22)
168    xf86UnblockSIGIO(oldsigio);
169#else
170    input_unlock();
171#endif
172}
173
174void
175vmwareWriteWordToFIFO(VMWAREPtr pVMWARE, CARD32 value)
176{
177    volatile CARD32* vmwareFIFO = pVMWARE->vmwareFIFO;
178
179    /* Need to sync? */
180    if ((vmwareFIFO[SVGA_FIFO_NEXT_CMD] + sizeof(CARD32) == vmwareFIFO[SVGA_FIFO_STOP])
181     || (vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - sizeof(CARD32) &&
182	 vmwareFIFO[SVGA_FIFO_STOP] == vmwareFIFO[SVGA_FIFO_MIN])) {
183        VmwareLog(("Syncing because of full fifo\n"));
184        vmwareWaitForFB(pVMWARE);
185    }
186
187    vmwareFIFO[vmwareFIFO[SVGA_FIFO_NEXT_CMD] / sizeof(CARD32)] = value;
188
189    write_mem_barrier();
190
191    if(vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] -
192       sizeof(CARD32)) {
193        vmwareFIFO[SVGA_FIFO_NEXT_CMD] = vmwareFIFO[SVGA_FIFO_MIN];
194    } else {
195        vmwareFIFO[SVGA_FIFO_NEXT_CMD] += sizeof(CARD32);
196    }
197}
198
199void
200vmwareWaitForFB(VMWAREPtr pVMWARE)
201{
202    vmwareWriteReg(pVMWARE, SVGA_REG_SYNC, 1);
203    while (vmwareReadReg(pVMWARE, SVGA_REG_BUSY));
204}
205
206void
207vmwareSendSVGACmdUpdate(VMWAREPtr pVMWARE, BoxPtr pBB)
208{
209    vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_UPDATE);
210    vmwareWriteWordToFIFO(pVMWARE, pBB->x1);
211    vmwareWriteWordToFIFO(pVMWARE, pBB->y1);
212    vmwareWriteWordToFIFO(pVMWARE, pBB->x2 - pBB->x1);
213    vmwareWriteWordToFIFO(pVMWARE, pBB->y2 - pBB->y1);
214}
215
216void
217vmwareSendSVGACmdUpdateFullScreen(VMWAREPtr pVMWARE)
218{
219    BoxRec BB;
220
221    BB.x1 = 0;
222    BB.y1 = 0;
223    BB.x2 = pVMWARE->ModeReg.svga_reg_width;
224    BB.y2 = pVMWARE->ModeReg.svga_reg_height;
225    vmwareSendSVGACmdUpdate(pVMWARE, &BB);
226}
227
228static CARD32
229vmwareCalculateWeight(CARD32 mask)
230{
231    CARD32 weight;
232
233    for (weight = 0; mask; mask >>= 1) {
234        if (mask & 1) {
235            weight++;
236        }
237    }
238    return weight;
239}
240
241/*
242 *-----------------------------------------------------------------------------
243 *
244 * VMXGetVMwareSvgaId --
245 *
246 *    Retrieve the SVGA_ID of the VMware SVGA adapter.
247 *    This function should hide any backward compatibility mess.
248 *
249 * Results:
250 *    The SVGA_ID_* of the present VMware adapter.
251 *
252 * Side effects:
253 *    ins/outs
254 *
255 *-----------------------------------------------------------------------------
256 */
257
258static uint32
259VMXGetVMwareSvgaId(VMWAREPtr pVMWARE)
260{
261    uint32 vmware_svga_id;
262
263    /* Any version with any SVGA_ID_* support will initialize SVGA_REG_ID
264     * to SVGA_ID_0 to support versions of this driver with SVGA_ID_0.
265     *
266     * Versions of SVGA_ID_0 ignore writes to the SVGA_REG_ID register.
267     *
268     * Versions of SVGA_ID_1 will allow us to overwrite the content
269     * of the SVGA_REG_ID register only with the values SVGA_ID_0 or SVGA_ID_1.
270     *
271     * Versions of SVGA_ID_2 will allow us to overwrite the content
272     * of the SVGA_REG_ID register only with the values SVGA_ID_0 or SVGA_ID_1
273     * or SVGA_ID_2.
274     */
275
276    vmwareWriteReg(pVMWARE, SVGA_REG_ID, SVGA_ID_2);
277    vmware_svga_id = vmwareReadReg(pVMWARE, SVGA_REG_ID);
278    if (vmware_svga_id == SVGA_ID_2) {
279        return SVGA_ID_2;
280    }
281
282    vmwareWriteReg(pVMWARE, SVGA_REG_ID, SVGA_ID_1);
283    vmware_svga_id = vmwareReadReg(pVMWARE, SVGA_REG_ID);
284    if (vmware_svga_id == SVGA_ID_1) {
285        return SVGA_ID_1;
286    }
287
288    if (vmware_svga_id == SVGA_ID_0) {
289        return SVGA_ID_0;
290    }
291
292    /* No supported VMware SVGA devices found */
293    return SVGA_ID_INVALID;
294}
295
296static Bool
297VMWAREPreInit(ScrnInfoPtr pScrn, int flags)
298{
299    MessageType from;
300    VMWAREPtr pVMWARE;
301    OptionInfoPtr options;
302    int bpp24flags;
303    uint32 id;
304    int i;
305    ClockRange* clockRanges;
306    unsigned long domainIOBase = 0;
307    uint32 width = 0, height = 0;
308    Bool defaultMode;
309
310#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
311#ifndef BUILD_FOR_420
312    domainIOBase = pScrn->domainIOBase;
313#endif
314#endif
315
316    if (flags & PROBE_DETECT) {
317        return FALSE;
318    }
319
320    if (pScrn->numEntities != 1) {
321        return FALSE;
322    }
323
324    if (!VMWAREGetRec(pScrn)) {
325        return FALSE;
326    }
327    pVMWARE = VMWAREPTR(pScrn);
328
329    pVMWARE->pvtSema = &pScrn->vtSema;
330
331    pVMWARE->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
332    pVMWARE->PciInfo = xf86GetPciInfoForEntity(pVMWARE->pEnt->index);
333    if (pVMWARE->PciInfo == NULL) {
334        return FALSE;
335    }
336
337    if (DEVICE_ID(pVMWARE->PciInfo) == PCI_DEVICE_ID_VMWARE_SVGA) {
338        pVMWARE->indexReg = domainIOBase +
339           SVGA_LEGACY_BASE_PORT + SVGA_INDEX_PORT*sizeof(uint32);
340        pVMWARE->valueReg = domainIOBase +
341           SVGA_LEGACY_BASE_PORT + SVGA_VALUE_PORT*sizeof(uint32);
342    } else {
343        /* Note:  This setting of valueReg causes unaligned I/O */
344#if XSERVER_LIBPCIACCESS
345        pVMWARE->portIOBase = pVMWARE->PciInfo->regions[0].base_addr;
346#else
347        pVMWARE->portIOBase = pVMWARE->PciInfo->ioBase[0];
348#endif
349        pVMWARE->indexReg = domainIOBase +
350           pVMWARE->portIOBase + SVGA_INDEX_PORT;
351        pVMWARE->valueReg = domainIOBase +
352           pVMWARE->portIOBase + SVGA_VALUE_PORT;
353    }
354    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
355               "VMware SVGA regs at (0x%04lx, 0x%04lx)\n",
356               pVMWARE->indexReg, pVMWARE->valueReg);
357
358    if (!xf86LoadSubModule(pScrn, "vgahw")) {
359        return FALSE;
360    }
361
362    xf86LoaderReqSymLists(vgahwSymbols, NULL);
363
364    if (!vgaHWGetHWRec(pScrn)) {
365        return FALSE;
366    }
367
368#ifdef HAVE_XORG_SERVER_1_12_0
369    vgaHWSetStdFuncs(VGAHWPTR(pScrn));
370#endif
371
372    /*
373     * Save the current video state.  Do it here before VMXGetVMwareSvgaId
374     * writes to any registers.
375     */
376    VMWARESave(pScrn);
377
378    id = VMXGetVMwareSvgaId(pVMWARE);
379    if (id == SVGA_ID_0 || id == SVGA_ID_INVALID) {
380        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
381                   "No supported VMware SVGA found (read ID 0x%08x).\n", id);
382        return FALSE;
383    }
384    pVMWARE->suspensionSavedRegId = id;
385
386#if !XSERVER_LIBPCIACCESS
387    pVMWARE->PciTag = pciTag(pVMWARE->PciInfo->bus, pVMWARE->PciInfo->device,
388                             pVMWARE->PciInfo->func);
389#endif
390    pVMWARE->Primary = xf86IsPrimaryPci(pVMWARE->PciInfo);
391
392    pScrn->monitor = pScrn->confScreen->monitor;
393
394#ifdef ACCELERATE_OPS
395    pVMWARE->vmwareCapability = vmwareReadReg(pVMWARE, SVGA_REG_CAPABILITIES);
396#else
397    pVMWARE->vmwareCapability = vmwareReadReg(pVMWARE, SVGA_REG_CAPABILITIES) &
398	SVGA_CAP_PITCHLOCK;
399#endif
400
401    pVMWARE->bitsPerPixel = vmwareReadReg(pVMWARE,
402                                          SVGA_REG_HOST_BITS_PER_PIXEL);
403    if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) {
404       vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, pVMWARE->bitsPerPixel);
405    }
406
407    pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH);
408    pVMWARE->videoRam = vmwareReadReg(pVMWARE, SVGA_REG_VRAM_SIZE);
409    pVMWARE->memPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_FB_START);
410    pVMWARE->maxWidth = vmwareReadReg(pVMWARE, SVGA_REG_MAX_WIDTH);
411    pVMWARE->maxHeight = vmwareReadReg(pVMWARE, SVGA_REG_MAX_HEIGHT);
412    pVMWARE->cursorDefined = FALSE;
413    pVMWARE->cursorShouldBeHidden = FALSE;
414
415    if (pVMWARE->vmwareCapability & SVGA_CAP_CURSOR_BYPASS_2) {
416        pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_REMOVE_FROM_FB;
417        pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_RESTORE_TO_FB;
418    } else {
419        pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_HIDE;
420        pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_SHOW;
421    }
422
423    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "caps:  0x%08X\n", pVMWARE->vmwareCapability);
424    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "depth: %d\n", pVMWARE->depth);
425    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "bpp:   %d\n", pVMWARE->bitsPerPixel);
426
427    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "vram:  %d\n", pVMWARE->videoRam);
428    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "pbase: 0x%08lx\n", pVMWARE->memPhysBase);
429    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mwidt: %d\n", pVMWARE->maxWidth);
430    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mheig: %d\n", pVMWARE->maxHeight);
431
432    if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) {
433        bpp24flags = Support24bppFb | Support32bppFb;
434    } else {
435        switch (pVMWARE->depth) {
436        case 16:
437            /*
438             * In certain cases, the Windows host appears to
439             * report 16 bpp and 16 depth but 555 weight.  Just
440             * silently convert it to depth of 15.
441             */
442            if (pVMWARE->bitsPerPixel == 16 &&
443                pVMWARE->weight.green == 5)
444                pVMWARE->depth = 15;
445        case 8:
446        case 15:
447            bpp24flags = NoDepth24Support;
448         break;
449        case 32:
450            /*
451             * There is no 32 bit depth, apparently it can get
452             * reported this way sometimes on the Windows host.
453             */
454            if (pVMWARE->bitsPerPixel == 32)
455                pVMWARE->depth = 24;
456        case 24:
457            if (pVMWARE->bitsPerPixel == 24)
458                bpp24flags = Support24bppFb;
459            else
460                bpp24flags = Support32bppFb;
461            break;
462       default:
463            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
464                       "Adapter is using an unsupported depth (%d).\n",
465                       pVMWARE->depth);
466            return FALSE;
467       }
468    }
469
470    if (!xf86SetDepthBpp(pScrn, pVMWARE->depth, pVMWARE->bitsPerPixel,
471                         pVMWARE->bitsPerPixel, bpp24flags)) {
472        return FALSE;
473    }
474
475    /* Check that the returned depth is one we support */
476    switch (pScrn->depth) {
477    case 8:
478    case 15:
479    case 16:
480    case 24:
481        /* OK */
482        break;
483    default:
484        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
485                   "Given depth (%d) is not supported by this driver\n",
486                   pScrn->depth);
487        return FALSE;
488    }
489
490    if (pScrn->bitsPerPixel != pVMWARE->bitsPerPixel) {
491        if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) {
492            vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL,
493                           pScrn->bitsPerPixel);
494            pVMWARE->bitsPerPixel =
495               vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL);
496            pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH);
497        } else {
498            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
499                       "Currently unavailable depth/bpp of %d/%d requested.\n"
500                       "\tThe guest X server must run at the same depth and bpp as the host\n"
501                       "\t(which are currently %d/%d).  This is automatically detected.  Please\n"
502                       "\tdo not specify a depth on the command line or via the config file.\n",
503                       pScrn->depth, pScrn->bitsPerPixel,
504                       pVMWARE->depth, pVMWARE->bitsPerPixel);
505            return FALSE;
506        }
507    }
508
509    /*
510     * Defer reading the colour registers until here in case we changed
511     * bpp above.
512     */
513
514    pVMWARE->weight.red =
515       vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_RED_MASK));
516    pVMWARE->weight.green =
517       vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_GREEN_MASK));
518    pVMWARE->weight.blue =
519       vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_BLUE_MASK));
520    pVMWARE->offset.blue = 0;
521    pVMWARE->offset.green = pVMWARE->weight.blue;
522    pVMWARE->offset.red = pVMWARE->weight.green + pVMWARE->offset.green;
523    pVMWARE->defaultVisual = vmwareReadReg(pVMWARE, SVGA_REG_PSEUDOCOLOR) ?
524       PseudoColor : TrueColor;
525
526    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
527                   2, "depth: %d\n", pVMWARE->depth);
528    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
529                   2, "bpp:   %d\n", pVMWARE->bitsPerPixel);
530    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
531                   2, "w.red: %d\n", (int)pVMWARE->weight.red);
532    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
533                   2, "w.grn: %d\n", (int)pVMWARE->weight.green);
534    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
535                   2, "w.blu: %d\n", (int)pVMWARE->weight.blue);
536    xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
537                   2, "vis:   %d\n", pVMWARE->defaultVisual);
538
539    if (pScrn->depth != pVMWARE->depth) {
540        if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) {
541            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
542                       "Currently unavailable depth of %d requested.\n"
543                       "\tIf the guest X server's BPP matches the host's "
544                       "BPP, then\n\tthe guest X server's depth must also "
545                       "match the\n\thost's depth (currently %d).\n",
546                       pScrn->depth, pVMWARE->depth);
547        } else {
548            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
549                       "Currently unavailable depth of %d requested.\n"
550                       "\tThe guest X server must run at the same depth as "
551                       "the host (which\n\tis currently %d).  This is "
552                       "automatically detected.  Please do not\n\tspecify "
553                       "a depth on the command line or via the config file.\n",
554                       pScrn->depth, pVMWARE->depth);
555        }
556           return FALSE;
557    }
558    xf86PrintDepthBpp(pScrn);
559
560#if 0
561    if (pScrn->depth == 24 && pix24bpp == 0) {
562        pix24bpp = xf86GetBppFromDepth(pScrn, 24);
563    }
564#endif
565
566    if (pScrn->depth > 8) {
567        rgb zeros = { 0, 0, 0 };
568
569        if (!xf86SetWeight(pScrn, pVMWARE->weight, zeros)) {
570            return FALSE;
571        }
572        /* FIXME check returned weight */
573    }
574    if (!xf86SetDefaultVisual(pScrn, pVMWARE->defaultVisual)) {
575        return FALSE;
576    }
577    if (pScrn->defaultVisual != pVMWARE->defaultVisual) {
578        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
579                   "Given visual (%d) is not supported by this driver (%d is required)\n",
580                   pScrn->defaultVisual, pVMWARE->defaultVisual);
581        return FALSE;
582    }
583#if 0
584    bytesPerPixel = pScrn->bitsPerPixel / 8;
585#endif
586    pScrn->progClock = TRUE;
587
588#if 0 /* MGA does not do this */
589    if (pScrn->visual != 0) {	/* FIXME */
590        /* print error message */
591        return FALSE;
592    }
593#endif
594
595    xf86CollectOptions(pScrn, NULL);
596    if (!(options = VMWARECopyOptions()))
597        return FALSE;
598    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
599
600    if (pScrn->depth <= 8) {
601        pScrn->rgbBits = 8;
602    }
603
604    if (!pScrn->chipset) {
605        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04x is not recognised\n", DEVICE_ID(pVMWARE->PciInfo));
606        return FALSE;
607    }
608
609    from = X_DEFAULT;
610    pVMWARE->hwCursor = TRUE;
611    if (xf86GetOptValBool(options, OPTION_HW_CURSOR, &pVMWARE->hwCursor)) {
612        from = X_CONFIG;
613    }
614    if (pVMWARE->hwCursor && !(pVMWARE->vmwareCapability & SVGA_CAP_CURSOR)) {
615        xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW cursor is not supported in this configuration\n");
616        from = X_PROBED;
617        pVMWARE->hwCursor = FALSE;
618    }
619    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
620               pVMWARE->hwCursor ? "HW" : "SW");
621    pScrn->videoRam = pVMWARE->videoRam / 1024;
622    pScrn->memPhysBase = pVMWARE->memPhysBase;
623
624    from = X_DEFAULT;
625    defaultMode = TRUE;
626    if (xf86GetOptValBool(options, OPTION_DEFAULT_MODE, &defaultMode)) {
627        from = X_CONFIG;
628    }
629
630    width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH);
631    height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT);
632    width = MAX(width, VMW_MIN_INITIAL_WIDTH);
633    height = MAX(height, VMW_MIN_INITIAL_HEIGHT);
634
635    if (width > pVMWARE->maxWidth || height > pVMWARE->maxHeight) {
636	/*
637	 * This is an error condition and shouldn't happen.
638	 * revert to MIN_INITIAL_ values
639	 */
640	width = VMW_MIN_INITIAL_WIDTH;
641	height = VMW_MIN_INITIAL_HEIGHT;
642    }
643
644    xf86DrvMsg(pScrn->scrnIndex, from,
645	       "Will %sset up a driver mode with dimensions %dx%d.\n",
646	       defaultMode ? "" : "not ", width, height);
647
648    free(options);
649
650    {
651        Gamma zeros = { 0.0, 0.0, 0.0 };
652        if (!xf86SetGamma(pScrn, zeros)) {
653            return FALSE;
654        }
655    }
656#if 0
657    if ((i = xf86GetPciInfoForScreen(pScrn->scrnIndex, &pciList, NULL)) != 1) {
658        /* print error message */
659        VMWAREFreeRec(pScrn);
660        if (i > 0) {
661            free(pciList);
662        }
663        return FALSE;
664    }
665#endif
666    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
667    clockRanges->next = NULL;
668    clockRanges->minClock = 1;
669    clockRanges->maxClock = 400000000;
670    clockRanges->clockIndex = -1;
671    clockRanges->interlaceAllowed = FALSE;
672    clockRanges->doubleScanAllowed = FALSE;
673    clockRanges->ClockMulFactor = 1;
674    clockRanges->ClockDivFactor = 1;
675
676    if (defaultMode) {
677	vmwareAddDefaultMode(pScrn, width, height);
678    }
679
680    i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes,
681                          clockRanges, NULL, 256, pVMWARE->maxWidth,
682                          pVMWARE->bitsPerPixel * 1,
683                          128, pVMWARE->maxHeight,
684                          pScrn->display->virtualX, pScrn->display->virtualY,
685                          pVMWARE->videoRam,
686                          LOOKUP_BEST_REFRESH | LOOKUP_OPTIONAL_TOLERANCES);
687
688    if (i == -1) {
689        VMWAREFreeRec(pScrn);
690        return FALSE;
691    }
692    xf86PruneDriverModes(pScrn);
693    if (i == 0 || pScrn->modes == NULL) {
694        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
695        VMWAREFreeRec(pScrn);
696        return FALSE;
697    }
698
699    pScrn->currentMode = pScrn->modes;
700    pScrn->virtualX = pScrn->modes->HDisplay;
701    pScrn->virtualY = pScrn->modes->VDisplay;
702
703    xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
704
705    xf86PrintModes(pScrn);
706    xf86SetDpi(pScrn, 0, 0);
707    if (!xf86LoadSubModule(pScrn, "fb") ||
708        !xf86LoadSubModule(pScrn, "shadowfb")) {
709        VMWAREFreeRec(pScrn);
710        return FALSE;
711    }
712    xf86LoaderReqSymLists(fbSymbols, shadowfbSymbols, NULL);
713
714    /* Need ramdac for hwcursor */
715    if (pVMWARE->hwCursor) {
716        if (!xf86LoadSubModule(pScrn, "ramdac")) {
717            VMWAREFreeRec(pScrn);
718            return FALSE;
719        }
720        xf86LoaderReqSymLists(ramdacSymbols, NULL);
721    }
722
723    return TRUE;
724}
725
726static Bool
727VMWAREMapMem(ScrnInfoPtr pScrn)
728{
729    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
730#if XSERVER_LIBPCIACCESS
731    int err;
732    struct pci_device *const device = pVMWARE->PciInfo;
733    void *fbBase;
734#endif
735
736#if XSERVER_LIBPCIACCESS
737   err = pci_device_map_range(device,
738                              pVMWARE->memPhysBase,
739                              pVMWARE->videoRam,
740                              PCI_DEV_MAP_FLAG_WRITABLE,
741			      &fbBase);
742   if (err) {
743       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
744                  "Unable to map frame buffer BAR. %s (%d)\n",
745                  strerror (err), err);
746       return FALSE;
747   }
748   pVMWARE->FbBase = fbBase;
749#else
750    pVMWARE->FbBase = xf86MapPciMem(pScrn->scrnIndex, 0,
751                                    pVMWARE->PciTag,
752                                    pVMWARE->memPhysBase,
753                                    pVMWARE->videoRam);
754#endif
755    if (!pVMWARE->FbBase)
756        return FALSE;
757
758    VmwareLog(("FB Mapped: %p/%u -> %p/%u\n",
759               pVMWARE->memPhysBase, pVMWARE->videoRam,
760               pVMWARE->FbBase, pVMWARE->videoRam));
761    return TRUE;
762}
763
764static Bool
765VMWAREUnmapMem(ScrnInfoPtr pScrn)
766{
767    VMWAREPtr pVMWARE;
768
769    pVMWARE = VMWAREPTR(pScrn);
770
771    VmwareLog(("Unmapped: %p/%u\n", pVMWARE->FbBase, pVMWARE->videoRam));
772
773#if XSERVER_LIBPCIACCESS
774    pci_device_unmap_range(pVMWARE->PciInfo, pVMWARE->FbBase, pVMWARE->videoRam);
775#else
776    xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->FbBase, pVMWARE->videoRam);
777#endif
778    pVMWARE->FbBase = NULL;
779    return TRUE;
780}
781
782static void
783VMWARESave(ScrnInfoPtr pScrn)
784{
785    vgaHWPtr hwp = VGAHWPTR(pScrn);
786    vgaRegPtr vgaReg = &hwp->SavedReg;
787    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
788    VMWARERegPtr vmwareReg = &pVMWARE->SavedReg;
789
790    vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
791
792    vmwareReg->svga_reg_enable = vmwareReadReg(pVMWARE, SVGA_REG_ENABLE);
793    vmwareReg->svga_reg_width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH);
794    vmwareReg->svga_reg_height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT);
795    vmwareReg->svga_reg_bits_per_pixel =
796       vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL);
797    vmwareReg->svga_reg_id = vmwareReadReg(pVMWARE, SVGA_REG_ID);
798
799    /* XXX this should be based on the cap bit, not hwCursor... */
800    if (pVMWARE->hwCursor) {
801       vmwareReg->svga_reg_cursor_on =
802          vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ON);
803       vmwareReg->svga_reg_cursor_x =
804          vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_X);
805       vmwareReg->svga_reg_cursor_y =
806          vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_Y);
807       vmwareReg->svga_reg_cursor_id =
808          vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ID);
809    }
810
811    vmwareReg->svga_fifo_enabled = vmwareReadReg(pVMWARE, SVGA_REG_CONFIG_DONE);
812}
813
814static void
815VMWARERestoreRegs(ScrnInfoPtr pScrn, VMWARERegPtr vmwareReg)
816{
817    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
818    VmwareLog(("VMWARERestoreRegs: W: %d, H: %d, BPP: %d, Enable: %d\n",
819	       vmwareReg->svga_reg_width, vmwareReg->svga_reg_height,
820	       vmwareReg->svga_reg_bits_per_pixel, vmwareReg->svga_reg_enable));
821    if (vmwareReg->svga_reg_enable) {
822        vmwareWriteReg(pVMWARE, SVGA_REG_ID, vmwareReg->svga_reg_id);
823        vmwareWriteReg(pVMWARE, SVGA_REG_WIDTH, vmwareReg->svga_reg_width);
824        vmwareWriteReg(pVMWARE, SVGA_REG_HEIGHT, vmwareReg->svga_reg_height);
825        vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL,
826                       vmwareReg->svga_reg_bits_per_pixel);
827        vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable);
828        vmwareWriteReg(pVMWARE, SVGA_REG_GUEST_ID, GUEST_OS_LINUX);
829        if (pVMWARE->hwCursor) {
830            vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ID,
831                           vmwareReg->svga_reg_cursor_id);
832            vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_X,
833                           vmwareReg->svga_reg_cursor_x);
834            vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_Y,
835                           vmwareReg->svga_reg_cursor_y);
836            vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ON,
837                           vmwareReg->svga_reg_cursor_on);
838        }
839    } else {
840        vmwareWriteReg(pVMWARE, SVGA_REG_ID, vmwareReg->svga_reg_id);
841        vmwareWriteReg(pVMWARE, SVGA_REG_WIDTH, vmwareReg->svga_reg_width);
842        vmwareWriteReg(pVMWARE, SVGA_REG_HEIGHT, vmwareReg->svga_reg_height);
843        vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL,
844                       vmwareReg->svga_reg_bits_per_pixel);
845	vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable);
846    }
847}
848
849static void
850VMWARERestore(ScrnInfoPtr pScrn)
851{
852    vgaHWPtr hwp = VGAHWPTR(pScrn);
853    vgaRegPtr vgaReg = &hwp->SavedReg;
854    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
855    VMWARERegPtr vmwareReg = &pVMWARE->SavedReg;
856
857    vmwareWaitForFB(pVMWARE);
858    if (!vmwareReg->svga_fifo_enabled) {
859        VMWAREStopFIFO(pScrn);
860    }
861
862    vgaHWProtect(pScrn, TRUE);
863    VMWARERestoreRegs(pScrn, vmwareReg);
864    vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
865    vgaHWProtect(pScrn, FALSE);
866}
867
868static Bool
869VMWAREModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool rebuildPixmap)
870{
871    vgaHWPtr hwp = VGAHWPTR(pScrn);
872    vgaRegPtr vgaReg = &hwp->ModeReg;
873    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
874    VMWARERegPtr vmwareReg = &pVMWARE->ModeReg;
875
876    vgaHWUnlock(hwp);
877    if (!vgaHWInit(pScrn, mode))
878        return FALSE;
879    pScrn->vtSema = TRUE;
880
881    if (pVMWARE->vmwareCapability & SVGA_CAP_PITCHLOCK)
882	vmwareWriteReg(pVMWARE, SVGA_REG_PITCHLOCK, 0);
883    vmwareReg->svga_reg_enable = 1;
884    vmwareReg->svga_reg_width = max(mode->HDisplay, pScrn->virtualX);
885    vmwareReg->svga_reg_height = max(mode->VDisplay, pScrn->virtualY);
886    vmwareReg->svga_reg_bits_per_pixel = pVMWARE->bitsPerPixel;
887
888    vgaHWProtect(pScrn, TRUE);
889
890    vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
891    VMWARERestoreRegs(pScrn, vmwareReg);
892
893    if (pVMWARE->hwCursor) {
894        vmwareCursorModeInit(pScrn, mode);
895    }
896
897    VmwareLog(("Required mode: %ux%u\n", mode->HDisplay, mode->VDisplay));
898    VmwareLog(("Virtual:       %ux%u\n", pScrn->virtualX, pScrn->virtualY));
899    VmwareLog(("dispWidth:     %u\n", pScrn->displayWidth));
900    pVMWARE->fbOffset = vmwareReadReg(pVMWARE, SVGA_REG_FB_OFFSET);
901    pVMWARE->fbPitch = vmwareReadReg(pVMWARE, SVGA_REG_BYTES_PER_LINE);
902    pVMWARE->FbSize = vmwareReadReg(pVMWARE, SVGA_REG_FB_SIZE);
903
904    pScrn->displayWidth = (pVMWARE->fbPitch * 8) / ((pScrn->bitsPerPixel + 7) & ~7);
905    VmwareLog(("fbOffset:      %u\n", pVMWARE->fbOffset));
906    VmwareLog(("fbPitch:       %u\n", pVMWARE->fbPitch));
907    VmwareLog(("fbSize:        %u\n", pVMWARE->FbSize));
908    VmwareLog(("New dispWidth: %u\n", pScrn->displayWidth));
909
910    vmwareCheckVideoSanity(pScrn);
911
912    if (rebuildPixmap) {
913        pScrn->pScreen->ModifyPixmapHeader((*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen),
914                                           pScrn->pScreen->width,
915                                           pScrn->pScreen->height,
916                                           pScrn->pScreen->rootDepth,
917                                           pScrn->bitsPerPixel,
918                                           PixmapBytePad(pScrn->displayWidth,
919                                                         pScrn->pScreen->rootDepth),
920                                           (pointer)(pVMWARE->FbBase + pScrn->fbOffset));
921
922        (*pScrn->EnableDisableFBAccess)(XF86_SCRN_ARG(pScrn), FALSE);
923        (*pScrn->EnableDisableFBAccess)(XF86_SCRN_ARG(pScrn), TRUE);
924    }
925
926    vgaHWProtect(pScrn, FALSE);
927
928    /*
929     * Push the new Xinerama state to X clients and the hardware,
930     * synchronously with the mode change. Note that this must happen
931     * AFTER we write the new width and height to the hardware
932     * registers, since updating the WIDTH and HEIGHT registers will
933     * reset the device's multimon topology.
934     */
935    vmwareNextXineramaState(pVMWARE);
936
937    return TRUE;
938}
939
940void
941vmwareNextXineramaState(VMWAREPtr pVMWARE)
942{
943    VMWARERegPtr vmwareReg = &pVMWARE->ModeReg;
944
945    /*
946     * Switch to the next Xinerama state (from pVMWARE->xineramaNextState).
947     *
948     * This new state will be available to X clients via the Xinerama
949     * extension, and we push the new state to the virtual hardware,
950     * in order to configure a number of virtual monitors within the
951     * device's framebuffer.
952     *
953     * This function can be called at any time, but it should usually be
954     * called just after a mode switch. This is for two reasons:
955     *
956     *   1) We don't want X clients to see a Xinerama topology and a video
957     *      mode that are inconsistent with each other, so we'd like to switch
958     *      both at the same time.
959     *
960     *   2) We must set the host's display topology registers after setting
961     *      the new video mode, since writes to WIDTH/HEIGHT will reset the
962     *      hardware display topology.
963     */
964
965    /*
966     * Update Xinerama info appropriately.
967     */
968    if (pVMWARE->xinerama && !pVMWARE->xineramaStatic) {
969       if (pVMWARE->xineramaNextState) {
970          free(pVMWARE->xineramaState);
971          pVMWARE->xineramaState = pVMWARE->xineramaNextState;
972          pVMWARE->xineramaNumOutputs = pVMWARE->xineramaNextNumOutputs;
973
974          pVMWARE->xineramaNextState = NULL;
975          pVMWARE->xineramaNextNumOutputs = 0;
976
977       } else {
978          /*
979           * There is no next state pending. Switch back to
980           * single-monitor mode. This is necessary for resetting the
981           * Xinerama state if we get a mode change which doesn't
982           * follow a VMwareCtrlDoSetTopology call.
983           */
984          VMWAREXineramaPtr basicState =
985             (VMWAREXineramaPtr)calloc(1, sizeof (VMWAREXineramaRec));
986          if (basicState) {
987             basicState->x_org = 0;
988             basicState->y_org = 0;
989             basicState->width = vmwareReg->svga_reg_width;
990             basicState->height = vmwareReg->svga_reg_height;
991
992             free(pVMWARE->xineramaState);
993             pVMWARE->xineramaState = basicState;
994             pVMWARE->xineramaNumOutputs = 1;
995          }
996       }
997    }
998
999    /*
1000     * Update host's view of guest topology. This tells the device
1001     * how we're carving up its framebuffer into virtual screens.
1002     */
1003    if (pVMWARE->vmwareCapability & SVGA_CAP_DISPLAY_TOPOLOGY) {
1004        if (pVMWARE->xinerama) {
1005            int i = 0;
1006            VMWAREXineramaPtr xineramaState = pVMWARE->xineramaState;
1007            vmwareWriteReg(pVMWARE, SVGA_REG_NUM_GUEST_DISPLAYS,
1008                           pVMWARE->xineramaNumOutputs);
1009
1010            for (i = 0; i < pVMWARE->xineramaNumOutputs; i++) {
1011                vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, i);
1012                vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_IS_PRIMARY, i == 0);
1013                vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_X,
1014                               xineramaState[i].x_org);
1015                vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_Y,
1016                               xineramaState[i].y_org);
1017                vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_WIDTH,
1018                               xineramaState[i].width);
1019                vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_HEIGHT,
1020                               xineramaState[i].height);
1021            }
1022        } else {
1023            vmwareWriteReg(pVMWARE, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
1024
1025            vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, 0);
1026            vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_IS_PRIMARY, TRUE);
1027            vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_X, 0);
1028            vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_POSITION_Y, 0);
1029            vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_WIDTH, vmwareReg->svga_reg_width);
1030            vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_HEIGHT, vmwareReg->svga_reg_height);
1031        }
1032
1033        /* Done. */
1034        vmwareWriteReg(pVMWARE, SVGA_REG_DISPLAY_ID, SVGA_INVALID_DISPLAY_ID);
1035    }
1036}
1037
1038static void
1039VMWAREAdjustFrame(ADJUST_FRAME_ARGS_DECL)
1040{
1041    /* FIXME */
1042}
1043
1044static void
1045VMWAREInitFIFO(ScrnInfoPtr pScrn)
1046{
1047    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1048#if XSERVER_LIBPCIACCESS
1049    struct pci_device *const device = pVMWARE->PciInfo;
1050    int err;
1051    void *mmioVirtBase;
1052#endif
1053    volatile CARD32* vmwareFIFO;
1054    Bool extendedFifo;
1055    int min;
1056
1057    TRACEPOINT
1058
1059    pVMWARE->mmioPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_MEM_START);
1060    pVMWARE->mmioSize = vmwareReadReg(pVMWARE, SVGA_REG_MEM_SIZE) & ~3;
1061#if XSERVER_LIBPCIACCESS
1062    err = pci_device_map_range(device, pVMWARE->mmioPhysBase,
1063                               pVMWARE->mmioSize,
1064                               PCI_DEV_MAP_FLAG_WRITABLE,
1065                               &mmioVirtBase);
1066    if (err) {
1067        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1068                   "Unable to map mmio BAR. %s (%d)\n",
1069                   strerror (err), err);
1070        return;
1071    }
1072    pVMWARE->mmioVirtBase = mmioVirtBase;
1073#else
1074    pVMWARE->mmioVirtBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
1075                                          pVMWARE->PciTag,
1076                                          pVMWARE->mmioPhysBase,
1077                                          pVMWARE->mmioSize);
1078#endif
1079    vmwareFIFO = pVMWARE->vmwareFIFO = (CARD32*)pVMWARE->mmioVirtBase;
1080
1081    extendedFifo = pVMWARE->vmwareCapability & SVGA_CAP_EXTENDED_FIFO;
1082    min = extendedFifo ? vmwareReadReg(pVMWARE, SVGA_REG_MEM_REGS) : 4;
1083
1084    vmwareWaitForFB(pVMWARE);
1085    vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 0);
1086
1087    vmwareFIFO[SVGA_FIFO_MIN] = min * sizeof(CARD32);
1088    vmwareFIFO[SVGA_FIFO_MAX] = pVMWARE->mmioSize;
1089    vmwareFIFO[SVGA_FIFO_NEXT_CMD] = min * sizeof(CARD32);
1090    vmwareFIFO[SVGA_FIFO_STOP] = min * sizeof(CARD32);
1091    vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 1);
1092}
1093
1094static void
1095VMWAREStopFIFO(ScrnInfoPtr pScrn)
1096{
1097    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1098
1099    TRACEPOINT
1100
1101    vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 0);
1102#if XSERVER_LIBPCIACCESS
1103    pci_device_unmap_range(pVMWARE->PciInfo, pVMWARE->mmioVirtBase, pVMWARE->mmioSize);
1104#else
1105    xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->mmioVirtBase, pVMWARE->mmioSize);
1106#endif
1107}
1108
1109static Bool
1110VMWARECloseScreen(CLOSE_SCREEN_ARGS_DECL)
1111{
1112    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1113    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1114    ScreenPtr save = &pVMWARE->ScrnFuncs;
1115
1116    VmwareLog(("cursorSema: %d\n", pVMWARE->cursorSema));
1117
1118    if (*pVMWARE->pvtSema) {
1119        if (pVMWARE->videoStreams) {
1120            vmwareVideoEnd(pScreen);
1121        }
1122
1123        if (pVMWARE->CursorInfoRec) {
1124            vmwareCursorCloseScreen(pScreen);
1125        }
1126
1127        VMWARERestore(pScrn);
1128        VMWAREUnmapMem(pScrn);
1129
1130        pScrn->vtSema = FALSE;
1131    }
1132
1133    pScreen->CloseScreen = save->CloseScreen;
1134    pScreen->SaveScreen = save->SaveScreen;
1135
1136#if VMWARE_DRIVER_FUNC
1137    pScrn->DriverFunc = NULL;
1138#endif
1139
1140    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
1141}
1142
1143static Bool
1144VMWARESaveScreen(ScreenPtr pScreen, int mode)
1145{
1146    VmwareLog(("VMWareSaveScreen() mode = %d\n", mode));
1147
1148    /*
1149     * This thoroughly fails to do anything useful to svga mode.  I doubt
1150     * we care; who wants to idle-blank their VM's screen anyway?
1151     */
1152    return vgaHWSaveScreen(pScreen, mode);
1153}
1154
1155/* disabled by default to reduce spew in DEBUG_LOGGING mode. */
1156/*#define DEBUG_LOG_UPDATES*/
1157
1158static void
1159VMWAREPreDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr)
1160{
1161    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1162
1163#ifdef DEBUG_LOG_UPDATES
1164    {
1165        int i;
1166        for (i = 0; i < nboxes; i++) {
1167            VmwareLog(("PreUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes - i,
1168                       boxPtr[i].x1, boxPtr[i].y1,
1169                       boxPtr[i].x2 - boxPtr[i].x1,
1170                       boxPtr[i].y2 - boxPtr[i].y1));
1171        }
1172    }
1173#endif
1174
1175    /*
1176     * We only register this callback if we have a HW cursor.
1177     */
1178    while (nboxes--) {
1179        if (BOX_INTERSECT(*boxPtr, pVMWARE->hwcur.box)) {
1180            if (!pVMWARE->cursorExcludedForUpdate) {
1181                PRE_OP_HIDE_CURSOR();
1182                pVMWARE->cursorExcludedForUpdate = TRUE;
1183            }
1184	    break;
1185        }
1186        boxPtr++;
1187    }
1188}
1189
1190static void
1191VMWAREPostDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr)
1192{
1193    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1194    while (nboxes--) {
1195#ifdef DEBUG_LOG_UPDATES
1196        VmwareLog(("PostUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes,
1197                   boxPtr->x1, boxPtr->y1,
1198                   boxPtr->x2 - boxPtr->x1, boxPtr->y2 - boxPtr->y1));
1199#endif
1200
1201        /* Clip off (y only) for offscreen memory */
1202        if (boxPtr->y2 >= pVMWARE->ModeReg.svga_reg_height)
1203            boxPtr->y2 = pVMWARE->ModeReg.svga_reg_height;
1204        if (boxPtr->y1 >= pVMWARE->ModeReg.svga_reg_height)
1205            boxPtr->y1 = pVMWARE->ModeReg.svga_reg_height;
1206        if (boxPtr->y1 == boxPtr->y2) {
1207            boxPtr++;
1208            continue;
1209        }
1210
1211        vmwareSendSVGACmdUpdate(pVMWARE, boxPtr++);
1212    }
1213
1214    if (pVMWARE->hwCursor && pVMWARE->cursorExcludedForUpdate) {
1215        POST_OP_SHOW_CURSOR();
1216        pVMWARE->cursorExcludedForUpdate = FALSE;
1217    }
1218}
1219
1220static void
1221VMWARELoadPalette(ScrnInfoPtr pScrn, int numColors, int* indices,
1222                  LOCO* colors, VisualPtr pVisual)
1223{
1224    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1225    int i;
1226
1227    for (i = 0; i < numColors; i++) {
1228        vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 0, colors[*indices].red);
1229        vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 1, colors[*indices].green);
1230        vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 2, colors[*indices].blue);
1231        indices++;
1232    }
1233    VmwareLog(("Palette loading done\n"));
1234}
1235
1236
1237DisplayModeRec *
1238VMWAREAddDisplayMode(ScrnInfoPtr pScrn,
1239                     const char *name,
1240                     int width,
1241                     int height)
1242{
1243   DisplayModeRec *mode;
1244   char * modeName;
1245
1246   mode = malloc(sizeof(DisplayModeRec));
1247   memset(mode, 0, sizeof *mode);
1248
1249   modeName = malloc(strlen(name) + 1);
1250   strcpy(modeName, name);
1251   mode->name = modeName;
1252   mode->status = MODE_OK;
1253   mode->type = M_T_DEFAULT;
1254   mode->HDisplay = width;
1255   mode->VDisplay = height;
1256
1257   mode->next = pScrn->modes;
1258   mode->prev = pScrn->modes->prev;
1259   pScrn->modes->prev->next = mode;
1260   pScrn->modes->prev = mode;
1261
1262   return mode;
1263}
1264
1265
1266/*
1267 *-----------------------------------------------------------------------------
1268 *
1269 * vmwareIsRegionEqual --
1270 *
1271 *    This function implements REGION_EQUAL because older versions of
1272 *    regionstr.h don't define it.
1273 *    It is a slightly modified version of miRegionEqual from $Xorg: miregion.c
1274 *
1275 * Results:
1276 *    TRUE if regions are equal; FALSE otherwise
1277 *
1278 * Side effects:
1279 *    None.
1280 *
1281 *-----------------------------------------------------------------------------
1282 */
1283
1284Bool
1285vmwareIsRegionEqual(const RegionPtr reg1,
1286                    const RegionPtr reg2)
1287{
1288    int i, num;
1289    BoxPtr rects1, rects2;
1290
1291    if ((reg1->extents.x1 != reg2->extents.x1) ||
1292        (reg1->extents.x2 != reg2->extents.x2) ||
1293        (reg1->extents.y1 != reg2->extents.y1) ||
1294        (reg1->extents.y2 != reg2->extents.y2)) {
1295        return FALSE;
1296    }
1297
1298    num = REGION_NUM_RECTS(reg1);
1299    if (num != REGION_NUM_RECTS(reg2)) {
1300        return FALSE;
1301    }
1302
1303    rects1 = REGION_RECTS(reg1);
1304    rects2 = REGION_RECTS(reg2);
1305
1306    for (i = 0; i < num; i++) {
1307        if ((rects1[i].x1 != rects2[i].x1) ||
1308            (rects1[i].x2 != rects2[i].x2) ||
1309            (rects1[i].y1 != rects2[i].y1) ||
1310            (rects1[i].y2 != rects2[i].y2)) {
1311            return FALSE;
1312        }
1313    }
1314
1315    return TRUE;
1316}
1317
1318static Bool
1319VMWAREScreenInit(SCREEN_INIT_ARGS_DECL)
1320{
1321    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1322    vgaHWPtr hwp;
1323    VMWAREPtr pVMWARE;
1324    OptionInfoPtr options;
1325    Bool useXinerama = TRUE;
1326
1327    pVMWARE = VMWAREPTR(pScrn);
1328
1329
1330    xf86CollectOptions(pScrn, NULL);
1331    if (!(options = VMWARECopyOptions()))
1332        return FALSE;
1333    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
1334
1335    /*
1336     * Init xinerama preferences.
1337     */
1338    useXinerama = xf86ReturnOptValBool(options, OPTION_XINERAMA,
1339                                       pVMWARE->vmwareCapability & SVGA_CAP_MULTIMON);
1340    if (useXinerama && !(pVMWARE->vmwareCapability & SVGA_CAP_MULTIMON)) {
1341       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1342                  "Xinerama is not safely supported by the current virtual hardware. "
1343                  "Do not request resolutions that require > 16MB of framebuffer.\n");
1344    }
1345
1346
1347    if (useXinerama && xf86IsOptionSet(options, OPTION_GUI_LAYOUT)) {
1348       CONST_ABI_18_0 char *topology = xf86GetOptValString(options, OPTION_GUI_LAYOUT);
1349       if (topology) {
1350          pVMWARE->xineramaState =
1351             VMWAREParseTopologyString(pScrn, topology,
1352				       &pVMWARE->xineramaNumOutputs, "gui");
1353
1354         pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL;
1355
1356         free((void *)topology);
1357       }
1358    } else if (useXinerama &&
1359	       xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) {
1360       CONST_ABI_18_0 char *topology = xf86GetOptValString(options, OPTION_STATIC_XINERAMA);
1361       if (topology) {
1362          pVMWARE->xineramaState =
1363             VMWAREParseTopologyString(pScrn, topology,
1364				       &pVMWARE->xineramaNumOutputs,
1365				       "static Xinerama");
1366
1367         pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL;
1368
1369         free((void *)topology);
1370       }
1371    }
1372
1373    free(options);
1374
1375    /* Initialise VMWARE_CTRL extension. */
1376    VMwareCtrl_ExtInit(pScrn);
1377
1378    /* Initialise Xinerama extension. */
1379    if (useXinerama) {
1380       VMwareXinerama_ExtInit(pScrn);
1381    }
1382
1383    if (pVMWARE->xinerama && pVMWARE->xineramaStatic) {
1384       xf86DrvMsg(pScrn->scrnIndex, X_INFO, pVMWARE->xineramaState ?
1385                                            "Using static Xinerama.\n" :
1386                                            "Failed to configure static Xinerama.\n");
1387    }
1388
1389    /*
1390     * If using the vgahw module, its data structures and related
1391     * things are typically initialised/mapped here.
1392     */
1393    hwp = VGAHWPTR(pScrn);
1394    vgaHWGetIOBase(hwp);
1395
1396    VMWAREInitFIFO(pScrn);
1397
1398    /* Initialise the first mode */
1399    VMWAREModeInit(pScrn, pScrn->currentMode, FALSE);
1400
1401    /* Set the viewport if supported */
1402    VMWAREAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
1403
1404    /*
1405     * Setup the screen's visuals, and initialise the framebuffer
1406     * code.
1407     */
1408    VMWAREMapMem(pScrn);
1409
1410    /*
1411     * Clear the framebuffer (and any black-border mode areas).
1412     */
1413    memset(pVMWARE->FbBase, 0, pVMWARE->FbSize);
1414    vmwareSendSVGACmdUpdateFullScreen(pVMWARE);
1415
1416    /* Reset the visual list */
1417    miClearVisualTypes();
1418
1419    /*
1420     * Setup the visuals supported.  This driver only supports
1421     * TrueColor for bpp > 8, so the default set of visuals isn't
1422     * acceptable.  To deal with this, call miSetVisualTypes with
1423     * the appropriate visual mask.
1424     */
1425    if (pScrn->bitsPerPixel > 8) {
1426        if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
1427                              pScrn->rgbBits, pScrn->defaultVisual)) {
1428            return FALSE;
1429        }
1430    } else {
1431        if (!miSetVisualTypes(pScrn->depth,
1432                              miGetDefaultVisualMask(pScrn->depth),
1433                              pScrn->rgbBits, pScrn->defaultVisual)) {
1434            return FALSE;
1435        }
1436    }
1437
1438    miSetPixmapDepths();
1439
1440    /*
1441     * Initialise the framebuffer.
1442     */
1443    if (!fbScreenInit(pScreen, pVMWARE->FbBase + pVMWARE->fbOffset,
1444                      pScrn->virtualX, pScrn->virtualY,
1445                      pScrn->xDpi, pScrn->yDpi,
1446                      pScrn->displayWidth,
1447                      pScrn->bitsPerPixel)) {
1448        return FALSE;
1449    }
1450
1451    /* Override the default mask/offset settings */
1452    if (pScrn->bitsPerPixel > 8) {
1453        int i;
1454        VisualPtr visual;
1455
1456        for (i = 0, visual = pScreen->visuals;
1457             i < pScreen->numVisuals; i++, visual++) {
1458            if ((visual->class | DynamicClass) == DirectColor) {
1459                visual->offsetRed = pScrn->offset.red;
1460                visual->offsetGreen = pScrn->offset.green;
1461                visual->offsetBlue = pScrn->offset.blue;
1462                visual->redMask = pScrn->mask.red;
1463                visual->greenMask = pScrn->mask.green;
1464                visual->blueMask = pScrn->mask.blue;
1465            }
1466        }
1467    }
1468
1469    /* must be after RGB ordering fixed */
1470    fbPictureInit (pScreen, 0, 0);
1471
1472    /*
1473     * Save the old screen vector.
1474     */
1475    pVMWARE->ScrnFuncs = *pScreen;
1476
1477    /*
1478     * Set initial black & white colourmap indices.
1479     */
1480    xf86SetBlackWhitePixels(pScreen);
1481
1482    /*
1483     * Initialize shadowfb to notify us of dirty rectangles.  We only
1484     * need preFB access callbacks if we're using the hw cursor.
1485     */
1486    if (!ShadowFBInit2(pScreen,
1487                       pVMWARE->hwCursor ? VMWAREPreDirtyBBUpdate : NULL,
1488                       VMWAREPostDirtyBBUpdate)) {
1489        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1490                   "ShadowFB initialization failed\n");
1491        return FALSE;
1492    }
1493
1494    /*
1495     * If we have a hw cursor, we need to hook functions that might
1496     * read from the framebuffer.
1497     */
1498    if (pVMWARE->hwCursor) {
1499        vmwareCursorHookWrappers(pScreen);
1500    }
1501
1502    /*
1503     * If backing store is to be supported (as is usually the case),
1504     * initialise it.
1505     */
1506    xf86SetBackingStore(pScreen);
1507    xf86SetSilkenMouse(pScreen);
1508
1509    /*
1510     * Initialize software cursor.
1511     */
1512    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1513
1514    /*
1515     * Initialize hardware cursor.
1516     */
1517    if (pVMWARE->hwCursor) {
1518        if (!vmwareCursorInit(pScreen)) {
1519            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1520                       "Hardware cursor initialization failed\n");
1521            pVMWARE->hwCursor = FALSE;
1522        }
1523    }
1524
1525    /*
1526     * Install colourmap functions.  If using the vgahw module,
1527     * vgaHandleColormaps would usually be called here.
1528     */
1529    if (!fbCreateDefColormap(pScreen))
1530        return FALSE;
1531
1532    if (!xf86HandleColormaps(pScreen, 256, 8,
1533                             VMWARELoadPalette, NULL,
1534                             CMAP_PALETTED_TRUECOLOR |
1535                             CMAP_RELOAD_ON_MODE_SWITCH)) {
1536        return FALSE;
1537    }
1538
1539    /*
1540     * We explicitly add a set of default modes because the X server will
1541     * not include modes larger than the initial one.
1542     */
1543   {
1544      unsigned int i;
1545      unsigned int numModes = sizeof (VMWAREDefaultModes) / sizeof *(VMWAREDefaultModes);
1546      char name[10];
1547      for (i = 0; i < numModes; i++) {
1548         const VMWAREDefaultMode *mode = &VMWAREDefaultModes[i];
1549
1550         /* Only modes that fit the hardware maximums should be added. */
1551         if (mode->width <= pVMWARE->maxWidth && mode->height <= pVMWARE->maxHeight) {
1552            snprintf(name, 10, "%dx%d", mode->width, mode->height);
1553            VMWAREAddDisplayMode(pScrn, name, mode->width, mode->height);
1554         }
1555      }
1556
1557      /* Add the hardware maximums as a mode. */
1558      snprintf(name, 10, "%dx%d", pVMWARE->maxWidth, pVMWARE->maxHeight);
1559      VMWAREAddDisplayMode(pScrn, name, pVMWARE->maxWidth, pVMWARE->maxHeight);
1560   }
1561
1562    /*
1563     * We will lazily add the dynamic modes as the are needed when new
1564     * modes are requested through the control extension.
1565     */
1566    memset(&pVMWARE->dynModes, 0, sizeof pVMWARE->dynModes);
1567
1568#if VMWARE_DRIVER_FUNC
1569    pScrn->DriverFunc = VMWareDriverFunc;
1570#endif
1571
1572    /* Report any unused options (only for the first generation) */
1573    if (serverGeneration == 1) {
1574        xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1575    }
1576
1577    /* Initialize Xv extension */
1578    pVMWARE->videoStreams = NULL;
1579    if (vmwareVideoEnabled(pVMWARE)) {
1580        if (!vmwareVideoInit(pScreen)) {
1581            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Xv initialization failed\n");
1582        }
1583    }
1584
1585    /**
1586     * Wrap CloseScreen and SaveScreen. Do this late since we
1587     * want to be first in the callchain, to avoid using resources
1588     * already taken down in CloseScreen.
1589     */
1590
1591    pVMWARE->ScrnFuncs.CloseScreen = pScreen->CloseScreen;
1592    pVMWARE->ScrnFuncs.SaveScreen = pScreen->SaveScreen;
1593
1594    pScreen->CloseScreen = VMWARECloseScreen;
1595    pScreen->SaveScreen = VMWARESaveScreen;
1596
1597    /* Done */
1598    return TRUE;
1599}
1600
1601static Bool
1602VMWARESwitchMode(SWITCH_MODE_ARGS_DECL)
1603{
1604    SCRN_INFO_PTR(arg);
1605    ScreenPtr pScreen = pScrn->pScreen;
1606
1607    pScreen->mmWidth = (pScreen->width * VMWARE_INCHTOMM +
1608			pScrn->xDpi / 2) / pScrn->xDpi;
1609    pScreen->mmHeight = (pScreen->height * VMWARE_INCHTOMM +
1610			 pScrn->yDpi / 2) / pScrn->yDpi;
1611
1612    return VMWAREModeInit(pScrn, mode, TRUE);
1613}
1614
1615static Bool
1616VMWAREEnterVT(VT_FUNC_ARGS_DECL)
1617{
1618    SCRN_INFO_PTR(arg);
1619    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1620
1621    /*
1622     * After system resumes from hiberation, EnterVT will be called and this
1623     * is a good place to restore the SVGA ID register.
1624     */
1625    vmwareWriteReg(pVMWARE, SVGA_REG_ID, pVMWARE->suspensionSavedRegId);
1626
1627    if (!pVMWARE->SavedReg.svga_fifo_enabled) {
1628        VMWAREInitFIFO(pScrn);
1629    }
1630
1631    return VMWAREModeInit(pScrn, pScrn->currentMode, TRUE);
1632}
1633
1634static void
1635VMWARELeaveVT(VT_FUNC_ARGS_DECL)
1636{
1637    SCRN_INFO_PTR(arg);
1638    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1639
1640    /*
1641     * Before shutting down system for hibneration, LeaveVT will be called,
1642     * we save the ID register value here and later restore it in EnterVT.
1643     */
1644    pVMWARE->suspensionSavedRegId = vmwareReadReg(pVMWARE, SVGA_REG_ID);
1645
1646    VMWARERestore(pScrn);
1647}
1648
1649static void
1650VMWAREFreeScreen(FREE_SCREEN_ARGS_DECL)
1651{
1652    SCRN_INFO_PTR(arg);
1653    /*
1654     * If the vgahw module is used vgaHWFreeHWRec() would be called
1655     * here.
1656     */
1657   VMWAREFreeRec(pScrn);
1658}
1659
1660static ModeStatus
1661VMWAREValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
1662{
1663    return MODE_OK;
1664}
1665
1666void
1667vmwlegacy_hookup(ScrnInfoPtr pScrn)
1668{
1669    pScrn->PreInit = VMWAREPreInit;
1670    pScrn->ScreenInit = VMWAREScreenInit;
1671    pScrn->SwitchMode = VMWARESwitchMode;
1672    pScrn->EnterVT = VMWAREEnterVT;
1673    pScrn->LeaveVT = VMWARELeaveVT;
1674    pScrn->FreeScreen = VMWAREFreeScreen;
1675    pScrn->ValidMode = VMWAREValidMode;
1676}
1677
1678#ifdef XFree86LOADER
1679void
1680VMWARERefSymLists(void)
1681{
1682    LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols,
1683		      shadowfbSymbols, NULL);
1684}
1685#endif	/* XFree86LOADER */
1686