Files
xf86-video-vmware/src/vmware_bootstrap.c
Enrico Weigelt, metux IT consult 1aa9991347 drop compat for ancient xserver versions
We're relying on at least 1.18 now.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-02-11 14:28:57 +01:00

576 lines
15 KiB
C

/*
* Copyright 2011 VMWare, Inc.
* All Rights Reserved.
*
* 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, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
*
* Author: Unknown at vmware
* Author: Thomas Hellstrom <thellstrom@vmware.com>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xf86.h"
#include "compiler.h"
#include "xf86Pci.h" /* pci */
#include "vm_device_version.h"
#include "vmware_bootstrap.h"
#include <stdint.h>
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
#include "xf86Resources.h"
#endif
#ifndef XSERVER_LIBPCIACCESS
#include "vm_basic_types.h"
#include "svga_reg.h"
#endif
#ifndef HAVE_XORG_SERVER_1_5_0
#include <xf86_ansic.h>
#include <xf86_libc.h>
#endif
#ifdef XSERVER_PLATFORM_BUS
#include "xf86platformBus.h"
#endif
#ifdef HaveDriverFuncs
#define VMWARE_DRIVER_FUNC HaveDriverFuncs
#else
#define VMWARE_DRIVER_FUNC 0
#endif
/*
* So that the file compiles unmodified when dropped in to a < 6.9 source tree.
*/
#ifndef _X_EXPORT
#define _X_EXPORT
#endif
/*
* This is the only way I know to turn a #define of an integer constant into
* a constant string.
*/
#define VMW_INNERSTRINGIFY(s) #s
#define VMW_STRING(str) VMW_INNERSTRINGIFY(str)
#define VMWARE_DRIVER_NAME "vmware"
#define VMWARE_NAME "vmware"
static char vmware_driver_name[] = VMWARE_DRIVER_NAME;
#define VMWARE_DRIVER_VERSION \
(PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL)
#define VMWARE_DRIVER_VERSION_STRING \
VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \
"." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL)
#if !XSERVER_LIBPCIACCESS
static const char VMWAREBuildStr[] = "VMware Guest X Server "
VMWARE_DRIVER_VERSION_STRING " - build=$Name$\n";
#else
static char vmware_name[] = VMWARE_NAME;
#endif
/*
* Standard four digit version string expected by VMware Tools installer.
* As the driver's version is only {major, minor, patchlevel},
* The fourth digit may describe the commit number relative to the
* last version tag as output from `git describe`
*/
#ifdef __GNUC__
#ifdef VMW_SUBPATCH
const char vmware_drv_modinfo[]
__attribute__((section(".modinfo"),unused)) =
"version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH);
#else
const char vmware_drv_modinfo[]
__attribute__((section(".modinfo"),unused)) =
"version=" VMWARE_DRIVER_VERSION_STRING ".0";
#endif /*VMW_SUBPATCH*/
#endif
#ifndef XSERVER_LIBPCIACCESS
static resRange vmwareLegacyRes[] = {
{ ResExcIoBlock, SVGA_LEGACY_BASE_PORT,
SVGA_LEGACY_BASE_PORT + SVGA_NUM_PORTS*sizeof(uint32)},
_VGA_EXCLUSIVE, _END
};
#else
#define vmwareLegacyRes NULL
#endif
#if XSERVER_LIBPCIACCESS
#define VENDOR_ID(p) (p)->vendor_id
#define DEVICE_ID(p) (p)->device_id
#define SUBVENDOR_ID(p) (p)->subvendor_id
#define SUBSYS_ID(p) (p)->subdevice_id
#define CHIP_REVISION(p) (p)->revision
#else
#define VENDOR_ID(p) (p)->vendor
#define DEVICE_ID(p) (p)->chipType
#define SUBVENDOR_ID(p) (p)->subsysVendor
#define SUBSYS_ID(p) (p)->subsysCard
#define CHIP_REVISION(p) (p)->chipRev
#endif
#if XSERVER_LIBPCIACCESS
#define VMWARE_DEVICE_MATCH(d, i) \
{PCI_VENDOR_ID_VMWARE, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
static const struct pci_id_match VMwareDeviceMatch[] = {
VMWARE_DEVICE_MATCH (PCI_DEVICE_ID_VMWARE_SVGA2, 0 ),
VMWARE_DEVICE_MATCH (PCI_DEVICE_ID_VMWARE_SVGA, 0 ),
{ 0, 0, 0 },
};
#endif
/*
* Currently, even the PCI obedient 0405 chip still only obeys IOSE and
* MEMSE for the SVGA resources. Thus, RES_EXCLUSIVE_VGA is required.
*
* The 0710 chip also uses hardcoded IO ports that aren't disablable.
*/
static PciChipsets VMWAREPciChipsets[] = {
{ PCI_DEVICE_ID_VMWARE_SVGA2, PCI_DEVICE_ID_VMWARE_SVGA2, RES_EXCLUSIVE_VGA },
{ PCI_DEVICE_ID_VMWARE_SVGA, PCI_DEVICE_ID_VMWARE_SVGA, vmwareLegacyRes },
{ -1, -1, RES_UNDEFINED }
};
static SymTabRec VMWAREChipsets[] = {
{ PCI_DEVICE_ID_VMWARE_SVGA2, "vmware0405" },
{ PCI_DEVICE_ID_VMWARE_SVGA, "vmware0710" },
{ -1, NULL }
};
#ifdef XFree86LOADER
static XF86ModuleVersionInfo vmwareVersRec = {
VMWARE_DRIVER_NAME,
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XORG_VERSION_CURRENT,
PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
MOD_CLASS_VIDEODRV,
{ 0, 0, 0, 0}
};
#endif /* XFree86LOADER */
static const OptionInfoRec VMWAREOptions[] = {
{ OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_XINERAMA, "Xinerama", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_STATIC_XINERAMA, "StaticXinerama", OPTV_STRING, {0}, FALSE },
{ OPTION_GUI_LAYOUT, "GuiLayout", OPTV_STRING, {0}, FALSE },
{ OPTION_DEFAULT_MODE, "AddDefaultMode", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE},
{ OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE},
{ OPTION_DIRECT_PRESENTS, "DirectPresents", OPTV_BOOLEAN, {0}, FALSE},
{ OPTION_HW_PRESENTS, "HWPresents", OPTV_BOOLEAN, {0}, FALSE},
{ OPTION_RENDERCHECK, "RenderCheck", OPTV_BOOLEAN, {0}, FALSE},
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
OptionInfoPtr VMWARECopyOptions(void)
{
OptionInfoPtr options;
if (!(options = malloc(sizeof(VMWAREOptions))))
return NULL;
memcpy(options, VMWAREOptions, sizeof(VMWAREOptions));
return options;
}
/*
* Also in vmwgfx_hosted.h, which we don't include.
*/
void *
vmwgfx_hosted_detect(void);
static Bool
VMwarePreinitStub(ScrnInfoPtr pScrn, int flags)
{
#if XSERVER_LIBPCIACCESS
struct pci_device *pciInfo;
#else
pciVideoPtr pciInfo;
#endif /* XSERVER_LIBPCIACCESS */
EntityInfoPtr pEnt;
pScrn->PreInit = pScrn->driverPrivate;
#ifdef BUILD_VMWGFX
pScrn->driverPrivate = NULL;
/*
* Try vmwgfx path.
*/
if ((*pScrn->PreInit)(pScrn, flags))
return TRUE;
/*
* Can't run legacy hosted
*/
if (vmwgfx_hosted_detect())
return FALSE;
#else
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Driver was compiled without KMS- and 3D support.\n");
#endif /* defined(BUILD_VMWGFX) */
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Disabling 3D support.\n");
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Disabling Render Acceleration.\n");
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Disabling RandR12+ support.\n");
pScrn->driverPrivate = NULL;
vmwlegacy_hookup(pScrn);
pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
pciInfo = xf86GetPciInfoForEntity(pEnt->index);
if (pciInfo == NULL)
return FALSE;
pScrn->chipset = xstrdup(xf86TokenToString(VMWAREChipsets,
DEVICE_ID(pciInfo)));
if (pScrn->chipset == NULL)
return FALSE;
return (*pScrn->PreInit)(pScrn, flags);
};
#if XSERVER_LIBPCIACCESS
static Bool
VMwarePciProbe (DriverPtr drv,
int entity_num,
struct pci_device *device,
intptr_t match_data)
{
ScrnInfoPtr scrn = NULL;
scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VMWAREPciChipsets,
NULL, NULL, NULL, NULL, NULL);
if (scrn != NULL) {
scrn->driverVersion = VMWARE_DRIVER_VERSION;
scrn->driverName = vmware_driver_name;
scrn->name = vmware_name;
scrn->Probe = NULL;
}
switch (DEVICE_ID(device)) {
case PCI_DEVICE_ID_VMWARE_SVGA2:
case PCI_DEVICE_ID_VMWARE_SVGA:
xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n");
#ifdef BUILD_VMWGFX
vmwgfx_hookup(scrn);
#else
vmwlegacy_hookup(scrn);
#endif /* defined(BUILD_VMWGFX) */
scrn->driverPrivate = scrn->PreInit;
scrn->PreInit = VMwarePreinitStub;
break;
default:
xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Unknown device\n");
}
return scrn != NULL;
}
#else
/*
*----------------------------------------------------------------------
*
* RewriteTagString --
*
* Rewrites the given string, removing the $Name$, and
* replacing it with the contents. The output string must
* have enough room, or else.
*
* Results:
*
* Output string updated.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static void
RewriteTagString(const char *istr, char *ostr, int osize)
{
int chr;
Bool inTag = FALSE;
char *op = ostr;
do {
chr = *istr++;
if (chr == '$') {
if (inTag) {
inTag = FALSE;
for (; op > ostr && op[-1] == ' '; op--) {
}
continue;
}
if (strncmp(istr, "Name:", 5) == 0) {
istr += 5;
istr += strspn(istr, " ");
inTag = TRUE;
continue;
}
}
*op++ = chr;
} while (chr);
}
static Bool
VMWAREProbe(DriverPtr drv, int flags)
{
int numDevSections, numUsed;
GDevPtr *devSections;
int *usedChips;
int i;
Bool foundScreen = FALSE;
char buildString[sizeof(VMWAREBuildStr)];
RewriteTagString(VMWAREBuildStr, buildString, sizeof(VMWAREBuildStr));
xf86MsgVerb(X_PROBED, 4, "%s", buildString);
numDevSections = xf86MatchDevice(VMWARE_DRIVER_NAME, &devSections);
if (numDevSections <= 0) {
#ifdef DEBUG
xf86MsgVerb(X_ERROR, 0, "No vmware driver section\n");
#endif
return FALSE;
}
if (xf86GetPciVideoInfo()) {
VmwareLog(("Some PCI Video Info Exists\n"));
numUsed = xf86MatchPciInstances(VMWARE_NAME, PCI_VENDOR_ID_VMWARE,
VMWAREChipsets, VMWAREPciChipsets, devSections,
numDevSections, drv, &usedChips);
free(devSections);
if (numUsed <= 0)
return FALSE;
if (flags & PROBE_DETECT)
foundScreen = TRUE;
else
for (i = 0; i < numUsed; i++) {
ScrnInfoPtr pScrn = NULL;
VmwareLog(("Even some VMware SVGA PCI instances exists\n"));
pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i],
VMWAREPciChipsets, NULL, NULL, NULL,
NULL, NULL);
if (pScrn) {
VmwareLog(("And even configuration succeeded\n"));
pScrn->driverVersion = VMWARE_DRIVER_VERSION;
pScrn->driverName = VMWARE_DRIVER_NAME;
pScrn->name = VMWARE_NAME;
pScrn->Probe = VMWAREProbe;
#ifdef BUILD_VMWGFX
vmwgfx_hookup(pScrn);
#else
vmwlegacy_hookup(pScrn);
#endif /* defined(BUILD_VMWGFX) */
pScrn->driverPrivate = pScrn->PreInit;
pScrn->PreInit = VMwarePreinitStub;
foundScreen = TRUE;
}
}
free(usedChips);
}
return foundScreen;
}
#endif
#ifdef XSERVER_PLATFORM_BUS
static Bool
VMwarePlatformProbe(DriverPtr drv, int entity, int flags,
struct xf86_platform_device *dev, intptr_t match_data)
{
ScrnInfoPtr pScrn;
int scrnFlag = 0;
if (!dev->pdev)
return FALSE;
if (flags & PLATFORM_PROBE_GPU_SCREEN)
scrnFlag = XF86_ALLOCATE_GPU_SCREEN;
pScrn = xf86AllocateScreen(drv, scrnFlag);
if (!pScrn)
return FALSE;
if (xf86IsEntitySharable(entity))
xf86SetEntityShared(entity);
xf86AddEntityToScreen(pScrn, entity);
pScrn->driverVersion = VMWARE_DRIVER_VERSION;
pScrn->driverName = VMWARE_DRIVER_NAME;
pScrn->name = VMWARE_NAME;
pScrn->Probe = NULL;
#ifdef BUILD_VMWGFX
vmwgfx_hookup(pScrn);
#else
vmwlegacy_hookup(pScrn);
#endif
pScrn->driverPrivate = pScrn->PreInit;
pScrn->PreInit = VMwarePreinitStub;
return TRUE;
}
#endif
static void
VMWAREIdentify(int flags)
{
xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets);
}
static const OptionInfoRec *
VMWAREAvailableOptions(int chipid, int busid)
{
return VMWAREOptions;
}
#if VMWARE_DRIVER_FUNC
static Bool
VMWareDriverFunc(ScrnInfoPtr pScrn,
xorgDriverFuncOp op,
pointer data)
{
uint32_t *flag;
xorgRRModeMM *modemm;
switch (op) {
case GET_REQUIRED_HW_INTERFACES:
flag = (uint32_t *)data;
if (flag) {
#ifdef BUILD_VMWGFX
vmwgfx_modify_flags(flag);
#else
*flag = HW_IO | HW_MMIO;
#endif
}
return TRUE;
case RR_GET_MODE_MM:
modemm = (xorgRRModeMM *)data;
/*
* Because changing the resolution of the guest is usually changing the size
* of a window on the host desktop, the real physical DPI will not change. To
* keep the guest in sync, we scale the 'physical' screen dimensions to
* keep the DPI constant.
*/
if (modemm && modemm->mode) {
modemm->mmWidth = (modemm->mode->HDisplay * VMWARE_INCHTOMM +
pScrn->xDpi / 2) / pScrn->xDpi;
modemm->mmHeight = (modemm->mode->VDisplay * VMWARE_INCHTOMM +
pScrn->yDpi / 2) / pScrn->yDpi;
}
return TRUE;
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 18
case SUPPORTS_SERVER_FDS:
return TRUE;
#endif
default:
return FALSE;
}
}
#endif
_X_EXPORT DriverRec vmware = {
VMWARE_DRIVER_VERSION,
vmware_driver_name,
VMWAREIdentify,
#if XSERVER_LIBPCIACCESS
NULL,
#else
VMWAREProbe,
#endif
VMWAREAvailableOptions,
NULL,
0,
#if VMWARE_DRIVER_FUNC
VMWareDriverFunc,
#endif
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 4
#if XSERVER_LIBPCIACCESS
VMwareDeviceMatch,
VMwarePciProbe,
#else
NULL,
NULL,
#endif
#endif
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 13
#ifdef XSERVER_PLATFORM_BUS
VMwarePlatformProbe,
#else
NULL,
#endif
#endif
};
#ifdef XFree86LOADER
static MODULESETUPPROTO(vmwareSetup);
_X_EXPORT XF86ModuleData vmwareModuleData = {
&vmwareVersRec,
vmwareSetup,
NULL
};
static pointer
vmwareSetup(pointer module, pointer opts, int *errmaj, int *errmin)
{
static Bool setupDone = FALSE;
if (!setupDone) {
setupDone = TRUE;
xf86AddDriver(&vmware, module, VMWARE_DRIVER_FUNC);
VMWARERefSymLists();
return (pointer)1;
}
if (errmaj) {
*errmaj = LDR_ONCEONLY;
}
return NULL;
}
#endif /* XFree86LOADER */