PDMDriver.cpp revision e56dcfc21604789f99b06a9353f45ed5205256ad
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * PDM - Pluggable Device and Driver Manager, Driver parts.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * Copyright (C) 2006-2010 Oracle Corporation
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * available from http://www.virtualbox.org. This file is free software;
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * General Public License (GPL) as published by the Free Software
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync/*******************************************************************************
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync* Header Files *
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync*******************************************************************************/
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync/*******************************************************************************
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync* Structures and Typedefs *
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync*******************************************************************************/
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * Internal callback structure pointer.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * The main purpose is to define the extra data we associate
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * with PDMDRVREGCB so we can find the VM instance and so on.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync /** The callback structure. */
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync /** A bit of padding. */
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync /** VM Handle. */
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync /** Pointer to the configuration node the registrations should be
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * associated with. Can be NULL. */
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync/*******************************************************************************
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync* Internal Functions *
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync*******************************************************************************/
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsyncstatic DECLCALLBACK(int) pdmR3DrvRegister(PCPDMDRVREGCB pCallbacks, PCPDMDRVREG pReg);
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsyncstatic int pdmR3DrvLoad(PVM pVM, PPDMDRVREGCBINT pRegCB, const char *pszFilename, const char *pszName);
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * Register external drivers
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * @returns VBox status code.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * @param pVM The VM to operate on.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * @param pfnCallback Driver registration callback
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsyncVMMR3DECL(int) PDMR3RegisterDrivers(PVM pVM, FNPDMVBOXDRIVERSREGISTER pfnCallback)
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * The registration callbacks.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync AssertMsgFailed(("VBoxDriversRegister failed with rc=%Rrc\n"));
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * This function will initialize the drivers for this VM instance.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * First of all this mean loading the builtin drivers and letting them
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * register themselves. Beyond that any additional driver modules are
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * loaded and called for registration.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * @returns VBox status code.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * @param pVM VM Handle.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync AssertRelease(!(RT_OFFSETOF(PDMDRVINS, achInstanceData) & 15));
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync AssertCompile(sizeof(pDrvInsAssert->Internal.s) <= sizeof(pDrvInsAssert->Internal.padding));
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync AssertRelease(sizeof(pDrvInsAssert->Internal.s) <= sizeof(pDrvInsAssert->Internal.padding));
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * The registration callbacks.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * Load the builtin module
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync PCFGMNODE pDriversNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM/Drivers");
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync int rc = CFGMR3QueryBool(pDriversNode, "LoadBuiltin", &fLoadBuiltin);
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync AssertMsgFailed(("Configuration error: Querying boolean \"LoadBuiltin\" failed with %Rrc\n", rc));
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync /* make filename */
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync char *pszFilename = pdmR3FileR3("VBoxDD", true /*fShared*/);
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync rc = pdmR3DrvLoad(pVM, &RegCB, pszFilename, "VBoxDD");
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * Load additional driver modules.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync for (PCFGMNODE pCur = CFGMR3GetFirstChild(pDriversNode); pCur; pCur = CFGMR3GetNextChild(pCur))
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * Get the name and path.
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync rc = CFGMR3GetName(pCur, &szName[0], sizeof(szName));
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync AssertMsgFailed(("configuration error: The module name is too long, cchName=%zu.\n", CFGMR3GetNameLen(pCur)));
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync /* the path is optional, if no path the module name + path is used. */
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync rc = CFGMR3QueryString(pCur, "Path", &szFilename[0], sizeof(szFilename));
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync AssertMsgFailed(("configuration error: Failure to query the module path, rc=%Rrc.\n", rc));
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync /* prepend path? */
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync char *psz = pdmR3FileR3(szFilename, false /*fShared*/);
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync AssertMsgFailed(("Filename too long! cch=%d '%s'\n", cch, psz));
a5e7ae69e440f6816420fc99599f044e79e716b6vboxsync * Load the module and register it's drivers.
return rc;
return VINF_SUCCESS;
static int pdmR3DrvLoad(PVM pVM, PPDMDRVREGCBINT pRegCB, const char *pszFilename, const char *pszName)
Log(("PDM: Calling VBoxDriversRegister (%p) of %s (%s)\n", pfnVBoxDriversRegister, pszName, pszFilename));
AssertMsgFailed(("Failed to locate 'VBoxDriversRegister' in %s (%s) rc=%Rrc\n", pszName, pszFilename, rc));
return rc;
AssertMsgReturn(!(pReg->fFlags & ~(PDM_DRVREG_FLAGS_HOST_BITS_MASK | PDM_DRVREG_FLAGS_R0 | PDM_DRVREG_FLAGS_RC)),
AssertMsgReturn((pReg->fFlags & PDM_DRVREG_FLAGS_HOST_BITS_MASK) == PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
return VERR_PDM_DRIVER_NAME_CLASH;
int rc;
if (pDrv)
if (pDrvPrev)
return VINF_SUCCESS;
return rc;
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(int) pdmR3DrvHlp_DBGFInfoRegister(PPDMDRVINS pDrvIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler)
LogFlow(("pdmR3DrvHlp_DBGFInfoRegister: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
int rc = DBGFR3InfoRegisterDriver(pDrvIns->Internal.s.pVMR3, pszName, pszDesc, pfnHandler, pDrvIns);
LogFlow(("pdmR3DrvHlp_DBGFInfoRegister: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName, pDrvIns->iInstance, rc));
return rc;
LogFlow(("pdmR3DrvHlp_DBGFInfoDeregister: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
LogFlow(("pdmR3DrvHlp_DBGFInfoDeregister: 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)
rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDrvIns->pReg->szR0Mod, pDrvIns->Internal.s.pDrv->pszR0SearchPath, szSymbol,
return rc;
const char *pcszId)