PDMDevice.cpp revision 2bce97064c3a5a1dba52a6e0b76c8282ca7b4c5e
/* $Id$ */
/** @file
* PDM - Pluggable Device and Driver Manager, Device parts.
*/
/*
* Copyright (C) 2006-2007 innotek GmbH
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License as published by the Free Software Foundation,
* in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
* distribution. VirtualBox OSE is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_PDM_DEVICE
#include "PDMInternal.h"
#include <iprt/semaphore.h>
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* Internal callback structure pointer.
* The main purpose is to define the extra data we associate
* with PDMDEVREGCB so we can find the VM instance and so on.
*/
typedef struct PDMDEVREGCBINT
{
/** The callback structure. */
/** A bit of padding. */
/** VM Handle. */
typedef const PDMDEVREGCBINT *PCPDMDEVREGCBINT;
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
/* VSlick regex:
search : \om/\*\*.+?\*\/\nDECLCALLBACKMEMBER\(([^,]*), *pfn([^)]*)\)\(
replace: \/\*\* @copydoc PDMDEVHLP::pfn\2 \*\/\nstatic DECLCALLBACK\(\1\) pdmR3DevHlp_\2\(
*/
/** @name R3 DevHlp
* @{
*/
static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn, PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc);
static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterGC(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTGCPTR pvUser, const char *pszOut, const char *pszIn, const char *pszOutStr, const char *pszInStr, const char *pszDesc);
static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTR0PTR pvUser, const char *pszOut, const char *pszIn, const char *pszOutStr, const char *pszInStr, const char *pszDesc);
static DECLCALLBACK(int) pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts);
static DECLCALLBACK(int) pdmR3DevHlp_MMIORegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTHCPTR pvUser,
const char *pszDesc);
static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterGC(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser,
const char *pszDesc);
static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterR0(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser,
const char *pszDesc);
static DECLCALLBACK(int) pdmR3DevHlp_MMIODeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
static DECLCALLBACK(int) pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, const void *pvBinary, bool fShadow, const char *pszDesc);
static DECLCALLBACK(int) pdmR3DevHlp_SSMRegister(PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
static DECLCALLBACK(int) pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERHC ppTimer);
static DECLCALLBACK(PTMTIMERHC) pdmR3DevHlp_TMTimerCreateExternal(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMEREXT pfnCallback, void *pvUser, const char *pszDesc);
static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback);
static DECLCALLBACK(void) pdmR3DevHlp_PCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc);
static DECLCALLBACK(int) pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...);
static DECLCALLBACK(int) pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va);
static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, ...);
static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list va);
static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
static DECLCALLBACK(int) pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args);
static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler);
static DECLCALLBACK(void) pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...);
static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args);
static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, const char *pszName);
static DECLCALLBACK(int) pdmR3DevHlp_PDMThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3);
static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3);
static DECLCALLBACK(int) pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3);
static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3);
static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp);
static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp);
static DECLCALLBACK(int) pdmR3DevHlp_PDMQueueCreate(PPDMDEVINS pDevIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval, PFNPDMQUEUEDEV pfnCallback, bool fGCEnabled, PPDMQUEUE *ppQueue);
static DECLCALLBACK(void) pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead);
static DECLCALLBACK(void) pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite);
static DECLCALLBACK(int) pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb);
static DECLCALLBACK(int) pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb);
static DECLCALLBACK(int) pdmR3DevHlp_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc);
static DECLCALLBACK(int) pdmR3DevHlp_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC);
static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr);
static DECLCALLBACK(bool) pdmR3DevHlp_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser);
static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead);
static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten);
static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel);
static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value);
static DECLCALLBACK(int) pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp);
static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead);
static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr);
static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel);
static DECLCALLBACK(uint8_t) pdmR3DevHlp_Untrusted_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value);
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
/** @} */
/** @name HC PIC Helpers
* @{
*/
#ifdef VBOX_WITH_PDM_LOCK
#endif
/** @} */
/** @name HC APIC Helpers
* @{
*/
#ifdef VBOX_WITH_PDM_LOCK
#endif
/** @} */
/** @name HC I/O APIC Helpers
* @{
*/
static DECLCALLBACK(void) pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
#ifdef VBOX_WITH_PDM_LOCK
#endif
/** @} */
/** @name HC PCI Bus Helpers
* @{
*/
#ifdef VBOX_WITH_PDM_LOCK
#endif
/** @} */
/** @def PDMDEV_ASSERT_DEVINS
* Asserts the validity of the driver instance.
*/
#ifdef VBOX_STRICT
# define PDMDEV_ASSERT_DEVINS(pDevIns) do { Assert(pDevIns); Assert(pDevIns->u32Version == PDM_DEVINS_VERSION); Assert(pDevIns->pvInstanceDataR3 == (void *)&pDevIns->achInstanceData[0]); } while (0)
#else
# define PDMDEV_ASSERT_DEVINS(pDevIns) do { } while (0)
#endif
static int pdmR3DevLoad(PVM pVM, PPDMDEVREGCBINT pRegCB, const char *pszFilename, const char *pszName);
/*
* Allow physical read and writes from any thread
*/
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/**
* The device helper structure for trusted devices.
*/
const PDMDEVHLP g_pdmR3DevHlpTrusted =
{
0,
0,
0,
0,
0,
0,
0,
0,
0,
PDM_DEVHLP_VERSION /* the end */
};
/**
* The device helper structure for non-trusted devices.
*/
const PDMDEVHLP g_pdmR3DevHlpUnTrusted =
{
0,
0,
0,
0,
0,
0,
0,
0,
0,
PDM_DEVHLP_VERSION /* the end */
};
/**
* PIC Device Helpers.
*/
const PDMPICHLPR3 g_pdmR3DevPicHlp =
{
#ifdef VBOX_WITH_PDM_LOCK
#endif
PDM_PICHLPR3_VERSION /* the end */
};
/**
* APIC Device Helpers.
*/
const PDMAPICHLPR3 g_pdmR3DevApicHlp =
{
#ifdef VBOX_WITH_PDM_LOCK
#endif
PDM_APICHLPR3_VERSION /* the end */
};
/**
* I/O APIC Device Helpers.
*/
const PDMIOAPICHLPR3 g_pdmR3DevIoApicHlp =
{
#ifdef VBOX_WITH_PDM_LOCK
#endif
PDM_IOAPICHLPR3_VERSION /* the end */
};
/**
* PCI Bus Device Helpers.
*/
const PDMPCIHLPR3 g_pdmR3DevPciHlp =
{
#ifdef VBOX_WITH_PDM_LOCK
#endif
PDM_PCIHLPR3_VERSION, /* the end */
};
/**
* DMAC Device Helpers.
*/
const PDMDMACHLP g_pdmR3DevDmacHlp =
{
};
/**
* RTC Device Helpers.
*/
const PDMRTCHLP g_pdmR3DevRtcHlp =
{
};
/**
* This function will initialize the devices for this VM instance.
*
*
* First of all this mean loading the builtin device and letting them
* register themselves. Beyond that any additional device modules are
* loaded and called for registration.
*
* Then the device configuration is enumerated, the instantiation order
* is determined, and finally they are instantiated.
*
* After all device have been successfully instantiated the the primary
* PCI Bus device is called to emulate the PCI BIOS, i.e. making the
* resource assignments. If there is no PCI device, this step is of course
* skipped.
*
* Finally the init completion routines of the instantiated devices
* are called.
*
* @returns VBox status code.
* @param pVM VM Handle.
*/
{
LogFlow(("pdmR3DevInit:\n"));
AssertRelease(sizeof(pVM->pdm.s.pDevInstances->Internal.s) <= sizeof(pVM->pdm.s.pDevInstances->Internal.padding));
/*
* Get the GC & R0 devhlps and create the devhlp R3 task queue.
*/
rc = PDMR3QueueCreateInternal(pVM, sizeof(PDMDEVHLPTASK), 8, 0, pdmR3DevHlpQueueConsumer, true, &pVM->pdm.s.pDevHlpQueueHC);
/*
* Initialize the callback structure.
*/
/*
* Load the builtin module
*/
bool fLoadBuiltin;
fLoadBuiltin = true;
else if (VBOX_FAILURE(rc))
{
return rc;
}
if (fLoadBuiltin)
{
/* make filename */
if (!pszFilename)
return VERR_NO_TMP_MEMORY;
if (VBOX_FAILURE(rc))
return rc;
/* make filename */
if (!pszFilename)
return VERR_NO_TMP_MEMORY;
if (VBOX_FAILURE(rc))
return rc;
}
/*
* Load additional device modules.
*/
{
/*
* Get the name and path.
*/
char szName[PDMMOD_NAME_LEN];
if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
{
AssertMsgFailed(("configuration error: The module name is too long, cchName=%d.\n", CFGMR3GetNameLen(pCur)));
return VERR_PDM_MODULE_NAME_TOO_LONG;
}
else if (VBOX_FAILURE(rc))
{
return rc;
}
/* the path is optional, if no path the module name + path is used. */
char szFilename[RTPATH_MAX];
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
else if (VBOX_FAILURE(rc))
{
return rc;
}
/* prepend path? */
if (!RTPathHavePath(szFilename))
{
if (!psz)
return VERR_NO_TMP_MEMORY;
if (cch > sizeof(szFilename))
{
return VERR_FILENAME_TOO_LONG;
}
}
/*
* Load the module and register it's devices.
*/
if (VBOX_FAILURE(rc))
return rc;
}
#ifdef VBOX_WITH_USB
/* ditto for USB Devices. */
if (RT_FAILURE(rc))
return rc;
#endif
/*
*
* Enumerate the device instance configurations
* and come up with a instantiation order.
*
*/
/* Switch to /Devices, which contains the device instantiations. */
/*
* Count the device instances.
*/
unsigned cDevs = 0;
for (pInstanceNode = CFGMR3GetFirstChild(pCur); pInstanceNode; pInstanceNode = CFGMR3GetNextChild(pInstanceNode))
cDevs++;
if (!cDevs)
{
Log(("PDM: No devices were configured!\n"));
return VINF_SUCCESS;
}
/*
* Collect info on each device instance.
*/
struct DEVORDER
{
/** Configuration node. */
/** Pointer to device. */
/** Init order. */
/** VBox instance number. */
} *paDevs = (struct DEVORDER *)alloca(sizeof(paDevs[0]) * (cDevs + 1)); /* (One extra for swapping) */
unsigned i = 0;
{
/* Get the device name. */
AssertMsgRCReturn(rc, ("Configuration error: device name is too long (or something)! rc=%Vrc\n", rc), rc);
/* Find the device. */
AssertMsgReturn(pDev, ("Configuration error: device '%s' not found!\n", szName), VERR_PDM_DEVICE_NOT_FOUND);
/* Configured priority or use default based on device class? */
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
{
/* nop */;
}
else
AssertMsgRCReturn(rc, ("Configuration error: reading \"Priority\" for the '%s' device failed rc=%Vrc!\n", szName, rc), rc);
/* Enumerate the device instances. */
for (pInstanceNode = CFGMR3GetFirstChild(pCur); pInstanceNode; pInstanceNode = CFGMR3GetNextChild(pInstanceNode))
{
/* Get the instance number. */
char szInstance[32];
AssertMsgRCReturn(rc, ("Configuration error: instance name is too long (or something)! rc=%Vrc\n", rc), rc);
AssertMsgRCReturn(rc, ("Configuration error: RTStrToInt32Ex failed on the instance name '%s'! rc=%Vrc\n", szInstance, rc), rc);
AssertMsgReturn(!*pszNext, ("Configuration error: the instance name '%s' isn't all digits. (%s)\n", szInstance, pszNext), VERR_INVALID_PARAMETER);
/* next instance */
i++;
}
} /* devices */
/*
* Sort the device array ascending on u32Order. (bubble)
*/
unsigned c = cDevs - 1;
while (c)
{
unsigned j = 0;
for (i = 0; i < c; i++)
{
j = i;
}
c = j;
}
/*
*
* Instantiate the devices.
*
*/
for (i = 0; i < cDevs; i++)
{
/*
* Gather a bit of config.
*/
/* trusted */
bool fTrusted;
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
fTrusted = false;
else if (VBOX_FAILURE(rc))
{
return rc;
}
/* config node */
if (!pConfigNode)
{
if (VBOX_FAILURE(rc))
{
return rc;
}
}
/*
* Allocate the device instance.
*/
else
if (VBOX_FAILURE(rc))
{
AssertMsgFailed(("Failed to allocate %d bytes of instance data for device '%s'. rc=%Vrc\n",
return rc;
}
/*
* Initialize it.
*/
//pDevIns->Internal.s.pNextHC = NULL;
//pDevIns->Internal.s.pPerDeviceNextHC = NULL;
//pDevIns->Internal.s.pLunsHC = NULL;
//pDevIns->Internal.s.pPciDevice = NULL;
//pDevIns->Internal.s.pPciBus = NULL; /** @todo pci bus selection. (in 2008 perhaps) */
/*
* Link it into all the lists.
*/
/* The global instance FIFO. */
if (!pPrev1)
else
{
}
/* The per device instance FIFO. */
if (!pPrev2)
else
{
}
/*
* Call the constructor.
*/
Log(("PDM: Constructing device '%s' instance %d...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
if (VBOX_FAILURE(rc))
{
AssertMsgFailed(("Failed to construct '%s'/%d! %Vra\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
/* because we're damn lazy right now, we'll say that the destructor will be called even if the constructor fails. */
return rc;
}
} /* for device instances */
#ifdef VBOX_WITH_USB
/* ditto for USB Devices. */
if (RT_FAILURE(rc))
return rc;
#endif
/*
*
* PCI BIOS Fake and Init Complete.
*
*/
{
if (VBOX_FAILURE(rc))
{
return rc;
}
}
{
{
if (VBOX_FAILURE(rc))
{
AssertMsgFailed(("InitComplete on device '%s'/%d failed with rc=%Vrc\n",
return rc;
}
}
}
#ifdef VBOX_WITH_USB
/* ditto for USB Devices. */
if (RT_FAILURE(rc))
return rc;
#endif
return VINF_SUCCESS;
}
/**
* Lookups a device structure by name.
* @internal
*/
{
return pDev;
return NULL;
}
/**
* Loads one device module and call the registration entry point.
*
* @returns VBox status code.
* @param pVM VM handle.
* @param pRegCB The registration callback stuff.
* @param pszFilename Module filename.
* @param pszName Module name.
*/
static int pdmR3DevLoad(PVM pVM, PPDMDEVREGCBINT pRegCB, const char *pszFilename, const char *pszName)
{
/*
* Load it.
*/
if (VBOX_SUCCESS(rc))
{
/*
* Get the registration export and call it.
*/
if (VBOX_SUCCESS(rc))
{
Log(("PDM: Calling VBoxDevicesRegister (%p) of %s (%s)\n", pfnVBoxDevicesRegister, pszName, pszFilename));
if (VBOX_SUCCESS(rc))
else
AssertMsgFailed(("VBoxDevicesRegister failed with rc=%Vrc for module %s (%s)\n", rc, pszName, pszFilename));
}
else
{
AssertMsgFailed(("Failed to locate 'VBoxDevicesRegister' in %s (%s) rc=%Vrc\n", pszName, pszFilename, rc));
if (rc == VERR_SYMBOL_NOT_FOUND)
}
}
else
AssertMsgFailed(("Failed to load VBoxDD!\n"));
return rc;
}
/**
* Registers a device with the current VM instance.
*
* @returns VBox status code.
* @param pCallbacks Pointer to the callback table.
* @param pDevReg Pointer to the device registration record.
* This data must be permanent and readonly.
*/
{
/*
* Validate the registration structure.
*/
{
return VERR_PDM_UNKNOWN_DEVREG_VERSION;
}
if ( !pDevReg->szDeviceName[0]
{
}
{
AssertMsgFailed(("Invalid GC module name '%s' - (Device %s)\n", pDevReg->szGCMod, pDevReg->szDeviceName));
}
{
AssertMsgFailed(("Invalid R0 module name '%s' - (Device %s)\n", pDevReg->szR0Mod, pDevReg->szDeviceName));
}
{
AssertMsgFailed(("Invalid host bits flags! fFlags=%#x (Device %s)\n", pDevReg->fFlags, pDevReg->szDeviceName));
}
{
AssertMsgFailed(("Invalid guest bits flags! fFlags=%#x (Device %s)\n", pDevReg->fFlags, pDevReg->szDeviceName));
}
{
}
if (pDevReg->cMaxInstances <= 0)
{
AssertMsgFailed(("Max instances %u! (Device %s)\n", pDevReg->cMaxInstances, pDevReg->szDeviceName));
}
if (pDevReg->cbInstance > (RTUINT)(pDevReg->fFlags & (PDM_DEVREG_FLAGS_GC | PDM_DEVREG_FLAGS_R0) ? 96 * _1K : _1M))
{
AssertMsgFailed(("Instance size %d bytes! (Device %s)\n", pDevReg->cbInstance, pDevReg->szDeviceName));
}
if (!pDevReg->pfnConstruct)
{
}
/* Check matching guest bits last without any asserting. Enables trial and error registration. */
{
Log(("PDM: Rejected device '%s' because it didn't match the guest bits.\n", pDevReg->szDeviceName));
}
/*
* Check for duplicate and find FIFO entry at the same time.
*/
{
{
return VERR_PDM_DEVICE_NAME_CLASH;
}
}
/*
* Allocate new device structure and insert it into the list.
*/
if (pDev)
{
pDev->cInstances = 0;
if (pDevPrev)
else
return VINF_SUCCESS;
}
return VERR_NO_MEMORY;
}
/**
* Allocate memory which is associated with current VM instance
* and automatically freed on it's destruction.
*
* @returns Pointer to allocated memory. The memory is *NOT* zero-ed.
* @param pCallbacks Pointer to the callback table.
* @param cb Number of bytes to allocate.
*/
{
return pv;
}
/**
* Queue consumer callback for internal component.
*
* @returns Success indicator.
* If false the item will not be removed and the flushing will stop.
* @param pVM The VM handle.
* @param pItem The item to consume. Upon return this item will be freed.
*/
{
{
break;
break;
break;
default:
break;
}
return true;
}
/** @copydoc PDMDEVHLP::pfnIOPortRegister */
static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn,
{
LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p p32_tszDesc=%p:{%s}\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
int rc = IOMR3IOPortRegisterR3(pDevIns->Internal.s.pVMHC, pDevIns, Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc);
LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnIOPortRegisterGC */
static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterGC(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTGCPTR pvUser,
{
LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
/*
* Resolve the functions (one of the can be NULL).
*/
int rc = VINF_SUCCESS;
{
if (pszIn)
{
}
{
}
RTGCPTR GCPtrInStr = 0;
{
rc = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszInStr, &GCPtrInStr);
}
RTGCPTR GCPtrOutStr = 0;
{
rc = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszOutStr, &GCPtrOutStr);
}
if (VBOX_SUCCESS(rc))
rc = IOMIOPortRegisterGC(pDevIns->Internal.s.pVMHC, pDevIns, Port, cPorts, pvUser, GCPtrOut, GCPtrIn, GCPtrOutStr, GCPtrInStr, pszDesc);
}
else
{
AssertMsgFailed(("No GC module for this driver!\n"));
}
LogFlow(("pdmR3DevHlp_IOPortRegisterGC: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnIOPortRegisterR0 */
static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTR0PTR pvUser,
{
LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
return VINF_SUCCESS; /* NOP */
/*
* Resolve the functions (one of the can be NULL).
*/
int rc = VINF_SUCCESS;
{
if (pszIn)
{
rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszIn, &pfnR0PtrIn);
}
{
rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszOut, &pfnR0PtrOut);
}
{
rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszInStr, &pfnR0PtrInStr);
}
{
rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszOutStr, &pfnR0PtrOutStr);
}
if (VBOX_SUCCESS(rc))
rc = IOMIOPortRegisterR0(pDevIns->Internal.s.pVMHC, pDevIns, Port, cPorts, pvUser, pfnR0PtrOut, pfnR0PtrIn, pfnR0PtrOutStr, pfnR0PtrInStr, pszDesc);
}
else
{
AssertMsgFailed(("No R0 module for this driver!\n"));
}
LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnIOPortDeregister */
static DECLCALLBACK(int) pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts)
{
LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: Port=%#x cPorts=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnMMIORegister */
static DECLCALLBACK(int) pdmR3DevHlp_MMIORegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTHCPTR pvUser,
const char *pszDesc)
{
LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pfnWrite=%p pfnRead=%p pfnFill=%p pszDesc=%p:{%s}\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill, pszDesc, pszDesc));
int rc = IOMR3MMIORegisterR3(pDevIns->Internal.s.pVMHC, pDevIns, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill, pszDesc);
LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnMMIORegisterGC */
static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterGC(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser,
const char *pszDesc)
{
LogFlow(("pdmR3DevHlp_MMIORegisterGC: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pszWrite=%p:{%s} pszRead=%p:{%s} pszFill=%p:{%s} pszDesc=%p:{%s}\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill, pszDesc, pszDesc));
/*
* Resolve the functions.
* Not all function have to present, leave it to IOM to enforce this.
*/
int rc = VINF_SUCCESS;
{
RTGCPTR GCPtrWrite = 0;
if (pszWrite)
rc = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszWrite, &GCPtrWrite);
int rc2 = VINF_SUCCESS;
if (pszRead)
rc2 = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszRead, &GCPtrRead);
int rc3 = VINF_SUCCESS;
if (pszFill)
rc3 = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszFill, &GCPtrFill);
rc = IOMMMIORegisterGC(pDevIns->Internal.s.pVMHC, pDevIns, GCPhysStart, cbRange, pvUser, GCPtrWrite, GCPtrRead, GCPtrFill, pszDesc);
else
{
}
}
else
{
AssertMsgFailed(("No GC module for this driver!\n"));
}
LogFlow(("pdmR3DevHlp_MMIORegisterGC: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnMMIORegisterR0 */
static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterR0(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser,
const char *pszDesc)
{
LogFlow(("pdmR3DevHlp_MMIORegisterHC: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pszWrite=%p:{%s} pszRead=%p:{%s} pszFill=%p:{%s} pszDesc=%p:{%s}\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill, pszDesc, pszDesc));
return VINF_SUCCESS; /* NOP */
/*
* Resolve the functions.
* Not all function have to present, leave it to IOM to enforce this.
*/
int rc = VINF_SUCCESS;
{
if (pszWrite)
rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszWrite, &pfnR0PtrWrite);
int rc2 = VINF_SUCCESS;
if (pszRead)
rc2 = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszRead, &pfnR0PtrRead);
int rc3 = VINF_SUCCESS;
if (pszFill)
rc3 = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszFill, &pfnR0PtrFill);
rc = IOMMMIORegisterR0(pDevIns->Internal.s.pVMHC, pDevIns, GCPhysStart, cbRange, pvUser, pfnR0PtrWrite, pfnR0PtrRead, pfnR0PtrFill, pszDesc);
else
{
}
}
else
{
AssertMsgFailed(("No R0 module for this driver!\n"));
}
LogFlow(("pdmR3DevHlp_MMIORegisterR0: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnMMIODeregister */
static DECLCALLBACK(int) pdmR3DevHlp_MMIODeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
{
LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x\n",
LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnROMRegister */
static DECLCALLBACK(int) pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, const void *pvBinary, bool fShadow, const char *pszDesc)
{
LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvBinary=%p fShadow=%RTbool pszDesc=%p:{%s}\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvBinary, fShadow, pszDesc, pszDesc));
int rc = MMR3PhysRomRegister(pDevIns->Internal.s.pVMHC, pDevIns, GCPhysStart, cbRange, pvBinary, fShadow, pszDesc);
LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnSSMRegister */
static DECLCALLBACK(int) pdmR3DevHlp_SSMRegister(PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
{
LogFlow(("pdmR3DevHlp_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",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, u32Instance, u32Version, cbGuess, pfnSavePrep, pfnSaveExec, pfnSaveDone, pfnLoadPrep, pfnLoadExec, pfnLoadDone));
int rc = SSMR3Register(pDevIns->Internal.s.pVMHC, pDevIns, pszName, u32Instance, u32Version, cbGuess,
LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnTMTimerCreate */
static DECLCALLBACK(int) pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERHC ppTimer)
{
LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pszDesc=%p:{%s} ppTimer=%p\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, enmClock, pfnCallback, pszDesc, pszDesc, ppTimer));
int rc = TMR3TimerCreateDevice(pDevIns->Internal.s.pVMHC, pDevIns, enmClock, pfnCallback, pszDesc, ppTimer);
LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnTMTimerCreateExternal */
static DECLCALLBACK(PTMTIMERHC) pdmR3DevHlp_TMTimerCreateExternal(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMEREXT pfnCallback, void *pvUser, const char *pszDesc)
{
}
/** @copydoc PDMDEVHLP::pfnPCIRegister */
{
LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: pPciDev=%p:{.config={%#.256Vhxs}\n",
/*
* Validate input.
*/
if (!pPciDev)
{
LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (pPciDev)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
{
LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (vendor)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
{
/** @todo the PCI device vs. PDM device designed is a bit flawed if we have to
* support a PDM device with multiple PCI devices. This might become a problem
* when upgrading the chipset for instance...
*/
AssertMsgFailed(("Only one PCI device per device is currently implemented!\n"));
return VERR_INTERNAL_ERROR;
}
/*
* Choose the PCI bus for the device.
* This is simple. If the device was configured for a particular bus, it'll
* already have one. If not, we'll just take the first one.
*/
if (!pBus)
int rc;
if (pBus)
{
/*
* Check the configuration for PCI device and function assignment.
*/
int iDev = -1;
if (VBOX_SUCCESS(rc))
{
if (u8Device > 31)
{
AssertMsgFailed(("Configuration error: PCIDeviceNo=%d, max is 31. (%s/%d)\n",
return VERR_INTERNAL_ERROR;
}
if (VBOX_FAILURE(rc))
{
AssertMsgFailed(("Configuration error: PCIDeviceNo, but PCIFunctionNo query failed with rc=%Vrc (%s/%d)\n",
return rc;
}
if (u8Function > 7)
{
AssertMsgFailed(("Configuration error: PCIFunctionNo=%d, max is 7. (%s/%d)\n",
return VERR_INTERNAL_ERROR;
}
}
else if (rc != VERR_CFGM_VALUE_NOT_FOUND)
{
AssertMsgFailed(("Configuration error: PCIDeviceNo query failed with rc=%Vrc (%s/%d)\n",
return rc;
}
/*
* Call the pci bus device to do the actual registration.
*/
if (VBOX_SUCCESS(rc))
{
else
Log(("PDM: Registered device '%s'/%d as PCI device %d on bus %d\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev->devfn, pDevIns->Internal.s.pPciBusHC->iBus));
}
}
else
{
AssertMsgFailed(("Configuration error: No PCI bus available. This could be related to init order too!\n"));
}
LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnPCIIORegionRegister */
static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
{
LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: iRegion=%d cbRegion=%#x enmType=%d pfnCallback=%p\n",
/*
* Validate input.
*/
{
LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (iRegion)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
switch (enmType)
{
case PCI_ADDRESS_SPACE_MEM:
case PCI_ADDRESS_SPACE_IO:
break;
default:
LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (enmType)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if (!pfnCallback)
{
LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (callback)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
/*
* Must have a PCI device registered!
*/
int rc;
if (pPciDev)
{
/*
* We're currently restricted to page aligned MMIO regions.
*/
{
Log(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: aligning cbRegion %#x -> %#x\n",
}
rc = pBus->pfnIORegionRegisterR3(pBus->pDevInsR3, pPciDev, iRegion, cbRegion, enmType, pfnCallback);
}
else
{
AssertMsgFailed(("No PCI device registered!\n"));
}
LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnPCISetConfigCallbacks */
static DECLCALLBACK(void) pdmR3DevHlp_PCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
{
LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: pPciDev=%p pfnRead=%p ppfnReadOld=%p pfnWrite=%p ppfnWriteOld=%p\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld));
/*
* Validate input and resolve defaults.
*/
if (!pPciDev)
/*
* Do the job.
*/
pBus->pfnSetConfigCallbacksR3(pBus->pDevInsR3, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld);
LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
}
/** @copydoc PDMDEVHLP::pfnPCISetIrq */
{
LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
/*
* Validate input.
*/
/** @todo iIrq and iLevel checks. */
/*
* Must have a PCI device registered!
*/
if (pPciDev)
{
PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusHC; /** @todo the bus should be associated with the PCI device not the PDM device. */
#ifdef VBOX_WITH_PDM_LOCK
#else /* !VBOX_WITH_PDM_LOCK */
/*
* For the convenience of the device we put no thread restriction on this interface.
* That means we'll have to check which thread we're in and choose our path.
*/
else
{
Log(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
while (rc == VERR_TIMEOUT)
}
#endif /* !VBOX_WITH_PDM_LOCK */
}
else
AssertReleaseMsgFailed(("No PCI device registered!\n"));
LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
}
/** @copydoc PDMDEVHLP::pfnPCISetIrqNoWait */
{
#ifdef VBOX_WITH_PDM_LOCK
#else /* !VBOX_WITH_PDM_LOCK */
LogFlow(("pdmR3DevHlp_PCISetIrqNoWait: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
/*
* Validate input.
*/
/** @todo iIrq and iLevel checks. */
/*
* Must have a PCI device registered!
*/
if (pPciDev)
{
/*
* For the convenience of the device we put no thread restriction on this interface.
* That means we'll have to check which thread we're in and choose our path.
*/
else
{
Log(("pdmR3DevHlp_PCISetIrqNoWait: caller='%s'/%d: Queueing call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
int rc = VMR3ReqCallEx(pDevIns->Internal.s.pVMHC, NULL, RT_INDEFINITE_WAIT, VMREQFLAGS_NO_WAIT | VMREQFLAGS_VOID,
}
}
else
AssertReleaseMsgFailed(("No PCI device registered!\n"));
LogFlow(("pdmR3DevHlp_PCISetIrqNoWait: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
#endif /* !VBOX_WITH_PDM_LOCK */
}
/** @copydoc PDMDEVHLP::pfnISASetIrq */
{
LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
/*
* Validate input.
*/
/** @todo iIrq and iLevel checks. */
#ifdef VBOX_WITH_PDM_LOCK
#else /* !VBOX_WITH_PDM_LOCK */
else
{
Log(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
while (rc == VERR_TIMEOUT)
}
#endif /* !VBOX_WITH_PDM_LOCK */
LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
}
/** @copydoc PDMDEVHLP::pfnISASetIrqNoWait */
{
#ifdef VBOX_WITH_PDM_LOCK
#else /* !VBOX_WITH_PDM_LOCK */
LogFlow(("pdmR3DevHlp_ISASetIrqNoWait: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
/*
* Validate input.
*/
/** @todo iIrq and iLevel checks. */
/*
* For the convenience of the device we put no thread restriction on this interface.
* That means we'll have to check which thread we're in and choose our path.
*/
else
{
Log(("pdmR3DevHlp_ISASetIrqNoWait: caller='%s'/%d: Queueing call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
}
LogFlow(("pdmR3DevHlp_ISASetIrqNoWait: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
#endif /* !VBOX_WITH_PDM_LOCK */
}
/** @copydoc PDMDEVHLP::pfnDriverAttach */
static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
{
LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
/*
* Lookup the LUN, it might already be registered.
*/
break;
/*
* Create the LUN if if wasn't found, else check if driver is already attached to it.
*/
if (!pLun)
{
if ( !pBaseInterface
|| !pszDesc
|| !*pszDesc)
{
return VERR_INVALID_PARAMETER;
}
if (!pLun)
return VERR_NO_MEMORY;
if (!pLunPrev)
else
Log(("pdmR3DevHlp_DriverAttach: Registered LUN#%d '%s' with device '%s'/%d.\n",
}
{
AssertMsgFailed(("Already attached! The device should keep track of such things!\n"));
LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_PDM_DRIVER_ALREADY_ATTACHED));
return VERR_PDM_DRIVER_ALREADY_ATTACHED;
}
/*
* Get the attached driver configuration.
*/
int rc;
char szNode[48];
if (pNode)
{
char *pszName;
if (VBOX_SUCCESS(rc))
{
/*
* Find the driver.
*/
if (pDrv)
{
/* config node */
if (!pConfigNode)
if (VBOX_SUCCESS(rc))
{
/*
* Allocate the driver instance.
*/
if (pNew)
{
/*
* Initialize the instance structure (declaration order).
*/
//pNew->Internal.s.pUp = NULL;
//pNew->Internal.s.pDown = NULL;
//pNew->Internal.s.fDetaching = false;
//pNew->pDownBase = NULL;
//pNew->IBase.pfnQueryInterface = NULL;
/*
* Link with LUN and call the constructor.
*/
if (VBOX_SUCCESS(rc))
{
Log(("PDM: Attached driver '%s'/%d to LUN#%d on device '%s'/%d.\n",
pDrv->pDrvReg->szDriverName, pNew->iInstance, iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
LogFlow(("pdmR3DevHlp_DriverAttach: caller '%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
/*
* Might return != VINF_SUCCESS (e.g. VINF_NAT_DNS) */
return rc;
}
/*
* Free the driver.
*/
pDrv->cInstances--;
}
else
{
rc = VERR_NO_MEMORY;
}
}
else
}
else
{
}
}
else
{
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
}
}
else
LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnMMHeapAlloc */
{
LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
return pv;
}
/** @copydoc PDMDEVHLP::pfnMMHeapAllocZ */
{
LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
return pv;
}
/** @copydoc PDMDEVHLP::pfnMMHeapFree */
{
LogFlow(("pdmR3DevHlp_MMHeapFree: caller='%s'/%d: pv=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
}
/** @copydoc PDMDEVHLP::pfnVMSetError */
static DECLCALLBACK(int) pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
{
int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMHC, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
return rc;
}
/** @copydoc PDMDEVHLP::pfnVMSetErrorV */
static DECLCALLBACK(int) pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
{
int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMHC, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
return rc;
}
/** @copydoc PDMDEVHLP::pfnVMSetRuntimeError */
static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, ...)
{
return rc;
}
/** @copydoc PDMDEVHLP::pfnVMSetRuntimeErrorV */
static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list va)
{
return rc;
}
/** @copydoc PDMDEVHLP::pfnAssertEMT */
static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
{
return true;
char szMsg[100];
RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
return false;
}
/** @copydoc PDMDEVHLP::pfnAssertOther */
static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
{
return true;
char szMsg[100];
RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
return false;
}
/** @copydoc PDMDEVHLP::pfnDBGFStopV */
static DECLCALLBACK(int) pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args)
{
#ifdef LOG_ENABLED
LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: pszFile=%p:{%s} iLine=%d pszFunction=%p:{%s} pszFormat=%p:{%s} (%N)\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszFile, pszFile, iLine, pszFunction, pszFunction, pszFormat, pszFormat, pszFormat, &va2));
#endif
LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnDBGFInfoRegister */
static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler)
{
LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, pszDesc, pszDesc, pfnHandler));
LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnSTAMRegister */
static DECLCALLBACK(void) pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
{
}
/** @copydoc PDMDEVHLP::pfnSTAMRegisterF */
static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
{
}
/** @copydoc PDMDEVHLP::pfnSTAMRegisterV */
static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
{
}
/** @copydoc PDMDEVHLP::pfnRTCRegister */
static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
{
LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
/*
* Validate input.
*/
{
LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (version)\n",
return VERR_INVALID_PARAMETER;
}
{
LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
return VERR_INVALID_PARAMETER;
}
if (!ppRtcHlp)
{
LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (ppRtcHlp)\n",
return VERR_INVALID_PARAMETER;
}
/*
* Only one DMA device.
*/
{
AssertMsgFailed(("Only one RTC device is supported!\n"));
LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
return VERR_INVALID_PARAMETER;
}
/*
* Allocate and initialize pci bus structure.
*/
int rc = VINF_SUCCESS;
if (pRtc)
{
/* set the helper pointer. */
*ppRtcHlp = &g_pdmR3DevRtcHlp;
Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
}
else
rc = VERR_NO_MEMORY;
LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
return rc;
}
/** @copydoc PDMDEVHLP::pfnPDMQueueCreate */
static DECLCALLBACK(int) pdmR3DevHlp_PDMQueueCreate(PPDMDEVINS pDevIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval,
{
LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fGCEnabled=%RTbool ppQueue=%p\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue));
int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue);
LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: returns %Vrc *ppQueue=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *ppQueue));
return rc;
}
/** @copydoc PDMDEVHLP::pfnCritSectInit */
static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, const char *pszName)
{
LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszName=%p:{%s}\n",
LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnUTCNow */
{
LogFlow(("pdmR3DevHlp_UTCNow: caller='%s'/%d: pTime=%p\n",
LogFlow(("pdmR3DevHlp_UTCNow: caller='%s'/%d: returns %RU64\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, RTTimeSpecGetNano(pTime)));
return pTime;
}
/** @copydoc PDMDEVHLP::pfnPDMThreadCreate */
static DECLCALLBACK(int) pdmR3DevHlp_PDMThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
{
LogFlow(("pdmR3DevHlp_PDMThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMHC, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
LogFlow(("pdmR3DevHlp_PDMThreadCreate: caller='%s'/%d: returns %Vrc *ppThread=%RTthrd\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
return rc;
}
/** @copydoc PDMDEVHLP::pfnGetVM */
{
LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns->Internal.s.pVMHC));
}
/** @copydoc PDMDEVHLP::pfnPCIBusRegister */
static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
{
LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterHC=%p, .pfnIORegionRegisterHC=%p, .pfnSetIrqHC=%p, "
".pfnSaveExecHC=%p, .pfnLoadExecHC=%p, .pfnFakePCIBIOSHC=%p, .pszSetIrqGC=%p:{%s}} ppPciHlpR3=%p\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterHC,
pPciBusReg->pfnIORegionRegisterHC, pPciBusReg->pfnSetIrqHC, pPciBusReg->pfnSaveExecHC, pPciBusReg->pfnLoadExecHC,
/*
* Validate the structure.
*/
{
LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if ( !pPciBusReg->pfnRegisterHC
|| !pPciBusReg->pfnSetIrqHC
|| !pPciBusReg->pfnSaveExecHC
|| !pPciBusReg->pfnLoadExecHC
|| !pPciBusReg->pfnFakePCIBIOSHC)
{
LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if ( pPciBusReg->pszSetIrqGC
{
LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if ( pPciBusReg->pszSetIrqR0
{
LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if (!ppPciHlpR3)
{
LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (ppPciHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
/*
* Find free PCI bus entry.
*/
unsigned iBus = 0;
break;
{
LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (pci bus)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
/*
* Resolve and init the GC bits.
*/
if (pPciBusReg->pszSetIrqGC)
{
int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pPciBusReg->pszSetIrqGC, &pPciBus->pfnSetIrqGC);
if (VBOX_FAILURE(rc))
{
LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
}
else
{
pPciBus->pfnSetIrqGC = 0;
}
/*
* Resolve and init the R0 bits.
*/
if ( HWACCMR3IsAllowed(pVM)
&& pPciBusReg->pszSetIrqR0)
{
int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPciBusReg->pszSetIrqR0, &pPciBus->pfnSetIrqR0);
if (VBOX_FAILURE(rc))
{
LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
}
else
{
pPciBus->pfnSetIrqR0 = 0;
}
/*
* Init the HC bits.
*/
Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
/* set the helper pointer and return. */
LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
return VINF_SUCCESS;
}
/** @copydoc PDMDEVHLP::pfnPICRegister */
static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
{
LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrqHC=%p, .pfnGetInterruptHC=%p, .pszGetIrqGC=%p:{%s}, .pszGetInterruptGC=%p:{%s}} ppPicHlpR3=%p\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrqHC, pPicReg->pfnGetInterruptHC,
pPicReg->pszSetIrqGC, pPicReg->pszSetIrqGC, pPicReg->pszGetInterruptGC, pPicReg->pszGetInterruptGC, ppPicHlpR3));
/*
* Validate input.
*/
{
LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if ( !pPicReg->pfnSetIrqHC
|| !pPicReg->pfnGetInterruptHC)
{
LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if ( ( pPicReg->pszSetIrqGC
|| pPicReg->pszGetInterruptGC)
)
{
LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if ( pPicReg->pszSetIrqGC
{
LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (GC flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if ( pPicReg->pszSetIrqR0
{
LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (R0 flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if (!ppPicHlpR3)
{
LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (ppPicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
/*
* Only one PIC device.
*/
{
AssertMsgFailed(("Only one pic device is supported!\n"));
LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
/*
* GC stuff.
*/
if (pPicReg->pszSetIrqGC)
{
int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pPicReg->pszSetIrqGC, &pVM->pdm.s.Pic.pfnSetIrqGC);
if (VBOX_SUCCESS(rc))
{
rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pPicReg->pszGetInterruptGC, &pVM->pdm.s.Pic.pfnGetInterruptGC);
}
if (VBOX_FAILURE(rc))
{
LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
}
else
{
}
/*
* R0 stuff.
*/
if ( HWACCMR3IsAllowed(pVM)
&& pPicReg->pszSetIrqR0)
{
int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszSetIrqR0, &pVM->pdm.s.Pic.pfnSetIrqR0);
if (VBOX_SUCCESS(rc))
{
rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszGetInterruptR0, &pVM->pdm.s.Pic.pfnGetInterruptR0);
}
if (VBOX_FAILURE(rc))
{
LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
}
else
{
}
/*
* HC stuff.
*/
Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
/* set the helper pointer and return. */
LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
return VINF_SUCCESS;
}
/** @copydoc PDMDEVHLP::pfnAPICRegister */
static DECLCALLBACK(int) pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
{
LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: pApicReg=%p:{.u32Version=%#x, .pfnGetInterruptHC=%p, .pfnSetBaseHC=%p, .pfnGetBaseHC=%p, "
".pfnSetTPRHC=%p, .pfnGetTPRHC=%p, .pfnBusDeliverHC=%p, pszGetInterruptGC=%p:{%s}, pszSetBaseGC=%p:{%s}, pszGetBaseGC=%p:{%s}, "
".pszSetTPRGC=%p:{%s}, .pszGetTPRGC=%p:{%s}, .pszBusDeliverGC=%p:{%s}} ppApicHlpR3=%p\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pApicReg, pApicReg->u32Version, pApicReg->pfnGetInterruptHC, pApicReg->pfnSetBaseHC,
pApicReg->pfnGetBaseHC, pApicReg->pfnSetTPRHC, pApicReg->pfnGetTPRHC, pApicReg->pfnBusDeliverHC, pApicReg->pszGetInterruptGC,
pApicReg->pszGetInterruptGC, pApicReg->pszSetBaseGC, pApicReg->pszSetBaseGC, pApicReg->pszGetBaseGC, pApicReg->pszGetBaseGC,
pApicReg->pszSetTPRGC, pApicReg->pszSetTPRGC, pApicReg->pszGetTPRGC, pApicReg->pszGetTPRGC, pApicReg->pszBusDeliverGC,
/*
* Validate input.
*/
{
LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if ( !pApicReg->pfnGetInterruptHC
|| !pApicReg->pfnSetBaseHC
|| !pApicReg->pfnGetBaseHC
|| !pApicReg->pfnSetTPRHC
|| !pApicReg->pfnGetTPRHC
|| !pApicReg->pfnBusDeliverHC)
{
LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if ( ( pApicReg->pszGetInterruptGC
|| pApicReg->pszSetBaseGC
|| pApicReg->pszGetBaseGC
|| pApicReg->pszSetTPRGC
|| pApicReg->pszGetTPRGC
|| pApicReg->pszBusDeliverGC)
)
{
LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if ( ( pApicReg->pszGetInterruptR0
|| pApicReg->pszSetBaseR0
|| pApicReg->pszGetBaseR0
|| pApicReg->pszSetTPRR0
|| pApicReg->pszGetTPRR0
|| pApicReg->pszBusDeliverR0)
)
{
LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (R0 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if (!ppApicHlpR3)
{
LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (ppApicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
/*
* Only one APIC device. (malc: only in UP case actually)
*/
{
AssertMsgFailed(("Only one apic device is supported!\n"));
LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
/*
* Resolve & initialize the GC bits.
*/
if (pApicReg->pszGetInterruptGC)
{
int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszGetInterruptGC, &pVM->pdm.s.Apic.pfnGetInterruptGC);
if (RT_SUCCESS(rc))
{
rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszSetBaseGC, &pVM->pdm.s.Apic.pfnSetBaseGC);
}
if (RT_SUCCESS(rc))
{
rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszGetBaseGC, &pVM->pdm.s.Apic.pfnGetBaseGC);
}
if (RT_SUCCESS(rc))
{
rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszSetTPRGC, &pVM->pdm.s.Apic.pfnSetTPRGC);
}
if (RT_SUCCESS(rc))
{
rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszGetTPRGC, &pVM->pdm.s.Apic.pfnGetTPRGC);
}
if (RT_SUCCESS(rc))
{
rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszBusDeliverGC, &pVM->pdm.s.Apic.pfnBusDeliverGC);
}
if (VBOX_FAILURE(rc))
{
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
}
else
{
}
/*
* Resolve & initialize the R0 bits.
*/
if ( HWACCMR3IsAllowed(pVM)
{
int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, &pVM->pdm.s.Apic.pfnGetInterruptR0);
if (RT_SUCCESS(rc))
{
rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, &pVM->pdm.s.Apic.pfnSetBaseR0);
}
if (RT_SUCCESS(rc))
{
rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, &pVM->pdm.s.Apic.pfnGetBaseR0);
}
if (RT_SUCCESS(rc))
{
rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, &pVM->pdm.s.Apic.pfnSetTPRR0);
}
if (RT_SUCCESS(rc))
{
rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, &pVM->pdm.s.Apic.pfnGetTPRR0);
}
if (RT_SUCCESS(rc))
{
rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, &pVM->pdm.s.Apic.pfnBusDeliverR0);
}
if (VBOX_FAILURE(rc))
{
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
}
else
{
}
/*
* Initialize the HC bits.
*/
Log(("PDM: Registered APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
/* set the helper pointer and return. */
LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
return VINF_SUCCESS;
}
/** @copydoc PDMDEVHLP::pfnIOAPICRegister */
static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
{
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrqHC=%p, .pszSetIrqGC=%p:{%s}} ppIoApicHlpR3=%p\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrqHC, pIoApicReg->pszSetIrqGC,
/*
* Validate input.
*/
{
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if (!pIoApicReg->pfnSetIrqHC)
{
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if ( pIoApicReg->pszSetIrqGC
{
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if ( pIoApicReg->pszSetIrqR0
{
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if (!ppIoApicHlpR3)
{
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (ppApicHlp)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
/*
* The I/O APIC requires the APIC to be present (hacks++).
* If the I/O APIC does GC stuff so must the APIC.
*/
{
AssertMsgFailed(("Configuration error / Init order error! No APIC!\n"));
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
if ( pIoApicReg->pszSetIrqGC
{
AssertMsgFailed(("Configuration error! APIC doesn't do GC, I/O APIC does!\n"));
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no GC APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
/*
* Only one I/O APIC device.
*/
{
AssertMsgFailed(("Only one ioapic device is supported!\n"));
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (only one)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
return VERR_INVALID_PARAMETER;
}
/*
* Resolve & initialize the GC bits.
*/
if (pIoApicReg->pszSetIrqGC)
{
int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pIoApicReg->pszSetIrqGC, &pVM->pdm.s.IoApic.pfnSetIrqGC);
if (VBOX_FAILURE(rc))
{
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
}
else
{
}
/*
* Resolve & initialize the R0 bits.
*/
if ( HWACCMR3IsAllowed(pVM)
&& pIoApicReg->pszSetIrqR0)
{
int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, &pVM->pdm.s.IoApic.pfnSetIrqR0);
if (VBOX_FAILURE(rc))
{
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
}
else
{
}
/*
* Initialize the HC bits.
*/
Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
/* set the helper pointer and return. */
LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
return VINF_SUCCESS;
}
/** @copydoc PDMDEVHLP::pfnDMACRegister */
static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
{
LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: pDmacReg=%p:{.u32Version=%#x, .pfnRun=%p, .pfnRegister=%p, .pfnReadMemory=%p, .pfnWriteMemory=%p, .pfnSetDREQ=%p, .pfnGetChannelMode=%p} ppDmacHlp=%p\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
/*
* Validate input.
*/
{
LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (version)\n",
return VERR_INVALID_PARAMETER;
}
|| !pDmacReg->pfnRegister
|| !pDmacReg->pfnReadMemory
|| !pDmacReg->pfnWriteMemory
|| !pDmacReg->pfnSetDREQ
|| !pDmacReg->pfnGetChannelMode)
{
LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
return VERR_INVALID_PARAMETER;
}
if (!ppDmacHlp)
{
LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (ppDmacHlp)\n",
return VERR_INVALID_PARAMETER;
}
/*
* Only one DMA device.
*/
{
AssertMsgFailed(("Only one DMA device is supported!\n"));
LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
return VERR_INVALID_PARAMETER;
}
/*
* Allocate and initialize pci bus structure.
*/
int rc = VINF_SUCCESS;
PPDMDMAC pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMHC, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
if (pDmac)
{
/* set the helper pointer. */
Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
}
else
rc = VERR_NO_MEMORY;
LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
return rc;
}
/** @copydoc PDMDEVHLP::pfnPhysRead */
static DECLCALLBACK(void) pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
{
LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbRead=%#x\n",
/*
* For the convenience of the device we put no thread restriction on this interface.
* That means we'll have to check which thread we're in and choose our path.
*/
#else
else
{
Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
while (rc == VERR_TIMEOUT)
}
#endif
Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
}
/** @copydoc PDMDEVHLP::pfnPhysWrite */
static DECLCALLBACK(void) pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
{
LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbWrite=%#x\n",
/*
* For the convenience of the device we put no thread restriction on this interface.
* That means we'll have to check which thread we're in and choose our path.
*/
#else
else
{
Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
while (rc == VERR_TIMEOUT)
}
#endif
Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
}
/** @copydoc PDMDEVHLP::pfnPhysReadGCVirt */
static DECLCALLBACK(int) pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
{
LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: pvDst=%p GCVirt=%VGv cb=%#x\n",
LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnPhysWriteGCVirt */
static DECLCALLBACK(int) pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
{
LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: GCVirtDst=%VGv pvSrc=%p cb=%#x\n",
LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnPhysReserve */
static DECLCALLBACK(int) pdmR3DevHlp_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
{
LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: GCPhys=%VGp cbRange=%#x pszDesc=%p:{%s}\n",
LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnPhys2HCVirt */
static DECLCALLBACK(int) pdmR3DevHlp_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC)
{
LogFlow(("pdmR3DevHlp_Phys2HCVirt: caller='%s'/%d: GCPhys=%VGp cbRange=%#x ppvHC=%p\n",
LogFlow(("pdmR3DevHlp_Phys2HCVirt: caller='%s'/%d: returns %Vrc *ppvHC=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *ppvHC));
return rc;
}
/** @copydoc PDMDEVHLP::pfnPhysGCPtr2HCPtr */
static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr)
{
LogFlow(("pdmR3DevHlp_PhysGCPtr2HCPtr: caller='%s'/%d: GCPtr=%VGv pHCPtr=%p\n",
LogFlow(("pdmR3DevHlp_PhysGCPtr2HCPtr: caller='%s'/%d: returns %Vrc *pHCPtr=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *pHCPtr));
return rc;
}
/** @copydoc PDMDEVHLP::pfnA20IsEnabled */
{
LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fRc));
return fRc;
}
/** @copydoc PDMDEVHLP::pfnA20Set */
{
LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fEnable));
//Assert(*(unsigned *)&fEnable <= 1);
}
/** @copydoc PDMDEVHLP::pfnVMReset */
{
LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: VM_FF_RESET %d -> 1\n",
/*
* We postpone this operation because we're likely to be inside a I/O instruction
* and the EIP will be updated when we return.
* We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
*/
bool fHaltOnReset;
{
Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
rc = VINF_EM_HALT;
}
else
{
rc = VINF_EM_RESET;
}
LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnVMSuspend */
{
LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnVMPowerOff */
{
LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnLockVM */
{
}
/** @copydoc PDMDEVHLP::pfnUnlockVM */
{
}
/** @copydoc PDMDEVHLP::pfnAssertVMLock */
static DECLCALLBACK(bool) pdmR3DevHlp_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
{
if (VMMR3LockIsOwner(pVM))
return true;
char szMsg[100];
RTStrPrintf(szMsg, sizeof(szMsg), "AssertVMLocked '%s'/%d ThreadOwner=%RTnthrd/%RTthrd/'%s' Self='%s'\n",
return false;
}
/** @copydoc PDMDEVHLP::pfnDMARegister */
static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
{
LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
int rc = VINF_SUCCESS;
else
{
AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
}
LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Vrc\n",
return rc;
}
/** @copydoc PDMDEVHLP::pfnDMAReadMemory */
static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
{
LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
int rc = VINF_SUCCESS;
{
uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
if (pcbRead)
}
else
{
AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
}
LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Vrc\n",
return rc;
}
/** @copydoc PDMDEVHLP::pfnDMAWriteMemory */
static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
{
LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
int rc = VINF_SUCCESS;
{
uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
if (pcbWritten)
*pcbWritten = cb;
}
else
{
AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
}
LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Vrc\n",
return rc;
}
/** @copydoc PDMDEVHLP::pfnDMASetDREQ */
static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
{
LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
int rc = VINF_SUCCESS;
else
{
AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
}
LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Vrc\n",
return rc;
}
/** @copydoc PDMDEVHLP::pfnDMAGetChannelMode */
{
LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
else
{
AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
}
LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
return u8Mode;
}
/** @copydoc PDMDEVHLP::pfnDMASchedule */
{
LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
VMR3NotifyFF(pVM, true);
}
/** @copydoc PDMDEVHLP::pfnCMOSWrite */
{
LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
int rc;
else
LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
return rc;
}
/** @copydoc PDMDEVHLP::pfnCMOSRead */
{
LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
int rc;
else
LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
return rc;
}
/** @copydoc PDMDEVHLP::pfnGetCpuId */
{
LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
}
/** @copydoc PDMDEVHLP::pfnROMProtectShadow */
static DECLCALLBACK(int) pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
{
LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x\n",
LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
return rc;
}
/** @copydoc PDMDEVHLP::pfnGetVM */
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return NULL;
}
/** @copydoc PDMDEVHLP::pfnPCIBusRegister */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnPICRegister */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnAPICRegister */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnIOAPICRegister */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnDMACRegister */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnPhysRead */
static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
}
/** @copydoc PDMDEVHLP::pfnPhysWrite */
static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
}
/** @copydoc PDMDEVHLP::pfnPhysReadGCVirt */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnPhysWriteGCVirt */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnPhysReserve */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnPhys2HCVirt */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnPhysGCPtr2HCPtr */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnA20IsEnabled */
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return false;
}
/** @copydoc PDMDEVHLP::pfnA20Set */
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
}
/** @copydoc PDMDEVHLP::pfnVMReset */
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnVMSuspend */
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnVMPowerOff */
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnLockVM */
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnUnlockVM */
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnAssertVMLock */
static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return false;
}
/** @copydoc PDMDEVHLP::pfnDMARegister */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnDMAReadMemory */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
if (pcbRead)
*pcbRead = 0;
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnDMAWriteMemory */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
if (pcbWritten)
*pcbWritten = 0;
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnDMASetDREQ */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnDMAGetChannelMode */
static DECLCALLBACK(uint8_t) pdmR3DevHlp_Untrusted_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return 3 << 2 /* illegal mode type */;
}
/** @copydoc PDMDEVHLP::pfnDMASchedule */
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
}
/** @copydoc PDMDEVHLP::pfnCMOSWrite */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnCMOSRead */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMDEVHLP::pfnQueryCPUId */
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
}
/** @copydoc PDMDEVHLP::pfnROMProtectShadow */
static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
{
AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return VERR_ACCESS_DENIED;
}
/** @copydoc PDMPICHLPR3::pfnSetInterruptFF */
{
LogFlow(("pdmR3PicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 1\n",
#ifdef VBOX_WITH_PDM_LOCK
VMR3NotifyFF(pVM, true);
#endif
}
/** @copydoc PDMPICHLPR3::pfnClearInterruptFF */
{
LogFlow(("pdmR3PicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 0\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_PIC)));
}
#ifdef VBOX_WITH_PDM_LOCK
/** @copydoc PDMPICHLPR3::pfnLock */
{
}
/** @copydoc PDMPICHLPR3::pfnUnlock */
{
}
#endif /* VBOX_WITH_PDM_LOCK */
/** @copydoc PDMPICHLPR3::pfnGetGCHelpers */
{
RTGCPTR pGCHelpers = 0;
LogFlow(("pdmR3PicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
return pGCHelpers;
}
/** @copydoc PDMPICHLPR3::pfnGetR0Helpers */
{
PCPDMPICHLPR0 pR0Helpers = 0;
LogFlow(("pdmR3PicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
return pR0Helpers;
}
/** @copydoc PDMAPICHLPR3::pfnSetInterruptFF */
{
LogFlow(("pdmR3ApicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT %d -> 1\n",
#ifdef VBOX_WITH_PDM_LOCK
VMR3NotifyFF(pVM, true);
#endif
}
/** @copydoc PDMAPICHLPR3::pfnClearInterruptFF */
{
LogFlow(("pdmR3ApicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT %d -> 0\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_APIC)));
}
/** @copydoc PDMAPICHLPR3::pfnChangeFeature */
{
LogFlow(("pdmR3ApicHlp_ClearInterruptFF: caller='%s'/%d: fEnabled=%RTbool\n",
if (fEnabled)
else
}
#ifdef VBOX_WITH_PDM_LOCK
/** @copydoc PDMAPICHLPR3::pfnLock */
{
}
/** @copydoc PDMAPICHLPR3::pfnUnlock */
{
}
#endif /* VBOX_WITH_PDM_LOCK */
/** @copydoc PDMAPICHLPR3::pfnGetGCHelpers */
{
RTGCPTR pGCHelpers = 0;
LogFlow(("pdmR3ApicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
return pGCHelpers;
}
/** @copydoc PDMAPICHLPR3::pfnGetR0Helpers */
{
PCPDMAPICHLPR0 pR0Helpers = 0;
LogFlow(("pdmR3ApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
return pR0Helpers;
}
/** @copydoc PDMIOAPICHLPR3::pfnApicBusDeliver */
static DECLCALLBACK(void) pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
{
#ifndef VBOX_WITH_PDM_LOCK
#endif
LogFlow(("pdmR3IoApicHlp_ApicBusDeliver: caller='%s'/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8\n",
pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode));
pVM->pdm.s.Apic.pfnBusDeliverR3(pVM->pdm.s.Apic.pDevInsR3, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode);
}
#ifdef VBOX_WITH_PDM_LOCK
/** @copydoc PDMIOAPICHLPR3::pfnLock */
{
}
/** @copydoc PDMIOAPICHLPR3::pfnUnlock */
{
}
#endif /* VBOX_WITH_PDM_LOCK */
/** @copydoc PDMIOAPICHLPR3::pfnGetGCHelpers */
{
RTGCPTR pGCHelpers = 0;
LogFlow(("pdmR3IoApicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
return pGCHelpers;
}
/** @copydoc PDMIOAPICHLPR3::pfnGetR0Helpers */
{
LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
return pR0Helpers;
}
/** @copydoc PDMPCIHLPR3::pfnIsaSetIrq */
{
#ifndef VBOX_WITH_PDM_LOCK
#endif
}
/** @copydoc PDMPCIHLPR3::pfnIoApicSetIrq */
{
#ifndef VBOX_WITH_PDM_LOCK
#endif
}
#ifdef VBOX_WITH_PDM_LOCK
/** @copydoc PDMPCIHLPR3::pfnLock */
{
}
/** @copydoc PDMPCIHLPR3::pfnUnlock */
{
}
#endif /* VBOX_WITH_PDM_LOCK */
/** @copydoc PDMPCIHLPR3::pfnGetGCHelpers */
{
RTGCPTR pGCHelpers = 0;
LogFlow(("pdmR3IoApicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
return pGCHelpers;
}
/** @copydoc PDMPCIHLPR3::pfnGetR0Helpers */
{
PCPDMPCIHLPR0 pR0Helpers = 0;
LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
return pR0Helpers;
}
/**
* Locates a LUN.
*
* @returns VBox status code.
* @param pVM VM Handle.
* @param pszDevice Device name.
* @param iInstance Device instance.
* @param iLun The Logical Unit to obtain the interface of.
* @param ppLun Where to store the pointer to the LUN if found.
* @thread Try only do this in EMT...
*/
int pdmR3DevFindLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMLUN *ppLun)
{
/*
* Iterate registered devices looking for the device.
*/
{
{
/*
* Iterate device instances.
*/
for (PPDMDEVINS pDevIns = pDev->pInstances; pDevIns; pDevIns = pDevIns->Internal.s.pPerDeviceNextHC)
{
{
/*
* Iterate luns.
*/
{
{
return VINF_SUCCESS;
}
}
return VERR_PDM_LUN_NOT_FOUND;
}
}
}
}
return VERR_PDM_DEVICE_NOT_FOUND;
}
/**
* Attaches a preconfigured driver to an existing device instance.
*
* This is used to change drivers and suchlike at runtime.
*
* @returns VBox status code.
* @param pVM VM Handle.
* @param pszDevice Device name.
* @param iInstance Device instance.
* @param iLun The Logical Unit to obtain the interface of.
* @param ppBase Where to store the base interface pointer. Optional.
* @thread EMT
*/
PDMR3DECL(int) PDMR3DeviceAttach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMIBASE *ppBase)
{
LogFlow(("PDMR3DeviceAttach: pszDevice=%p:{%s} iInstance=%d iLun=%d ppBase=%p\n",
/*
* Find the LUN in question.
*/
if (VBOX_SUCCESS(rc))
{
/*
* Can we attach anything at runtime?
*/
{
{
}
else
}
else
if (ppBase)
}
else if (ppBase)
if (ppBase)
else
return rc;
}
/**
* Detaches a driver from an existing device instance.
*
* This is used to change drivers and suchlike at runtime.
*
* @returns VBox status code.
* @param pVM VM Handle.
* @param pszDevice Device name.
* @param iInstance Device instance.
* @param iLun The Logical Unit to obtain the interface of.
* @thread EMT
*/
{
LogFlow(("PDMR3DeviceDetach: pszDevice=%p:{%s} iInstance=%d iLun=%d\n",
/*
* Find the LUN in question.
*/
if (VBOX_SUCCESS(rc))
{
/*
* Can we detach anything at runtime?
*/
{
else
}
else
}
return rc;
}