PDMDriver.cpp revision 766956791b9a42fc91ba6f8bd8be7f6a6f7ba092
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * PDM - Pluggable Device and Driver Manager, Driver parts.
1be6c03d6e9f1ef801ff29b318baa5d42f1bfc2evboxsync * Copyright (C) 2006-2010 Oracle Corporation
c98fb3e16fcd571a790eab772c0c66173d225205vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
c98fb3e16fcd571a790eab772c0c66173d225205vboxsync * available from http://www.virtualbox.org. This file is free software;
c98fb3e16fcd571a790eab772c0c66173d225205vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync/*******************************************************************************
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync* Header Files *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync*******************************************************************************/
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/*******************************************************************************
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync* Structures and Typedefs *
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync*******************************************************************************/
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Internal callback structure pointer.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * The main purpose is to define the extra data we associate
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * with PDMDRVREGCB so we can find the VM instance and so on.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** The callback structure. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /** A bit of padding. */
9621896680fea9b2078823e8ef2e64cec5bf2da0vboxsync /** VM Handle. */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/*******************************************************************************
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync* Internal Functions *
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync*******************************************************************************/
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic DECLCALLBACK(int) pdmR3DrvRegister(PCPDMDRVREGCB pCallbacks, PCPDMDRVREG pReg);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic int pdmR3DrvLoad(PVM pVM, PPDMDRVREGCBINT pRegCB, const char *pszFilename, const char *pszName);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Register external drivers
d428342802b081b076970ddb499d215b79f087ccvboxsync * @returns VBox status code.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * @param pVM The VM to operate on.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * @param pfnCallback Driver registration callback
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncVMMR3DECL(int) PDMR3RegisterDrivers(PVM pVM, FNPDMVBOXDRIVERSREGISTER pfnCallback)
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * The registration callbacks.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgFailed(("VBoxDriversRegister failed with rc=%Rrc\n"));
3f1eb07aba9eee6394f3084c956149ee9a27df09vboxsync * This function will initialize the drivers for this VM instance.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * First of all this mean loading the builtin drivers and letting them
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * register themselves. Beyond that any additional driver modules are
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * loaded and called for registration.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * @returns VBox status code.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * @param pVM VM Handle.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertRelease(!(RT_OFFSETOF(PDMDRVINS, achInstanceData) & 15));
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertRelease(sizeof(pDrvInsAssert->Internal.s) <= sizeof(pDrvInsAssert->Internal.padding));
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * The registration callbacks.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Load the builtin module
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync PCFGMNODE pDriversNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM/Drivers");
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync int rc = CFGMR3QueryBool(pDriversNode, "LoadBuiltin", &fLoadBuiltin);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgFailed(("Configuration error: Querying boolean \"LoadBuiltin\" failed with %Rrc\n", rc));
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /* make filename */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync char *pszFilename = pdmR3FileR3("VBoxDD", /*fShared=*/true);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync rc = pdmR3DrvLoad(pVM, &RegCB, pszFilename, "VBoxDD");
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Load additional driver modules.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync for (PCFGMNODE pCur = CFGMR3GetFirstChild(pDriversNode); pCur; pCur = CFGMR3GetNextChild(pCur))
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Get the name and path.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync rc = CFGMR3GetName(pCur, &szName[0], sizeof(szName));
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgFailed(("configuration error: The module name is too long, cchName=%zu.\n", CFGMR3GetNameLen(pCur)));
1be6c03d6e9f1ef801ff29b318baa5d42f1bfc2evboxsync /* the path is optional, if no path the module name + path is used. */
1be6c03d6e9f1ef801ff29b318baa5d42f1bfc2evboxsync rc = CFGMR3QueryString(pCur, "Path", &szFilename[0], sizeof(szFilename));
1be6c03d6e9f1ef801ff29b318baa5d42f1bfc2evboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgFailed(("configuration error: Failure to query the module path, rc=%Rrc.\n", rc));
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync /* prepend path? */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgFailed(("Filename too long! cch=%d '%s'\n", cch, psz));
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Load the module and register it's drivers.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync rc = pdmR3DrvLoad(pVM, &RegCB, szFilename, szName);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Loads one driver module and call the registration entry point.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * @returns VBox status code.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * @param pVM VM handle.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * @param pRegCB The registration callback stuff.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * @param pszFilename Module filename.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * @param pszName Module name.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic int pdmR3DrvLoad(PVM pVM, PPDMDRVREGCBINT pRegCB, const char *pszFilename, const char *pszName)
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync int rc = pdmR3LoadR3U(pVM->pUVM, pszFilename, pszName);
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync * Get the registration export and call it.
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync rc = PDMR3LdrGetSymbolR3(pVM, pszName, "VBoxDriversRegister", (void **)&pfnVBoxDriversRegister);
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync Log(("PDM: Calling VBoxDriversRegister (%p) of %s (%s)\n", pfnVBoxDriversRegister, pszName, pszFilename));
4e47bb772df0d04d1ded3e06354de547d52e2d06vboxsync rc = pfnVBoxDriversRegister(&pRegCB->Core, VBOX_VERSION);
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync Log(("PDM: Successfully loaded driver module %s (%s).\n", pszName, pszFilename));
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgFailed(("VBoxDriversRegister failed with rc=%Rrc\n"));
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgFailed(("Failed to locate 'VBoxDriversRegister' in %s (%s) rc=%Rrc\n", pszName, pszFilename, rc));
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgFailed(("Failed to load %s (%s) rc=%Rrc!\n", pszName, pszFilename, rc));
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync/** @interface_method_impl{PDMDRVREGCB,pfnRegister} */
cacc4e75dbbff469c10a505168208f064c6c385cvboxsyncstatic DECLCALLBACK(int) pdmR3DrvRegister(PCPDMDRVREGCB pCallbacks, PCPDMDRVREG pReg)
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Validate the registration structure.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgReturn(pReg->u32Version == PDM_DRVREG_VERSION,
11bc79171b92d5853ebfa8b47a6db79a85347df3vboxsync AssertReturn(pReg->szName[0], VERR_PDM_INVALID_DRIVER_REGISTRATION);
11bc79171b92d5853ebfa8b47a6db79a85347df3vboxsync AssertMsgReturn(memchr(pReg->szName, '\0', sizeof(pReg->szName)),
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgReturn( !(pReg->fFlags & PDM_DRVREG_FLAGS_R0)
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync && memchr(pReg->szR0Mod, '\0', sizeof(pReg->szR0Mod))),
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync ("%s: %.*s\n", pReg->szName, sizeof(pReg->szR0Mod), pReg->szR0Mod),
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgReturn( !(pReg->fFlags & PDM_DRVREG_FLAGS_RC)
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync && memchr(pReg->szRCMod, '\0', sizeof(pReg->szRCMod))),
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync ("%s: %.*s\n", pReg->szName, sizeof(pReg->szRCMod), pReg->szRCMod),
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgReturn(!(pReg->fFlags & ~(PDM_DRVREG_FLAGS_HOST_BITS_MASK | PDM_DRVREG_FLAGS_R0 | PDM_DRVREG_FLAGS_RC)),
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgReturn((pReg->fFlags & PDM_DRVREG_FLAGS_HOST_BITS_MASK) == PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgReturn(VALID_PTR(pReg->pfnRelocate) || !(pReg->fFlags & PDM_DRVREG_FLAGS_RC),
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgReturn(pReg->u32VersionEnd == PDM_DRVREG_VERSION,
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Check for duplicate and find FIFO entry at the same time.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync PCPDMDRVREGCBINT pRegCB = (PCPDMDRVREGCBINT)pCallbacks;
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync AssertMsgFailed(("Driver '%s' already exists\n", pReg->szName));
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync * Allocate new driver structure and insert it into the list.
cacc4e75dbbff469c10a505168208f064c6c385cvboxsync pDrv = (PPDMDRV)MMR3HeapAlloc(pRegCB->pVM, MM_TAG_PDM_DRIVER, sizeof(*pDrv));
0dfc79e0666da4c8853deda18a14ebf5819d0d78vboxsync Log(("PDM: Registered driver '%s'\n", pReg->szName));
return VERR_NO_MEMORY;
return pDrv;
return NULL;
char *pszName;
if ( pDrv
if (!pConfigNode)
if (fHyperHeap)
if (pNew)
//pNew->Internal.s.pDown = NULL;
//pNew->Internal.s.fDetaching = false;
//pNew->Internal.s.fVMReset = false;
//pNew->Internal.s.pfnAsyncNotify = NULL;
if (pDrvAbove)
else if (pLun)
if (pLun)
if (pLun)
pDrvAbove, pDrvAbove ? pDrvAbove->pReg->szName : "", pDrvAbove ? pDrvAbove->iInstance : UINT32_MAX));
pDrvAbove, pDrvAbove ? pDrvAbove->pReg->szName : "", pDrvAbove ? pDrvAbove->iInstance : UINT32_MAX));
else if (pDrv)
AssertMsgFailed(("Too many instances of driver '%s', max is %u\n", pszName, pDrv->pReg->cMaxInstances));
return rc;
LogFlow(("pdmR3DrvDetach: pDrvIns=%p '%s'/%d\n", pDrvIns, pDrvIns->pReg->szName, pDrvIns->iInstance));
return VINF_SUCCESS; }
AssertMsgFailed(("Cannot detach driver instance because the driver/device above doesn't support it!\n"));
return VINF_SUCCESS;
if (fHyperHeap)
static DECLCALLBACK(int) pdmR3DrvHlp_Attach(PPDMDRVINS pDrvIns, uint32_t fFlags, PPDMIBASE *ppBaseInterface)
LogFlow(("pdmR3DrvHlp_Attach: caller='%s'/%d: fFlags=%#x\n", pDrvIns->pReg->szName, pDrvIns->iInstance, fFlags));
int rc;
if (pNode)
rc = pdmR3DrvInstantiate(pVM, pNode, &pDrvIns->IBase, pDrvIns, pDrvIns->Internal.s.pLun, ppBaseInterface);
return rc;
int rc;
return rc;
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_MountPrepare(PPDMDRVINS pDrvIns, const char *pszFilename, const char *pszCoreDriver)
pDrvIns->pReg->szName, 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->pReg->szName, 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->pReg->szName, pDrvIns->iInstance);
static DECLCALLBACK(int) pdmR3DrvHlp_VMSetError(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVMR3, 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.pVMR3, 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;
LogFlow(("pdmR3DrvHlp_VMState: caller='%s'/%d: returns %d (%s)\n", pDrvIns->pReg->szName, pDrvIns->iInstance,
return enmVMState;
LogFlow(("pdmR3DrvHlp_VMState: caller='%s'/%d: returns %RTbool)\n", pDrvIns->pReg->szName, pDrvIns->iInstance,
fRc));
return fRc;
LogFlow(("pdmR3DrvHlp_GetSupDrvSession: caller='%s'/%d: returns %p)\n", pDrvIns->pReg->szName, pDrvIns->iInstance,
pSession));
return pSession;
static DECLCALLBACK(int) pdmR3DrvHlp_QueueCreate(PPDMDRVINS pDrvIns, uint32_t cbItem, uint32_t 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->pReg->szName, 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->pReg->szName, 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->pReg->szName, pDrvIns->iInstance, enmClock, pfnCallback, pvUser, fFlags, pszDesc, pszDesc, ppTimer));
int rc = TMR3TimerCreateDriver(pDrvIns->Internal.s.pVMR3, pDrvIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, ppTimer);
LogFlow(("pdmR3DrvHlp_TMTimerCreate: caller='%s'/%d: returns %Rrc *ppTimer=%p\n", pDrvIns->pReg->szName, pDrvIns->iInstance, rc, *ppTimer));
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_SSMRegister(PPDMDRVINS pDrvIns, uint32_t uVersion, size_t cbGuess,
" pfnLivePrep=%p pfnLiveExec=%p pfnLiveVote=%p pfnSavePrep=%p pfnSaveExec=%p pfnSaveDone=%p pszLoadPrep=%p pfnLoadExec=%p pfnLoaddone=%p\n",
int rc = SSMR3RegisterDriver(pDrvIns->Internal.s.pVMR3, pDrvIns, pDrvIns->pReg->szName, pDrvIns->iInstance,
LogFlow(("pdmR3DrvHlp_SSMRegister: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName, 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->pReg->szName, 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.pVMR3, 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.pVMR3, 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.pVMR3->pVMR0, NIL_VMCPUID, uOperation, 0, (PSUPVMMR0REQHDR)pvArg);
LogFlow(("pdmR3DrvHlp_SUPCallVMMR0Ex: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName, 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.pVMR3, pDrvIns, fVersions, cPorts, pUsbHubReg, ppUsbHubHlp);
LogFlow(("pdmR3DrvHlp_USBRegisterHub: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName, pDrvIns->iInstance, rc));
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_SetAsyncNotification(PPDMDRVINS pDrvIns, PFNPDMDRVASYNCNOTIFY pfnAsyncNotify)
LogFlow(("pdmR3DrvHlp_SetAsyncNotification: caller='%s'/%d: pfnAsyncNotify=%p\n", pDrvIns->pReg->szName, pDrvIns->iInstance, pfnAsyncNotify));
AssertStmt(pDrvIns->Internal.s.fVMSuspended || pDrvIns->Internal.s.fVMReset, rc = VERR_WRONG_ORDER);
LogFlow(("pdmR3DrvHlp_SetAsyncNotification: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName, pDrvIns->iInstance, rc));
return rc;
LogFlow(("pdmR3DrvHlp_AsyncNotificationCompleted: caller='%s'/%d:\n", pDrvIns->pReg->szName, pDrvIns->iInstance));
LogFlow(("pdmR3DrvHlp_AsyncNotificationCompleted: caller='%s'/%d: enmVMState=%d\n", pDrvIns->pReg->szName, pDrvIns->iInstance, enmVMState));
static DECLCALLBACK(int) pdmR3DrvHlp_ThreadCreate(PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
LogFlow(("pdmR3DrvHlp_ThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
pDrvIns->pReg->szName, pDrvIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
int rc = pdmR3ThreadCreateDriver(pDrvIns->Internal.s.pVMR3, pDrvIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
LogFlow(("pdmR3DrvHlp_ThreadCreate: caller='%s'/%d: returns %Rrc *ppThread=%RTthrd\n", pDrvIns->pReg->szName, pDrvIns->iInstance,
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_AsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
const char *pszDesc)
LogFlow(("pdmR3DrvHlp_AsyncCompletionTemplateCreate: caller='%s'/%d: ppTemplate=%p pfnCompleted=%p pszDesc=%p:{%s}\n",
int rc = PDMR3AsyncCompletionTemplateCreateDriver(pDrvIns->Internal.s.pVMR3, pDrvIns, ppTemplate, pfnCompleted, pvTemplateUser, pszDesc);
LogFlow(("pdmR3DrvHlp_AsyncCompletionTemplateCreate: caller='%s'/%d: returns %Rrc *ppThread=%p\n", pDrvIns->pReg->szName,
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_LdrGetRCInterfaceSymbols(PPDMDRVINS pDrvIns, void *pvInterface, size_t cbInterface,
LogFlow(("pdmR3DrvHlp_LdrGetRCInterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
pDrvIns->pReg->szName, pDrvIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
int rc;
AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'drv' and contain the driver name!\n",
LogFlow(("pdmR3DrvHlp_LdrGetRCInterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName,
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_LdrGetR0InterfaceSymbols(PPDMDRVINS pDrvIns, void *pvInterface, size_t cbInterface,
LogFlow(("pdmR3DrvHlp_LdrGetR0InterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
pDrvIns->pReg->szName, pDrvIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
int rc;
AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'drv' and contain the driver name!\n",
LogFlow(("pdmR3DrvHlp_LdrGetR0InterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName,
return rc;
int rc = pdmR3CritSectInitDriver(pVM, pDrvIns, pCritSect, RT_SRC_POS_ARGS, "%s_%u", pszName, pDrvIns->iInstance);
return rc;
static DECLCALLBACK(int) pdmR3DrvHlp_CallR0(PPDMDRVINS pDrvIns, uint32_t uOperation, uint64_t u64Arg)
return rc;