summaryrefslogtreecommitdiff
path: root/src/vmware_bootstrap.c
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2011-11-22 18:37:44 +0100
committerThomas Hellstrom <thellstrom@vmware.com>2011-11-25 16:51:46 +0100
commit2aa256c96496ed6dd9dbd5880c278f4422500b0f (patch)
treeee82bb082b11d45c5566ff377a256866588e285f /src/vmware_bootstrap.c
parent70487eee975c63b5ed1492927bbc661425278276 (diff)
vmwlegacy: Factor out bootstrap functions
Preparing for choosing driver path in preinit instead of using shim loader. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Jakob Bornecrantz <jakob@vmware.com>
Diffstat (limited to 'src/vmware_bootstrap.c')
-rw-r--r--src/vmware_bootstrap.c465
1 files changed, 465 insertions, 0 deletions
diff --git a/src/vmware_bootstrap.c b/src/vmware_bootstrap.c
new file mode 100644
index 0000000..45f8cc2
--- /dev/null
+++ b/src/vmware_bootstrap.c
@@ -0,0 +1,465 @@
+/*
+ * 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 "xf86PciInfo.h" /* pci vendor id */
+#include "xf86Pci.h" /* pci */
+#include "vm_device_version.h"
+#include "vmware_bootstrap.h"
+
+#ifndef HAVE_XORG_SERVER_1_5_0
+#include <xf86_ansic.h>
+#include <xf86_libc.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
+/*
+ * So that the file compiles unmodified when dropped into an xfree source tree.
+ */
+#ifndef XORG_VERSION_CURRENT
+#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT
+#endif
+
+/*
+ * Sanity check that xf86PciInfo.h has the correct values (which come from
+ * the VMware source tree in vm_device_version.h.
+ */
+#if PCI_CHIP_VMWARE0405 != PCI_DEVICE_ID_VMWARE_SVGA2
+#error "PCI_CHIP_VMWARE0405 is wrong, update it from vm_device_version.h"
+#endif
+#if PCI_CHIP_VMWARE0710 != PCI_DEVICE_ID_VMWARE_SVGA
+#error "PCI_CHIP_VMWARE0710 is wrong, update it from vm_device_version.h"
+#endif
+#if PCI_VENDOR_VMWARE != PCI_VENDOR_ID_VMWARE
+#error "PCI_VENDOR_VMWARE is wrong, update it from vm_device_version.h"
+#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_NAME "vmwlegacy"
+#define VMWARE_DRIVER_NAME "vmwlegacy"
+#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)
+
+static const char VMWAREBuildStr[] = "VMware Guest X Server "
+ VMWARE_DRIVER_VERSION_STRING " - build=$Name$\n";
+
+/*
+ * 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 vmwlegacy_drv_modinfo[]
+__attribute__((section(".modinfo"),unused)) =
+ "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH);
+#else
+const char vmwlegacy_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_VMWARE, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
+
+static const struct pci_id_match VMwareDeviceMatch[] = {
+ VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0405, 0 ),
+ VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0710, 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_CHIP_VMWARE0405, PCI_CHIP_VMWARE0405, RES_EXCLUSIVE_VGA },
+ { PCI_CHIP_VMWARE0710, PCI_CHIP_VMWARE0710, vmwareLegacyRes },
+ { -1, -1, RES_UNDEFINED }
+};
+
+static SymTabRec VMWAREChipsets[] = {
+ { PCI_CHIP_VMWARE0405, "vmware0405" },
+ { PCI_CHIP_VMWARE0710, "vmware0710" },
+ { -1, NULL }
+};
+
+#ifdef XFree86LOADER
+static XF86ModuleVersionInfo vmwlegacyVersRec = {
+ 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_DEFAULT_MODE, "AddDefaultMode", 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;
+}
+
+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;
+ pScrn->driverPrivate = NULL;
+
+ pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+ if (pEnt->location.type != BUS_PCI)
+ return FALSE;
+
+ pciInfo = xf86GetPciInfoForEntity(pEnt->index);
+ if (pciInfo == NULL)
+ return FALSE;
+
+ pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets,
+ DEVICE_ID(pciInfo));
+
+ ErrorF("Stub bitsperpixel is %d\n", pScrn->bitsPerPixel);
+
+ 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;
+ EntityInfoPtr entity;
+
+ 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;
+ }
+
+ entity = xf86GetEntityInfo(entity_num);
+ switch (DEVICE_ID(device)) {
+ case PCI_CHIP_VMWARE0405:
+ case PCI_CHIP_VMWARE0710:
+ xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n");
+ vmwlegacy_hookup(scrn);
+ scrn->driverPrivate = scrn->PreInit;
+ scrn->PreInit = VMwarePreinitStub;
+ break;
+ default:
+ xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Unknown device\n");
+ }
+ return scrn != NULL;
+}
+#else
+
+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_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 suceeded\n"));
+ pScrn->driverVersion = VMWARE_DRIVER_VERSION;
+ pScrn->driverName = VMWARE_DRIVER_NAME;
+ pScrn->name = VMWARE_NAME;
+ pScrn->Probe = VMWAREProbe;
+ pScrn->PreInit = VMWAREPreInit;
+ vmwlegacy_hookup(scrn);
+ scrn->driverPrivate = scrn->PreInit;
+ scrn->PreInit = VMwarePreinitStub;
+ foundScreen = TRUE;
+ }
+ }
+ free(usedChips);
+ }
+ return foundScreen;
+}
+#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)
+{
+ CARD32 *flag;
+ xorgRRModeMM *modemm;
+
+ switch (op) {
+ case GET_REQUIRED_HW_INTERFACES:
+ flag = (CARD32 *)data;
+
+ if (flag) {
+ *flag = HW_IO | HW_MMIO;
+ }
+ 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;
+ default:
+ return FALSE;
+ }
+}
+#endif
+
+
+_X_EXPORT DriverRec vmwlegacy = {
+ VMWARE_DRIVER_VERSION,
+ VMWARE_DRIVER_NAME,
+ VMWAREIdentify,
+#if XSERVER_LIBPCIACCESS
+ NULL,
+#else
+ VMWAREProbe,
+#endif
+ VMWAREAvailableOptions,
+ NULL,
+ 0,
+#if VMWARE_DRIVER_FUNC
+ VMWareDriverFunc,
+#endif
+#if XSERVER_LIBPCIACCESS
+ VMwareDeviceMatch,
+ VMwarePciProbe,
+#endif
+};
+
+#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5)
+
+#define xf86LoaderReqSymLists(...) do {} while (0)
+#define LoaderRefSymLists(...) do {} while (0)
+
+#else
+
+const char *vgahwSymbols[] = {
+ "vgaHWGetHWRec",
+ "vgaHWGetIOBase",
+ "vgaHWGetIndex",
+ "vgaHWInit",
+ "vgaHWProtect",
+ "vgaHWRestore",
+ "vgaHWSave",
+ "vgaHWSaveScreen",
+ "vgaHWUnlock",
+ NULL
+};
+
+static const char *fbSymbols[] = {
+ "fbCreateDefColormap",
+ "fbPictureInit",
+ "fbScreenInit",
+ NULL
+};
+
+static const char *ramdacSymbols[] = {
+ "xf86CreateCursorInfoRec",
+ "xf86DestroyCursorInfoRec",
+ "xf86InitCursor",
+ NULL
+};
+
+static const char *shadowfbSymbols[] = {
+ "ShadowFBInit2",
+ NULL
+};
+#endif
+
+#ifdef XFree86LOADER
+static MODULESETUPPROTO(vmwlegacySetup);
+
+_X_EXPORT XF86ModuleData vmwlegacyModuleData = {
+ &vmwlegacyVersRec,
+ vmwlegacySetup,
+ NULL
+};
+
+static pointer
+vmwlegacySetup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = FALSE;
+
+ if (!setupDone) {
+ setupDone = TRUE;
+
+ xf86AddDriver(&vmwlegacy, module, VMWARE_DRIVER_FUNC);
+
+ LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols,
+ shadowfbSymbols, NULL);
+
+ return (pointer)1;
+ }
+ if (errmaj) {
+ *errmaj = LDR_ONCEONLY;
+ }
+ return NULL;
+}
+#endif /* XFree86LOADER */