vboxvideo.c revision a5fca05de4ecdebae5a4df8769c61d43d5d209c4
/* $Id$ */
/** @file
*
* Linux Additions X11 graphics driver
*/
/*
* Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
* --------------------------------------------------------------------
*
* This code is based on the X.Org VESA driver with the following copyrights:
*
* Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
* Copyright 2008 Red Hat, Inc.
* Copyright 2012 Red Hat, Inc.
*
* and the following permission notice (not all original sourse files include
* the last paragraph):
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of Conectiva Linux shall
* not be used in advertising or otherwise to promote the sale, use or other
* dealings in this Software without prior written authorization from
* Conectiva Linux.
*
* Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
* David Dawes <dawes@xfree86.org>
* Adam Jackson <ajax@redhat.com>
* Dave Airlie <airlied@redhat.com>
*/
#ifdef XORG_7X
# include <stdlib.h>
# include <string.h>
#endif
#include "xf86.h"
#include "xf86_OSproc.h"
# include "xf86Resources.h"
#endif
/* This was accepted upstream in X.Org Server 1.16 which bumped the video
* driver ABI to 17. */
# define SET_HAVE_VT_PROPERTY
#endif
#ifndef PCIACCESS
/* Drivers for PCI hardware need this */
# include "xf86PciInfo.h"
/* Drivers that need to access the PCI config space directly need this */
# include "xf86Pci.h"
#endif
#include "fb.h"
#include "vboxvideo.h"
#include <VBox/VBoxGuest.h>
#include "version-generated.h"
#include "product-generated.h"
#include <xf86.h>
#include <misc.h>
/* All drivers initialising the SW cursor need this */
#include "mipointer.h"
/* Colormap handling */
#include "micmap.h"
#include "xf86cmap.h"
/* DPMS */
/* #define DPMS_SERVER
#include "extensions/dpms.h" */
/* VGA hardware functions for setting and restoring text mode */
#include "vgaHW.h"
#ifdef VBOXVIDEO_13
/* X.org 1.3+ mode setting */
# define _HAVE_STRING_ARCH_strsep /* bits/string2.h, __strsep_1c. */
# include "xf86Crtc.h"
# include "xf86Modes.h"
#endif
/* For setting the root window property. */
#include "property.h"
#ifdef VBOX_DRI
# include "xf86drm.h"
# include "xf86drmMode.h"
#endif
/* Mandatory functions */
static void VBOXIdentify(int flags);
#ifndef PCIACCESS
#else
#endif
int flags);
/* locally used functions */
{
if (!pScrn->driverPrivate)
{
#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
#endif
}
}
enum GenericTypes
{
};
#ifdef PCIACCESS
static const struct pci_id_match vbox_device_match[] = {
{
0, 0, 0
},
{ 0, 0, 0 },
};
#endif
/* Supported chipsets */
static SymTabRec VBOXChipsets[] =
{
{VBOX_DEVICEID, "vbox"},
{-1, NULL}
};
static PciChipsets VBOXPCIchipsets[] = {
};
/*
* This contains the functions needed by the server after loading the
* driver module. It must be supplied, and gets added the driver list by
* the Module Setup function in the dynamic case. In the static case a
* reference to this is compiled in, and this requires that the name of
* this DriverRec be an upper-case version of the driver name.
*/
#ifdef XORG_7X
#endif
#ifdef PCIACCESS
NULL,
#else
#endif
NULL,
0,
#ifdef XORG_7X
NULL,
#endif
#ifdef PCIACCESS
#endif
};
/* No options for now */
static const OptionInfoRec VBOXOptions[] = {
};
#ifndef XORG_7X
/*
* List of symbols from other modules that this module references. This
* list is used to tell the loader that it is OK for symbols here to be
* unresolved providing that it hasn't been told that they haven't been
* told that they are essential via a call to xf86LoaderReqSymbols() or
* xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about
* unresolved symbols that are not required.
*/
static const char *fbSymbols[] = {
"fbPictureInit",
"fbScreenInit",
};
static const char *shadowfbSymbols[] = {
"ShadowFBInit2",
};
static const char *ramdacSymbols[] = {
"xf86DestroyCursorInfoRec",
"xf86InitCursor",
"xf86CreateCursorInfoRec",
};
static const char *vgahwSymbols[] = {
"vgaHWFreeHWRec",
"vgaHWGetHWRec",
"vgaHWGetIOBase",
"vgaHWGetIndex",
"vgaHWRestore",
"vgaHWSave",
"vgaHWSetStdFuncs",
};
#endif /* !XORG_7X */
#ifdef VBOXVIDEO_13
/* X.org 1.3+ mode-setting support ******************************************/
/* For descriptions of these functions and structures, see
hw/xfree86/modes/xf86Crtc.h and hw/xfree86/modes/xf86Modes.h in the
X.Org source tree. */
{
/* Save the size in case we need to re-set it later. */
/* Don't fiddle with the hardware if we are switched
* to a virtual terminal. */
"We do not own the active VT, exiting.\n");
return TRUE;
}
}
static const xf86CrtcConfigFuncsRec VBOXCrtcConfigFuncs = {
};
static void
{
/* Don't fiddle with the hardware if we are switched
* to a virtual terminal. */
"We do not own the active VT, exiting.\n");
return;
}
}
static Bool
/* We use this function to check whether the X server owns the active virtual
* terminal before attempting a mode switch, since the RandR extension isn't
* very dilligent here, which can mean crashes if we are unlucky. This is
* not the way it the function is intended - it is meant for reporting modes
* which the hardware can't handle. I hope that this won't confuse any clients
* connecting to us. */
static Bool
static void
{ (void) crtc; }
static void
DisplayModePtr adjusted_mode, int x, int y)
{
(void) mode;
/* Don't fiddle with the hardware if we are switched
* to a virtual terminal. */
{
"We do not own the active VT, exiting.\n");
return;
}
adjusted_mode->VDisplay, x, y);
}
static void
static void *
static const xf86CrtcFuncsRec VBOXCrtcFuncs = {
.dpms = vbox_crtc_dpms,
.lock = vbox_crtc_lock,
.commit = vbox_crtc_stub,
returns NULL. */
.shadow_destroy = NULL,
.show_cursor = NULL,
.hide_cursor = NULL,
.load_cursor_argb = NULL,
};
static void
{ (void) output; }
static void
{
/* Don't fiddle with the hardware if we are switched
* to a virtual terminal. */
"We do not own the active VT, exiting.\n");
return;
}
}
static int
{
return MODE_OK;
}
static Bool
static void
/* A virtual monitor is always connected. */
static xf86OutputStatus
{
}
static DisplayModePtr vbox_output_add_mode(VBOXPtr pVBox, DisplayModePtr *pModes, const char *pszName, int x, int y,
{
int cRefresh = 60;
/* We don't ask the host whether it likes user defined modes,
* as we assume that the user really wanted that mode. */
if (isPreferred)
/* Older versions of VBox only support screen widths which are a multiple
* of 8 */
else
} else {
}
return pMode;
}
static DisplayModePtr
{
unsigned i, cIndex = 0;
TRACE_ENTRY();
TRACE_EXIT();
return pModes;
}
static const xf86OutputFuncsRec VBOXOutputFuncs = {
.dpms = vbox_output_dpms,
#ifdef RANDR_12_INTERFACE
.set_property = NULL,
#endif
};
#endif /* VBOXVIDEO_13 */
/* Module loader interface */
static MODULESETUPPROTO(vboxSetup);
static XF86ModuleVersionInfo vboxVersionRec =
{
#ifdef XORG_7X
#else
#endif
1, /* Module major version. Xorg-specific */
0, /* Module minor version. Xorg-specific */
1, /* Module patchlevel. Xorg-specific */
ABI_CLASS_VIDEODRV, /* This is a video driver */
{0, 0, 0, 0}
};
/*
* This data is accessed by the loader. The name must be the module name
* followed by "ModuleData".
*/
#ifdef XORG_7X
#endif
static pointer
{
if (!Initialised)
{
Initialised = TRUE;
#ifdef PCIACCESS
#else
#endif
#ifndef XORG_7X
NULL);
#endif
(void *)&VBOXVIDEO);
}
if (ErrorMajor)
return (NULL);
}
static const OptionInfoRec *
{
return (VBOXOptions);
}
static void
VBOXIdentify(int flags)
{
}
#ifndef XF86_SCRN_INTERFACE
char **argv)
# else
#endif /* XF86_SCRN_INTERFACE */
{
}
/*
* One of these functions is called once, at the start of the first server
* generation to do a minimal probe for supported hardware.
*/
#ifdef PCIACCESS
static Bool
{
TRACE_ENTRY();
if (!pVBox)
return FALSE;
}
}
#endif
#ifndef PCIACCESS
static Bool
{
int numDevSections;
/*
* Find the config file Device sections that match this
* driver, and return if there are none.
*/
&devSections)) <= 0)
return (FALSE);
/* PCI BUS */
if (xf86GetPciVideoInfo())
{
int numUsed;
int *usedChips;
int i;
if (numUsed > 0)
{
if (flags & PROBE_DETECT)
foundScreen = TRUE;
else
for (i = 0; i < numUsed; i++)
{
/* Allocate a ScrnInfoRec */
{
foundScreen = TRUE;
}
}
}
}
return (foundScreen);
}
#endif
/*
* QUOTE from the XFree86 DESIGN document:
*
* The purpose of this function is to find out all the information
* required to determine if the configuration is usable, and to initialise
* those parts of the ScrnInfoRec that can be set once at the beginning of
* the first server generation.
*
* (...)
*
* This includes probing for video memory, clocks, ramdac, and all other
* and related info. It includes validating and determining the set of
* video modes that will be used (and anything that is required to
* determine that).
*
* This information should be determined in the least intrusive way
* possible. The state of the HW must remain unchanged by this function.
* Although video memory (including MMIO) may be mapped within this
* function, it must be unmapped before returning.
*
* END QUOTE
*/
static Bool
{
unsigned DispiId;
TRACE_ENTRY();
/* Are we really starting the server, or is this just a dummy run? */
if (flags & PROBE_DETECT)
return (FALSE);
"VirtualBox guest additions video driver version "
VBOX_VERSION_STRING "\n");
/* Get our private data from the ScrnInfoRec structure. */
if (!pVBox)
return FALSE;
/* Entity information seems to mean bus information. */
/* The ramdac module is needed for the hardware cursor. */
return FALSE;
/* The framebuffer module. */
return (FALSE);
return FALSE;
return FALSE;
#ifdef VBOX_DRI_OLD
/* Load the dri module. */
return FALSE;
#else
# ifdef VBOX_DRI
/* Load the dri module. */
return FALSE;
# endif
#endif
#ifndef PCIACCESS
return FALSE;
#endif
/* Set up our ScrnInfoRec structure to describe our virtual
capabilities to X. */
/** @note needed during colourmap initialisation */
/* Let's create a nice, capable virtual monitor. */
/* Using the PCI information caused problems with non-powers-of-two
sized video RAM configurations */
/* Check if the chip restricts horizontal resolution or not. */
/* Set up clock information that will support all modes we need. */
return FALSE;
/* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
{
"The VBox additions only support 16 and 32bpp graphics modes\n");
return FALSE;
}
#ifdef VBOXVIDEO_13
/* Work around a bug in the original X server modesetting code, which
* took the first valid values set to these two as maxima over the
* server lifetime. */
#else
/* We don't validate with xf86ValidateModes and xf86PruneModes as we
* already know what we like and what we don't. */
/* Set the right virtual resolution. */
#endif /* !VBOXVIDEO_13 */
/* Needed before we initialise DRI. */
/* VGA hardware initialisation */
if (!vgaHWGetHWRec(pScrn))
return FALSE;
/* Must be called before any VGA registers are saved or restored */
/* Colour weight - we always call this, since we are always in
truecolour. */
return (FALSE);
/* visual init */
return (FALSE);
/* Set the DPI. Perhaps we should read this from the host? */
if (pScrn->memPhysBase == 0) {
#ifdef PCIACCESS
#else
#endif
}
TRACE_EXIT();
return (TRUE);
}
/**
* Dummy function for setting the colour palette, which we actually never
* touch. However, the server still requires us to provide this.
*/
static void
{
(void)pVisual;
}
#define HAS_VT_ATOM_NAME "XFree86_has_VT"
#define VBOXVIDEO_DRIVER_ATOM_NAME "VBOXVIDEO_DRIVER_IN_USE"
/* The memory storing the initial value of the XFree86_has_VT root window
* property. This has to remain available until server start-up, so we just
* use a global. */
/** Initialise a flag property on the root window to say whether the server VT
* is currently the active one as some clients need to know this. */
{
#ifdef SET_HAVE_VT_PROPERTY
FatalError("vboxvideo: failed to register VT property\n");
#endif /* SET_HAVE_VT_PROPERTY */
FatalError("vboxvideo: failed to register driver in use property\n");
}
#ifdef SET_HAVE_VT_PROPERTY
/** Update a flag property on the root window to say whether the server VT
* is currently the active one as some clients need to know this. */
{
int i;
FALSE);
if (property_name == BAD_RESOURCE)
FatalError("Failed to retrieve \"HAS_VT\" atom\n");
return;
}
#endif /* SET_HAVE_VT_PROPERTY */
/*
* QUOTE from the XFree86 DESIGN document:
*
* This is called at the start of each server generation.
*
* (...)
*
* Decide which operations need to be placed under resource access
* control. (...) Map any video memory or other memory regions. (...)
* Save the video card state. (...) Initialise the initial video
* mode.
*
* End QUOTE.
*/
{
unsigned flags;
TRACE_ENTRY();
if (!VBOXMapVidMem(pScrn))
return (FALSE);
/* save current video state */
/* mi layer - reset the visual list (?)*/
return (FALSE);
if (!miSetPixmapDepths())
return (FALSE);
#ifdef VBOX_DRI
# ifndef VBOX_DRI_OLD /* DRI2 */
/* Tell the kernel driver, if present, that we are taking over. */
# endif
#endif
return (FALSE);
/* Fixup RGB ordering */
/** @note the X server uses this even in true colour. */
}
}
/* must be after RGB ordering fixed */
fbPictureInit(pScreen, 0, 0);
#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
#endif
#ifdef VBOXVIDEO_13
/* Initialise CRTC and output configuration for use with randr1.2. */
{
uint32_t i;
{
char szOutput[256];
/* Setup our virtual CRTCs. */
/* Set up our virtual outputs. */
/* We are not interested in the monitor section in the
* configuration file. */
TRACE_LOG("Created crtc (%p) and output %s (%p)\n",
}
}
/* Set a sane minimum and maximum mode size to match what the hardware
* supports. */
xf86CrtcSetSizeRange(pScrn, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL, VBOX_VIDEO_MAX_VIRTUAL);
return (FALSE);
}
/* Initialise randr 1.2 mode-setting functions and set first mode.
* Note that the mode won't be usable until the server has resized the
* framebuffer to something reasonable. */
if (!xf86CrtcScreenInit(pScreen)) {
return FALSE;
}
if (!xf86SetDesiredModes(pScrn)) {
return FALSE;
}
#else /* !VBOXVIDEO_13 */
/* set first video mode */
return FALSE;
/* Save the size in case we need to re-set it later. */
#endif /* !VBOXVIDEO_13 */
/* software cursor */
/* colourmap code */
if (!miCreateDefColormap(pScreen))
return (FALSE);
return (FALSE);
#ifdef VBOXVIDEO_13
#else
#endif
#ifdef VBOXVIDEO_13
#else
/* We probably do want to support power management - even if we just use
a dummy function. */
#endif
/* Report any unused options (only for the first generation) */
if (serverGeneration == 1)
"Unable to start the VirtualBox mouse pointer integration with the host system.\n");
#ifdef VBOX_DRI_OLD
#endif
return (TRUE);
}
{
TRACE_ENTRY();
#ifdef VBOX_DRI_OLD
{
/* Tell the kernel driver, if present, that we are taking over. */
}
#endif
/* Re-assert this in case we had a change request while switched out. */
#ifdef VBOXVIDEO_13
if (!xf86SetDesiredModes(pScrn))
return FALSE;
#else
return FALSE;
#endif
#ifdef SET_HAVE_VT_PROPERTY
#endif
return TRUE;
}
{
#ifdef VBOXVIDEO_13
unsigned i;
#endif
TRACE_ENTRY();
#ifdef VBOXVIDEO_13
#endif
vboxClearVRAM(pScrn, 0, 0);
#ifdef VBOX_DRI_OLD
#endif
#ifdef SET_HAVE_VT_PROPERTY
#endif
TRACE_EXIT();
}
{
#endif
{
#ifdef VBOXVIDEO_13
unsigned i;
#endif
vboxClearVRAM(pScrn, 0, 0);
}
#ifdef VBOX_DRI
# ifndef VBOX_DRI_OLD /* DRI2 */
/* Tell the kernel driver, if present, that we are going away. */
fRestore = false;
# endif
#endif
if (fRestore)
#endif
/* Do additional bits which are separate for historical reasons */
#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
#endif
#ifndef XF86_SCRN_INTERFACE
#else
#endif
}
{
#ifndef VBOXVIDEO_13
/* Save the size in case we need to re-set it later. */
#endif
{
"We do not own the active VT, exiting.\n");
return TRUE;
}
#ifdef VBOXVIDEO_13
#else
#endif
return rc;
}
{
TRACE_ENTRY();
/* Don't fiddle with the hardware if we are switched
* to a virtual terminal. */
{
"We do not own the active VT, exiting.\n");
return;
}
TRACE_EXIT();
}
{
/* Destroy the VGA hardware record */
/* And our private record */
}
static Bool
{
TRACE_ENTRY();
{
#ifdef PCIACCESS
#else
#endif
}
return rc;
}
static void
{
TRACE_ENTRY();
return;
#ifdef PCIACCESS
#else
#endif
TRACE_EXIT();
}
static Bool
{
return TRUE;
}
void
{
TRACE_ENTRY();
&pVBox->cSavedPitch,
&pVBox->fSavedFlags);
}
void
{
#ifdef VBOX_DRI
#endif
TRACE_ENTRY();
#ifdef VBOX_DRI
/* Do not try to re-set the VGA state if a mode-setting driver is loaded. */
{
return;
}
#endif
if (pVBox->fSavedVBEMode)
pVBox->fSavedFlags, 0, 0);
else
}
static void
int flags)
{
}