14da3402dSthorpej/* $Id: vboxvideo.c,v 1.2 2020/10/22 20:47:23 thorpej Exp $ */
2e07dc26bSmrg/** @file
3e07dc26bSmrg * Linux Additions X11 graphics driver
4e07dc26bSmrg */
5e07dc26bSmrg
6e07dc26bSmrg/*
7e07dc26bSmrg * Copyright (C) 2006-2017 Oracle Corporation
8e07dc26bSmrg *
9e07dc26bSmrg * This code is based on the X.Org VESA driver with the following copyrights:
10e07dc26bSmrg *
11e07dc26bSmrg * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
12e07dc26bSmrg * Copyright 2008 Red Hat, Inc.
13e07dc26bSmrg * Copyright 2012 Red Hat, Inc.
14e07dc26bSmrg *
15e07dc26bSmrg * Permission is hereby granted, free of charge, to any person obtaining a
16e07dc26bSmrg * copy of this software and associated documentation files (the "Software"),
17e07dc26bSmrg * to deal in the Software without restriction, including without limitation
18e07dc26bSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
19e07dc26bSmrg * and/or sell copies of the Software, and to permit persons to whom the
20e07dc26bSmrg * Software is furnished to do so, subject to the following conditions:
21e07dc26bSmrg *
22e07dc26bSmrg * The above copyright notice and this permission notice shall be included in
23e07dc26bSmrg * all copies or substantial portions of the Software.
24e07dc26bSmrg *
25e07dc26bSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26e07dc26bSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27e07dc26bSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
28e07dc26bSmrg * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
29e07dc26bSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
30e07dc26bSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
31e07dc26bSmrg * USE OR OTHER DEALINGS IN THE SOFTWARE.
32e07dc26bSmrg *
33e07dc26bSmrg * Except as contained in this notice, the name of Conectiva Linux shall
34e07dc26bSmrg * not be used in advertising or otherwise to promote the sale, use or other
35e07dc26bSmrg * dealings in this Software without prior written authorization from
36e07dc26bSmrg * Conectiva Linux.
37e07dc26bSmrg *
38e07dc26bSmrg * Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
39e07dc26bSmrg *          David Dawes <dawes@xfree86.org>
40e07dc26bSmrg *          Adam Jackson <ajax@redhat.com>
41e07dc26bSmrg *          Dave Airlie <airlied@redhat.com>
42e07dc26bSmrg *          Michael Thayer <michael.thayer@oracle.com>
43e07dc26bSmrg */
44e07dc26bSmrg
454da3402dSthorpej#include "vboxvideo_drv.h"
46e07dc26bSmrg#include <VBoxVideoVBE.h>
47e07dc26bSmrg
48e07dc26bSmrg/* Basic definitions and functions needed by all drivers. */
49e07dc26bSmrg#include "xf86.h"
50e07dc26bSmrg/* For video memory mapping. */
51e07dc26bSmrg#include "xf86_OSproc.h"
52e07dc26bSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
53e07dc26bSmrg/* PCI resources. */
54e07dc26bSmrg# include "xf86Resources.h"
55e07dc26bSmrg#endif
56e07dc26bSmrg/* Generic server linear frame-buffer APIs. */
57e07dc26bSmrg#include "fb.h"
58e07dc26bSmrg/* Colormap and visual handling. */
59e07dc26bSmrg#include "micmap.h"
60e07dc26bSmrg#include "xf86cmap.h"
61e07dc26bSmrg/* ShadowFB support */
62e07dc26bSmrg#include "shadowfb.h"
63e07dc26bSmrg/* VGA hardware functions for setting and restoring text mode */
64e07dc26bSmrg#include "vgaHW.h"
65e07dc26bSmrg#ifdef VBOXVIDEO_13
66e07dc26bSmrg/* X.org 1.3+ mode setting */
67e07dc26bSmrg# define _HAVE_STRING_ARCH_strsep /* bits/string2.h, __strsep_1c. */
68e07dc26bSmrg# include "xf86Crtc.h"
69e07dc26bSmrg# include "xf86Modes.h"
70e07dc26bSmrg/* For xf86RandR12GetOriginalVirtualSize(). */
71e07dc26bSmrg# include "xf86RandR12.h"
72e07dc26bSmrg#endif
73e07dc26bSmrg/* For setting the root window property. */
74e07dc26bSmrg#include "property.h"
75e07dc26bSmrg#include <X11/Xatom.h>
76e07dc26bSmrg
77e07dc26bSmrg#ifdef XORG_7X
78e07dc26bSmrg# include <stdlib.h>
79e07dc26bSmrg# include <string.h>
80e07dc26bSmrg# include <fcntl.h>
81e07dc26bSmrg# include <unistd.h>
82e07dc26bSmrg#endif
83e07dc26bSmrg
84e07dc26bSmrg/* Mandatory functions */
85e07dc26bSmrg
86e07dc26bSmrgstatic const OptionInfoRec * VBOXAvailableOptions(int chipid, int busid);
87e07dc26bSmrgstatic void VBOXIdentify(int flags);
88e07dc26bSmrg#ifndef PCIACCESS
89e07dc26bSmrgstatic Bool VBOXProbe(DriverPtr drv, int flags);
90e07dc26bSmrg#else
91e07dc26bSmrgstatic Bool VBOXPciProbe(DriverPtr drv, int entity_num,
92e07dc26bSmrg     struct pci_device *dev, intptr_t match_data);
93e07dc26bSmrg#endif
94e07dc26bSmrgstatic Bool VBOXPreInit(ScrnInfoPtr pScrn, int flags);
95e07dc26bSmrgstatic Bool VBOXScreenInit(ScreenPtr pScreen, int argc, char **argv);
96e07dc26bSmrgstatic Bool VBOXEnterVT(ScrnInfoPtr pScrn);
97e07dc26bSmrgstatic void VBOXLeaveVT(ScrnInfoPtr pScrn);
98e07dc26bSmrgstatic Bool VBOXCloseScreen(ScreenPtr pScreen);
99e07dc26bSmrg#ifndef VBOXVIDEO_13
100e07dc26bSmrgstatic Bool VBOXSaveScreen(ScreenPtr pScreen, int mode);
101e07dc26bSmrg#endif
102e07dc26bSmrgstatic Bool VBOXSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
103e07dc26bSmrgstatic void VBOXAdjustFrame(ScrnInfoPtr pScrn, int x, int y);
104e07dc26bSmrgstatic void VBOXFreeScreen(ScrnInfoPtr pScrn);
105e07dc26bSmrg#ifndef VBOXVIDEO_13
106e07dc26bSmrgstatic void VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, int flags);
107e07dc26bSmrg#endif
108e07dc26bSmrg
109e07dc26bSmrg/* locally used functions */
110e07dc26bSmrgstatic Bool VBOXMapVidMem(ScrnInfoPtr pScrn);
111e07dc26bSmrgstatic void VBOXUnmapVidMem(ScrnInfoPtr pScrn);
112e07dc26bSmrgstatic void VBOXSaveMode(ScrnInfoPtr pScrn);
113e07dc26bSmrgstatic void VBOXRestoreMode(ScrnInfoPtr pScrn);
114e07dc26bSmrgstatic void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, Bool fScreenInitTime);
115e07dc26bSmrg
116e07dc26bSmrg#ifndef XF86_SCRN_INTERFACE
117e07dc26bSmrg# define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]
118e07dc26bSmrg# define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]
119e07dc26bSmrg#endif
120e07dc26bSmrg
121e07dc26bSmrgstatic inline void VBOXSetRec(ScrnInfoPtr pScrn)
122e07dc26bSmrg{
123e07dc26bSmrg    if (!pScrn->driverPrivate)
124e07dc26bSmrg    {
125e07dc26bSmrg        VBOXPtr pVBox = (VBOXPtr)xnfcalloc(sizeof(VBOXRec), 1);
126e07dc26bSmrg        pScrn->driverPrivate = pVBox;
127e07dc26bSmrg#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
128e07dc26bSmrg        pVBox->fdACPIDevices = -1;
129e07dc26bSmrg#endif
130e07dc26bSmrg    }
131e07dc26bSmrg}
132e07dc26bSmrg
133e07dc26bSmrgenum GenericTypes
134e07dc26bSmrg{
135e07dc26bSmrg    CHIP_VBOX_GENERIC
136e07dc26bSmrg};
137e07dc26bSmrg
138e07dc26bSmrg#ifdef PCIACCESS
139e07dc26bSmrgstatic const struct pci_id_match vbox_device_match[] = {
140e07dc26bSmrg    {
141e07dc26bSmrg        VBOX_VENDORID, VBOX_DEVICEID, PCI_MATCH_ANY, PCI_MATCH_ANY,
142e07dc26bSmrg        0, 0, 0
143e07dc26bSmrg    },
144e07dc26bSmrg
145e07dc26bSmrg    { 0, 0, 0 },
146e07dc26bSmrg};
147e07dc26bSmrg#endif
148e07dc26bSmrg
149e07dc26bSmrg/* Supported chipsets */
150e07dc26bSmrgstatic SymTabRec VBOXChipsets[] =
151e07dc26bSmrg{
152e07dc26bSmrg    {VBOX_DEVICEID, "vbox"},
153e07dc26bSmrg    {-1,            NULL}
154e07dc26bSmrg};
155e07dc26bSmrg
156e07dc26bSmrgstatic PciChipsets VBOXPCIchipsets[] = {
157e07dc26bSmrg  { VBOX_DEVICEID, VBOX_DEVICEID, RES_SHARED_VGA },
158e07dc26bSmrg  { -1,            -1,            RES_UNDEFINED },
159e07dc26bSmrg};
160e07dc26bSmrg
161e07dc26bSmrg/*
162e07dc26bSmrg * This contains the functions needed by the server after loading the
163e07dc26bSmrg * driver module.  It must be supplied, and gets added the driver list by
164e07dc26bSmrg * the Module Setup function in the dynamic case.  In the static case a
165e07dc26bSmrg * reference to this is compiled in, and this requires that the name of
166e07dc26bSmrg * this DriverRec be an upper-case version of the driver name.
167e07dc26bSmrg */
168e07dc26bSmrg
169e07dc26bSmrg#ifdef XORG_7X
170e07dc26bSmrg_X_EXPORT
171e07dc26bSmrg#endif
172e07dc26bSmrgDriverRec VBOXVIDEO = {
173e07dc26bSmrg    VBOX_VERSION,
174e07dc26bSmrg    VBOX_DRIVER_NAME,
175e07dc26bSmrg    VBOXIdentify,
176e07dc26bSmrg#ifdef PCIACCESS
177e07dc26bSmrg    NULL,
178e07dc26bSmrg#else
179e07dc26bSmrg    VBOXProbe,
180e07dc26bSmrg#endif
181e07dc26bSmrg    VBOXAvailableOptions,
182e07dc26bSmrg    NULL,
183e07dc26bSmrg    0,
184e07dc26bSmrg#ifdef XORG_7X
185e07dc26bSmrg    NULL,
186e07dc26bSmrg#endif
187e07dc26bSmrg#ifdef PCIACCESS
188e07dc26bSmrg    vbox_device_match,
189e07dc26bSmrg    VBOXPciProbe
190e07dc26bSmrg#endif
191e07dc26bSmrg};
192e07dc26bSmrg
193e07dc26bSmrg/* No options for now */
194e07dc26bSmrgstatic const OptionInfoRec VBOXOptions[] = {
195e07dc26bSmrg    { -1, NULL, OPTV_NONE, {0}, FALSE }
196e07dc26bSmrg};
197e07dc26bSmrg
198e07dc26bSmrg#ifndef XORG_7X
199e07dc26bSmrg/*
200e07dc26bSmrg * List of symbols from other modules that this module references.  This
201e07dc26bSmrg * list is used to tell the loader that it is OK for symbols here to be
202e07dc26bSmrg * unresolved providing that it hasn't been told that they haven't been
203e07dc26bSmrg * told that they are essential via a call to xf86LoaderReqSymbols() or
204e07dc26bSmrg * xf86LoaderReqSymLists().  The purpose is this is to avoid warnings about
205e07dc26bSmrg * unresolved symbols that are not required.
206e07dc26bSmrg */
207e07dc26bSmrgstatic const char *fbSymbols[] = {
208e07dc26bSmrg    "fbPictureInit",
209e07dc26bSmrg    "fbScreenInit",
210e07dc26bSmrg    NULL
211e07dc26bSmrg};
212e07dc26bSmrg
213e07dc26bSmrgstatic const char *shadowfbSymbols[] = {
214e07dc26bSmrg    "ShadowFBInit2",
215e07dc26bSmrg    NULL
216e07dc26bSmrg};
217e07dc26bSmrg
218e07dc26bSmrgstatic const char *ramdacSymbols[] = {
219e07dc26bSmrg    "xf86DestroyCursorInfoRec",
220e07dc26bSmrg    "xf86InitCursor",
221e07dc26bSmrg    "xf86CreateCursorInfoRec",
222e07dc26bSmrg    NULL
223e07dc26bSmrg};
224e07dc26bSmrg
225e07dc26bSmrgstatic const char *vgahwSymbols[] = {
226e07dc26bSmrg    "vgaHWFreeHWRec",
227e07dc26bSmrg    "vgaHWGetHWRec",
228e07dc26bSmrg    "vgaHWGetIOBase",
229e07dc26bSmrg    "vgaHWGetIndex",
230e07dc26bSmrg    "vgaHWRestore",
231e07dc26bSmrg    "vgaHWSave",
232e07dc26bSmrg    "vgaHWSetStdFuncs",
233e07dc26bSmrg    NULL
234e07dc26bSmrg};
235e07dc26bSmrg#endif /* !XORG_7X */
236e07dc26bSmrg
237e07dc26bSmrg/** Resize the virtual framebuffer. */
238e07dc26bSmrgstatic Bool adjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
239e07dc26bSmrg{
240e07dc26bSmrg    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
241e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
242e07dc26bSmrg    int adjustedWidth = pScrn->bitsPerPixel == 16 ? (width + 1) & ~1 : width;
243e07dc26bSmrg    int cbLine = adjustedWidth * pScrn->bitsPerPixel / 8;
244e07dc26bSmrg    PixmapPtr pPixmap;
245e07dc26bSmrg
246e07dc26bSmrg    TRACE_LOG("width=%d, height=%d\n", width, height);
247e07dc26bSmrg    AssertMsg(width >= 0 && height >= 0, ("Invalid negative width (%d) or height (%d)\n", width, height));
248e07dc26bSmrg    if (pScreen == NULL)  /* Not yet initialised. */
249e07dc26bSmrg        return TRUE;
250e07dc26bSmrg    pPixmap = pScreen->GetScreenPixmap(pScreen);
251e07dc26bSmrg    AssertMsg(pPixmap != NULL, ("Failed to get the screen pixmap.\n"));
252e07dc26bSmrg    TRACE_LOG("pPixmap=%p adjustedWidth=%d height=%d pScrn->depth=%d pScrn->bitsPerPixel=%d cbLine=%d pVBox->base=%p pPixmap->drawable.width=%d pPixmap->drawable.height=%d\n",
253e07dc26bSmrg              (void *)pPixmap, adjustedWidth, height, pScrn->depth,
254e07dc26bSmrg              pScrn->bitsPerPixel, cbLine, pVBox->base,
255e07dc26bSmrg              pPixmap->drawable.width, pPixmap->drawable.height);
256e07dc26bSmrg    if (   adjustedWidth != pPixmap->drawable.width
257e07dc26bSmrg        || height != pPixmap->drawable.height)
258e07dc26bSmrg    {
259e07dc26bSmrg        if (   adjustedWidth > VBOX_VIDEO_MAX_VIRTUAL || height > VBOX_VIDEO_MAX_VIRTUAL
260e07dc26bSmrg            || (unsigned)cbLine * (unsigned)height >= pVBox->cbFBMax)
261e07dc26bSmrg        {
262e07dc26bSmrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
263e07dc26bSmrg                       "Virtual framebuffer %dx%d too large.  For information, video memory: %u Kb.\n",
264e07dc26bSmrg                       adjustedWidth, height, (unsigned) pVBox->cbFBMax / 1024);
265e07dc26bSmrg            return FALSE;
266e07dc26bSmrg        }
267e07dc26bSmrg        if (pScrn->vtSema)
268e07dc26bSmrg            vbvxClearVRAM(pScrn, ((size_t)pScrn->virtualX) * pScrn->virtualY * (pScrn->bitsPerPixel / 8),
269e07dc26bSmrg                          ((size_t)adjustedWidth) * height * (pScrn->bitsPerPixel / 8));
270e07dc26bSmrg        pScreen->ModifyPixmapHeader(pPixmap, adjustedWidth, height, pScrn->depth, pScrn->bitsPerPixel, cbLine, pVBox->base);
271e07dc26bSmrg    }
272e07dc26bSmrg    pScrn->displayWidth = pScrn->virtualX = adjustedWidth;
273e07dc26bSmrg    pScrn->virtualY = height;
274e07dc26bSmrg    return TRUE;
275e07dc26bSmrg}
276e07dc26bSmrg
277e07dc26bSmrg#ifndef VBOXVIDEO_13
278e07dc26bSmrg/** Set a video mode to the hardware, RandR 1.1 version.
279e07dc26bSmrg *
280e07dc26bSmrg * Since we no longer do virtual frame buffers, adjust the screen pixmap
281e07dc26bSmrg * dimensions to match.  The "override" parameters are for when we received a
282e07dc26bSmrg * mode hint while switched to a virtual terminal.  In this case VBoxClient will
283e07dc26bSmrg * have told us about the mode, but not yet been able to do a mode switch using
284e07dc26bSmrg * RandR.  We solve this by setting the requested mode to the host but keeping
285e07dc26bSmrg * the virtual frame-
286e07dc26bSmrg * buffer matching what the X server expects. */
287e07dc26bSmrgstatic void setModeRandR11(ScrnInfoPtr pScrn, DisplayModePtr pMode, Bool fScreenInitTime, Bool fEnterVTTime,
288e07dc26bSmrg                           int cXOverRide, int cYOverRide)
289e07dc26bSmrg{
290e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
291e07dc26bSmrg    struct vbvxFrameBuffer frameBuffer = { 0, 0, pMode->HDisplay, pMode->VDisplay, pScrn->bitsPerPixel};
292e07dc26bSmrg    int cXPhysical = cXOverRide > 0 ? min(cXOverRide, pMode->HDisplay) : pMode->HDisplay;
293e07dc26bSmrg    int cYPhysical = cYOverRide > 0 ? min(cYOverRide, pMode->VDisplay) : pMode->VDisplay;
294e07dc26bSmrg
295e07dc26bSmrg    pVBox->pScreens[0].aScreenLocation.cx = pMode->HDisplay;
296e07dc26bSmrg    pVBox->pScreens[0].aScreenLocation.cy = pMode->VDisplay;
297e07dc26bSmrg    if (fScreenInitTime)
298e07dc26bSmrg    {
299e07dc26bSmrg        /* The screen structure is not fully set up yet, so do not touch it. */
300e07dc26bSmrg        pScrn->displayWidth = pScrn->virtualX = pMode->HDisplay;
301e07dc26bSmrg        pScrn->virtualY = pMode->VDisplay;
302e07dc26bSmrg    }
303e07dc26bSmrg    else
304e07dc26bSmrg    {
305e07dc26bSmrg        xf86ScrnToScreen(pScrn)->width = pMode->HDisplay;
306e07dc26bSmrg        xf86ScrnToScreen(pScrn)->height = pMode->VDisplay;
307e07dc26bSmrg        /* This prevents a crash in CentOS 3.  I was unable to debug it to
308e07dc26bSmrg         * satisfaction, partly due to the lack of symbols.  My guess is that
309e07dc26bSmrg         * pScrn->ModifyPixmapHeader() expects certain things to be set up when
310e07dc26bSmrg         * it sees pScrn->vtSema set to true which are not quite done at this
311e07dc26bSmrg         * point of the VT switch. */
312e07dc26bSmrg        if (fEnterVTTime)
313e07dc26bSmrg            pScrn->vtSema = FALSE;
314e07dc26bSmrg        adjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
315e07dc26bSmrg        if (fEnterVTTime)
316e07dc26bSmrg            pScrn->vtSema = TRUE;
317e07dc26bSmrg    }
318e07dc26bSmrg    if (pMode->HDisplay != 0 && pMode->VDisplay != 0 && pScrn->vtSema)
319e07dc26bSmrg        vbvxSetMode(pScrn, 0, cXPhysical, cYPhysical, 0, 0, true, true, &frameBuffer);
320e07dc26bSmrg    pScrn->currentMode = pMode;
321e07dc26bSmrg}
322e07dc26bSmrg#endif
323e07dc26bSmrg
324e07dc26bSmrg#ifdef VBOXVIDEO_13
325e07dc26bSmrg/* X.org 1.3+ mode-setting support ******************************************/
326e07dc26bSmrg
327e07dc26bSmrg/** Set a video mode to the hardware, RandR 1.2 version.  If this is the first
328e07dc26bSmrg * screen, re-set the current mode for all others (the offset for the first
329e07dc26bSmrg * screen is always treated as zero by the hardware, so all other screens need
330e07dc26bSmrg * to be changed to compensate for any changes!).  The mode to set is taken
331e07dc26bSmrg * from the X.Org Crtc structure. */
332e07dc26bSmrgstatic void setModeRandR12(ScrnInfoPtr pScrn, unsigned cScreen)
333e07dc26bSmrg{
334e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
335e07dc26bSmrg    unsigned i;
336e07dc26bSmrg    struct vbvxFrameBuffer frameBuffer = { pVBox->pScreens[0].paCrtcs->x, pVBox->pScreens[0].paCrtcs->y, pScrn->virtualX,
337e07dc26bSmrg                                           pScrn->virtualY, pScrn->bitsPerPixel };
338e07dc26bSmrg    unsigned cFirst = cScreen;
339e07dc26bSmrg    unsigned cLast = cScreen != 0 ? cScreen + 1 : pVBox->cScreens;
340e07dc26bSmrg    int originalX, originalY;
341e07dc26bSmrg
342e07dc26bSmrg    /* Check that this code cannot trigger the resizing bug in X.Org Server 1.3.
343e07dc26bSmrg     * See the work-around in ScreenInit. */
344e07dc26bSmrg    xf86RandR12GetOriginalVirtualSize(pScrn, &originalX, &originalY);
345e07dc26bSmrg    AssertMsg(originalX == VBOX_VIDEO_MAX_VIRTUAL && originalY == VBOX_VIDEO_MAX_VIRTUAL, ("OriginalSize=%dx%d",
346e07dc26bSmrg               originalX, originalY));
347e07dc26bSmrg    for (i = cFirst; i < cLast; ++i)
348e07dc26bSmrg        if (pVBox->pScreens[i].paCrtcs->mode.HDisplay != 0 && pVBox->pScreens[i].paCrtcs->mode.VDisplay != 0 && pScrn->vtSema)
349e07dc26bSmrg            vbvxSetMode(pScrn, i, pVBox->pScreens[i].paCrtcs->mode.HDisplay, pVBox->pScreens[i].paCrtcs->mode.VDisplay,
350e07dc26bSmrg                        pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y, pVBox->pScreens[i].fPowerOn,
351e07dc26bSmrg                        pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected, &frameBuffer);
352e07dc26bSmrg}
353e07dc26bSmrg
354e07dc26bSmrg/** Wrapper around setModeRandR12() to avoid exposing non-obvious semantics.
355e07dc26bSmrg */
356e07dc26bSmrgstatic void setAllModesRandR12(ScrnInfoPtr pScrn)
357e07dc26bSmrg{
358e07dc26bSmrg    setModeRandR12(pScrn, 0);
359e07dc26bSmrg}
360e07dc26bSmrg
361e07dc26bSmrg/* For descriptions of these functions and structures, see
362e07dc26bSmrg   hw/xfree86/modes/xf86Crtc.h and hw/xfree86/modes/xf86Modes.h in the
363e07dc26bSmrg   X.Org source tree. */
364e07dc26bSmrg
365e07dc26bSmrgstatic Bool vbox_config_resize(ScrnInfoPtr pScrn, int cw, int ch)
366e07dc26bSmrg{
367e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
368e07dc26bSmrg    Bool rc;
369e07dc26bSmrg    unsigned i;
370e07dc26bSmrg
371e07dc26bSmrg    TRACE_LOG("width=%d, height=%d\n", cw, ch);
372e07dc26bSmrg    rc = adjustScreenPixmap(pScrn, cw, ch);
373e07dc26bSmrg    /* Power-on all screens (the server expects this) and set the new pitch to them. */
374e07dc26bSmrg    for (i = 0; i < pVBox->cScreens; ++i)
375e07dc26bSmrg        pVBox->pScreens[i].fPowerOn = true;
376e07dc26bSmrg    setAllModesRandR12(pScrn);
377e07dc26bSmrg    vbvxSetSolarisMouseRange(cw, ch);
378e07dc26bSmrg    return rc;
379e07dc26bSmrg}
380e07dc26bSmrg
381e07dc26bSmrgstatic const xf86CrtcConfigFuncsRec VBOXCrtcConfigFuncs = {
382e07dc26bSmrg    vbox_config_resize
383e07dc26bSmrg};
384e07dc26bSmrg
385e07dc26bSmrgstatic void
386e07dc26bSmrgvbox_crtc_dpms(xf86CrtcPtr crtc, int mode)
387e07dc26bSmrg{
388e07dc26bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
389e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
390e07dc26bSmrg    unsigned cDisplay = (uintptr_t)crtc->driver_private;
391e07dc26bSmrg
392e07dc26bSmrg    TRACE_LOG("mode=%d\n", mode);
393e07dc26bSmrg    pVBox->pScreens[cDisplay].fPowerOn = (mode != DPMSModeOff);
394e07dc26bSmrg    setModeRandR12(pScrn, cDisplay);
395e07dc26bSmrg}
396e07dc26bSmrg
397e07dc26bSmrgstatic Bool
398e07dc26bSmrgvbox_crtc_lock (xf86CrtcPtr crtc)
399e07dc26bSmrg{ RT_NOREF(crtc); return FALSE; }
400e07dc26bSmrg
401e07dc26bSmrg
402e07dc26bSmrg/* We use this function to check whether the X server owns the active virtual
403e07dc26bSmrg * terminal before attempting a mode switch, since the RandR extension isn't
404e07dc26bSmrg * very dilligent here, which can mean crashes if we are unlucky.  This is
405e07dc26bSmrg * not the way it the function is intended - it is meant for reporting modes
406e07dc26bSmrg * which the hardware can't handle.  I hope that this won't confuse any clients
407e07dc26bSmrg * connecting to us. */
408e07dc26bSmrgstatic Bool
409e07dc26bSmrgvbox_crtc_mode_fixup (xf86CrtcPtr crtc, DisplayModePtr mode,
410e07dc26bSmrg                      DisplayModePtr adjusted_mode)
411e07dc26bSmrg{ RT_NOREF(crtc, mode, adjusted_mode); return TRUE; }
412e07dc26bSmrg
413e07dc26bSmrgstatic void
414e07dc26bSmrgvbox_crtc_stub (xf86CrtcPtr crtc)
415e07dc26bSmrg{ RT_NOREF(crtc); }
416e07dc26bSmrg
417e07dc26bSmrgstatic void
418e07dc26bSmrgvbox_crtc_mode_set (xf86CrtcPtr crtc, DisplayModePtr mode,
419e07dc26bSmrg                    DisplayModePtr adjusted_mode, int x, int y)
420e07dc26bSmrg{
421e07dc26bSmrg    RT_NOREF(mode);
422e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(crtc->scrn);
423e07dc26bSmrg    unsigned cDisplay = (uintptr_t)crtc->driver_private;
424e07dc26bSmrg
425e07dc26bSmrg    TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name,
426e07dc26bSmrg           adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
427e07dc26bSmrg    pVBox->pScreens[cDisplay].fPowerOn = true;
428e07dc26bSmrg    pVBox->pScreens[cDisplay].aScreenLocation.cx = adjusted_mode->HDisplay;
429e07dc26bSmrg    pVBox->pScreens[cDisplay].aScreenLocation.cy = adjusted_mode->VDisplay;
430e07dc26bSmrg    pVBox->pScreens[cDisplay].aScreenLocation.x = x;
431e07dc26bSmrg    pVBox->pScreens[cDisplay].aScreenLocation.y = y;
432e07dc26bSmrg    setModeRandR12(crtc->scrn, cDisplay);
433e07dc26bSmrg}
434e07dc26bSmrg
435e07dc26bSmrgstatic void
436e07dc26bSmrgvbox_crtc_gamma_set (xf86CrtcPtr crtc, CARD16 *red,
437e07dc26bSmrg                     CARD16 *green, CARD16 *blue, int size)
438e07dc26bSmrg{ RT_NOREF(crtc, red, green, blue, size); }
439e07dc26bSmrg
440e07dc26bSmrgstatic void *
441e07dc26bSmrgvbox_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
442e07dc26bSmrg{ RT_NOREF(crtc, width, height); return NULL; }
443e07dc26bSmrg
444e07dc26bSmrgstatic const xf86CrtcFuncsRec VBOXCrtcFuncs = {
445e07dc26bSmrg    .dpms = vbox_crtc_dpms,
446e07dc26bSmrg    .save = NULL, /* These two are never called by the server. */
447e07dc26bSmrg    .restore = NULL,
448e07dc26bSmrg    .lock = vbox_crtc_lock,
449e07dc26bSmrg    .unlock = NULL, /* This will not be invoked if lock returns FALSE. */
450e07dc26bSmrg    .mode_fixup = vbox_crtc_mode_fixup,
451e07dc26bSmrg    .prepare = vbox_crtc_stub,
452e07dc26bSmrg    .mode_set = vbox_crtc_mode_set,
453e07dc26bSmrg    .commit = vbox_crtc_stub,
454e07dc26bSmrg    .gamma_set = vbox_crtc_gamma_set,
455e07dc26bSmrg    .shadow_allocate = vbox_crtc_shadow_allocate,
456e07dc26bSmrg    .shadow_create = NULL, /* These two should not be invoked if allocate
457e07dc26bSmrg                              returns NULL. */
458e07dc26bSmrg    .shadow_destroy = NULL,
459e07dc26bSmrg    .set_cursor_colors = NULL, /* We are still using the old cursor API. */
460e07dc26bSmrg    .set_cursor_position = NULL,
461e07dc26bSmrg    .show_cursor = NULL,
462e07dc26bSmrg    .hide_cursor = NULL,
463e07dc26bSmrg    .load_cursor_argb = NULL,
464e07dc26bSmrg    .destroy = vbox_crtc_stub
465e07dc26bSmrg};
466e07dc26bSmrg
467e07dc26bSmrgstatic void
468e07dc26bSmrgvbox_output_stub (xf86OutputPtr output)
469e07dc26bSmrg{ RT_NOREF(output); }
470e07dc26bSmrg
471e07dc26bSmrgstatic void
472e07dc26bSmrgvbox_output_dpms (xf86OutputPtr output, int mode)
473e07dc26bSmrg{
474e07dc26bSmrg    RT_NOREF(output, mode);
475e07dc26bSmrg}
476e07dc26bSmrg
477e07dc26bSmrgstatic int
478e07dc26bSmrgvbox_output_mode_valid (xf86OutputPtr output, DisplayModePtr mode)
479e07dc26bSmrg{
480e07dc26bSmrg    return MODE_OK;
481e07dc26bSmrg}
482e07dc26bSmrg
483e07dc26bSmrgstatic Bool
484e07dc26bSmrgvbox_output_mode_fixup (xf86OutputPtr output, DisplayModePtr mode,
485e07dc26bSmrg                        DisplayModePtr adjusted_mode)
486e07dc26bSmrg{ RT_NOREF(output, mode, adjusted_mode); return TRUE; }
487e07dc26bSmrg
488e07dc26bSmrgstatic void
489e07dc26bSmrgvbox_output_mode_set (xf86OutputPtr output, DisplayModePtr mode,
490e07dc26bSmrg                        DisplayModePtr adjusted_mode)
491e07dc26bSmrg{ RT_NOREF(output, mode, adjusted_mode); }
492e07dc26bSmrg
493e07dc26bSmrgstatic xf86OutputStatus
494e07dc26bSmrgvbox_output_detect (xf86OutputPtr output)
495e07dc26bSmrg{
496e07dc26bSmrg    ScrnInfoPtr pScrn = output->scrn;
497e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
498e07dc26bSmrg    uint32_t iScreen = (uintptr_t)output->driver_private;
499e07dc26bSmrg    return   pVBox->pScreens[iScreen].afConnected
500e07dc26bSmrg           ? XF86OutputStatusConnected : XF86OutputStatusDisconnected;
501e07dc26bSmrg}
502e07dc26bSmrg
503e07dc26bSmrgstatic DisplayModePtr vbox_output_add_mode(VBOXPtr pVBox, DisplayModePtr *pModes, const char *pszName, int x, int y,
504e07dc26bSmrg                                           Bool isPreferred, Bool isUserDef)
505e07dc26bSmrg{
506e07dc26bSmrg    TRACE_LOG("pszName=%s, x=%d, y=%d\n", pszName ? pszName : "(null)", x, y);
507e07dc26bSmrg    DisplayModePtr pMode = xnfcalloc(1, sizeof(DisplayModeRec));
508e07dc26bSmrg    int cRefresh = 60;
509e07dc26bSmrg
510e07dc26bSmrg    pMode->status        = MODE_OK;
511e07dc26bSmrg    /* We don't ask the host whether it likes user defined modes,
512e07dc26bSmrg     * as we assume that the user really wanted that mode. */
513e07dc26bSmrg    pMode->type          = isUserDef ? M_T_USERDEF : M_T_BUILTIN;
514e07dc26bSmrg    if (isPreferred)
515e07dc26bSmrg        pMode->type     |= M_T_PREFERRED;
516e07dc26bSmrg    /* Older versions of VBox only support screen widths which are a multiple
517e07dc26bSmrg     * of 8 */
518e07dc26bSmrg    if (pVBox->fAnyX)
519e07dc26bSmrg        pMode->HDisplay  = x;
520e07dc26bSmrg    else
521e07dc26bSmrg        pMode->HDisplay  = x & ~7;
522e07dc26bSmrg    pMode->HSyncStart    = pMode->HDisplay + 2;
523e07dc26bSmrg    pMode->HSyncEnd      = pMode->HDisplay + 4;
524e07dc26bSmrg    pMode->HTotal        = pMode->HDisplay + 6;
525e07dc26bSmrg    pMode->VDisplay      = y;
526e07dc26bSmrg    pMode->VSyncStart    = pMode->VDisplay + 2;
527e07dc26bSmrg    pMode->VSyncEnd      = pMode->VDisplay + 4;
528e07dc26bSmrg    pMode->VTotal        = pMode->VDisplay + 6;
529e07dc26bSmrg    pMode->Clock         = pMode->HTotal * pMode->VTotal * cRefresh / 1000; /* kHz */
530e07dc26bSmrg    if (NULL == pszName) {
531e07dc26bSmrg        xf86SetModeDefaultName(pMode);
532e07dc26bSmrg    } else {
533e07dc26bSmrg        pMode->name          = xnfstrdup(pszName);
534e07dc26bSmrg    }
535e07dc26bSmrg    *pModes = xf86ModesAdd(*pModes, pMode);
536e07dc26bSmrg    return pMode;
537e07dc26bSmrg}
538e07dc26bSmrg
539e07dc26bSmrgstatic DisplayModePtr
540e07dc26bSmrgvbox_output_get_modes (xf86OutputPtr output)
541e07dc26bSmrg{
542e07dc26bSmrg    DisplayModePtr pModes = NULL;
543e07dc26bSmrg    DisplayModePtr pPreferred = NULL;
544e07dc26bSmrg    ScrnInfoPtr pScrn = output->scrn;
545e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
546e07dc26bSmrg
547e07dc26bSmrg    TRACE_ENTRY();
548e07dc26bSmrg    uint32_t iScreen = (uintptr_t)output->driver_private;
549e07dc26bSmrg    pPreferred = vbox_output_add_mode(pVBox, &pModes, NULL,
550e07dc26bSmrg                         RT_CLAMP(pVBox->pScreens[iScreen].aPreferredSize.cx, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL),
551e07dc26bSmrg                         RT_CLAMP(pVBox->pScreens[iScreen].aPreferredSize.cy, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL),
552e07dc26bSmrg                         TRUE, FALSE);
553e07dc26bSmrg    vbox_output_add_mode(pVBox, &pModes, NULL, 2560, 1600, FALSE, FALSE);
554e07dc26bSmrg    vbox_output_add_mode(pVBox, &pModes, NULL, 2560, 1440, FALSE, FALSE);
555e07dc26bSmrg    vbox_output_add_mode(pVBox, &pModes, NULL, 2048, 1536, FALSE, FALSE);
556e07dc26bSmrg    vbox_output_add_mode(pVBox, &pModes, NULL, 1920, 1600, FALSE, FALSE);
557e07dc26bSmrg    vbox_output_add_mode(pVBox, &pModes, NULL, 1920, 1080, FALSE, FALSE);
558e07dc26bSmrg    vbox_output_add_mode(pVBox, &pModes, NULL, 1680, 1050, FALSE, FALSE);
559e07dc26bSmrg    vbox_output_add_mode(pVBox, &pModes, NULL, 1600, 1200, FALSE, FALSE);
560e07dc26bSmrg    vbox_output_add_mode(pVBox, &pModes, NULL, 1400, 1050, FALSE, FALSE);
561e07dc26bSmrg    vbox_output_add_mode(pVBox, &pModes, NULL, 1280, 1024, FALSE, FALSE);
562e07dc26bSmrg    vbox_output_add_mode(pVBox, &pModes, NULL, 1024, 768,  FALSE, FALSE);
563e07dc26bSmrg    vbox_output_add_mode(pVBox, &pModes, NULL, 800,  600,  FALSE, FALSE);
564e07dc26bSmrg    vbox_output_add_mode(pVBox, &pModes, NULL, 640,  480,  FALSE, FALSE);
565e07dc26bSmrg    VBOXEDIDSet(output, pPreferred);
566e07dc26bSmrg    TRACE_EXIT();
567e07dc26bSmrg    return pModes;
568e07dc26bSmrg}
569e07dc26bSmrg
570e07dc26bSmrgstatic const xf86OutputFuncsRec VBOXOutputFuncs = {
571e07dc26bSmrg    .create_resources = vbox_output_stub,
572e07dc26bSmrg    .dpms = vbox_output_dpms,
573e07dc26bSmrg    .save = NULL, /* These two are never called by the server. */
574e07dc26bSmrg    .restore = NULL,
575e07dc26bSmrg    .mode_valid = vbox_output_mode_valid,
576e07dc26bSmrg    .mode_fixup = vbox_output_mode_fixup,
577e07dc26bSmrg    .prepare = vbox_output_stub,
578e07dc26bSmrg    .commit = vbox_output_stub,
579e07dc26bSmrg    .mode_set = vbox_output_mode_set,
580e07dc26bSmrg    .detect = vbox_output_detect,
581e07dc26bSmrg    .get_modes = vbox_output_get_modes,
582e07dc26bSmrg#ifdef RANDR_12_INTERFACE
583e07dc26bSmrg     .set_property = NULL,
584e07dc26bSmrg#endif
585e07dc26bSmrg    .destroy = vbox_output_stub
586e07dc26bSmrg};
587e07dc26bSmrg#endif /* VBOXVIDEO_13 */
588e07dc26bSmrg
589e07dc26bSmrg/* Module loader interface */
590e07dc26bSmrgstatic MODULESETUPPROTO(vboxSetup);
591e07dc26bSmrg
592e07dc26bSmrgstatic XF86ModuleVersionInfo vboxVersionRec =
593e07dc26bSmrg{
594e07dc26bSmrg    VBOX_DRIVER_NAME,
595e07dc26bSmrg    "Oracle Corporation",
596e07dc26bSmrg    MODINFOSTRING1,
597e07dc26bSmrg    MODINFOSTRING2,
598e07dc26bSmrg#ifdef XORG_7X
599e07dc26bSmrg    XORG_VERSION_CURRENT,
600e07dc26bSmrg#else
601e07dc26bSmrg    XF86_VERSION_CURRENT,
602e07dc26bSmrg#endif
603e07dc26bSmrg    1,                          /* Module major version. Xorg-specific */
604e07dc26bSmrg    0,                          /* Module minor version. Xorg-specific */
605e07dc26bSmrg    1,                          /* Module patchlevel. Xorg-specific */
606e07dc26bSmrg    ABI_CLASS_VIDEODRV,         /* This is a video driver */
607e07dc26bSmrg    ABI_VIDEODRV_VERSION,
608e07dc26bSmrg    MOD_CLASS_VIDEODRV,
609e07dc26bSmrg    {0, 0, 0, 0}
610e07dc26bSmrg};
611e07dc26bSmrg
612e07dc26bSmrg/*
613e07dc26bSmrg * This data is accessed by the loader.  The name must be the module name
614e07dc26bSmrg * followed by "ModuleData".
615e07dc26bSmrg */
616e07dc26bSmrg#ifdef XORG_7X
617e07dc26bSmrg_X_EXPORT
618e07dc26bSmrg#endif
619e07dc26bSmrgXF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };
620e07dc26bSmrg
621e07dc26bSmrgstatic pointer
622e07dc26bSmrgvboxSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
623e07dc26bSmrg{
624e07dc26bSmrg    static Bool Initialised = FALSE;
625e07dc26bSmrg    RT_NOREF(Options, ErrorMinor);
626e07dc26bSmrg
627e07dc26bSmrg    if (!Initialised)
628e07dc26bSmrg    {
629e07dc26bSmrg        Initialised = TRUE;
630e07dc26bSmrg#ifdef PCIACCESS
631e07dc26bSmrg        xf86AddDriver(&VBOXVIDEO, Module, HaveDriverFuncs);
632e07dc26bSmrg#else
633e07dc26bSmrg        xf86AddDriver(&VBOXVIDEO, Module, 0);
634e07dc26bSmrg#endif
635e07dc26bSmrg#ifndef XORG_7X
636e07dc26bSmrg        LoaderRefSymLists(fbSymbols,
637e07dc26bSmrg                          shadowfbSymbols,
638e07dc26bSmrg                          ramdacSymbols,
639e07dc26bSmrg                          vgahwSymbols,
640e07dc26bSmrg                          NULL);
641e07dc26bSmrg#endif
642e07dc26bSmrg        xf86Msg(X_CONFIG, "Load address of symbol \"VBOXVIDEO\" is %p\n",
643e07dc26bSmrg                (void *)&VBOXVIDEO);
644e07dc26bSmrg        return (pointer)TRUE;
645e07dc26bSmrg    }
646e07dc26bSmrg
647e07dc26bSmrg    if (ErrorMajor)
648e07dc26bSmrg        *ErrorMajor = LDR_ONCEONLY;
649e07dc26bSmrg    return (NULL);
650e07dc26bSmrg}
651e07dc26bSmrg
652e07dc26bSmrg
653e07dc26bSmrgstatic const OptionInfoRec *
654e07dc26bSmrgVBOXAvailableOptions(int chipid, int busid)
655e07dc26bSmrg{
656e07dc26bSmrg    RT_NOREF(chipid, busid);
657e07dc26bSmrg    return (VBOXOptions);
658e07dc26bSmrg}
659e07dc26bSmrg
660e07dc26bSmrgstatic void
661e07dc26bSmrgVBOXIdentify(int flags)
662e07dc26bSmrg{
663e07dc26bSmrg    RT_NOREF(flags);
664e07dc26bSmrg    xf86PrintChipsets(VBOX_NAME, "guest driver for VirtualBox", VBOXChipsets);
665e07dc26bSmrg}
666e07dc26bSmrg
667e07dc26bSmrg#ifndef XF86_SCRN_INTERFACE
668e07dc26bSmrg# define SCRNINDEXAPI(pfn) pfn ## Index
669e07dc26bSmrgstatic Bool VBOXScreenInitIndex(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
670e07dc26bSmrg{
671e07dc26bSmrg    RT_NOREF(scrnIndex);
672e07dc26bSmrg    return VBOXScreenInit(pScreen, argc, argv);
673e07dc26bSmrg}
674e07dc26bSmrg
675e07dc26bSmrgstatic Bool VBOXEnterVTIndex(int scrnIndex, int flags)
676e07dc26bSmrg{ RT_NOREF(flags); return VBOXEnterVT(xf86Screens[scrnIndex]); }
677e07dc26bSmrg
678e07dc26bSmrgstatic void VBOXLeaveVTIndex(int scrnIndex, int flags)
679e07dc26bSmrg{ RT_NOREF(flags); VBOXLeaveVT(xf86Screens[scrnIndex]); }
680e07dc26bSmrg
681e07dc26bSmrgstatic Bool VBOXCloseScreenIndex(int scrnIndex, ScreenPtr pScreen)
682e07dc26bSmrg{ RT_NOREF(scrnIndex); return VBOXCloseScreen(pScreen); }
683e07dc26bSmrg
684e07dc26bSmrgstatic Bool VBOXSwitchModeIndex(int scrnIndex, DisplayModePtr pMode, int flags)
685e07dc26bSmrg{ RT_NOREF(flags); return VBOXSwitchMode(xf86Screens[scrnIndex], pMode); }
686e07dc26bSmrg
687e07dc26bSmrgstatic void VBOXAdjustFrameIndex(int scrnIndex, int x, int y, int flags)
688e07dc26bSmrg{ RT_NOREF(flags); VBOXAdjustFrame(xf86Screens[scrnIndex], x, y); }
689e07dc26bSmrg
690e07dc26bSmrgstatic void VBOXFreeScreenIndex(int scrnIndex, int flags)
691e07dc26bSmrg{ RT_NOREF(flags); VBOXFreeScreen(xf86Screens[scrnIndex]); }
692e07dc26bSmrg# else
693e07dc26bSmrg# define SCRNINDEXAPI(pfn) pfn
694e07dc26bSmrg#endif /* XF86_SCRN_INTERFACE */
695e07dc26bSmrg
696e07dc26bSmrgstatic void setScreenFunctions(ScrnInfoPtr pScrn, xf86ProbeProc pfnProbe)
697e07dc26bSmrg{
698e07dc26bSmrg    pScrn->driverVersion = VBOX_VERSION;
699e07dc26bSmrg    pScrn->driverName    = VBOX_DRIVER_NAME;
700e07dc26bSmrg    pScrn->name          = VBOX_NAME;
701e07dc26bSmrg    pScrn->Probe         = pfnProbe;
702e07dc26bSmrg    pScrn->PreInit       = VBOXPreInit;
703e07dc26bSmrg    pScrn->ScreenInit    = SCRNINDEXAPI(VBOXScreenInit);
704e07dc26bSmrg    pScrn->SwitchMode    = SCRNINDEXAPI(VBOXSwitchMode);
705e07dc26bSmrg    pScrn->AdjustFrame   = SCRNINDEXAPI(VBOXAdjustFrame);
706e07dc26bSmrg    pScrn->EnterVT       = SCRNINDEXAPI(VBOXEnterVT);
707e07dc26bSmrg    pScrn->LeaveVT       = SCRNINDEXAPI(VBOXLeaveVT);
708e07dc26bSmrg    pScrn->FreeScreen    = SCRNINDEXAPI(VBOXFreeScreen);
709e07dc26bSmrg}
710e07dc26bSmrg
711e07dc26bSmrg/*
712e07dc26bSmrg * One of these functions is called once, at the start of the first server
713e07dc26bSmrg * generation to do a minimal probe for supported hardware.
714e07dc26bSmrg */
715e07dc26bSmrg
716e07dc26bSmrg#ifdef PCIACCESS
717e07dc26bSmrgstatic Bool
718e07dc26bSmrgVBOXPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,
719e07dc26bSmrg             intptr_t match_data)
720e07dc26bSmrg{
721e07dc26bSmrg    ScrnInfoPtr pScrn;
722e07dc26bSmrg    int drmFd;
723e07dc26bSmrg
724e07dc26bSmrg    TRACE_ENTRY();
725e07dc26bSmrg
726e07dc26bSmrg    drmFd = open("/dev/dri/card0", O_RDWR, 0);
727e07dc26bSmrg    if (drmFd >= 0)
728e07dc26bSmrg    {
729e07dc26bSmrg        xf86Msg(X_INFO, "vboxvideo: kernel driver found, not loading.\n");
730e07dc26bSmrg        close(drmFd);
731e07dc26bSmrg        return FALSE;
732e07dc26bSmrg    }
733e07dc26bSmrg    /* It is safe to call this, as the X server enables I/O access before
734e07dc26bSmrg     * calling the probe call-backs. */
735e07dc26bSmrg    if (!xf86EnableIO())
736e07dc26bSmrg    {
737e07dc26bSmrg        xf86Msg(X_INFO, "vboxvideo: this driver requires direct hardware access.  You may wish to use the kernel driver instead.\n");
738e07dc26bSmrg        return FALSE;
739e07dc26bSmrg    }
740e07dc26bSmrg    pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, VBOXPCIchipsets,
741e07dc26bSmrg                                NULL, NULL, NULL, NULL, NULL);
742e07dc26bSmrg    if (pScrn != NULL) {
743e07dc26bSmrg        VBOXPtr pVBox;
744e07dc26bSmrg
745e07dc26bSmrg        VBOXSetRec(pScrn);
746e07dc26bSmrg        pVBox = VBOXGetRec(pScrn);
747e07dc26bSmrg        if (!pVBox)
748e07dc26bSmrg            return FALSE;
749e07dc26bSmrg        setScreenFunctions(pScrn, NULL);
750e07dc26bSmrg        pVBox->pciInfo = dev;
751e07dc26bSmrg    }
752e07dc26bSmrg
753e07dc26bSmrg    TRACE_LOG("returning %s\n", pScrn == NULL ? "false" : "true");
754e07dc26bSmrg    return (pScrn != NULL);
755e07dc26bSmrg}
756e07dc26bSmrg#endif
757e07dc26bSmrg
758e07dc26bSmrg#ifndef PCIACCESS
759e07dc26bSmrgstatic Bool
760e07dc26bSmrgVBOXProbe(DriverPtr drv, int flags)
761e07dc26bSmrg{
762e07dc26bSmrg    Bool foundScreen = FALSE;
763e07dc26bSmrg    int numDevSections;
764e07dc26bSmrg    GDevPtr *devSections;
765e07dc26bSmrg
766e07dc26bSmrg    /*
767e07dc26bSmrg     * Find the config file Device sections that match this
768e07dc26bSmrg     * driver, and return if there are none.
769e07dc26bSmrg     */
770e07dc26bSmrg    if ((numDevSections = xf86MatchDevice(VBOX_NAME,
771e07dc26bSmrg                      &devSections)) <= 0)
772e07dc26bSmrg    return (FALSE);
773e07dc26bSmrg
774e07dc26bSmrg    /* PCI BUS */
775e07dc26bSmrg    if (xf86GetPciVideoInfo())
776e07dc26bSmrg    {
777e07dc26bSmrg        int numUsed;
778e07dc26bSmrg        int *usedChips;
779e07dc26bSmrg        int i;
780e07dc26bSmrg        numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,
781e07dc26bSmrg                        VBOXChipsets, VBOXPCIchipsets,
782e07dc26bSmrg                        devSections, numDevSections,
783e07dc26bSmrg                        drv, &usedChips);
784e07dc26bSmrg        if (numUsed > 0)
785e07dc26bSmrg        {
786e07dc26bSmrg            if (flags & PROBE_DETECT)
787e07dc26bSmrg                foundScreen = TRUE;
788e07dc26bSmrg            else
789e07dc26bSmrg                for (i = 0; i < numUsed; i++)
790e07dc26bSmrg                {
791e07dc26bSmrg                    ScrnInfoPtr pScrn = NULL;
792e07dc26bSmrg                    /* Allocate a ScrnInfoRec  */
793e07dc26bSmrg                    if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
794e07dc26bSmrg                                     VBOXPCIchipsets,NULL,
795e07dc26bSmrg                                     NULL,NULL,NULL,NULL)))
796e07dc26bSmrg                    {
797e07dc26bSmrg                        setScreenFunctions(pScrn, VBOXProbe);
798e07dc26bSmrg                        foundScreen = TRUE;
799e07dc26bSmrg                    }
800e07dc26bSmrg                }
801e07dc26bSmrg            free(usedChips);
802e07dc26bSmrg        }
803e07dc26bSmrg    }
804e07dc26bSmrg    free(devSections);
805e07dc26bSmrg    return (foundScreen);
806e07dc26bSmrg}
807e07dc26bSmrg#endif
808e07dc26bSmrg
809e07dc26bSmrg
810e07dc26bSmrg/*
811e07dc26bSmrg * QUOTE from the XFree86 DESIGN document:
812e07dc26bSmrg *
813e07dc26bSmrg * The purpose of this function is to find out all the information
814e07dc26bSmrg * required to determine if the configuration is usable, and to initialise
815e07dc26bSmrg * those parts of the ScrnInfoRec that can be set once at the beginning of
816e07dc26bSmrg * the first server generation.
817e07dc26bSmrg *
818e07dc26bSmrg * (...)
819e07dc26bSmrg *
820e07dc26bSmrg * This includes probing for video memory, clocks, ramdac, and all other
821e07dc26bSmrg * HW info that is needed. It includes determining the depth/bpp/visual
822e07dc26bSmrg * and related info. It includes validating and determining the set of
823e07dc26bSmrg * video modes that will be used (and anything that is required to
824e07dc26bSmrg * determine that).
825e07dc26bSmrg *
826e07dc26bSmrg * This information should be determined in the least intrusive way
827e07dc26bSmrg * possible. The state of the HW must remain unchanged by this function.
828e07dc26bSmrg * Although video memory (including MMIO) may be mapped within this
829e07dc26bSmrg * function, it must be unmapped before returning.
830e07dc26bSmrg *
831e07dc26bSmrg * END QUOTE
832e07dc26bSmrg */
833e07dc26bSmrg
834e07dc26bSmrgstatic Bool
835e07dc26bSmrgVBOXPreInit(ScrnInfoPtr pScrn, int flags)
836e07dc26bSmrg{
837e07dc26bSmrg    VBOXPtr pVBox;
838e07dc26bSmrg    Gamma gzeros = {0.0, 0.0, 0.0};
839e07dc26bSmrg    rgb rzeros = {0, 0, 0};
840e07dc26bSmrg
841e07dc26bSmrg    TRACE_ENTRY();
842e07dc26bSmrg    /* Are we really starting the server, or is this just a dummy run? */
843e07dc26bSmrg    if (flags & PROBE_DETECT)
844e07dc26bSmrg        return (FALSE);
845e07dc26bSmrg
846e07dc26bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
847e07dc26bSmrg               "VirtualBox guest additions video driver version %d.%d\n",
848e07dc26bSmrg               VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR);
849e07dc26bSmrg
850e07dc26bSmrg    /* The ramdac module is needed for the hardware cursor. */
851e07dc26bSmrg    if (!xf86LoadSubModule(pScrn, "ramdac"))
852e07dc26bSmrg        return FALSE;
853e07dc26bSmrg
854e07dc26bSmrg    /* The framebuffer module. */
855e07dc26bSmrg    if (!xf86LoadSubModule(pScrn, "fb"))
856e07dc26bSmrg        return (FALSE);
857e07dc26bSmrg
858e07dc26bSmrg    if (!xf86LoadSubModule(pScrn, "shadowfb"))
859e07dc26bSmrg        return FALSE;
860e07dc26bSmrg
861e07dc26bSmrg    if (!xf86LoadSubModule(pScrn, "vgahw"))
862e07dc26bSmrg        return FALSE;
863e07dc26bSmrg
864e07dc26bSmrg    /* Get our private data from the ScrnInfoRec structure. */
865e07dc26bSmrg    VBOXSetRec(pScrn);
866e07dc26bSmrg    pVBox = VBOXGetRec(pScrn);
867e07dc26bSmrg    if (!pVBox)
868e07dc26bSmrg        return FALSE;
869e07dc26bSmrg
870e07dc26bSmrg    /* Entity information seems to mean bus information. */
871e07dc26bSmrg    pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
872e07dc26bSmrg
873e07dc26bSmrg#ifndef PCIACCESS
874e07dc26bSmrg    if (pVBox->pEnt->location.type != BUS_PCI)
875e07dc26bSmrg        return FALSE;
876e07dc26bSmrg
877e07dc26bSmrg    pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);
878e07dc26bSmrg    pVBox->pciTag = pciTag(pVBox->pciInfo->bus,
879e07dc26bSmrg                           pVBox->pciInfo->device,
880e07dc26bSmrg                           pVBox->pciInfo->func);
881e07dc26bSmrg#endif
882e07dc26bSmrg
883e07dc26bSmrg    /* Set up our ScrnInfoRec structure to describe our virtual
884e07dc26bSmrg       capabilities to X. */
885e07dc26bSmrg
886e07dc26bSmrg    pScrn->chipset = "vbox";
887e07dc26bSmrg    /** @note needed during colourmap initialisation */
888e07dc26bSmrg    pScrn->rgbBits = 8;
889e07dc26bSmrg
890e07dc26bSmrg    /* Let's create a nice, capable virtual monitor. */
891e07dc26bSmrg    pScrn->monitor = pScrn->confScreen->monitor;
892e07dc26bSmrg    pScrn->monitor->DDC = NULL;
893e07dc26bSmrg    pScrn->monitor->nHsync = 1;
894e07dc26bSmrg    pScrn->monitor->hsync[0].lo = 1;
895e07dc26bSmrg    pScrn->monitor->hsync[0].hi = 10000;
896e07dc26bSmrg    pScrn->monitor->nVrefresh = 1;
897e07dc26bSmrg    pScrn->monitor->vrefresh[0].lo = 1;
898e07dc26bSmrg    pScrn->monitor->vrefresh[0].hi = 100;
899e07dc26bSmrg
900e07dc26bSmrg    pScrn->progClock = TRUE;
901e07dc26bSmrg
902e07dc26bSmrg    /* Using the PCI information caused problems with non-powers-of-two
903e07dc26bSmrg       sized video RAM configurations */
904e07dc26bSmrg    pVBox->cbFBMax = VBoxVideoGetVRAMSize();
905e07dc26bSmrg    pScrn->videoRam = pVBox->cbFBMax / 1024;
906e07dc26bSmrg
907e07dc26bSmrg    /* Check if the chip restricts horizontal resolution or not. */
908e07dc26bSmrg    pVBox->fAnyX = VBoxVideoAnyWidthAllowed();
909e07dc26bSmrg
910e07dc26bSmrg    /* Set up clock information that will support all modes we need. */
911e07dc26bSmrg    pScrn->clockRanges = xnfcalloc(sizeof(ClockRange), 1);
912e07dc26bSmrg    pScrn->clockRanges->minClock = 1000;
913e07dc26bSmrg    pScrn->clockRanges->maxClock = 1000000000;
914e07dc26bSmrg    pScrn->clockRanges->clockIndex = -1;
915e07dc26bSmrg    pScrn->clockRanges->ClockMulFactor = 1;
916e07dc26bSmrg    pScrn->clockRanges->ClockDivFactor = 1;
917e07dc26bSmrg
918e07dc26bSmrg    if (!xf86SetDepthBpp(pScrn, 24, 0, 0, Support32bppFb))
919e07dc26bSmrg        return FALSE;
920e07dc26bSmrg    /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
921e07dc26bSmrg    if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
922e07dc26bSmrg    {
923e07dc26bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
924e07dc26bSmrg                   "The VBox additions only support 16 and 32bpp graphics modes\n");
925e07dc26bSmrg        return FALSE;
926e07dc26bSmrg    }
927e07dc26bSmrg    xf86PrintDepthBpp(pScrn);
928e07dc26bSmrg    vboxAddModes(pScrn);
929e07dc26bSmrg
930e07dc26bSmrg#ifdef VBOXVIDEO_13
931e07dc26bSmrg    pScrn->virtualX = VBOX_VIDEO_MAX_VIRTUAL;
932e07dc26bSmrg    pScrn->virtualY = VBOX_VIDEO_MAX_VIRTUAL;
933e07dc26bSmrg#else
934e07dc26bSmrg    /* We don't validate with xf86ValidateModes and xf86PruneModes as we
935e07dc26bSmrg     * already know what we like and what we don't. */
936e07dc26bSmrg
937e07dc26bSmrg    pScrn->currentMode = pScrn->modes;
938e07dc26bSmrg
939e07dc26bSmrg    /* Set the right virtual resolution. */
940e07dc26bSmrg    pScrn->virtualX = pScrn->bitsPerPixel == 16 ? (pScrn->currentMode->HDisplay + 1) & ~1 : pScrn->currentMode->HDisplay;
941e07dc26bSmrg    pScrn->virtualY = pScrn->currentMode->VDisplay;
942e07dc26bSmrg
943e07dc26bSmrg#endif /* !VBOXVIDEO_13 */
944e07dc26bSmrg
945e07dc26bSmrg    pScrn->displayWidth = pScrn->virtualX;
946e07dc26bSmrg
947e07dc26bSmrg    xf86PrintModes(pScrn);
948e07dc26bSmrg
949e07dc26bSmrg    /* VGA hardware initialisation */
950e07dc26bSmrg    if (!vgaHWGetHWRec(pScrn))
951e07dc26bSmrg        return FALSE;
952e07dc26bSmrg    /* Must be called before any VGA registers are saved or restored */
953e07dc26bSmrg    vgaHWSetStdFuncs(VGAHWPTR(pScrn));
954e07dc26bSmrg    vgaHWGetIOBase(VGAHWPTR(pScrn));
955e07dc26bSmrg
956e07dc26bSmrg    /* Colour weight - we always call this, since we are always in
957e07dc26bSmrg       truecolour. */
958e07dc26bSmrg    if (!xf86SetWeight(pScrn, rzeros, rzeros))
959e07dc26bSmrg        return (FALSE);
960e07dc26bSmrg
961e07dc26bSmrg    /* visual init */
962e07dc26bSmrg    if (!xf86SetDefaultVisual(pScrn, -1))
963e07dc26bSmrg        return (FALSE);
964e07dc26bSmrg
965e07dc26bSmrg    xf86SetGamma(pScrn, gzeros);
966e07dc26bSmrg
967e07dc26bSmrg    /* Set the DPI.  Perhaps we should read this from the host? */
968e07dc26bSmrg    xf86SetDpi(pScrn, 96, 96);
969e07dc26bSmrg
970e07dc26bSmrg    if (pScrn->memPhysBase == 0) {
971e07dc26bSmrg#ifdef PCIACCESS
972e07dc26bSmrg        pScrn->memPhysBase = pVBox->pciInfo->regions[0].base_addr;
973e07dc26bSmrg#else
974e07dc26bSmrg        pScrn->memPhysBase = pVBox->pciInfo->memBase[0];
975e07dc26bSmrg#endif
976e07dc26bSmrg        pScrn->fbOffset = 0;
977e07dc26bSmrg    }
978e07dc26bSmrg
979e07dc26bSmrg    TRACE_EXIT();
980e07dc26bSmrg    return (TRUE);
981e07dc26bSmrg}
982e07dc26bSmrg
983e07dc26bSmrg/**
984e07dc26bSmrg * Dummy function for setting the colour palette, which we actually never
985e07dc26bSmrg * touch.  However, the server still requires us to provide this.
986e07dc26bSmrg */
987e07dc26bSmrgstatic void
988e07dc26bSmrgvboxLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
989e07dc26bSmrg          LOCO *colors, VisualPtr pVisual)
990e07dc26bSmrg{
991e07dc26bSmrg    RT_NOREF(pScrn, numColors, indices, colors, pVisual);
992e07dc26bSmrg}
993e07dc26bSmrg
994e07dc26bSmrg/** Set the graphics and guest cursor support capabilities to the host if
995e07dc26bSmrg *  the user-space helper is running. */
996e07dc26bSmrgstatic void updateGraphicsCapability(ScrnInfoPtr pScrn, Bool hasVT)
997e07dc26bSmrg{
998e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
999e07dc26bSmrg
1000e07dc26bSmrg    if (!pVBox->fHaveHGSMIModeHints)
1001e07dc26bSmrg        return;
1002e07dc26bSmrg    VBoxHGSMISendCapsInfo(&pVBox->guestCtx,   hasVT
1003e07dc26bSmrg                                            ? VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION
1004e07dc26bSmrg                                            : VBVACAPS_DISABLE_CURSOR_INTEGRATION);
1005e07dc26bSmrg}
1006e07dc26bSmrg
1007e07dc26bSmrg#ifndef VBOXVIDEO_13
1008e07dc26bSmrg
1009e07dc26bSmrg#define PREFERRED_MODE_ATOM_NAME "VBOXVIDEO_PREFERRED_MODE"
1010e07dc26bSmrg
1011e07dc26bSmrgstatic void setSizesRandR11(ScrnInfoPtr pScrn)
1012e07dc26bSmrg{
1013e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
1014e07dc26bSmrg    DisplayModePtr pNewMode;
1015e07dc26bSmrg    int32_t propertyValue;
1016e07dc26bSmrg
1017e07dc26bSmrg    pNewMode = pScrn->modes != pScrn->currentMode ? pScrn->modes : pScrn->modes->next;
1018e07dc26bSmrg    pNewMode->HDisplay = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cx, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
1019e07dc26bSmrg    pNewMode->VDisplay = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cy, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
1020e07dc26bSmrg    propertyValue = (pNewMode->HDisplay << 16) + pNewMode->VDisplay;
1021e07dc26bSmrg    ChangeWindowProperty(ROOT_WINDOW(pScrn), MakeAtom(PREFERRED_MODE_ATOM_NAME,
1022e07dc26bSmrg                         sizeof(PREFERRED_MODE_ATOM_NAME) - 1, TRUE), XA_INTEGER, 32,
1023e07dc26bSmrg                         PropModeReplace, 1, &propertyValue, TRUE);
1024e07dc26bSmrg}
1025e07dc26bSmrg
1026e07dc26bSmrg#endif
1027e07dc26bSmrg
1028e07dc26bSmrgstatic void reprobeCursor(ScrnInfoPtr pScrn)
1029e07dc26bSmrg{
1030e07dc26bSmrg    if (ROOT_WINDOW(pScrn) == NULL)
1031e07dc26bSmrg        return;
1032e07dc26bSmrg#ifdef XF86_SCRN_INTERFACE
1033e07dc26bSmrg    pScrn->EnableDisableFBAccess(pScrn, FALSE);
1034e07dc26bSmrg    pScrn->EnableDisableFBAccess(pScrn, TRUE);
1035e07dc26bSmrg#else
1036e07dc26bSmrg    pScrn->EnableDisableFBAccess(pScrn->scrnIndex, FALSE);
1037e07dc26bSmrg    pScrn->EnableDisableFBAccess(pScrn->scrnIndex, TRUE);
1038e07dc26bSmrg#endif
1039e07dc26bSmrg}
1040e07dc26bSmrg
1041e07dc26bSmrgstatic void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, Bool fScreenInitTime)
1042e07dc26bSmrg{
1043e07dc26bSmrg    RT_NOREF(fScreenInitTime);
1044e07dc26bSmrg    TRACE_LOG("fScreenInitTime=%d\n", (int)fScreenInitTime);
1045e07dc26bSmrg#ifdef VBOXVIDEO_13
1046e07dc26bSmrg# if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
1047e07dc26bSmrg    RRGetInfo(xf86ScrnToScreen(pScrn), TRUE);
1048e07dc26bSmrg# else
1049e07dc26bSmrg    RRGetInfo(xf86ScrnToScreen(pScrn));
1050e07dc26bSmrg# endif
1051e07dc26bSmrg#else
1052e07dc26bSmrg    setSizesRandR11(pScrn);
1053e07dc26bSmrg#endif
1054e07dc26bSmrg    /* This calls EnableDisableFBAccess(), so only use when switched in. */
1055e07dc26bSmrg    if (pScrn->vtSema)
1056e07dc26bSmrg        reprobeCursor(pScrn);
1057e07dc26bSmrg}
1058e07dc26bSmrg
1059e07dc26bSmrg/* We update the size hints from the X11 property set by VBoxClient every time
1060e07dc26bSmrg * that the X server goes to sleep (to catch the property change request).
1061e07dc26bSmrg * Although this is far more often than necessary it should not have real-life
1062e07dc26bSmrg * performance consequences and allows us to simplify the code quite a bit. */
1063e07dc26bSmrgstatic void vboxBlockHandler(pointer pData,
1064e07dc26bSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 23
1065e07dc26bSmrg                             OSTimePtr pTimeout,
1066e07dc26bSmrg                             pointer pReadmask
1067e07dc26bSmrg#else
1068e07dc26bSmrg                             void *pTimeout
1069e07dc26bSmrg#endif
1070e07dc26bSmrg                  )
1071e07dc26bSmrg{
1072e07dc26bSmrg    ScrnInfoPtr pScrn = (ScrnInfoPtr)pData;
1073e07dc26bSmrg    Bool fNeedUpdate = false;
1074e07dc26bSmrg
1075e07dc26bSmrg    RT_NOREF(pTimeout);
1076e07dc26bSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 23
1077e07dc26bSmrg    RT_NOREF(pReadmask);
1078e07dc26bSmrg#endif
1079e07dc26bSmrg    if (pScrn->vtSema)
1080e07dc26bSmrg        vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, &fNeedUpdate);
1081e07dc26bSmrg    if (fNeedUpdate)
1082e07dc26bSmrg        setSizesAndCursorIntegration(pScrn, false);
1083e07dc26bSmrg}
1084e07dc26bSmrg
1085e07dc26bSmrg/*
1086e07dc26bSmrg * QUOTE from the XFree86 DESIGN document:
1087e07dc26bSmrg *
1088e07dc26bSmrg * This is called at the start of each server generation.
1089e07dc26bSmrg *
1090e07dc26bSmrg * (...)
1091e07dc26bSmrg *
1092e07dc26bSmrg * Decide which operations need to be placed under resource access
1093e07dc26bSmrg * control. (...) Map any video memory or other memory regions. (...)
1094e07dc26bSmrg * Save the video card state. (...) Initialise the initial video
1095e07dc26bSmrg * mode.
1096e07dc26bSmrg *
1097e07dc26bSmrg * End QUOTE.
1098e07dc26bSmrg */
1099e07dc26bSmrgstatic Bool VBOXScreenInit(ScreenPtr pScreen, int argc, char **argv)
1100e07dc26bSmrg{
1101e07dc26bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1102e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
1103e07dc26bSmrg    VisualPtr visual;
1104e07dc26bSmrg    RT_NOREF(argc, argv);
1105e07dc26bSmrg
1106e07dc26bSmrg    TRACE_ENTRY();
1107e07dc26bSmrg
1108e07dc26bSmrg    if (!VBOXMapVidMem(pScrn))
1109e07dc26bSmrg        return (FALSE);
1110e07dc26bSmrg
1111e07dc26bSmrg    /* save current video state */
1112e07dc26bSmrg    VBOXSaveMode(pScrn);
1113e07dc26bSmrg
1114e07dc26bSmrg    /* mi layer - reset the visual list (?)*/
1115e07dc26bSmrg    miClearVisualTypes();
1116e07dc26bSmrg    if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
1117e07dc26bSmrg                          pScrn->rgbBits, TrueColor))
1118e07dc26bSmrg        return (FALSE);
1119e07dc26bSmrg    if (!miSetPixmapDepths())
1120e07dc26bSmrg        return (FALSE);
1121e07dc26bSmrg
1122e07dc26bSmrg    if (!fbScreenInit(pScreen, pVBox->base,
1123e07dc26bSmrg                      pScrn->virtualX, pScrn->virtualY,
1124e07dc26bSmrg                      pScrn->xDpi, pScrn->yDpi,
1125e07dc26bSmrg                      pScrn->displayWidth, pScrn->bitsPerPixel))
1126e07dc26bSmrg        return (FALSE);
1127e07dc26bSmrg
1128e07dc26bSmrg    /* Fixup RGB ordering */
1129e07dc26bSmrg    /** @note the X server uses this even in true colour. */
1130e07dc26bSmrg    visual = pScreen->visuals + pScreen->numVisuals;
1131e07dc26bSmrg    while (--visual >= pScreen->visuals) {
1132e07dc26bSmrg        if ((visual->class | DynamicClass) == DirectColor) {
1133e07dc26bSmrg            visual->offsetRed   = pScrn->offset.red;
1134e07dc26bSmrg            visual->offsetGreen = pScrn->offset.green;
1135e07dc26bSmrg            visual->offsetBlue  = pScrn->offset.blue;
1136e07dc26bSmrg            visual->redMask     = pScrn->mask.red;
1137e07dc26bSmrg            visual->greenMask   = pScrn->mask.green;
1138e07dc26bSmrg            visual->blueMask    = pScrn->mask.blue;
1139e07dc26bSmrg        }
1140e07dc26bSmrg    }
1141e07dc26bSmrg
1142e07dc26bSmrg    /* must be after RGB ordering fixed */
1143e07dc26bSmrg    fbPictureInit(pScreen, 0, 0);
1144e07dc26bSmrg
1145e07dc26bSmrg    xf86SetBlackWhitePixels(pScreen);
1146e07dc26bSmrg    pScrn->vtSema = TRUE;
1147e07dc26bSmrg
1148e07dc26bSmrg#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
1149e07dc26bSmrg    vbvxSetUpLinuxACPI(pScreen);
1150e07dc26bSmrg#endif
1151e07dc26bSmrg
1152e07dc26bSmrg    if (!VBoxHGSMIIsSupported())
1153e07dc26bSmrg    {
1154e07dc26bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Graphics device too old to support.\n");
1155e07dc26bSmrg        return FALSE;
1156e07dc26bSmrg    }
1157e07dc26bSmrg    vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
1158e07dc26bSmrg    pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx);
1159e07dc26bSmrg    pVBox->pScreens = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->pScreens));
1160e07dc26bSmrg    pVBox->paVBVAModeHints = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->paVBVAModeHints));
1161e07dc26bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n", pVBox->cScreens);
1162e07dc26bSmrg    vboxEnableVbva(pScrn);
1163e07dc26bSmrg    /* Set up the dirty rectangle handler.  It will be added into a function
1164e07dc26bSmrg     * chain and gets removed when the screen is cleaned up. */
1165e07dc26bSmrg    if (ShadowFBInit2(pScreen, NULL, vbvxHandleDirtyRect) != TRUE)
1166e07dc26bSmrg        return FALSE;
1167e07dc26bSmrg    VBoxInitialiseSizeHints(pScrn);
1168e07dc26bSmrg
1169e07dc26bSmrg#ifdef VBOXVIDEO_13
1170e07dc26bSmrg    /* Initialise CRTC and output configuration for use with randr1.2. */
1171e07dc26bSmrg    xf86CrtcConfigInit(pScrn, &VBOXCrtcConfigFuncs);
1172e07dc26bSmrg
1173e07dc26bSmrg    {
1174e07dc26bSmrg        uint32_t i;
1175e07dc26bSmrg
1176e07dc26bSmrg        for (i = 0; i < pVBox->cScreens; ++i)
1177e07dc26bSmrg        {
1178e07dc26bSmrg            char szOutput[256];
1179e07dc26bSmrg
1180e07dc26bSmrg            /* Setup our virtual CRTCs. */
1181e07dc26bSmrg            pVBox->pScreens[i].paCrtcs = xf86CrtcCreate(pScrn, &VBOXCrtcFuncs);
1182e07dc26bSmrg            pVBox->pScreens[i].paCrtcs->driver_private = (void *)(uintptr_t)i;
1183e07dc26bSmrg
1184e07dc26bSmrg            /* Set up our virtual outputs. */
1185e07dc26bSmrg            snprintf(szOutput, sizeof(szOutput), "VGA-%u", i);
1186e07dc26bSmrg            pVBox->pScreens[i].paOutputs
1187e07dc26bSmrg                = xf86OutputCreate(pScrn, &VBOXOutputFuncs, szOutput);
1188e07dc26bSmrg
1189e07dc26bSmrg            /* We are not interested in the monitor section in the
1190e07dc26bSmrg             * configuration file. */
1191e07dc26bSmrg            xf86OutputUseScreenMonitor(pVBox->pScreens[i].paOutputs, FALSE);
1192e07dc26bSmrg            pVBox->pScreens[i].paOutputs->possible_crtcs = 1 << i;
1193e07dc26bSmrg            pVBox->pScreens[i].paOutputs->possible_clones = 0;
1194e07dc26bSmrg            pVBox->pScreens[i].paOutputs->driver_private = (void *)(uintptr_t)i;
1195e07dc26bSmrg            TRACE_LOG("Created crtc (%p) and output %s (%p)\n",
1196e07dc26bSmrg                      (void *)pVBox->pScreens[i].paCrtcs, szOutput,
1197e07dc26bSmrg                      (void *)pVBox->pScreens[i].paOutputs);
1198e07dc26bSmrg        }
1199e07dc26bSmrg    }
1200e07dc26bSmrg
1201e07dc26bSmrg    /* Set a sane minimum and maximum mode size to match what the hardware
1202e07dc26bSmrg     * supports. */
1203e07dc26bSmrg    xf86CrtcSetSizeRange(pScrn, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL, VBOX_VIDEO_MAX_VIRTUAL);
1204e07dc26bSmrg
1205e07dc26bSmrg    /* Now create our initial CRTC/output configuration. */
1206e07dc26bSmrg    if (!xf86InitialConfiguration(pScrn, TRUE)) {
1207e07dc26bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Initial CRTC configuration failed!\n");
1208e07dc26bSmrg        return (FALSE);
1209e07dc26bSmrg    }
1210e07dc26bSmrg
1211e07dc26bSmrg    /* Work around a bug in the original X server modesetting code, which took
1212e07dc26bSmrg     * the first valid values set to these two as maxima over the server
1213e07dc26bSmrg     * lifetime.  This bug was introduced on Feb 15 2007 and was fixed in commit
1214e07dc26bSmrg     * fa877d7f three months later, so it was present in X.Org Server 1.3. */
1215e07dc26bSmrg    pScrn->virtualX = VBOX_VIDEO_MAX_VIRTUAL;
1216e07dc26bSmrg    pScrn->virtualY = VBOX_VIDEO_MAX_VIRTUAL;
1217e07dc26bSmrg
1218e07dc26bSmrg    /* Initialise randr 1.2 mode-setting functions. */
1219e07dc26bSmrg    if (!xf86CrtcScreenInit(pScreen)) {
1220e07dc26bSmrg        return FALSE;
1221e07dc26bSmrg    }
1222e07dc26bSmrg
1223e07dc26bSmrg    /* set first video mode */
1224e07dc26bSmrg    if (!xf86SetDesiredModes(pScrn)) {
1225e07dc26bSmrg        return FALSE;
1226e07dc26bSmrg    }
1227e07dc26bSmrg#else  /* !VBOXVIDEO_13 */
1228e07dc26bSmrg    /* set first video mode */
1229e07dc26bSmrg    setModeRandR11(pScrn, pScrn->currentMode, true, false, 0, 0);
1230e07dc26bSmrg#endif /* !VBOXVIDEO_13 */
1231e07dc26bSmrg
1232e07dc26bSmrg    /* Say that we support graphics. */
1233e07dc26bSmrg    updateGraphicsCapability(pScrn, TRUE);
1234e07dc26bSmrg
1235e07dc26bSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 23
1236e07dc26bSmrg# define WakeupHandlerProcPtr ServerWakeupHandlerProcPtr
1237e07dc26bSmrg#endif
1238e07dc26bSmrg
1239e07dc26bSmrg    /* Register block and wake-up handlers for getting new screen size hints. */
1240e07dc26bSmrg    RegisterBlockAndWakeupHandlers(vboxBlockHandler, (WakeupHandlerProcPtr)NoopDDA, (pointer)pScrn);
1241e07dc26bSmrg
1242e07dc26bSmrg    /* software cursor */
1243e07dc26bSmrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1244e07dc26bSmrg
1245e07dc26bSmrg    /* colourmap code */
1246e07dc26bSmrg    if (!miCreateDefColormap(pScreen))
1247e07dc26bSmrg        return (FALSE);
1248e07dc26bSmrg
1249e07dc26bSmrg    if(!xf86HandleColormaps(pScreen, 256, 8, vboxLoadPalette, NULL, 0))
1250e07dc26bSmrg        return (FALSE);
1251e07dc26bSmrg
1252e07dc26bSmrg    pVBox->CloseScreen = pScreen->CloseScreen;
1253e07dc26bSmrg    pScreen->CloseScreen = SCRNINDEXAPI(VBOXCloseScreen);
1254e07dc26bSmrg#ifdef VBOXVIDEO_13
1255e07dc26bSmrg    pScreen->SaveScreen = xf86SaveScreen;
1256e07dc26bSmrg#else
1257e07dc26bSmrg    pScreen->SaveScreen = VBOXSaveScreen;
1258e07dc26bSmrg#endif
1259e07dc26bSmrg
1260e07dc26bSmrg#ifdef VBOXVIDEO_13
1261e07dc26bSmrg    xf86DPMSInit(pScreen, xf86DPMSSet, 0);
1262e07dc26bSmrg#else
1263e07dc26bSmrg    /* We probably do want to support power management - even if we just use
1264e07dc26bSmrg       a dummy function. */
1265e07dc26bSmrg    xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
1266e07dc26bSmrg#endif
1267e07dc26bSmrg
1268e07dc26bSmrg    /* Report any unused options (only for the first generation) */
1269e07dc26bSmrg    if (serverGeneration == 1)
1270e07dc26bSmrg        xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1271e07dc26bSmrg
1272e07dc26bSmrg    if (vbvxCursorInit(pScreen) != TRUE)
1273e07dc26bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1274e07dc26bSmrg                   "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
1275e07dc26bSmrg
1276e07dc26bSmrg    return (TRUE);
1277e07dc26bSmrg}
1278e07dc26bSmrg
1279e07dc26bSmrg#define NO_VT_ATOM_NAME "VBOXVIDEO_NO_VT"
1280e07dc26bSmrg
1281e07dc26bSmrgstatic Bool VBOXEnterVT(ScrnInfoPtr pScrn)
1282e07dc26bSmrg{
1283e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
1284e07dc26bSmrg#ifndef VBOXVIDEO_13
1285e07dc26bSmrg    /* If we got a mode request while we were switched out, temporarily override
1286e07dc26bSmrg     * the physical mode set to the device while keeping things consistent from
1287e07dc26bSmrg     * the server's point of view. */
1288e07dc26bSmrg    int cXOverRide = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cx, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
1289e07dc26bSmrg    int cYOverRide = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cy, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
1290e07dc26bSmrg#endif
1291e07dc26bSmrg
1292e07dc26bSmrg    TRACE_ENTRY();
1293e07dc26bSmrg    vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
1294e07dc26bSmrg    vboxEnableVbva(pScrn);
1295e07dc26bSmrg    /* Re-set video mode */
1296e07dc26bSmrg#ifdef VBOXVIDEO_13
1297e07dc26bSmrg    if (!xf86SetDesiredModes(pScrn)) {
1298e07dc26bSmrg        return FALSE;
1299e07dc26bSmrg    }
1300e07dc26bSmrg#else
1301e07dc26bSmrg    setModeRandR11(pScrn, pScrn->currentMode, false, true, cXOverRide, cYOverRide);
1302e07dc26bSmrg    DeleteProperty(ROOT_WINDOW(pScrn), MakeAtom(NO_VT_ATOM_NAME, sizeof(NO_VT_ATOM_NAME) - 1, TRUE));
1303e07dc26bSmrg#endif
1304e07dc26bSmrg    updateGraphicsCapability(pScrn, TRUE);
1305e07dc26bSmrg    return TRUE;
1306e07dc26bSmrg}
1307e07dc26bSmrg
1308e07dc26bSmrgstatic void VBOXLeaveVT(ScrnInfoPtr pScrn)
1309e07dc26bSmrg{
1310e07dc26bSmrg#ifdef VBOXVIDEO_13
1311e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
1312e07dc26bSmrg    unsigned i;
1313e07dc26bSmrg#else
1314e07dc26bSmrg    int32_t propertyValue = 0;
1315e07dc26bSmrg#endif
1316e07dc26bSmrg
1317e07dc26bSmrg    TRACE_ENTRY();
1318e07dc26bSmrg#ifdef VBOXVIDEO_13
1319e07dc26bSmrg    for (i = 0; i < pVBox->cScreens; ++i)
1320e07dc26bSmrg        vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
1321e07dc26bSmrg#else
1322e07dc26bSmrg    ChangeWindowProperty(ROOT_WINDOW(pScrn), MakeAtom(NO_VT_ATOM_NAME, sizeof(NO_VT_ATOM_NAME) - 1, FALSE), XA_INTEGER, 32,
1323e07dc26bSmrg                         PropModeReplace, 1, &propertyValue, TRUE);
1324e07dc26bSmrg#endif
1325e07dc26bSmrg    updateGraphicsCapability(pScrn, FALSE);
1326e07dc26bSmrg    vboxDisableVbva(pScrn);
1327e07dc26bSmrg    vbvxClearVRAM(pScrn, ((size_t)pScrn->virtualX) * pScrn->virtualY * (pScrn->bitsPerPixel / 8), 0);
1328e07dc26bSmrg    VBOXRestoreMode(pScrn);
1329e07dc26bSmrg    TRACE_EXIT();
1330e07dc26bSmrg}
1331e07dc26bSmrg
1332e07dc26bSmrgstatic Bool VBOXCloseScreen(ScreenPtr pScreen)
1333e07dc26bSmrg{
1334e07dc26bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1335e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
1336e07dc26bSmrg    BOOL ret;
1337e07dc26bSmrg
1338e07dc26bSmrg    if (pScrn->vtSema)
1339e07dc26bSmrg    {
1340e07dc26bSmrg#ifdef VBOXVIDEO_13
1341e07dc26bSmrg        unsigned i;
1342e07dc26bSmrg
1343e07dc26bSmrg        for (i = 0; i < pVBox->cScreens; ++i)
1344e07dc26bSmrg            vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
1345e07dc26bSmrg#endif
1346e07dc26bSmrg        vboxDisableVbva(pScrn);
1347e07dc26bSmrg        vbvxClearVRAM(pScrn, ((size_t)pScrn->virtualX) * pScrn->virtualY * (pScrn->bitsPerPixel / 8), 0);
1348e07dc26bSmrg    }
1349e07dc26bSmrg    if (pScrn->vtSema)
1350e07dc26bSmrg        VBOXRestoreMode(pScrn);
1351e07dc26bSmrg    if (pScrn->vtSema)
1352e07dc26bSmrg        VBOXUnmapVidMem(pScrn);
1353e07dc26bSmrg    pScrn->vtSema = FALSE;
1354e07dc26bSmrg
1355e07dc26bSmrg    vbvxCursorTerm(pVBox);
1356e07dc26bSmrg
1357e07dc26bSmrg    pScreen->CloseScreen = pVBox->CloseScreen;
1358e07dc26bSmrg#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
1359e07dc26bSmrg    vbvxCleanUpLinuxACPI(pScreen);
1360e07dc26bSmrg#endif
1361e07dc26bSmrg#ifndef XF86_SCRN_INTERFACE
1362e07dc26bSmrg    ret = pScreen->CloseScreen(pScreen->myNum, pScreen);
1363e07dc26bSmrg#else
1364e07dc26bSmrg    ret = pScreen->CloseScreen(pScreen);
1365e07dc26bSmrg#endif
1366e07dc26bSmrg    return ret;
1367e07dc26bSmrg}
1368e07dc26bSmrg
1369e07dc26bSmrgstatic Bool VBOXSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
1370e07dc26bSmrg{
1371e07dc26bSmrg    Bool rc = TRUE;
1372e07dc26bSmrg
1373e07dc26bSmrg    TRACE_LOG("HDisplay=%d, VDisplay=%d\n", pMode->HDisplay, pMode->VDisplay);
1374e07dc26bSmrg#ifdef VBOXVIDEO_13
1375e07dc26bSmrg    rc = xf86SetSingleMode(pScrn, pMode, RR_Rotate_0);
1376e07dc26bSmrg#else
1377e07dc26bSmrg    setModeRandR11(pScrn, pMode, false, false, 0, 0);
1378e07dc26bSmrg#endif
1379e07dc26bSmrg    TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1380e07dc26bSmrg    return rc;
1381e07dc26bSmrg}
1382e07dc26bSmrg
1383e07dc26bSmrgstatic void VBOXAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
1384e07dc26bSmrg{ RT_NOREF(pScrn, x, y); }
1385e07dc26bSmrg
1386e07dc26bSmrgstatic void VBOXFreeScreen(ScrnInfoPtr pScrn)
1387e07dc26bSmrg{
1388e07dc26bSmrg    /* Destroy the VGA hardware record */
1389e07dc26bSmrg    vgaHWFreeHWRec(pScrn);
1390e07dc26bSmrg    /* And our private record */
1391e07dc26bSmrg    free(pScrn->driverPrivate);
1392e07dc26bSmrg    pScrn->driverPrivate = NULL;
1393e07dc26bSmrg}
1394e07dc26bSmrg
1395e07dc26bSmrgstatic Bool
1396e07dc26bSmrgVBOXMapVidMem(ScrnInfoPtr pScrn)
1397e07dc26bSmrg{
1398e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
1399e07dc26bSmrg    Bool rc = TRUE;
1400e07dc26bSmrg
1401e07dc26bSmrg    TRACE_ENTRY();
1402e07dc26bSmrg    if (!pVBox->base)
1403e07dc26bSmrg    {
1404e07dc26bSmrg#ifdef PCIACCESS
1405e07dc26bSmrg        (void) pci_device_map_range(pVBox->pciInfo,
1406e07dc26bSmrg                                    pScrn->memPhysBase,
1407e07dc26bSmrg                                    pScrn->videoRam * 1024,
1408e07dc26bSmrg                                    PCI_DEV_MAP_FLAG_WRITABLE,
1409e07dc26bSmrg                                    & pVBox->base);
1410e07dc26bSmrg#else
1411e07dc26bSmrg        pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
1412e07dc26bSmrg                                    VIDMEM_FRAMEBUFFER,
1413e07dc26bSmrg                                    pVBox->pciTag, pScrn->memPhysBase,
1414e07dc26bSmrg                                    (unsigned) pScrn->videoRam * 1024);
1415e07dc26bSmrg#endif
1416e07dc26bSmrg        if (!pVBox->base)
1417e07dc26bSmrg            rc = FALSE;
1418e07dc26bSmrg    }
1419e07dc26bSmrg    TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1420e07dc26bSmrg    return rc;
1421e07dc26bSmrg}
1422e07dc26bSmrg
1423e07dc26bSmrgstatic void
1424e07dc26bSmrgVBOXUnmapVidMem(ScrnInfoPtr pScrn)
1425e07dc26bSmrg{
1426e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
1427e07dc26bSmrg
1428e07dc26bSmrg    TRACE_ENTRY();
1429e07dc26bSmrg    if (pVBox->base == NULL)
1430e07dc26bSmrg        return;
1431e07dc26bSmrg
1432e07dc26bSmrg#ifdef PCIACCESS
1433e07dc26bSmrg    (void) pci_device_unmap_range(pVBox->pciInfo,
1434e07dc26bSmrg                                  pVBox->base,
1435e07dc26bSmrg                                  pScrn->videoRam * 1024);
1436e07dc26bSmrg#else
1437e07dc26bSmrg    xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
1438e07dc26bSmrg                    (unsigned) pScrn->videoRam * 1024);
1439e07dc26bSmrg#endif
1440e07dc26bSmrg    pVBox->base = NULL;
1441e07dc26bSmrg    TRACE_EXIT();
1442e07dc26bSmrg}
1443e07dc26bSmrg
1444e07dc26bSmrg#ifndef VBOXVIDEO_13
1445e07dc26bSmrgstatic Bool
1446e07dc26bSmrgVBOXSaveScreen(ScreenPtr pScreen, int mode)
1447e07dc26bSmrg{
1448e07dc26bSmrg    RT_NOREF(pScreen, mode);
1449e07dc26bSmrg    return TRUE;
1450e07dc26bSmrg}
1451e07dc26bSmrg#endif
1452e07dc26bSmrg
1453e07dc26bSmrgvoid
1454e07dc26bSmrgVBOXSaveMode(ScrnInfoPtr pScrn)
1455e07dc26bSmrg{
1456e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
1457e07dc26bSmrg    vgaRegPtr vgaReg;
1458e07dc26bSmrg
1459e07dc26bSmrg    TRACE_ENTRY();
1460e07dc26bSmrg    vgaReg = &VGAHWPTR(pScrn)->SavedReg;
1461e07dc26bSmrg    vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
1462e07dc26bSmrg    pVBox->fSavedVBEMode = VBoxVideoGetModeRegisters(&pVBox->cSavedWidth,
1463e07dc26bSmrg                                                     &pVBox->cSavedHeight,
1464e07dc26bSmrg                                                     &pVBox->cSavedPitch,
1465e07dc26bSmrg                                                     &pVBox->cSavedBPP,
1466e07dc26bSmrg                                                     &pVBox->fSavedFlags);
1467e07dc26bSmrg}
1468e07dc26bSmrg
1469e07dc26bSmrgvoid
1470e07dc26bSmrgVBOXRestoreMode(ScrnInfoPtr pScrn)
1471e07dc26bSmrg{
1472e07dc26bSmrg    VBOXPtr pVBox = VBOXGetRec(pScrn);
1473e07dc26bSmrg    vgaRegPtr vgaReg;
1474e07dc26bSmrg
1475e07dc26bSmrg    TRACE_ENTRY();
1476e07dc26bSmrg    vgaReg = &VGAHWPTR(pScrn)->SavedReg;
1477e07dc26bSmrg    vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
1478e07dc26bSmrg    if (pVBox->fSavedVBEMode)
1479e07dc26bSmrg        VBoxVideoSetModeRegisters(pVBox->cSavedWidth, pVBox->cSavedHeight,
1480e07dc26bSmrg                                  pVBox->cSavedPitch, pVBox->cSavedBPP,
1481e07dc26bSmrg                                  pVBox->fSavedFlags, 0, 0);
1482e07dc26bSmrg    else
1483e07dc26bSmrg        VBoxVideoDisableVBE();
1484e07dc26bSmrg}
1485e07dc26bSmrg
1486e07dc26bSmrg#ifndef VBOXVIDEO_13
1487e07dc26bSmrgstatic void
1488e07dc26bSmrgVBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, int flags)
1489e07dc26bSmrg{
1490e07dc26bSmrg    RT_NOREF(pScrn, mode, flags);
1491e07dc26bSmrg}
1492e07dc26bSmrg#endif
1493