PDMDriver.cpp revision 83df31c21044349888e688d5f793ce39007e6693
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * PDM - Pluggable Device and Driver Manager, Driver parts.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * available from http://www.virtualbox.org. This file is free software;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * you can redistribute it and/or modify it under the terms of the GNU
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * General Public License (GPL) as published by the Free Software
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * additional information or have any questions.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync/*******************************************************************************
edc0ced209cf455268870a686b88fd851f3a4188vboxsync* Header Files *
edc0ced209cf455268870a686b88fd851f3a4188vboxsync*******************************************************************************/
edc0ced209cf455268870a686b88fd851f3a4188vboxsync/*******************************************************************************
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync* Structures and Typedefs *
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync*******************************************************************************/
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Internal callback structure pointer.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * The main purpose is to define the extra data we associate
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * with PDMDRVREGCB so we can find the VM instance and so on.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync /** The callback structure. */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync /** A bit of padding. */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync /** VM Handle. */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync/*******************************************************************************
edc0ced209cf455268870a686b88fd851f3a4188vboxsync* Internal Functions *
edc0ced209cf455268870a686b88fd851f3a4188vboxsync*******************************************************************************/
edc0ced209cf455268870a686b88fd851f3a4188vboxsync/** @def PDMDRV_ASSERT_DRVINS
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync * Asserts the validity of the driver instance.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Assert(pDrvIns->u32Version == PDM_DRVINS_VERSION); \
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Assert(pDrvIns->pvInstanceData == (void *)&pDrvIns->achInstanceData[0]); \
edc0ced209cf455268870a686b88fd851f3a4188vboxsync } while (0)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync# define PDMDRV_ASSERT_DRVINS(pDrvIns) do { } while (0)
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic DECLCALLBACK(int) pdmR3DrvRegister(PCPDMDRVREGCB pCallbacks, PCPDMDRVREG pDrvReg);
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic int pdmR3DrvLoad(PVM pVM, PPDMDRVREGCBINT pRegCB, const char *pszFilename, const char *pszName);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Register external drivers
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * @returns VBox status code.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * @param pVM The VM to operate on.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * @param pfnCallback Driver registration callback
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsyncVMMR3DECL(int) PDMR3RegisterDrivers(PVM pVM, FNPDMVBOXDRIVERSREGISTER pfnCallback)
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync * The registration callbacks.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("VBoxDriversRegister failed with rc=%Rrc\n"));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * This function will initialize the drivers for this VM instance.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * First of all this mean loading the builtin drivers and letting them
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * register themselves. Beyond that any additional driver modules are
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * loaded and called for registration.
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync * @returns VBox status code.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * @param pVM VM Handle.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertRelease(!(RT_OFFSETOF(PDMDRVINS, achInstanceData) & 15));
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync AssertRelease(sizeof(pDrvInsAssert->Internal.s) <= sizeof(pDrvInsAssert->Internal.padding));
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync * The registration callbacks.
cadd9de82d5169aad827fe8d68e41a78ebbc6410vboxsync * Load the builtin module
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync PCFGMNODE pDriversNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM/Drivers");
edc0ced209cf455268870a686b88fd851f3a4188vboxsync int rc = CFGMR3QueryBool(pDriversNode, "LoadBuiltin", &fLoadBuiltin);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("Configuration error: Querying boolean \"LoadBuiltin\" failed with %Rrc\n", rc));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync /* make filename */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync char *pszFilename = pdmR3FileR3("VBoxDD", /*fShared=*/true);
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync rc = pdmR3DrvLoad(pVM, &RegCB, pszFilename, "VBoxDD");
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Load additional driver modules.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync for (PCFGMNODE pCur = CFGMR3GetFirstChild(pDriversNode); pCur; pCur = CFGMR3GetNextChild(pCur))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Get the name and path.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync rc = CFGMR3GetName(pCur, &szName[0], sizeof(szName));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("configuration error: The module name is too long, cchName=%zu.\n", CFGMR3GetNameLen(pCur)));
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync /* the path is optional, if no path the module name + path is used. */
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync rc = CFGMR3QueryString(pCur, "Path", &szFilename[0], sizeof(szFilename));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("configuration error: Failure to query the module path, rc=%Rrc.\n", rc));
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync /* prepend path? */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("Filename too long! cch=%d '%s'\n", cch, psz));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Load the module and register it's drivers.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync rc = pdmR3DrvLoad(pVM, &RegCB, szFilename, szName);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Loads one driver module and call the registration entry point.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * @returns VBox status code.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * @param pVM VM handle.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * @param pRegCB The registration callback stuff.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * @param pszFilename Module filename.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * @param pszName Module name.
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsyncstatic int pdmR3DrvLoad(PVM pVM, PPDMDRVREGCBINT pRegCB, const char *pszFilename, const char *pszName)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync int rc = pdmR3LoadR3U(pVM->pUVM, pszFilename, pszName);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Get the registration export and call it.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync rc = PDMR3LdrGetSymbolR3(pVM, pszName, "VBoxDriversRegister", (void **)&pfnVBoxDriversRegister);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Log(("PDM: Calling VBoxDriversRegister (%p) of %s (%s)\n", pfnVBoxDriversRegister, pszName, pszFilename));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync rc = pfnVBoxDriversRegister(&pRegCB->Core, VBOX_VERSION);
edc0ced209cf455268870a686b88fd851f3a4188vboxsync Log(("PDM: Successfully loaded driver module %s (%s).\n", pszName, pszFilename));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("VBoxDriversRegister failed with rc=%Rrc\n"));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("Failed to locate 'VBoxDriversRegister' in %s (%s) rc=%Rrc\n", pszName, pszFilename, rc));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("Failed to load %s (%s) rc=%Rrc!\n", pszName, pszFilename, rc));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync/** @copydoc PDMDRVREGCB::pfnRegister */
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncstatic DECLCALLBACK(int) pdmR3DrvRegister(PCPDMDRVREGCB pCallbacks, PCPDMDRVREG pDrvReg)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Validate the registration structure.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("Unknown struct version %#x!\n", pDrvReg->u32Version));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync || strlen(pDrvReg->szDriverName) >= sizeof(pDrvReg->szDriverName))
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync AssertMsgFailed(("Invalid name '%s'\n", pDrvReg->szDriverName));
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync if ((pDrvReg->fFlags & PDM_DRVREG_FLAGS_HOST_BITS_MASK) != PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT)
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync AssertMsgFailed(("Invalid host bits flags! fFlags=%#x (Driver %s)\n", pDrvReg->fFlags, pDrvReg->szDriverName));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("Max instances %u! (Driver %s)\n", pDrvReg->cMaxInstances, pDrvReg->szDriverName));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("Instance size above 1MB, %d bytes! (Driver %s)\n", pDrvReg->cbInstance, pDrvReg->szDriverName));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("No constructore! (Driver %s)\n", pDrvReg->szDriverName));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Check for duplicate and find FIFO entry at the same time.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync PCPDMDRVREGCBINT pRegCB = (PCPDMDRVREGCBINT)pCallbacks;
edc0ced209cf455268870a686b88fd851f3a4188vboxsync if (!strcmp(pDrv->pDrvReg->szDriverName, pDrvReg->szDriverName))
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("Driver '%s' already exists\n", pDrvReg->szDriverName));
cadd9de82d5169aad827fe8d68e41a78ebbc6410vboxsync * Allocate new driver structure and insert it into the list.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync pDrv = (PPDMDRV)MMR3HeapAlloc(pRegCB->pVM, MM_TAG_PDM_DRIVER, sizeof(*pDrv));
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync Log(("PDM: Registered driver '%s'\n", pDrvReg->szDriverName));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Lookups a driver structure by name.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * @internal
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncPPDMDRV pdmR3DrvLookup(PVM pVM, const char *pszName)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync for (PPDMDRV pDrv = pVM->pdm.s.pDrvs; pDrv; pDrv = pDrv->pNext)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Detaches a driver from whatever it's attached to.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * This will of course lead to the destruction of the driver and all drivers below it in the chain.
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync * @returns VINF_SUCCESS
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync * @param pDrvIns The driver instance to detach.
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsyncint pdmR3DrvDetach(PPDMDRVINS pDrvIns, uint32_t fFlags)
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync LogFlow(("pdmR3DrvDetach: pDrvIns=%p '%s'/%d\n", pDrvIns, pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Check that we're not doing this recursively, that could have unwanted sideeffects!
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("Recursive detach! '%s'/%d\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync * Check that we actually can detach this instance.
ecc1743369d58e0618f528b22a7b82b57dcd47advboxsync * The requirement is that the driver/device above has a detach method.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync : !pDrvIns->Internal.s.pLun->pDevIns->pDevReg->pfnDetach)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync AssertMsgFailed(("Cannot detach driver instance because the driver/device above doesn't support it!\n"));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Join paths with pdmR3DrvDestroyChain.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Destroys a driver chain starting with the specified driver.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * This is used when unplugging a device at run time.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * @param pDrvIns Pointer to the driver instance to start with.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
edc0ced209cf455268870a686b88fd851f3a4188vboxsyncvoid pdmR3DrvDestroyChain(PPDMDRVINS pDrvIns, uint32_t fFlags)
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Detach the bottommost driver until we've detached pDrvIns.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync /* find the driver to detach. */
edc0ced209cf455268870a686b88fd851f3a4188vboxsync LogFlow(("pdmR3DrvDetach: pCur=%p '%s'/%d\n", pCur, pCur->pDrvReg->szDriverName, pCur->iInstance));
edc0ced209cf455268870a686b88fd851f3a4188vboxsync * Unlink it and notify parent.
edc0ced209cf455268870a686b88fd851f3a4188vboxsync /* driver parent */
int rc;
if (pNode)
char *pszName;
if (pDrv)
if (!pConfigNode)
if (pNew)
pNew->pUpBase = &pDrvIns->IBase; /* This ain't safe, you can calc the pDrvIns of the up/down driver! */
Log(("PDM: Constructing driver '%s' instance %d...\n", pNew->pDrvReg->szDriverName, pNew->iInstance));
return rc;
int rc;
return rc;
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_MountPrepare(PPDMDRVINS pDrvIns, const char *pszFilename, const char *pszCoreDriver)
pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pszFilename, pszFilename, pszCoreDriver, pszCoreDriver));
return VERR_PDM_DRIVER_ALREADY_ATTACHED;
if (pNode)
if (!pszCoreDriver)
return VERR_NOT_IMPLEMENTED;
return rc;
return rc;
static DECLCALLBACK(bool) pdmR3DrvHlp_AssertEMT(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance);
static DECLCALLBACK(bool) pdmR3DrvHlp_AssertOther(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance);
static DECLCALLBACK(int) pdmR3DrvHlp_VMSetError(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVM, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_VMSetErrorV(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVM, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_VMSetRuntimeError(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_VMSetRuntimeErrorV(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_PDMQueueCreate(PPDMDRVINS pDrvIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval,
LogFlow(("pdmR3DrvHlp_PDMQueueCreate: caller='%s'/%d: cbItem=%d cItems=%d cMilliesInterval=%d pfnCallback=%p pszName=%p:{%s} ppQueue=%p\n",
pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, pszName, pszName, ppQueue, ppQueue));
int rc = PDMR3QueueCreateDriver(pVM, pDrvIns, cbItem, cItems, cMilliesInterval, pfnCallback, pszName, ppQueue);
LogFlow(("pdmR3DrvHlp_PDMQueueCreate: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc, *ppQueue));
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_TMTimerCreate(PPDMDRVINS pDrvIns, TMCLOCK enmClock, PFNTMTIMERDRV pfnCallback, void *pvUser, uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer)
LogFlow(("pdmR3DrvHlp_TMTimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pvUser=%p fFlags=%#x pszDesc=%p:{%s} ppTimer=%p\n",
pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, enmClock, pfnCallback, pvUser, fFlags, pszDesc, pszDesc, ppTimer));
int rc = TMR3TimerCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, ppTimer);
LogFlow(("pdmR3DrvHlp_TMTimerCreate: caller='%s'/%d: returns %Rrc *ppTimer=%p\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc, *ppTimer));
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_SSMRegister(PPDMDRVINS pDrvIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
LogFlow(("pdmR3DrvHlp_SSMRegister: caller='%s'/%d: pszName=%p:{%s} u32Instance=%#x u32Version=#x cbGuess=%#x pfnSavePrep=%p pfnSaveExec=%p pfnSaveDone=%p pszLoadPrep=%p pfnLoadExec=%p pfnLoaddone=%p\n",
pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pszName, pszName, u32Instance, u32Version, cbGuess, pfnSavePrep, pfnSaveExec, pfnSaveDone, pfnLoadPrep, pfnLoadExec, pfnLoadDone));
int rc = SSMR3RegisterDriver(pDrvIns->Internal.s.pVM, pDrvIns, pszName, u32Instance, u32Version, cbGuess,
LogFlow(("pdmR3DrvHlp_SSMRegister: caller='%s'/%d: returns %Rrc\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_SSMDeregister(PPDMDRVINS pDrvIns, const char *pszName, uint32_t u32Instance)
LogFlow(("pdmR3DrvHlp_SSMDeregister: caller='%s'/%d: returns %Rrc\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
return rc;
static DECLCALLBACK(void) pdmR3DrvHlp_STAMRegister(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
/** @todo track the samples so they can be dumped & deregistered when the driver instance is destroyed.
static DECLCALLBACK(void) pdmR3DrvHlp_STAMRegisterF(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
int rc = STAMR3RegisterV(pDrvIns->Internal.s.pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
static DECLCALLBACK(void) pdmR3DrvHlp_STAMRegisterV(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
int rc = STAMR3RegisterV(pDrvIns->Internal.s.pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_SUPCallVMMR0Ex(PPDMDRVINS pDrvIns, unsigned uOperation, void *pvArg, unsigned cbArg)
int rc;
rc = SUPR3CallVMMR0Ex(pDrvIns->Internal.s.pVM->pVMR0, NIL_VMCPUID, uOperation, 0, (PSUPVMMR0REQHDR)pvArg);
LogFlow(("pdmR3DrvHlp_SUPCallVMMR0Ex: caller='%s'/%d: returns %Rrc\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_USBRegisterHub(PPDMDRVINS pDrvIns, uint32_t fVersions, uint32_t cPorts, PCPDMUSBHUBREG pUsbHubReg, PPCPDMUSBHUBHLP ppUsbHubHlp)
LogFlow(("pdmR3DrvHlp_USBRegisterHub: caller='%s'/%d: fVersions=%#x cPorts=%#x pUsbHubReg=%p ppUsbHubHlp=%p\n",
#ifdef VBOX_WITH_USB
int rc = pdmR3UsbRegisterHub(pDrvIns->Internal.s.pVM, pDrvIns, fVersions, cPorts, pUsbHubReg, ppUsbHubHlp);
LogFlow(("pdmR3DrvHlp_USBRegisterHub: caller='%s'/%d: returns %Rrc\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_PDMThreadCreate(PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
LogFlow(("pdmR3DrvHlp_PDMThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
int rc = pdmR3ThreadCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
LogFlow(("pdmR3DrvHlp_PDMThreadCreate: caller='%s'/%d: returns %Rrc *ppThread=%RTthrd\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance,
return rc;
LogFlow(("pdmR3DrvHlp_VMState: caller='%s'/%d: returns %d (%s)\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance,
return enmVMState;
static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
const char *pszDesc)
LogFlow(("pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate: caller='%s'/%d: ppTemplate=%p pfnCompleted=%p pszDesc=%p:{%s}\n",
int rc = PDMR3AsyncCompletionTemplateCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, ppTemplate, pfnCompleted, pvTemplateUser, pszDesc);
LogFlow(("pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate: caller='%s'/%d: returns %Rrc *ppThread=%p\n", pDrvIns->pDrvReg->szDriverName,
return rc;