VirtualBox

source: vbox/trunk/src/VBox/VMM/PDMDevice.cpp@ 7523

Last change on this file since 7523 was 7523, checked in by vboxsync, 17 years ago

Unconditionally resolve R0 function addresses

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 177.2 KB
Line 
1/* $Id: PDMDevice.cpp 7523 2008-03-25 09:52:30Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, Device parts.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_PDM_DEVICE
23#include "PDMInternal.h"
24#include <VBox/pdm.h>
25#include <VBox/mm.h>
26#include <VBox/pgm.h>
27#include <VBox/iom.h>
28#include <VBox/cfgm.h>
29#include <VBox/rem.h>
30#include <VBox/dbgf.h>
31#include <VBox/vm.h>
32#include <VBox/vmm.h>
33
34#include <VBox/version.h>
35#include <VBox/log.h>
36#include <VBox/err.h>
37#include <iprt/alloc.h>
38#include <iprt/alloca.h>
39#include <iprt/asm.h>
40#include <iprt/assert.h>
41#include <iprt/path.h>
42#include <iprt/semaphore.h>
43#include <iprt/string.h>
44#include <iprt/thread.h>
45
46
47
48/*******************************************************************************
49* Structures and Typedefs *
50*******************************************************************************/
51/**
52 * Internal callback structure pointer.
53 * The main purpose is to define the extra data we associate
54 * with PDMDEVREGCB so we can find the VM instance and so on.
55 */
56typedef struct PDMDEVREGCBINT
57{
58 /** The callback structure. */
59 PDMDEVREGCB Core;
60 /** A bit of padding. */
61 uint32_t u32[4];
62 /** VM Handle. */
63 PVM pVM;
64} PDMDEVREGCBINT, *PPDMDEVREGCBINT;
65typedef const PDMDEVREGCBINT *PCPDMDEVREGCBINT;
66
67
68/*******************************************************************************
69* Internal Functions *
70*******************************************************************************/
71static DECLCALLBACK(int) pdmR3DevReg_Register(PPDMDEVREGCB pCallbacks, PCPDMDEVREG pDevReg);
72static DECLCALLBACK(void *) pdmR3DevReg_MMHeapAlloc(PPDMDEVREGCB pCallbacks, size_t cb);
73static DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem);
74
75/* VSlick regex:
76search : \om/\*\*.+?\*\/\nDECLCALLBACKMEMBER\(([^,]*), *pfn([^)]*)\)\(
77replace: \/\*\* @copydoc PDMDEVHLP::pfn\2 \*\/\nstatic DECLCALLBACK\(\1\) pdmR3DevHlp_\2\(
78 */
79
80/** @name R3 DevHlp
81 * @{
82 */
83static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn, PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc);
84static 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);
85static 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);
86static DECLCALLBACK(int) pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts);
87static DECLCALLBACK(int) pdmR3DevHlp_MMIORegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTHCPTR pvUser,
88 PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill,
89 const char *pszDesc);
90static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterGC(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser,
91 const char *pszWrite, const char *pszRead, const char *pszFill,
92 const char *pszDesc);
93static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterR0(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser,
94 const char *pszWrite, const char *pszRead, const char *pszFill,
95 const char *pszDesc);
96static DECLCALLBACK(int) pdmR3DevHlp_MMIODeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
97static DECLCALLBACK(int) pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, const void *pvBinary, bool fShadow, const char *pszDesc);
98static DECLCALLBACK(int) pdmR3DevHlp_SSMRegister(PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
99 PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
100 PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone);
101static DECLCALLBACK(int) pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer);
102static DECLCALLBACK(PTMTIMERR3) pdmR3DevHlp_TMTimerCreateExternal(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMEREXT pfnCallback, void *pvUser, const char *pszDesc);
103static DECLCALLBACK(int) pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev);
104static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback);
105static DECLCALLBACK(void) pdmR3DevHlp_PCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
106 PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld);
107static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
108static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel);
109static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
110static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel);
111static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc);
112static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAlloc(PPDMDEVINS pDevIns, size_t cb);
113static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb);
114static DECLCALLBACK(void) pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv);
115static DECLCALLBACK(int) pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...);
116static DECLCALLBACK(int) pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va);
117static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, ...);
118static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list va);
119static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
120static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
121static DECLCALLBACK(int) pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args);
122static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler);
123static DECLCALLBACK(void) pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
124static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...);
125static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args);
126static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, const char *pszName);
127static DECLCALLBACK(PRTTIMESPEC) pdmR3DevHlp_UTCNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime);
128static DECLCALLBACK(int) pdmR3DevHlp_PDMThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
129 PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
130
131static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns);
132static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3);
133static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3);
134static DECLCALLBACK(int) pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3);
135static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3);
136static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp);
137static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp);
138static DECLCALLBACK(int) pdmR3DevHlp_PDMQueueCreate(PPDMDEVINS pDevIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval, PFNPDMQUEUEDEV pfnCallback, bool fGCEnabled, PPDMQUEUE *ppQueue);
139static DECLCALLBACK(void) pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead);
140static DECLCALLBACK(void) pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite);
141static DECLCALLBACK(int) pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb);
142static DECLCALLBACK(int) pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb);
143static DECLCALLBACK(int) pdmR3DevHlp_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc);
144static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys);
145static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns);
146static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable);
147static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns);
148static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns);
149static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns);
150static DECLCALLBACK(int) pdmR3DevHlp_LockVM(PPDMDEVINS pDevIns);
151static DECLCALLBACK(int) pdmR3DevHlp_UnlockVM(PPDMDEVINS pDevIns);
152static DECLCALLBACK(bool) pdmR3DevHlp_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
153static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser);
154static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead);
155static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten);
156static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel);
157static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel);
158static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns);
159static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value);
160static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value);
161static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
162 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx);
163static DECLCALLBACK(int) pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
164
165static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns);
166static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3);
167static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3);
168static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3);
169static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3);
170static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp);
171static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead);
172static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite);
173static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb);
174static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb);
175static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc);
176static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC);
177static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr);
178
179static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns);
180static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable);
181static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns);
182static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns);
183static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns);
184static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_LockVM(PPDMDEVINS pDevIns);
185static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_UnlockVM(PPDMDEVINS pDevIns);
186static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
187static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser);
188static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead);
189static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten);
190static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel);
191static DECLCALLBACK(uint8_t) pdmR3DevHlp_Untrusted_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel);
192static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_DMASchedule(PPDMDEVINS pDevIns);
193static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value);
194static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value);
195static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_QueryCPUId(PPDMDEVINS pDevIns, uint32_t iLeaf,
196 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx);
197static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
198/** @} */
199
200
201/** @name HC PIC Helpers
202 * @{
203 */
204static DECLCALLBACK(void) pdmR3PicHlp_SetInterruptFF(PPDMDEVINS pDevIns);
205static DECLCALLBACK(void) pdmR3PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns);
206#ifdef VBOX_WITH_PDM_LOCK
207static DECLCALLBACK(int) pdmR3PicHlp_Lock(PPDMDEVINS pDevIns, int rc);
208static DECLCALLBACK(void) pdmR3PicHlp_Unlock(PPDMDEVINS pDevIns);
209#endif
210static DECLCALLBACK(PCPDMPICHLPGC) pdmR3PicHlp_GetGCHelpers(PPDMDEVINS pDevIns);
211static DECLCALLBACK(PCPDMPICHLPR0) pdmR3PicHlp_GetR0Helpers(PPDMDEVINS pDevIns);
212/** @} */
213
214
215/** @name HC APIC Helpers
216 * @{
217 */
218static DECLCALLBACK(void) pdmR3ApicHlp_SetInterruptFF(PPDMDEVINS pDevIns);
219static DECLCALLBACK(void) pdmR3ApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns);
220static DECLCALLBACK(void) pdmR3ApicHlp_ChangeFeature(PPDMDEVINS pDevIns, bool fEnabled);
221#ifdef VBOX_WITH_PDM_LOCK
222static DECLCALLBACK(int) pdmR3ApicHlp_Lock(PPDMDEVINS pDevIns, int rc);
223static DECLCALLBACK(void) pdmR3ApicHlp_Unlock(PPDMDEVINS pDevIns);
224#endif
225static DECLCALLBACK(PCPDMAPICHLPGC) pdmR3ApicHlp_GetGCHelpers(PPDMDEVINS pDevIns);
226static DECLCALLBACK(PCPDMAPICHLPR0) pdmR3ApicHlp_GetR0Helpers(PPDMDEVINS pDevIns);
227/** @} */
228
229
230/** @name HC I/O APIC Helpers
231 * @{
232 */
233static DECLCALLBACK(void) pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
234 uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode);
235#ifdef VBOX_WITH_PDM_LOCK
236static DECLCALLBACK(int) pdmR3IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc);
237static DECLCALLBACK(void) pdmR3IoApicHlp_Unlock(PPDMDEVINS pDevIns);
238#endif
239static DECLCALLBACK(PCPDMIOAPICHLPGC) pdmR3IoApicHlp_GetGCHelpers(PPDMDEVINS pDevIns);
240static DECLCALLBACK(PCPDMIOAPICHLPR0) pdmR3IoApicHlp_GetR0Helpers(PPDMDEVINS pDevIns);
241/** @} */
242
243
244/** @name HC PCI Bus Helpers
245 * @{
246 */
247static DECLCALLBACK(void) pdmR3PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
248static DECLCALLBACK(void) pdmR3PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
249#ifdef VBOX_WITH_PDM_LOCK
250static DECLCALLBACK(int) pdmR3PciHlp_Lock(PPDMDEVINS pDevIns, int rc);
251static DECLCALLBACK(void) pdmR3PciHlp_Unlock(PPDMDEVINS pDevIns);
252#endif
253static DECLCALLBACK(PCPDMPCIHLPGC) pdmR3PciHlp_GetGCHelpers(PPDMDEVINS pDevIns);
254static DECLCALLBACK(PCPDMPCIHLPR0) pdmR3PciHlp_GetR0Helpers(PPDMDEVINS pDevIns);
255/** @} */
256
257/** @def PDMDEV_ASSERT_DEVINS
258 * Asserts the validity of the driver instance.
259 */
260#ifdef VBOX_STRICT
261# define PDMDEV_ASSERT_DEVINS(pDevIns) do { Assert(pDevIns); Assert(pDevIns->u32Version == PDM_DEVINS_VERSION); Assert(pDevIns->pvInstanceDataR3 == (void *)&pDevIns->achInstanceData[0]); } while (0)
262#else
263# define PDMDEV_ASSERT_DEVINS(pDevIns) do { } while (0)
264#endif
265static int pdmR3DevLoad(PVM pVM, PPDMDEVREGCBINT pRegCB, const char *pszFilename, const char *pszName);
266
267
268/*
269 * Allow physical read and writes from any thread
270 */
271#define PDM_PHYS_READWRITE_FROM_ANY_THREAD
272
273/*******************************************************************************
274* Global Variables *
275*******************************************************************************/
276/**
277 * The device helper structure for trusted devices.
278 */
279const PDMDEVHLP g_pdmR3DevHlpTrusted =
280{
281 PDM_DEVHLP_VERSION,
282 pdmR3DevHlp_IOPortRegister,
283 pdmR3DevHlp_IOPortRegisterGC,
284 pdmR3DevHlp_IOPortRegisterR0,
285 pdmR3DevHlp_IOPortDeregister,
286 pdmR3DevHlp_MMIORegister,
287 pdmR3DevHlp_MMIORegisterGC,
288 pdmR3DevHlp_MMIORegisterR0,
289 pdmR3DevHlp_MMIODeregister,
290 pdmR3DevHlp_ROMRegister,
291 pdmR3DevHlp_SSMRegister,
292 pdmR3DevHlp_TMTimerCreate,
293 pdmR3DevHlp_TMTimerCreateExternal,
294 pdmR3DevHlp_PCIRegister,
295 pdmR3DevHlp_PCIIORegionRegister,
296 pdmR3DevHlp_PCISetConfigCallbacks,
297 pdmR3DevHlp_PCISetIrq,
298 pdmR3DevHlp_PCISetIrqNoWait,
299 pdmR3DevHlp_ISASetIrq,
300 pdmR3DevHlp_ISASetIrqNoWait,
301 pdmR3DevHlp_DriverAttach,
302 pdmR3DevHlp_MMHeapAlloc,
303 pdmR3DevHlp_MMHeapAllocZ,
304 pdmR3DevHlp_MMHeapFree,
305 pdmR3DevHlp_VMSetError,
306 pdmR3DevHlp_VMSetErrorV,
307 pdmR3DevHlp_VMSetRuntimeError,
308 pdmR3DevHlp_VMSetRuntimeErrorV,
309 pdmR3DevHlp_AssertEMT,
310 pdmR3DevHlp_AssertOther,
311 pdmR3DevHlp_DBGFStopV,
312 pdmR3DevHlp_DBGFInfoRegister,
313 pdmR3DevHlp_STAMRegister,
314 pdmR3DevHlp_STAMRegisterF,
315 pdmR3DevHlp_STAMRegisterV,
316 pdmR3DevHlp_RTCRegister,
317 pdmR3DevHlp_PDMQueueCreate,
318 pdmR3DevHlp_CritSectInit,
319 pdmR3DevHlp_UTCNow,
320 pdmR3DevHlp_PDMThreadCreate,
321 pdmR3DevHlp_PhysGCPtr2GCPhys,
322 0,
323 0,
324 0,
325 0,
326 0,
327 0,
328 0,
329 0,
330 pdmR3DevHlp_GetVM,
331 pdmR3DevHlp_PCIBusRegister,
332 pdmR3DevHlp_PICRegister,
333 pdmR3DevHlp_APICRegister,
334 pdmR3DevHlp_IOAPICRegister,
335 pdmR3DevHlp_DMACRegister,
336 pdmR3DevHlp_PhysRead,
337 pdmR3DevHlp_PhysWrite,
338 pdmR3DevHlp_PhysReadGCVirt,
339 pdmR3DevHlp_PhysWriteGCVirt,
340 pdmR3DevHlp_PhysReserve,
341 pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt,
342 pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr,
343 pdmR3DevHlp_A20IsEnabled,
344 pdmR3DevHlp_A20Set,
345 pdmR3DevHlp_VMReset,
346 pdmR3DevHlp_VMSuspend,
347 pdmR3DevHlp_VMPowerOff,
348 pdmR3DevHlp_LockVM,
349 pdmR3DevHlp_UnlockVM,
350 pdmR3DevHlp_AssertVMLock,
351 pdmR3DevHlp_DMARegister,
352 pdmR3DevHlp_DMAReadMemory,
353 pdmR3DevHlp_DMAWriteMemory,
354 pdmR3DevHlp_DMASetDREQ,
355 pdmR3DevHlp_DMAGetChannelMode,
356 pdmR3DevHlp_DMASchedule,
357 pdmR3DevHlp_CMOSWrite,
358 pdmR3DevHlp_CMOSRead,
359 pdmR3DevHlp_GetCpuId,
360 pdmR3DevHlp_ROMProtectShadow,
361 PDM_DEVHLP_VERSION /* the end */
362};
363
364
365/**
366 * The device helper structure for non-trusted devices.
367 */
368const PDMDEVHLP g_pdmR3DevHlpUnTrusted =
369{
370 PDM_DEVHLP_VERSION,
371 pdmR3DevHlp_IOPortRegister,
372 pdmR3DevHlp_IOPortRegisterGC,
373 pdmR3DevHlp_IOPortRegisterR0,
374 pdmR3DevHlp_IOPortDeregister,
375 pdmR3DevHlp_MMIORegister,
376 pdmR3DevHlp_MMIORegisterGC,
377 pdmR3DevHlp_MMIORegisterR0,
378 pdmR3DevHlp_MMIODeregister,
379 pdmR3DevHlp_ROMRegister,
380 pdmR3DevHlp_SSMRegister,
381 pdmR3DevHlp_TMTimerCreate,
382 pdmR3DevHlp_TMTimerCreateExternal,
383 pdmR3DevHlp_PCIRegister,
384 pdmR3DevHlp_PCIIORegionRegister,
385 pdmR3DevHlp_PCISetConfigCallbacks,
386 pdmR3DevHlp_PCISetIrq,
387 pdmR3DevHlp_PCISetIrqNoWait,
388 pdmR3DevHlp_ISASetIrq,
389 pdmR3DevHlp_ISASetIrqNoWait,
390 pdmR3DevHlp_DriverAttach,
391 pdmR3DevHlp_MMHeapAlloc,
392 pdmR3DevHlp_MMHeapAllocZ,
393 pdmR3DevHlp_MMHeapFree,
394 pdmR3DevHlp_VMSetError,
395 pdmR3DevHlp_VMSetErrorV,
396 pdmR3DevHlp_VMSetRuntimeError,
397 pdmR3DevHlp_VMSetRuntimeErrorV,
398 pdmR3DevHlp_AssertEMT,
399 pdmR3DevHlp_AssertOther,
400 pdmR3DevHlp_DBGFStopV,
401 pdmR3DevHlp_DBGFInfoRegister,
402 pdmR3DevHlp_STAMRegister,
403 pdmR3DevHlp_STAMRegisterF,
404 pdmR3DevHlp_STAMRegisterV,
405 pdmR3DevHlp_RTCRegister,
406 pdmR3DevHlp_PDMQueueCreate,
407 pdmR3DevHlp_CritSectInit,
408 pdmR3DevHlp_UTCNow,
409 pdmR3DevHlp_PDMThreadCreate,
410 pdmR3DevHlp_PhysGCPtr2GCPhys,
411 0,
412 0,
413 0,
414 0,
415 0,
416 0,
417 0,
418 0,
419 pdmR3DevHlp_Untrusted_GetVM,
420 pdmR3DevHlp_Untrusted_PCIBusRegister,
421 pdmR3DevHlp_Untrusted_PICRegister,
422 pdmR3DevHlp_Untrusted_APICRegister,
423 pdmR3DevHlp_Untrusted_IOAPICRegister,
424 pdmR3DevHlp_Untrusted_DMACRegister,
425 pdmR3DevHlp_Untrusted_PhysRead,
426 pdmR3DevHlp_Untrusted_PhysWrite,
427 pdmR3DevHlp_Untrusted_PhysReadGCVirt,
428 pdmR3DevHlp_Untrusted_PhysWriteGCVirt,
429 pdmR3DevHlp_Untrusted_PhysReserve,
430 pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt,
431 pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr,
432 pdmR3DevHlp_Untrusted_A20IsEnabled,
433 pdmR3DevHlp_Untrusted_A20Set,
434 pdmR3DevHlp_Untrusted_VMReset,
435 pdmR3DevHlp_Untrusted_VMSuspend,
436 pdmR3DevHlp_Untrusted_VMPowerOff,
437 pdmR3DevHlp_Untrusted_LockVM,
438 pdmR3DevHlp_Untrusted_UnlockVM,
439 pdmR3DevHlp_Untrusted_AssertVMLock,
440 pdmR3DevHlp_Untrusted_DMARegister,
441 pdmR3DevHlp_Untrusted_DMAReadMemory,
442 pdmR3DevHlp_Untrusted_DMAWriteMemory,
443 pdmR3DevHlp_Untrusted_DMASetDREQ,
444 pdmR3DevHlp_Untrusted_DMAGetChannelMode,
445 pdmR3DevHlp_Untrusted_DMASchedule,
446 pdmR3DevHlp_Untrusted_CMOSWrite,
447 pdmR3DevHlp_Untrusted_CMOSRead,
448 pdmR3DevHlp_Untrusted_QueryCPUId,
449 pdmR3DevHlp_Untrusted_ROMProtectShadow,
450 PDM_DEVHLP_VERSION /* the end */
451};
452
453
454/**
455 * PIC Device Helpers.
456 */
457const PDMPICHLPR3 g_pdmR3DevPicHlp =
458{
459 PDM_PICHLPR3_VERSION,
460 pdmR3PicHlp_SetInterruptFF,
461 pdmR3PicHlp_ClearInterruptFF,
462#ifdef VBOX_WITH_PDM_LOCK
463 pdmR3PicHlp_Lock,
464 pdmR3PicHlp_Unlock,
465#endif
466 pdmR3PicHlp_GetGCHelpers,
467 pdmR3PicHlp_GetR0Helpers,
468 PDM_PICHLPR3_VERSION /* the end */
469};
470
471
472/**
473 * APIC Device Helpers.
474 */
475const PDMAPICHLPR3 g_pdmR3DevApicHlp =
476{
477 PDM_APICHLPR3_VERSION,
478 pdmR3ApicHlp_SetInterruptFF,
479 pdmR3ApicHlp_ClearInterruptFF,
480 pdmR3ApicHlp_ChangeFeature,
481#ifdef VBOX_WITH_PDM_LOCK
482 pdmR3ApicHlp_Lock,
483 pdmR3ApicHlp_Unlock,
484#endif
485 pdmR3ApicHlp_GetGCHelpers,
486 pdmR3ApicHlp_GetR0Helpers,
487 PDM_APICHLPR3_VERSION /* the end */
488};
489
490
491/**
492 * I/O APIC Device Helpers.
493 */
494const PDMIOAPICHLPR3 g_pdmR3DevIoApicHlp =
495{
496 PDM_IOAPICHLPR3_VERSION,
497 pdmR3IoApicHlp_ApicBusDeliver,
498#ifdef VBOX_WITH_PDM_LOCK
499 pdmR3IoApicHlp_Lock,
500 pdmR3IoApicHlp_Unlock,
501#endif
502 pdmR3IoApicHlp_GetGCHelpers,
503 pdmR3IoApicHlp_GetR0Helpers,
504 PDM_IOAPICHLPR3_VERSION /* the end */
505};
506
507
508/**
509 * PCI Bus Device Helpers.
510 */
511const PDMPCIHLPR3 g_pdmR3DevPciHlp =
512{
513 PDM_PCIHLPR3_VERSION,
514 pdmR3PciHlp_IsaSetIrq,
515 pdmR3PciHlp_IoApicSetIrq,
516#ifdef VBOX_WITH_PDM_LOCK
517 pdmR3PciHlp_Lock,
518 pdmR3PciHlp_Unlock,
519#endif
520 pdmR3PciHlp_GetGCHelpers,
521 pdmR3PciHlp_GetR0Helpers,
522 PDM_PCIHLPR3_VERSION, /* the end */
523};
524
525
526/**
527 * DMAC Device Helpers.
528 */
529const PDMDMACHLP g_pdmR3DevDmacHlp =
530{
531 PDM_DMACHLP_VERSION
532};
533
534
535/**
536 * RTC Device Helpers.
537 */
538const PDMRTCHLP g_pdmR3DevRtcHlp =
539{
540 PDM_RTCHLP_VERSION
541};
542
543
544/**
545 * This function will initialize the devices for this VM instance.
546 *
547 *
548 * First of all this mean loading the builtin device and letting them
549 * register themselves. Beyond that any additional device modules are
550 * loaded and called for registration.
551 *
552 * Then the device configuration is enumerated, the instantiation order
553 * is determined, and finally they are instantiated.
554 *
555 * After all device have been successfully instantiated the the primary
556 * PCI Bus device is called to emulate the PCI BIOS, i.e. making the
557 * resource assignments. If there is no PCI device, this step is of course
558 * skipped.
559 *
560 * Finally the init completion routines of the instantiated devices
561 * are called.
562 *
563 * @returns VBox status code.
564 * @param pVM VM Handle.
565 */
566int pdmR3DevInit(PVM pVM)
567{
568 LogFlow(("pdmR3DevInit:\n"));
569
570 AssertRelease(!(RT_OFFSETOF(PDMDEVINS, achInstanceData) & 15));
571 AssertRelease(sizeof(pVM->pdm.s.pDevInstances->Internal.s) <= sizeof(pVM->pdm.s.pDevInstances->Internal.padding));
572
573 /*
574 * Get the GC & R0 devhlps and create the devhlp R3 task queue.
575 */
576 GCPTRTYPE(PCPDMDEVHLPGC) pDevHlpGC;
577 int rc = PDMR3GetSymbolGC(pVM, NULL, "g_pdmGCDevHlp", &pDevHlpGC);
578 AssertReleaseRCReturn(rc, rc);
579
580 R0PTRTYPE(PCPDMDEVHLPR0) pDevHlpR0;
581 rc = PDMR3GetSymbolR0(pVM, NULL, "g_pdmR0DevHlp", &pDevHlpR0);
582 AssertReleaseRCReturn(rc, rc);
583
584 rc = PDMR3QueueCreateInternal(pVM, sizeof(PDMDEVHLPTASK), 8, 0, pdmR3DevHlpQueueConsumer, true, &pVM->pdm.s.pDevHlpQueueHC);
585 AssertRCReturn(rc, rc);
586 pVM->pdm.s.pDevHlpQueueGC = PDMQueueGCPtr(pVM->pdm.s.pDevHlpQueueHC);
587
588
589 /*
590 * Initialize the callback structure.
591 */
592 PDMDEVREGCBINT RegCB;
593 RegCB.Core.u32Version = PDM_DEVREG_CB_VERSION;
594 RegCB.Core.pfnRegister = pdmR3DevReg_Register;
595 RegCB.Core.pfnMMHeapAlloc = pdmR3DevReg_MMHeapAlloc;
596 RegCB.pVM = pVM;
597
598 /*
599 * Load the builtin module
600 */
601 PCFGMNODE pDevicesNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM/Devices");
602 bool fLoadBuiltin;
603 rc = CFGMR3QueryBool(pDevicesNode, "LoadBuiltin", &fLoadBuiltin);
604 if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
605 fLoadBuiltin = true;
606 else if (VBOX_FAILURE(rc))
607 {
608 AssertMsgFailed(("Configuration error: Querying boolean \"LoadBuiltin\" failed with %Vrc\n", rc));
609 return rc;
610 }
611 if (fLoadBuiltin)
612 {
613 /* make filename */
614 char *pszFilename = pdmR3FileR3("VBoxDD", /* fShared = */ true);
615 if (!pszFilename)
616 return VERR_NO_TMP_MEMORY;
617 rc = pdmR3DevLoad(pVM, &RegCB, pszFilename, "VBoxDD");
618 RTMemTmpFree(pszFilename);
619 if (VBOX_FAILURE(rc))
620 return rc;
621
622 /* make filename */
623 pszFilename = pdmR3FileR3("VBoxDD2", /* fShared = */ true);
624 if (!pszFilename)
625 return VERR_NO_TMP_MEMORY;
626 rc = pdmR3DevLoad(pVM, &RegCB, pszFilename, "VBoxDD2");
627 RTMemTmpFree(pszFilename);
628 if (VBOX_FAILURE(rc))
629 return rc;
630 }
631
632 /*
633 * Load additional device modules.
634 */
635 PCFGMNODE pCur;
636 for (pCur = CFGMR3GetFirstChild(pDevicesNode); pCur; pCur = CFGMR3GetNextChild(pCur))
637 {
638 /*
639 * Get the name and path.
640 */
641 char szName[PDMMOD_NAME_LEN];
642 rc = CFGMR3GetName(pCur, &szName[0], sizeof(szName));
643 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
644 {
645 AssertMsgFailed(("configuration error: The module name is too long, cchName=%d.\n", CFGMR3GetNameLen(pCur)));
646 return VERR_PDM_MODULE_NAME_TOO_LONG;
647 }
648 else if (VBOX_FAILURE(rc))
649 {
650 AssertMsgFailed(("CFGMR3GetName -> %Vrc.\n", rc));
651 return rc;
652 }
653
654 /* the path is optional, if no path the module name + path is used. */
655 char szFilename[RTPATH_MAX];
656 rc = CFGMR3QueryString(pCur, "Path", &szFilename[0], sizeof(szFilename));
657 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
658 strcpy(szFilename, szName);
659 else if (VBOX_FAILURE(rc))
660 {
661 AssertMsgFailed(("configuration error: Failure to query the module path, rc=%Vrc.\n", rc));
662 return rc;
663 }
664
665 /* prepend path? */
666 if (!RTPathHavePath(szFilename))
667 {
668 char *psz = pdmR3FileR3(szFilename);
669 if (!psz)
670 return VERR_NO_TMP_MEMORY;
671 size_t cch = strlen(psz) + 1;
672 if (cch > sizeof(szFilename))
673 {
674 RTMemTmpFree(psz);
675 AssertMsgFailed(("Filename too long! cch=%d '%s'\n", cch, psz));
676 return VERR_FILENAME_TOO_LONG;
677 }
678 memcpy(szFilename, psz, cch);
679 RTMemTmpFree(psz);
680 }
681
682 /*
683 * Load the module and register it's devices.
684 */
685 rc = pdmR3DevLoad(pVM, &RegCB, szFilename, szName);
686 if (VBOX_FAILURE(rc))
687 return rc;
688 }
689
690#ifdef VBOX_WITH_USB
691 /* ditto for USB Devices. */
692 rc = pdmR3UsbLoadModules(pVM);
693 if (RT_FAILURE(rc))
694 return rc;
695#endif
696
697
698 /*
699 *
700 * Enumerate the device instance configurations
701 * and come up with a instantiation order.
702 *
703 */
704 /* Switch to /Devices, which contains the device instantiations. */
705 pDevicesNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "Devices");
706
707 /*
708 * Count the device instances.
709 */
710 PCFGMNODE pInstanceNode;
711 unsigned cDevs = 0;
712 for (pCur = CFGMR3GetFirstChild(pDevicesNode); pCur; pCur = CFGMR3GetNextChild(pCur))
713 for (pInstanceNode = CFGMR3GetFirstChild(pCur); pInstanceNode; pInstanceNode = CFGMR3GetNextChild(pInstanceNode))
714 cDevs++;
715 if (!cDevs)
716 {
717 Log(("PDM: No devices were configured!\n"));
718 return VINF_SUCCESS;
719 }
720 Log2(("PDM: cDevs=%d!\n", cDevs));
721
722 /*
723 * Collect info on each device instance.
724 */
725 struct DEVORDER
726 {
727 /** Configuration node. */
728 PCFGMNODE pNode;
729 /** Pointer to device. */
730 PPDMDEV pDev;
731 /** Init order. */
732 uint32_t u32Order;
733 /** VBox instance number. */
734 uint32_t iInstance;
735 } *paDevs = (struct DEVORDER *)alloca(sizeof(paDevs[0]) * (cDevs + 1)); /* (One extra for swapping) */
736 Assert(paDevs);
737 unsigned i = 0;
738 for (pCur = CFGMR3GetFirstChild(pDevicesNode); pCur; pCur = CFGMR3GetNextChild(pCur))
739 {
740 /* Get the device name. */
741 char szName[sizeof(paDevs[0].pDev->pDevReg->szDeviceName)];
742 rc = CFGMR3GetName(pCur, szName, sizeof(szName));
743 AssertMsgRCReturn(rc, ("Configuration error: device name is too long (or something)! rc=%Vrc\n", rc), rc);
744
745 /* Find the device. */
746 PPDMDEV pDev = pdmR3DevLookup(pVM, szName);
747 AssertMsgReturn(pDev, ("Configuration error: device '%s' not found!\n", szName), VERR_PDM_DEVICE_NOT_FOUND);
748
749 /* Configured priority or use default based on device class? */
750 uint32_t u32Order;
751 rc = CFGMR3QueryU32(pCur, "Priority", &u32Order);
752 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
753 {
754 uint32_t u32 = pDev->pDevReg->fClass;
755 for (u32Order = 1; !(u32 & u32Order); u32Order <<= 1)
756 /* nop */;
757 }
758 else
759 AssertMsgRCReturn(rc, ("Configuration error: reading \"Priority\" for the '%s' device failed rc=%Vrc!\n", szName, rc), rc);
760
761 /* Enumerate the device instances. */
762 for (pInstanceNode = CFGMR3GetFirstChild(pCur); pInstanceNode; pInstanceNode = CFGMR3GetNextChild(pInstanceNode))
763 {
764 paDevs[i].pNode = pInstanceNode;
765 paDevs[i].pDev = pDev;
766 paDevs[i].u32Order = u32Order;
767
768 /* Get the instance number. */
769 char szInstance[32];
770 rc = CFGMR3GetName(pInstanceNode, szInstance, sizeof(szInstance));
771 AssertMsgRCReturn(rc, ("Configuration error: instance name is too long (or something)! rc=%Vrc\n", rc), rc);
772 char *pszNext = NULL;
773 rc = RTStrToUInt32Ex(szInstance, &pszNext, 0, &paDevs[i].iInstance);
774 AssertMsgRCReturn(rc, ("Configuration error: RTStrToInt32Ex failed on the instance name '%s'! rc=%Vrc\n", szInstance, rc), rc);
775 AssertMsgReturn(!*pszNext, ("Configuration error: the instance name '%s' isn't all digits. (%s)\n", szInstance, pszNext), VERR_INVALID_PARAMETER);
776
777 /* next instance */
778 i++;
779 }
780 } /* devices */
781 Assert(i == cDevs);
782
783 /*
784 * Sort the device array ascending on u32Order. (bubble)
785 */
786 unsigned c = cDevs - 1;
787 while (c)
788 {
789 unsigned j = 0;
790 for (i = 0; i < c; i++)
791 if (paDevs[i].u32Order > paDevs[i + 1].u32Order)
792 {
793 paDevs[cDevs] = paDevs[i + 1];
794 paDevs[i + 1] = paDevs[i];
795 paDevs[i] = paDevs[cDevs];
796 j = i;
797 }
798 c = j;
799 }
800
801
802 /*
803 *
804 * Instantiate the devices.
805 *
806 */
807 for (i = 0; i < cDevs; i++)
808 {
809 /*
810 * Gather a bit of config.
811 */
812 /* trusted */
813 bool fTrusted;
814 rc = CFGMR3QueryBool(paDevs[i].pNode, "Trusted", &fTrusted);
815 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
816 fTrusted = false;
817 else if (VBOX_FAILURE(rc))
818 {
819 AssertMsgFailed(("configuration error: failed to query boolean \"Trusted\", rc=%Vrc\n", rc));
820 return rc;
821 }
822 /* config node */
823 PCFGMNODE pConfigNode = CFGMR3GetChild(paDevs[i].pNode, "Config");
824 if (!pConfigNode)
825 {
826 rc = CFGMR3InsertNode(paDevs[i].pNode, "Config", &pConfigNode);
827 if (VBOX_FAILURE(rc))
828 {
829 AssertMsgFailed(("Failed to create Config node! rc=%Vrc\n", rc));
830 return rc;
831 }
832 }
833 CFGMR3SetRestrictedRoot(pConfigNode);
834
835 /*
836 * Allocate the device instance.
837 */
838 size_t cb = RT_OFFSETOF(PDMDEVINS, achInstanceData[paDevs[i].pDev->pDevReg->cbInstance]);
839 cb = RT_ALIGN_Z(cb, 16);
840 PPDMDEVINS pDevIns;
841 if (paDevs[i].pDev->pDevReg->fFlags & (PDM_DEVREG_FLAGS_GC | PDM_DEVREG_FLAGS_R0))
842 rc = MMR3HyperAllocOnceNoRel(pVM, cb, 0, MM_TAG_PDM_DEVICE, (void **)&pDevIns);
843 else
844 rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_DEVICE, cb, (void **)&pDevIns);
845 if (VBOX_FAILURE(rc))
846 {
847 AssertMsgFailed(("Failed to allocate %d bytes of instance data for device '%s'. rc=%Vrc\n",
848 cb, paDevs[i].pDev->pDevReg->szDeviceName, rc));
849 return rc;
850 }
851
852 /*
853 * Initialize it.
854 */
855 pDevIns->u32Version = PDM_DEVINS_VERSION;
856 //pDevIns->Internal.s.pNextHC = NULL;
857 //pDevIns->Internal.s.pPerDeviceNextHC = NULL;
858 pDevIns->Internal.s.pDevHC = paDevs[i].pDev;
859 pDevIns->Internal.s.pVMHC = pVM;
860 pDevIns->Internal.s.pVMGC = pVM->pVMGC;
861 //pDevIns->Internal.s.pLunsHC = NULL;
862 pDevIns->Internal.s.pCfgHandle = paDevs[i].pNode;
863 //pDevIns->Internal.s.pPciDevice = NULL;
864 //pDevIns->Internal.s.pPciBus = NULL; /** @todo pci bus selection. (in 2008 perhaps) */
865 pDevIns->pDevHlp = fTrusted ? &g_pdmR3DevHlpTrusted : &g_pdmR3DevHlpUnTrusted;
866 pDevIns->pDevHlpGC = pDevHlpGC;
867 pDevIns->pDevHlpR0 = pDevHlpR0;
868 pDevIns->pDevReg = paDevs[i].pDev->pDevReg;
869 pDevIns->pCfgHandle = pConfigNode;
870 pDevIns->iInstance = paDevs[i].iInstance;
871 pDevIns->pvInstanceDataR3 = &pDevIns->achInstanceData[0];
872 pDevIns->pvInstanceDataGC = pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_GC
873 ? MMHyperHC2GC(pVM, pDevIns->pvInstanceDataR3) : 0;
874 pDevIns->pvInstanceDataR0 = pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0
875 ? MMHyperR3ToR0(pVM, pDevIns->pvInstanceDataR3) : 0;
876
877 /*
878 * Link it into all the lists.
879 */
880 /* The global instance FIFO. */
881 PPDMDEVINS pPrev1 = pVM->pdm.s.pDevInstances;
882 if (!pPrev1)
883 pVM->pdm.s.pDevInstances = pDevIns;
884 else
885 {
886 while (pPrev1->Internal.s.pNextHC)
887 pPrev1 = pPrev1->Internal.s.pNextHC;
888 pPrev1->Internal.s.pNextHC = pDevIns;
889 }
890
891 /* The per device instance FIFO. */
892 PPDMDEVINS pPrev2 = paDevs[i].pDev->pInstances;
893 if (!pPrev2)
894 paDevs[i].pDev->pInstances = pDevIns;
895 else
896 {
897 while (pPrev2->Internal.s.pPerDeviceNextHC)
898 pPrev2 = pPrev2->Internal.s.pPerDeviceNextHC;
899 pPrev2->Internal.s.pPerDeviceNextHC = pDevIns;
900 }
901
902 /*
903 * Call the constructor.
904 */
905 Log(("PDM: Constructing device '%s' instance %d...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
906 rc = pDevIns->pDevReg->pfnConstruct(pDevIns, pDevIns->iInstance, pDevIns->pCfgHandle);
907 if (VBOX_FAILURE(rc))
908 {
909 NoDmik(AssertMsgFailed(("Failed to construct '%s'/%d! %Vra\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc)));
910 /* because we're damn lazy right now, we'll say that the destructor will be called even if the constructor fails. */
911 return rc;
912 }
913 } /* for device instances */
914
915#ifdef VBOX_WITH_USB
916 /* ditto for USB Devices. */
917 rc = pdmR3UsbInstantiateDevices(pVM);
918 if (RT_FAILURE(rc))
919 return rc;
920#endif
921
922
923 /*
924 *
925 * PCI BIOS Fake and Init Complete.
926 *
927 */
928 if (pVM->pdm.s.aPciBuses[0].pDevInsR3)
929 {
930 pdmLock(pVM);
931 rc = pVM->pdm.s.aPciBuses[0].pfnFakePCIBIOSR3(pVM->pdm.s.aPciBuses[0].pDevInsR3);
932 pdmUnlock(pVM);
933 if (VBOX_FAILURE(rc))
934 {
935 AssertMsgFailed(("PCI BIOS fake failed rc=%Vrc\n", rc));
936 return rc;
937 }
938 }
939
940 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextHC)
941 {
942 if (pDevIns->pDevReg->pfnInitComplete)
943 {
944 rc = pDevIns->pDevReg->pfnInitComplete(pDevIns);
945 if (VBOX_FAILURE(rc))
946 {
947 AssertMsgFailed(("InitComplete on device '%s'/%d failed with rc=%Vrc\n",
948 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
949 return rc;
950 }
951 }
952 }
953
954#ifdef VBOX_WITH_USB
955 /* ditto for USB Devices. */
956 rc = pdmR3UsbVMInitComplete(pVM);
957 if (RT_FAILURE(rc))
958 return rc;
959#endif
960
961 LogFlow(("pdmR3DevInit: returns %Vrc\n", VINF_SUCCESS));
962 return VINF_SUCCESS;
963}
964
965
966/**
967 * Lookups a device structure by name.
968 * @internal
969 */
970PPDMDEV pdmR3DevLookup(PVM pVM, const char *pszName)
971{
972 RTUINT cchName = strlen(pszName);
973 for (PPDMDEV pDev = pVM->pdm.s.pDevs; pDev; pDev = pDev->pNext)
974 if ( pDev->cchName == cchName
975 && !strcmp(pDev->pDevReg->szDeviceName, pszName))
976 return pDev;
977 return NULL;
978}
979
980
981/**
982 * Loads one device module and call the registration entry point.
983 *
984 * @returns VBox status code.
985 * @param pVM VM handle.
986 * @param pRegCB The registration callback stuff.
987 * @param pszFilename Module filename.
988 * @param pszName Module name.
989 */
990static int pdmR3DevLoad(PVM pVM, PPDMDEVREGCBINT pRegCB, const char *pszFilename, const char *pszName)
991{
992 /*
993 * Load it.
994 */
995 int rc = pdmR3LoadR3U(pVM->pUVM, pszFilename, pszName);
996 if (VBOX_SUCCESS(rc))
997 {
998 /*
999 * Get the registration export and call it.
1000 */
1001 FNPDMVBOXDEVICESREGISTER *pfnVBoxDevicesRegister;
1002 rc = PDMR3GetSymbolR3(pVM, pszName, "VBoxDevicesRegister", (void **)&pfnVBoxDevicesRegister);
1003 if (VBOX_SUCCESS(rc))
1004 {
1005 Log(("PDM: Calling VBoxDevicesRegister (%p) of %s (%s)\n", pfnVBoxDevicesRegister, pszName, pszFilename));
1006 rc = pfnVBoxDevicesRegister(&pRegCB->Core, VBOX_VERSION);
1007 if (VBOX_SUCCESS(rc))
1008 Log(("PDM: Successfully loaded device module %s (%s).\n", pszName, pszFilename));
1009 else
1010 AssertMsgFailed(("VBoxDevicesRegister failed with rc=%Vrc for module %s (%s)\n", rc, pszName, pszFilename));
1011 }
1012 else
1013 {
1014 AssertMsgFailed(("Failed to locate 'VBoxDevicesRegister' in %s (%s) rc=%Vrc\n", pszName, pszFilename, rc));
1015 if (rc == VERR_SYMBOL_NOT_FOUND)
1016 rc = VERR_PDM_NO_REGISTRATION_EXPORT;
1017 }
1018 }
1019 else
1020 AssertMsgFailed(("Failed to load %s %s!\n", pszFilename, pszName));
1021 return rc;
1022}
1023
1024
1025
1026/**
1027 * Registers a device with the current VM instance.
1028 *
1029 * @returns VBox status code.
1030 * @param pCallbacks Pointer to the callback table.
1031 * @param pDevReg Pointer to the device registration record.
1032 * This data must be permanent and readonly.
1033 */
1034static DECLCALLBACK(int) pdmR3DevReg_Register(PPDMDEVREGCB pCallbacks, PCPDMDEVREG pDevReg)
1035{
1036 /*
1037 * Validate the registration structure.
1038 */
1039 Assert(pDevReg);
1040 if (pDevReg->u32Version != PDM_DEVREG_VERSION)
1041 {
1042 AssertMsgFailed(("Unknown struct version %#x!\n", pDevReg->u32Version));
1043 return VERR_PDM_UNKNOWN_DEVREG_VERSION;
1044 }
1045 if ( !pDevReg->szDeviceName[0]
1046 || strlen(pDevReg->szDeviceName) >= sizeof(pDevReg->szDeviceName))
1047 {
1048 AssertMsgFailed(("Invalid name '%s'\n", pDevReg->szDeviceName));
1049 return VERR_PDM_INVALID_DEVICE_REGISTRATION;
1050 }
1051 if ( (pDevReg->fFlags & PDM_DEVREG_FLAGS_GC)
1052 && ( !pDevReg->szGCMod[0]
1053 || strlen(pDevReg->szGCMod) >= sizeof(pDevReg->szGCMod)))
1054 {
1055 AssertMsgFailed(("Invalid GC module name '%s' - (Device %s)\n", pDevReg->szGCMod, pDevReg->szDeviceName));
1056 return VERR_PDM_INVALID_DEVICE_REGISTRATION;
1057 }
1058 if ( (pDevReg->fFlags & PDM_DEVREG_FLAGS_R0)
1059 && ( !pDevReg->szR0Mod[0]
1060 || strlen(pDevReg->szR0Mod) >= sizeof(pDevReg->szR0Mod)))
1061 {
1062 AssertMsgFailed(("Invalid R0 module name '%s' - (Device %s)\n", pDevReg->szR0Mod, pDevReg->szDeviceName));
1063 return VERR_PDM_INVALID_DEVICE_REGISTRATION;
1064 }
1065 if ((pDevReg->fFlags & PDM_DEVREG_FLAGS_HOST_BITS_MASK) != PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT)
1066 {
1067 AssertMsgFailed(("Invalid host bits flags! fFlags=%#x (Device %s)\n", pDevReg->fFlags, pDevReg->szDeviceName));
1068 return VERR_PDM_INVALID_DEVICE_HOST_BITS;
1069 }
1070 if (!(pDevReg->fFlags & PDM_DEVREG_FLAGS_GUEST_BITS_MASK))
1071 {
1072 AssertMsgFailed(("Invalid guest bits flags! fFlags=%#x (Device %s)\n", pDevReg->fFlags, pDevReg->szDeviceName));
1073 return VERR_PDM_INVALID_DEVICE_REGISTRATION;
1074 }
1075 if (!pDevReg->fClass)
1076 {
1077 AssertMsgFailed(("No class! (Device %s)\n", pDevReg->szDeviceName));
1078 return VERR_PDM_INVALID_DEVICE_REGISTRATION;
1079 }
1080 if (pDevReg->cMaxInstances <= 0)
1081 {
1082 AssertMsgFailed(("Max instances %u! (Device %s)\n", pDevReg->cMaxInstances, pDevReg->szDeviceName));
1083 return VERR_PDM_INVALID_DEVICE_REGISTRATION;
1084 }
1085 if (pDevReg->cbInstance > (RTUINT)(pDevReg->fFlags & (PDM_DEVREG_FLAGS_GC | PDM_DEVREG_FLAGS_R0) ? 96 * _1K : _1M))
1086 {
1087 AssertMsgFailed(("Instance size %d bytes! (Device %s)\n", pDevReg->cbInstance, pDevReg->szDeviceName));
1088 return VERR_PDM_INVALID_DEVICE_REGISTRATION;
1089 }
1090 if (!pDevReg->pfnConstruct)
1091 {
1092 AssertMsgFailed(("No constructore! (Device %s)\n", pDevReg->szDeviceName));
1093 return VERR_PDM_INVALID_DEVICE_REGISTRATION;
1094 }
1095 /* Check matching guest bits last without any asserting. Enables trial and error registration. */
1096 if (!(pDevReg->fFlags & PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT))
1097 {
1098 Log(("PDM: Rejected device '%s' because it didn't match the guest bits.\n", pDevReg->szDeviceName));
1099 return VERR_PDM_INVALID_DEVICE_GUEST_BITS;
1100 }
1101
1102 /*
1103 * Check for duplicate and find FIFO entry at the same time.
1104 */
1105 PCPDMDEVREGCBINT pRegCB = (PCPDMDEVREGCBINT)pCallbacks;
1106 PPDMDEV pDevPrev = NULL;
1107 PPDMDEV pDev = pRegCB->pVM->pdm.s.pDevs;
1108 for (; pDev; pDevPrev = pDev, pDev = pDev->pNext)
1109 {
1110 if (!strcmp(pDev->pDevReg->szDeviceName, pDevReg->szDeviceName))
1111 {
1112 AssertMsgFailed(("Device '%s' already exists\n", pDevReg->szDeviceName));
1113 return VERR_PDM_DEVICE_NAME_CLASH;
1114 }
1115 }
1116
1117 /*
1118 * Allocate new device structure and insert it into the list.
1119 */
1120 pDev = (PPDMDEV)MMR3HeapAlloc(pRegCB->pVM, MM_TAG_PDM_DEVICE, sizeof(*pDev));
1121 if (pDev)
1122 {
1123 pDev->pNext = NULL;
1124 pDev->cInstances = 0;
1125 pDev->pInstances = NULL;
1126 pDev->pDevReg = pDevReg;
1127 pDev->cchName = strlen(pDevReg->szDeviceName);
1128
1129 if (pDevPrev)
1130 pDevPrev->pNext = pDev;
1131 else
1132 pRegCB->pVM->pdm.s.pDevs = pDev;
1133 Log(("PDM: Registered device '%s'\n", pDevReg->szDeviceName));
1134 return VINF_SUCCESS;
1135 }
1136 return VERR_NO_MEMORY;
1137}
1138
1139
1140/**
1141 * Allocate memory which is associated with current VM instance
1142 * and automatically freed on it's destruction.
1143 *
1144 * @returns Pointer to allocated memory. The memory is *NOT* zero-ed.
1145 * @param pCallbacks Pointer to the callback table.
1146 * @param cb Number of bytes to allocate.
1147 */
1148static DECLCALLBACK(void *) pdmR3DevReg_MMHeapAlloc(PPDMDEVREGCB pCallbacks, size_t cb)
1149{
1150 Assert(pCallbacks);
1151 Assert(pCallbacks->u32Version == PDM_DEVREG_CB_VERSION);
1152 LogFlow(("pdmR3DevReg_MMHeapAlloc: cb=%#x\n", cb));
1153
1154 void *pv = MMR3HeapAlloc(((PPDMDEVREGCBINT)pCallbacks)->pVM, MM_TAG_PDM_DEVICE_USER, cb);
1155
1156 LogFlow(("pdmR3DevReg_MMHeapAlloc: returns %p\n", pv));
1157 return pv;
1158}
1159
1160
1161/**
1162 * Queue consumer callback for internal component.
1163 *
1164 * @returns Success indicator.
1165 * If false the item will not be removed and the flushing will stop.
1166 * @param pVM The VM handle.
1167 * @param pItem The item to consume. Upon return this item will be freed.
1168 */
1169static DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
1170{
1171 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)pItem;
1172 LogFlow(("pdmR3DevHlpQueueConsumer: enmOp=%d pDevIns=%p\n", pTask->enmOp, pTask->pDevInsHC));
1173 switch (pTask->enmOp)
1174 {
1175 case PDMDEVHLPTASKOP_ISA_SET_IRQ:
1176 PDMIsaSetIrq(pVM, pTask->u.SetIRQ.iIrq, pTask->u.SetIRQ.iLevel);
1177 break;
1178
1179 case PDMDEVHLPTASKOP_PCI_SET_IRQ:
1180 pdmR3DevHlp_PCISetIrq(pTask->pDevInsHC, pTask->u.SetIRQ.iIrq, pTask->u.SetIRQ.iLevel);
1181 break;
1182
1183 case PDMDEVHLPTASKOP_IOAPIC_SET_IRQ:
1184 PDMIoApicSetIrq(pVM, pTask->u.SetIRQ.iIrq, pTask->u.SetIRQ.iLevel);
1185 break;
1186
1187 default:
1188 AssertReleaseMsgFailed(("Invalid operation %d\n", pTask->enmOp));
1189 break;
1190 }
1191 return true;
1192}
1193
1194
1195/** @copydoc PDMDEVHLP::pfnIOPortRegister */
1196static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn,
1197 PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc)
1198{
1199 PDMDEV_ASSERT_DEVINS(pDevIns);
1200 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,
1201 Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc, pszDesc));
1202 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
1203
1204 int rc = IOMR3IOPortRegisterR3(pDevIns->Internal.s.pVMHC, pDevIns, Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc);
1205
1206 LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1207 return rc;
1208}
1209
1210
1211/** @copydoc PDMDEVHLP::pfnIOPortRegisterGC */
1212static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterGC(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTGCPTR pvUser,
1213 const char *pszOut, const char *pszIn,
1214 const char *pszOutStr, const char *pszInStr, const char *pszDesc)
1215{
1216 PDMDEV_ASSERT_DEVINS(pDevIns);
1217 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
1218 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,
1219 Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
1220
1221 /*
1222 * Resolve the functions (one of the can be NULL).
1223 */
1224 int rc = VINF_SUCCESS;
1225 if ( pDevIns->pDevReg->szGCMod[0]
1226 && (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_GC))
1227 {
1228 RTGCPTR GCPtrIn = 0;
1229 if (pszIn)
1230 {
1231 rc = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszIn, &GCPtrIn);
1232 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pDevReg->szGCMod, pszIn));
1233 }
1234 RTGCPTR GCPtrOut = 0;
1235 if (pszOut && VBOX_SUCCESS(rc))
1236 {
1237 rc = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszOut, &GCPtrOut);
1238 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pDevReg->szGCMod, pszOut));
1239 }
1240 RTGCPTR GCPtrInStr = 0;
1241 if (pszInStr && VBOX_SUCCESS(rc))
1242 {
1243 rc = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszInStr, &GCPtrInStr);
1244 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pDevReg->szGCMod, pszInStr));
1245 }
1246 RTGCPTR GCPtrOutStr = 0;
1247 if (pszOutStr && VBOX_SUCCESS(rc))
1248 {
1249 rc = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszOutStr, &GCPtrOutStr);
1250 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pDevReg->szGCMod, pszOutStr));
1251 }
1252
1253 if (VBOX_SUCCESS(rc))
1254 rc = IOMIOPortRegisterGC(pDevIns->Internal.s.pVMHC, pDevIns, Port, cPorts, pvUser, GCPtrOut, GCPtrIn, GCPtrOutStr, GCPtrInStr, pszDesc);
1255 }
1256 else
1257 {
1258 AssertMsgFailed(("No GC module for this driver!\n"));
1259 rc = VERR_INVALID_PARAMETER;
1260 }
1261
1262 LogFlow(("pdmR3DevHlp_IOPortRegisterGC: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1263 return rc;
1264}
1265
1266
1267/** @copydoc PDMDEVHLP::pfnIOPortRegisterR0 */
1268static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTR0PTR pvUser,
1269 const char *pszOut, const char *pszIn,
1270 const char *pszOutStr, const char *pszInStr, const char *pszDesc)
1271{
1272 PDMDEV_ASSERT_DEVINS(pDevIns);
1273 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
1274 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,
1275 Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
1276
1277 /*
1278 * Resolve the functions (one of the can be NULL).
1279 */
1280 int rc = VINF_SUCCESS;
1281 if ( pDevIns->pDevReg->szR0Mod[0]
1282 && (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
1283 {
1284 R0PTRTYPE(PFNIOMIOPORTIN) pfnR0PtrIn = 0;
1285 if (pszIn)
1286 {
1287 rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszIn, &pfnR0PtrIn);
1288 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pDevReg->szR0Mod, pszIn));
1289 }
1290 R0PTRTYPE(PFNIOMIOPORTOUT) pfnR0PtrOut = 0;
1291 if (pszOut && VBOX_SUCCESS(rc))
1292 {
1293 rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszOut, &pfnR0PtrOut);
1294 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pDevReg->szR0Mod, pszOut));
1295 }
1296 R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnR0PtrInStr = 0;
1297 if (pszInStr && VBOX_SUCCESS(rc))
1298 {
1299 rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszInStr, &pfnR0PtrInStr);
1300 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pDevReg->szR0Mod, pszInStr));
1301 }
1302 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnR0PtrOutStr = 0;
1303 if (pszOutStr && VBOX_SUCCESS(rc))
1304 {
1305 rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszOutStr, &pfnR0PtrOutStr);
1306 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pDevReg->szR0Mod, pszOutStr));
1307 }
1308
1309 if (VBOX_SUCCESS(rc))
1310 rc = IOMIOPortRegisterR0(pDevIns->Internal.s.pVMHC, pDevIns, Port, cPorts, pvUser, pfnR0PtrOut, pfnR0PtrIn, pfnR0PtrOutStr, pfnR0PtrInStr, pszDesc);
1311 }
1312 else
1313 {
1314 AssertMsgFailed(("No R0 module for this driver!\n"));
1315 rc = VERR_INVALID_PARAMETER;
1316 }
1317
1318 LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1319 return rc;
1320}
1321
1322
1323/** @copydoc PDMDEVHLP::pfnIOPortDeregister */
1324static DECLCALLBACK(int) pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts)
1325{
1326 PDMDEV_ASSERT_DEVINS(pDevIns);
1327 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
1328 LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: Port=%#x cPorts=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
1329 Port, cPorts));
1330
1331 int rc = IOMR3IOPortDeregister(pDevIns->Internal.s.pVMHC, pDevIns, Port, cPorts);
1332
1333 LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1334 return rc;
1335}
1336
1337
1338/** @copydoc PDMDEVHLP::pfnMMIORegister */
1339static DECLCALLBACK(int) pdmR3DevHlp_MMIORegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTHCPTR pvUser,
1340 PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill,
1341 const char *pszDesc)
1342{
1343 PDMDEV_ASSERT_DEVINS(pDevIns);
1344 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
1345 LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pfnWrite=%p pfnRead=%p pfnFill=%p pszDesc=%p:{%s}\n",
1346 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill, pszDesc, pszDesc));
1347
1348 int rc = IOMR3MMIORegisterR3(pDevIns->Internal.s.pVMHC, pDevIns, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill, pszDesc);
1349
1350 LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1351 return rc;
1352}
1353
1354
1355/** @copydoc PDMDEVHLP::pfnMMIORegisterGC */
1356static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterGC(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser,
1357 const char *pszWrite, const char *pszRead, const char *pszFill,
1358 const char *pszDesc)
1359{
1360 PDMDEV_ASSERT_DEVINS(pDevIns);
1361 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
1362 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",
1363 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill, pszDesc, pszDesc));
1364
1365 /*
1366 * Resolve the functions.
1367 * Not all function have to present, leave it to IOM to enforce this.
1368 */
1369 int rc = VINF_SUCCESS;
1370 if ( pDevIns->pDevReg->szGCMod[0]
1371 && (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_GC))
1372 {
1373 RTGCPTR GCPtrWrite = 0;
1374 if (pszWrite)
1375 rc = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszWrite, &GCPtrWrite);
1376 RTGCPTR GCPtrRead = 0;
1377 int rc2 = VINF_SUCCESS;
1378 if (pszRead)
1379 rc2 = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszRead, &GCPtrRead);
1380 RTGCPTR GCPtrFill = 0;
1381 int rc3 = VINF_SUCCESS;
1382 if (pszFill)
1383 rc3 = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszFill, &GCPtrFill);
1384 if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3))
1385 rc = IOMMMIORegisterGC(pDevIns->Internal.s.pVMHC, pDevIns, GCPhysStart, cbRange, pvUser, GCPtrWrite, GCPtrRead, GCPtrFill, pszDesc);
1386 else
1387 {
1388 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszWrite)\n", pDevIns->pDevReg->szGCMod, pszWrite));
1389 AssertMsgRC(rc2, ("Failed to resolve %s.%s (pszRead)\n", pDevIns->pDevReg->szGCMod, pszRead));
1390 AssertMsgRC(rc3, ("Failed to resolve %s.%s (pszFill)\n", pDevIns->pDevReg->szGCMod, pszFill));
1391 if (VBOX_FAILURE(rc2) && VBOX_SUCCESS(rc))
1392 rc = rc2;
1393 if (VBOX_FAILURE(rc3) && VBOX_SUCCESS(rc))
1394 rc = rc3;
1395 }
1396 }
1397 else
1398 {
1399 AssertMsgFailed(("No GC module for this driver!\n"));
1400 rc = VERR_INVALID_PARAMETER;
1401 }
1402
1403 LogFlow(("pdmR3DevHlp_MMIORegisterGC: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1404 return rc;
1405}
1406
1407/** @copydoc PDMDEVHLP::pfnMMIORegisterR0 */
1408static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterR0(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser,
1409 const char *pszWrite, const char *pszRead, const char *pszFill,
1410 const char *pszDesc)
1411{
1412 PDMDEV_ASSERT_DEVINS(pDevIns);
1413 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
1414 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",
1415 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill, pszDesc, pszDesc));
1416
1417 /*
1418 * Resolve the functions.
1419 * Not all function have to present, leave it to IOM to enforce this.
1420 */
1421 int rc = VINF_SUCCESS;
1422 if ( pDevIns->pDevReg->szR0Mod[0]
1423 && (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
1424 {
1425 R0PTRTYPE(PFNIOMMMIOWRITE) pfnR0PtrWrite = 0;
1426 if (pszWrite)
1427 rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszWrite, &pfnR0PtrWrite);
1428 R0PTRTYPE(PFNIOMMMIOREAD) pfnR0PtrRead = 0;
1429 int rc2 = VINF_SUCCESS;
1430 if (pszRead)
1431 rc2 = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszRead, &pfnR0PtrRead);
1432 R0PTRTYPE(PFNIOMMMIOFILL) pfnR0PtrFill = 0;
1433 int rc3 = VINF_SUCCESS;
1434 if (pszFill)
1435 rc3 = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszFill, &pfnR0PtrFill);
1436 if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3))
1437 rc = IOMMMIORegisterR0(pDevIns->Internal.s.pVMHC, pDevIns, GCPhysStart, cbRange, pvUser, pfnR0PtrWrite, pfnR0PtrRead, pfnR0PtrFill, pszDesc);
1438 else
1439 {
1440 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszWrite)\n", pDevIns->pDevReg->szR0Mod, pszWrite));
1441 AssertMsgRC(rc2, ("Failed to resolve %s.%s (pszRead)\n", pDevIns->pDevReg->szR0Mod, pszRead));
1442 AssertMsgRC(rc3, ("Failed to resolve %s.%s (pszFill)\n", pDevIns->pDevReg->szR0Mod, pszFill));
1443 if (VBOX_FAILURE(rc2) && VBOX_SUCCESS(rc))
1444 rc = rc2;
1445 if (VBOX_FAILURE(rc3) && VBOX_SUCCESS(rc))
1446 rc = rc3;
1447 }
1448 }
1449 else
1450 {
1451 AssertMsgFailed(("No R0 module for this driver!\n"));
1452 rc = VERR_INVALID_PARAMETER;
1453 }
1454
1455 LogFlow(("pdmR3DevHlp_MMIORegisterR0: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1456 return rc;
1457}
1458
1459
1460/** @copydoc PDMDEVHLP::pfnMMIODeregister */
1461static DECLCALLBACK(int) pdmR3DevHlp_MMIODeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
1462{
1463 PDMDEV_ASSERT_DEVINS(pDevIns);
1464 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
1465 LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x\n",
1466 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange));
1467
1468 int rc = IOMR3MMIODeregister(pDevIns->Internal.s.pVMHC, pDevIns, GCPhysStart, cbRange);
1469
1470 LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1471 return rc;
1472}
1473
1474
1475/** @copydoc PDMDEVHLP::pfnROMRegister */
1476static DECLCALLBACK(int) pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, const void *pvBinary, bool fShadow, const char *pszDesc)
1477{
1478 PDMDEV_ASSERT_DEVINS(pDevIns);
1479 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
1480 LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvBinary=%p fShadow=%RTbool pszDesc=%p:{%s}\n",
1481 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvBinary, fShadow, pszDesc, pszDesc));
1482
1483 int rc = MMR3PhysRomRegister(pDevIns->Internal.s.pVMHC, pDevIns, GCPhysStart, cbRange, pvBinary, fShadow, pszDesc);
1484
1485 LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1486 return rc;
1487}
1488
1489
1490/** @copydoc PDMDEVHLP::pfnSSMRegister */
1491static DECLCALLBACK(int) pdmR3DevHlp_SSMRegister(PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
1492 PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
1493 PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
1494{
1495 PDMDEV_ASSERT_DEVINS(pDevIns);
1496 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
1497 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",
1498 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, u32Instance, u32Version, cbGuess, pfnSavePrep, pfnSaveExec, pfnSaveDone, pfnLoadPrep, pfnLoadExec, pfnLoadDone));
1499
1500 int rc = SSMR3Register(pDevIns->Internal.s.pVMHC, pDevIns, pszName, u32Instance, u32Version, cbGuess,
1501 pfnSavePrep, pfnSaveExec, pfnSaveDone,
1502 pfnLoadPrep, pfnLoadExec, pfnLoadDone);
1503
1504 LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1505 return rc;
1506}
1507
1508
1509/** @copydoc PDMDEVHLP::pfnTMTimerCreate */
1510static DECLCALLBACK(int) pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer)
1511{
1512 PDMDEV_ASSERT_DEVINS(pDevIns);
1513 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
1514 LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pszDesc=%p:{%s} ppTimer=%p\n",
1515 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, enmClock, pfnCallback, pszDesc, pszDesc, ppTimer));
1516
1517 int rc = TMR3TimerCreateDevice(pDevIns->Internal.s.pVMHC, pDevIns, enmClock, pfnCallback, pszDesc, ppTimer);
1518
1519 LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1520 return rc;
1521}
1522
1523
1524/** @copydoc PDMDEVHLP::pfnTMTimerCreateExternal */
1525static DECLCALLBACK(PTMTIMERR3) pdmR3DevHlp_TMTimerCreateExternal(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMEREXT pfnCallback, void *pvUser, const char *pszDesc)
1526{
1527 PDMDEV_ASSERT_DEVINS(pDevIns);
1528 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
1529
1530 return TMR3TimerCreateExternal(pDevIns->Internal.s.pVMHC, enmClock, pfnCallback, pvUser, pszDesc);
1531}
1532
1533/** @copydoc PDMDEVHLP::pfnPCIRegister */
1534static DECLCALLBACK(int) pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev)
1535{
1536 PDMDEV_ASSERT_DEVINS(pDevIns);
1537 PVM pVM = pDevIns->Internal.s.pVMHC;
1538 VM_ASSERT_EMT(pVM);
1539 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: pPciDev=%p:{.config={%#.256Vhxs}\n",
1540 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev, pPciDev->config));
1541
1542 /*
1543 * Validate input.
1544 */
1545 if (!pPciDev)
1546 {
1547 Assert(pPciDev);
1548 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (pPciDev)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1549 return VERR_INVALID_PARAMETER;
1550 }
1551 if (!pPciDev->config[0] && !pPciDev->config[1])
1552 {
1553 Assert(pPciDev->config[0] || pPciDev->config[1]);
1554 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (vendor)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1555 return VERR_INVALID_PARAMETER;
1556 }
1557 if (pDevIns->Internal.s.pPciDeviceHC)
1558 {
1559 /** @todo the PCI device vs. PDM device designed is a bit flawed if we have to
1560 * support a PDM device with multiple PCI devices. This might become a problem
1561 * when upgrading the chipset for instance...
1562 */
1563 AssertMsgFailed(("Only one PCI device per device is currently implemented!\n"));
1564 return VERR_INTERNAL_ERROR;
1565 }
1566
1567 /*
1568 * Choose the PCI bus for the device.
1569 * This is simple. If the device was configured for a particular bus, it'll
1570 * already have one. If not, we'll just take the first one.
1571 */
1572 PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusHC;
1573 if (!pBus)
1574 pBus = pDevIns->Internal.s.pPciBusHC = &pVM->pdm.s.aPciBuses[0];
1575 int rc;
1576 if (pBus)
1577 {
1578 if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_GC)
1579 pDevIns->Internal.s.pPciBusGC = MMHyperHC2GC(pVM, pDevIns->Internal.s.pPciBusHC);
1580
1581 /*
1582 * Check the configuration for PCI device and function assignment.
1583 */
1584 int iDev = -1;
1585 uint8_t u8Device;
1586 rc = CFGMR3QueryU8(pDevIns->Internal.s.pCfgHandle, "PCIDeviceNo", &u8Device);
1587 if (VBOX_SUCCESS(rc))
1588 {
1589 if (u8Device > 31)
1590 {
1591 AssertMsgFailed(("Configuration error: PCIDeviceNo=%d, max is 31. (%s/%d)\n",
1592 u8Device, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1593 return VERR_INTERNAL_ERROR;
1594 }
1595
1596 uint8_t u8Function;
1597 rc = CFGMR3QueryU8(pDevIns->Internal.s.pCfgHandle, "PCIFunctionNo", &u8Function);
1598 if (VBOX_FAILURE(rc))
1599 {
1600 AssertMsgFailed(("Configuration error: PCIDeviceNo, but PCIFunctionNo query failed with rc=%Vrc (%s/%d)\n",
1601 rc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1602 return rc;
1603 }
1604 if (u8Function > 7)
1605 {
1606 AssertMsgFailed(("Configuration error: PCIFunctionNo=%d, max is 7. (%s/%d)\n",
1607 u8Function, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1608 return VERR_INTERNAL_ERROR;
1609 }
1610 iDev = (u8Device << 3) | u8Function;
1611 }
1612 else if (rc != VERR_CFGM_VALUE_NOT_FOUND)
1613 {
1614 AssertMsgFailed(("Configuration error: PCIDeviceNo query failed with rc=%Vrc (%s/%d)\n",
1615 rc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1616 return rc;
1617 }
1618
1619 /*
1620 * Call the pci bus device to do the actual registration.
1621 */
1622 pdmLock(pVM);
1623 rc = pBus->pfnRegisterR3(pBus->pDevInsR3, pPciDev, pDevIns->pDevReg->szDeviceName, iDev);
1624 pdmUnlock(pVM);
1625 if (VBOX_SUCCESS(rc))
1626 {
1627 pDevIns->Internal.s.pPciDeviceHC = pPciDev;
1628 if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_GC)
1629 pDevIns->Internal.s.pPciDeviceGC = MMHyperHC2GC(pVM, pPciDev);
1630 else
1631 pDevIns->Internal.s.pPciDeviceGC = 0;
1632 pPciDev->pDevIns = pDevIns;
1633 Log(("PDM: Registered device '%s'/%d as PCI device %d on bus %d\n",
1634 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev->devfn, pDevIns->Internal.s.pPciBusHC->iBus));
1635 }
1636 }
1637 else
1638 {
1639 AssertMsgFailed(("Configuration error: No PCI bus available. This could be related to init order too!\n"));
1640 rc = VERR_PDM_NO_PCI_BUS;
1641 }
1642
1643 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1644 return rc;
1645}
1646
1647
1648/** @copydoc PDMDEVHLP::pfnPCIIORegionRegister */
1649static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
1650{
1651 PDMDEV_ASSERT_DEVINS(pDevIns);
1652 PVM pVM = pDevIns->Internal.s.pVMHC;
1653 VM_ASSERT_EMT(pVM);
1654 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: iRegion=%d cbRegion=%#x enmType=%d pfnCallback=%p\n",
1655 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, cbRegion, enmType, pfnCallback));
1656
1657 /*
1658 * Validate input.
1659 */
1660 if (iRegion < 0 || iRegion >= PCI_NUM_REGIONS)
1661 {
1662 Assert(iRegion >= 0 && iRegion < PCI_NUM_REGIONS);
1663 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (iRegion)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1664 return VERR_INVALID_PARAMETER;
1665 }
1666 switch (enmType)
1667 {
1668 case PCI_ADDRESS_SPACE_MEM:
1669 case PCI_ADDRESS_SPACE_IO:
1670 case PCI_ADDRESS_SPACE_MEM_PREFETCH:
1671 break;
1672 default:
1673 AssertMsgFailed(("enmType=%#x is unknown\n", enmType));
1674 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (enmType)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1675 return VERR_INVALID_PARAMETER;
1676 }
1677 if (!pfnCallback)
1678 {
1679 Assert(pfnCallback);
1680 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (callback)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1681 return VERR_INVALID_PARAMETER;
1682 }
1683 AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
1684
1685 /*
1686 * Must have a PCI device registered!
1687 */
1688 int rc;
1689 PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceHC;
1690 if (pPciDev)
1691 {
1692 /*
1693 * We're currently restricted to page aligned MMIO regions.
1694 */
1695 if ( (enmType == PCI_ADDRESS_SPACE_MEM || enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH)
1696 && cbRegion != RT_ALIGN_32(cbRegion, PAGE_SIZE))
1697 {
1698 Log(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: aligning cbRegion %#x -> %#x\n",
1699 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cbRegion, RT_ALIGN_32(cbRegion, PAGE_SIZE)));
1700 cbRegion = RT_ALIGN_32(cbRegion, PAGE_SIZE);
1701 }
1702
1703 PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusHC;
1704 Assert(pBus);
1705 pdmLock(pVM);
1706 rc = pBus->pfnIORegionRegisterR3(pBus->pDevInsR3, pPciDev, iRegion, cbRegion, enmType, pfnCallback);
1707 pdmUnlock(pVM);
1708 }
1709 else
1710 {
1711 AssertMsgFailed(("No PCI device registered!\n"));
1712 rc = VERR_PDM_NOT_PCI_DEVICE;
1713 }
1714
1715 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1716 return rc;
1717}
1718
1719
1720/** @copydoc PDMDEVHLP::pfnPCISetConfigCallbacks */
1721static DECLCALLBACK(void) pdmR3DevHlp_PCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
1722 PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)
1723{
1724 PDMDEV_ASSERT_DEVINS(pDevIns);
1725 PVM pVM = pDevIns->Internal.s.pVMHC;
1726 VM_ASSERT_EMT(pVM);
1727 LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: pPciDev=%p pfnRead=%p ppfnReadOld=%p pfnWrite=%p ppfnWriteOld=%p\n",
1728 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld));
1729
1730 /*
1731 * Validate input and resolve defaults.
1732 */
1733 AssertPtr(pfnRead);
1734 AssertPtr(pfnWrite);
1735 AssertPtrNull(ppfnReadOld);
1736 AssertPtrNull(ppfnWriteOld);
1737 AssertPtrNull(pPciDev);
1738
1739 if (!pPciDev)
1740 pPciDev = pDevIns->Internal.s.pPciDeviceHC;
1741 AssertReleaseMsg(pPciDev, ("You must register your device first!\n"));
1742 PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusHC;
1743 AssertRelease(pBus);
1744 AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
1745
1746 /*
1747 * Do the job.
1748 */
1749 pdmLock(pVM);
1750 pBus->pfnSetConfigCallbacksR3(pBus->pDevInsR3, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld);
1751 pdmUnlock(pVM);
1752
1753 LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1754}
1755
1756
1757/** @copydoc PDMDEVHLP::pfnPCISetIrq */
1758static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
1759{
1760 PDMDEV_ASSERT_DEVINS(pDevIns);
1761 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
1762
1763 /*
1764 * Validate input.
1765 */
1766 /** @todo iIrq and iLevel checks. */
1767
1768 /*
1769 * Must have a PCI device registered!
1770 */
1771 PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceHC;
1772 if (pPciDev)
1773 {
1774 PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusHC; /** @todo the bus should be associated with the PCI device not the PDM device. */
1775 Assert(pBus);
1776#ifdef VBOX_WITH_PDM_LOCK
1777 PVM pVM = pDevIns->Internal.s.pVMHC;
1778 pdmLock(pVM);
1779 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel);
1780 pdmUnlock(pVM);
1781
1782#else /* !VBOX_WITH_PDM_LOCK */
1783 /*
1784 * For the convenience of the device we put no thread restriction on this interface.
1785 * That means we'll have to check which thread we're in and choose our path.
1786 */
1787 if (VM_IS_EMT(pDevIns->Internal.s.pVMHC) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMHC))
1788 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel);
1789 else
1790 {
1791 Log(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1792 PVMREQ pReq;
1793 int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMHC, &pReq, RT_INDEFINITE_WAIT,
1794 (PFNRT)pBus->pfnSetIrqR3, 4, pBus->pDevInsR3, pPciDev, iIrq, iLevel);
1795 while (rc == VERR_TIMEOUT)
1796 rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
1797 AssertReleaseRC(rc);
1798 VMR3ReqFree(pReq);
1799 }
1800#endif /* !VBOX_WITH_PDM_LOCK */
1801 }
1802 else
1803 AssertReleaseMsgFailed(("No PCI device registered!\n"));
1804
1805 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1806}
1807
1808
1809/** @copydoc PDMDEVHLP::pfnPCISetIrqNoWait */
1810static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
1811{
1812#ifdef VBOX_WITH_PDM_LOCK
1813 pdmR3DevHlp_PCISetIrq(pDevIns, iIrq, iLevel);
1814#else /* !VBOX_WITH_PDM_LOCK */
1815 PDMDEV_ASSERT_DEVINS(pDevIns);
1816 LogFlow(("pdmR3DevHlp_PCISetIrqNoWait: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
1817
1818 /*
1819 * Validate input.
1820 */
1821 /** @todo iIrq and iLevel checks. */
1822
1823 /*
1824 * Must have a PCI device registered!
1825 */
1826 PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceHC;
1827 if (pPciDev)
1828 {
1829 PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusHC;
1830 Assert(pBus);
1831
1832 /*
1833 * For the convenience of the device we put no thread restriction on this interface.
1834 * That means we'll have to check which thread we're in and choose our path.
1835 */
1836 if (VM_IS_EMT(pDevIns->Internal.s.pVMHC) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMHC))
1837 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel);
1838 else
1839 {
1840 Log(("pdmR3DevHlp_PCISetIrqNoWait: caller='%s'/%d: Queueing call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1841 int rc = VMR3ReqCallEx(pDevIns->Internal.s.pVMHC, NULL, RT_INDEFINITE_WAIT, VMREQFLAGS_NO_WAIT | VMREQFLAGS_VOID,
1842 (PFNRT)pBus->pfnSetIrqR3, 4, pBus->pDevInsR3, pPciDev, iIrq, iLevel);
1843 AssertReleaseRC(rc);
1844 }
1845 }
1846 else
1847 AssertReleaseMsgFailed(("No PCI device registered!\n"));
1848
1849 LogFlow(("pdmR3DevHlp_PCISetIrqNoWait: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1850#endif /* !VBOX_WITH_PDM_LOCK */
1851}
1852
1853
1854/** @copydoc PDMDEVHLP::pfnISASetIrq */
1855static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
1856{
1857 PDMDEV_ASSERT_DEVINS(pDevIns);
1858 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
1859
1860 /*
1861 * Validate input.
1862 */
1863 /** @todo iIrq and iLevel checks. */
1864
1865 PVM pVM = pDevIns->Internal.s.pVMHC;
1866#ifdef VBOX_WITH_PDM_LOCK
1867 PDMIsaSetIrq(pVM, iIrq, iLevel); /* (The API takes the lock.) */
1868#else /* !VBOX_WITH_PDM_LOCK */
1869 if (VM_IS_EMT(pDevIns->Internal.s.pVMHC) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMHC))
1870 PDMIsaSetIrq(pVM, iIrq, iLevel);
1871 else
1872 {
1873 Log(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1874 PVMREQ pReq;
1875 int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMHC, &pReq, RT_INDEFINITE_WAIT,
1876 (PFNRT)PDMIsaSetIrq, 3, pVM, iIrq, iLevel);
1877 while (rc == VERR_TIMEOUT)
1878 rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
1879 AssertReleaseRC(rc);
1880 VMR3ReqFree(pReq);
1881 }
1882#endif /* !VBOX_WITH_PDM_LOCK */
1883
1884 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1885}
1886
1887/** @copydoc PDMDEVHLP::pfnISASetIrqNoWait */
1888static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
1889{
1890#ifdef VBOX_WITH_PDM_LOCK
1891 pdmR3DevHlp_ISASetIrq(pDevIns, iIrq, iLevel);
1892#else /* !VBOX_WITH_PDM_LOCK */
1893 PDMDEV_ASSERT_DEVINS(pDevIns);
1894 LogFlow(("pdmR3DevHlp_ISASetIrqNoWait: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
1895
1896 /*
1897 * Validate input.
1898 */
1899 /** @todo iIrq and iLevel checks. */
1900
1901 PVM pVM = pDevIns->Internal.s.pVMHC;
1902 /*
1903 * For the convenience of the device we put no thread restriction on this interface.
1904 * That means we'll have to check which thread we're in and choose our path.
1905 */
1906 if (VM_IS_EMT(pDevIns->Internal.s.pVMHC) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMHC))
1907 PDMIsaSetIrq(pVM, iIrq, iLevel);
1908 else
1909 {
1910 Log(("pdmR3DevHlp_ISASetIrqNoWait: caller='%s'/%d: Queueing call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1911 int rc = VMR3ReqCallEx(pDevIns->Internal.s.pVMHC, NULL, 0, VMREQFLAGS_NO_WAIT | VMREQFLAGS_VOID,
1912 (PFNRT)PDMIsaSetIrq, 3, pVM, iIrq, iLevel);
1913 AssertReleaseRC(rc);
1914 }
1915
1916 LogFlow(("pdmR3DevHlp_ISASetIrqNoWait: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1917#endif /* !VBOX_WITH_PDM_LOCK */
1918}
1919
1920
1921/** @copydoc PDMDEVHLP::pfnDriverAttach */
1922static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
1923{
1924 PDMDEV_ASSERT_DEVINS(pDevIns);
1925 PVM pVM = pDevIns->Internal.s.pVMHC;
1926 VM_ASSERT_EMT(pVM);
1927 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
1928 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
1929
1930 /*
1931 * Lookup the LUN, it might already be registered.
1932 */
1933 PPDMLUN pLunPrev = NULL;
1934 PPDMLUN pLun = pDevIns->Internal.s.pLunsHC;
1935 for (; pLun; pLunPrev = pLun, pLun = pLun->pNext)
1936 if (pLun->iLun == iLun)
1937 break;
1938
1939 /*
1940 * Create the LUN if if wasn't found, else check if driver is already attached to it.
1941 */
1942 if (!pLun)
1943 {
1944 if ( !pBaseInterface
1945 || !pszDesc
1946 || !*pszDesc)
1947 {
1948 Assert(pBaseInterface);
1949 Assert(pszDesc || *pszDesc);
1950 return VERR_INVALID_PARAMETER;
1951 }
1952
1953 pLun = (PPDMLUN)MMR3HeapAlloc(pVM, MM_TAG_PDM_LUN, sizeof(*pLun));
1954 if (!pLun)
1955 return VERR_NO_MEMORY;
1956
1957 pLun->iLun = iLun;
1958 pLun->pNext = pLunPrev ? pLunPrev->pNext : NULL;
1959 pLun->pTop = NULL;
1960 pLun->pBottom = NULL;
1961 pLun->pDevIns = pDevIns;
1962 pLun->pszDesc = pszDesc;
1963 pLun->pBase = pBaseInterface;
1964 if (!pLunPrev)
1965 pDevIns->Internal.s.pLunsHC = pLun;
1966 else
1967 pLunPrev->pNext = pLun;
1968 Log(("pdmR3DevHlp_DriverAttach: Registered LUN#%d '%s' with device '%s'/%d.\n",
1969 iLun, pszDesc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
1970 }
1971 else if (pLun->pTop)
1972 {
1973 AssertMsgFailed(("Already attached! The device should keep track of such things!\n"));
1974 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_PDM_DRIVER_ALREADY_ATTACHED));
1975 return VERR_PDM_DRIVER_ALREADY_ATTACHED;
1976 }
1977 Assert(pLun->pBase == pBaseInterface);
1978
1979
1980 /*
1981 * Get the attached driver configuration.
1982 */
1983 int rc;
1984 char szNode[48];
1985 RTStrPrintf(szNode, sizeof(szNode), "LUN#%d", iLun);
1986 PCFGMNODE pNode = CFGMR3GetChild(pDevIns->Internal.s.pCfgHandle, szNode);
1987 if (pNode)
1988 {
1989 char *pszName;
1990 rc = CFGMR3QueryStringAlloc(pNode, "Driver", &pszName);
1991 if (VBOX_SUCCESS(rc))
1992 {
1993 /*
1994 * Find the driver.
1995 */
1996 PPDMDRV pDrv = pdmR3DrvLookup(pVM, pszName);
1997 if (pDrv)
1998 {
1999 /* config node */
2000 PCFGMNODE pConfigNode = CFGMR3GetChild(pNode, "Config");
2001 if (!pConfigNode)
2002 rc = CFGMR3InsertNode(pNode, "Config", &pConfigNode);
2003 if (VBOX_SUCCESS(rc))
2004 {
2005 CFGMR3SetRestrictedRoot(pConfigNode);
2006
2007 /*
2008 * Allocate the driver instance.
2009 */
2010 size_t cb = RT_OFFSETOF(PDMDRVINS, achInstanceData[pDrv->pDrvReg->cbInstance]);
2011 cb = RT_ALIGN_Z(cb, 16);
2012 PPDMDRVINS pNew = (PPDMDRVINS)MMR3HeapAllocZ(pVM, MM_TAG_PDM_DRIVER, cb);
2013 if (pNew)
2014 {
2015 /*
2016 * Initialize the instance structure (declaration order).
2017 */
2018 pNew->u32Version = PDM_DRVINS_VERSION;
2019 //pNew->Internal.s.pUp = NULL;
2020 //pNew->Internal.s.pDown = NULL;
2021 pNew->Internal.s.pLun = pLun;
2022 pNew->Internal.s.pDrv = pDrv;
2023 pNew->Internal.s.pVM = pVM;
2024 //pNew->Internal.s.fDetaching = false;
2025 pNew->Internal.s.pCfgHandle = pNode;
2026 pNew->pDrvHlp = &g_pdmR3DrvHlp;
2027 pNew->pDrvReg = pDrv->pDrvReg;
2028 pNew->pCfgHandle = pConfigNode;
2029 pNew->iInstance = pDrv->cInstances++;
2030 pNew->pUpBase = pBaseInterface;
2031 //pNew->pDownBase = NULL;
2032 //pNew->IBase.pfnQueryInterface = NULL;
2033 pNew->pvInstanceData = &pNew->achInstanceData[0];
2034
2035 /*
2036 * Link with LUN and call the constructor.
2037 */
2038 pLun->pTop = pLun->pBottom = pNew;
2039 rc = pDrv->pDrvReg->pfnConstruct(pNew, pNew->pCfgHandle);
2040 if (VBOX_SUCCESS(rc))
2041 {
2042 MMR3HeapFree(pszName);
2043 *ppBaseInterface = &pNew->IBase;
2044 Log(("PDM: Attached driver '%s'/%d to LUN#%d on device '%s'/%d.\n",
2045 pDrv->pDrvReg->szDriverName, pNew->iInstance, iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
2046 LogFlow(("pdmR3DevHlp_DriverAttach: caller '%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
2047 /*
2048 * Might return != VINF_SUCCESS (e.g. VINF_NAT_DNS) */
2049 return rc;
2050 }
2051
2052 /*
2053 * Free the driver.
2054 */
2055 pLun->pTop = pLun->pBottom = NULL;
2056 ASMMemFill32(pNew, cb, 0xdeadd0d0);
2057 MMR3HeapFree(pNew);
2058 pDrv->cInstances--;
2059 }
2060 else
2061 {
2062 AssertMsgFailed(("Failed to allocate %d bytes for instantiating driver '%s'\n", cb, pszName));
2063 rc = VERR_NO_MEMORY;
2064 }
2065 }
2066 else
2067 AssertMsgFailed(("Failed to create Config node! rc=%Vrc\n", rc));
2068 }
2069 else
2070 {
2071 AssertMsgFailed(("Driver '%s' wasn't found!\n", pszName));
2072 rc = VERR_PDM_DRIVER_NOT_FOUND;
2073 }
2074 MMR3HeapFree(pszName);
2075 }
2076 else
2077 {
2078 AssertMsgFailed(("Query for string value of \"Driver\" -> %Vrc\n", rc));
2079 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
2080 rc = VERR_PDM_CFG_MISSING_DRIVER_NAME;
2081 }
2082 }
2083 else
2084 rc = VERR_PDM_NO_ATTACHED_DRIVER;
2085
2086
2087 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2088 return rc;
2089}
2090
2091
2092/** @copydoc PDMDEVHLP::pfnMMHeapAlloc */
2093static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAlloc(PPDMDEVINS pDevIns, size_t cb)
2094{
2095 PDMDEV_ASSERT_DEVINS(pDevIns);
2096 LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
2097
2098 void *pv = MMR3HeapAlloc(pDevIns->Internal.s.pVMHC, MM_TAG_PDM_DEVICE_USER, cb);
2099
2100 LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
2101 return pv;
2102}
2103
2104
2105/** @copydoc PDMDEVHLP::pfnMMHeapAllocZ */
2106static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb)
2107{
2108 PDMDEV_ASSERT_DEVINS(pDevIns);
2109 LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
2110
2111 void *pv = MMR3HeapAllocZ(pDevIns->Internal.s.pVMHC, MM_TAG_PDM_DEVICE_USER, cb);
2112
2113 LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
2114 return pv;
2115}
2116
2117
2118/** @copydoc PDMDEVHLP::pfnMMHeapFree */
2119static DECLCALLBACK(void) pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv)
2120{
2121 PDMDEV_ASSERT_DEVINS(pDevIns);
2122 LogFlow(("pdmR3DevHlp_MMHeapFree: caller='%s'/%d: pv=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
2123
2124 MMR3HeapFree(pv);
2125
2126 LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
2127}
2128
2129
2130/** @copydoc PDMDEVHLP::pfnVMSetError */
2131static DECLCALLBACK(int) pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
2132{
2133 PDMDEV_ASSERT_DEVINS(pDevIns);
2134 va_list args;
2135 va_start(args, pszFormat);
2136 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMHC, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
2137 va_end(args);
2138 return rc;
2139}
2140
2141
2142/** @copydoc PDMDEVHLP::pfnVMSetErrorV */
2143static DECLCALLBACK(int) pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
2144{
2145 PDMDEV_ASSERT_DEVINS(pDevIns);
2146 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMHC, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
2147 return rc;
2148}
2149
2150
2151/** @copydoc PDMDEVHLP::pfnVMSetRuntimeError */
2152static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, ...)
2153{
2154 PDMDEV_ASSERT_DEVINS(pDevIns);
2155 va_list args;
2156 va_start(args, pszFormat);
2157 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMHC, fFatal, pszErrorID, pszFormat, args);
2158 va_end(args);
2159 return rc;
2160}
2161
2162
2163/** @copydoc PDMDEVHLP::pfnVMSetRuntimeErrorV */
2164static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list va)
2165{
2166 PDMDEV_ASSERT_DEVINS(pDevIns);
2167 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMHC, fFatal, pszErrorID, pszFormat, va);
2168 return rc;
2169}
2170
2171
2172/** @copydoc PDMDEVHLP::pfnAssertEMT */
2173static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
2174{
2175 PDMDEV_ASSERT_DEVINS(pDevIns);
2176 if (VM_IS_EMT(pDevIns->Internal.s.pVMHC))
2177 return true;
2178
2179 char szMsg[100];
2180 RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
2181 AssertMsg1(szMsg, iLine, pszFile, pszFunction);
2182 AssertBreakpoint();
2183 return false;
2184}
2185
2186
2187/** @copydoc PDMDEVHLP::pfnAssertOther */
2188static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
2189{
2190 PDMDEV_ASSERT_DEVINS(pDevIns);
2191 if (!VM_IS_EMT(pDevIns->Internal.s.pVMHC))
2192 return true;
2193
2194 char szMsg[100];
2195 RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
2196 AssertMsg1(szMsg, iLine, pszFile, pszFunction);
2197 AssertBreakpoint();
2198 return false;
2199}
2200
2201
2202/** @copydoc PDMDEVHLP::pfnDBGFStopV */
2203static DECLCALLBACK(int) pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args)
2204{
2205 PDMDEV_ASSERT_DEVINS(pDevIns);
2206#ifdef LOG_ENABLED
2207 va_list va2;
2208 va_copy(va2, args);
2209 LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: pszFile=%p:{%s} iLine=%d pszFunction=%p:{%s} pszFormat=%p:{%s} (%N)\n",
2210 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszFile, pszFile, iLine, pszFunction, pszFunction, pszFormat, pszFormat, pszFormat, &va2));
2211 va_end(va2);
2212#endif
2213
2214 PVM pVM = pDevIns->Internal.s.pVMHC;
2215 VM_ASSERT_EMT(pVM);
2216 int rc = DBGFR3EventSrcV(pVM, DBGFEVENT_DEV_STOP, pszFile, iLine, pszFunction, pszFormat, args);
2217
2218 LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2219 return rc;
2220}
2221
2222
2223/** @copydoc PDMDEVHLP::pfnDBGFInfoRegister */
2224static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler)
2225{
2226 PDMDEV_ASSERT_DEVINS(pDevIns);
2227 LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
2228 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, pszDesc, pszDesc, pfnHandler));
2229
2230 PVM pVM = pDevIns->Internal.s.pVMHC;
2231 VM_ASSERT_EMT(pVM);
2232 int rc = DBGFR3InfoRegisterDevice(pVM, pszName, pszDesc, pfnHandler, pDevIns);
2233
2234 LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2235 return rc;
2236}
2237
2238
2239/** @copydoc PDMDEVHLP::pfnSTAMRegister */
2240static DECLCALLBACK(void) pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
2241{
2242 PDMDEV_ASSERT_DEVINS(pDevIns);
2243 PVM pVM = pDevIns->Internal.s.pVMHC;
2244 VM_ASSERT_EMT(pVM);
2245
2246 STAM_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc);
2247 NOREF(pVM);
2248}
2249
2250
2251
2252/** @copydoc PDMDEVHLP::pfnSTAMRegisterF */
2253static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
2254 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...)
2255{
2256 PDMDEV_ASSERT_DEVINS(pDevIns);
2257 PVM pVM = pDevIns->Internal.s.pVMHC;
2258 VM_ASSERT_EMT(pVM);
2259
2260 va_list args;
2261 va_start(args, pszName);
2262 int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
2263 va_end(args);
2264 AssertRC(rc);
2265
2266 NOREF(pVM);
2267}
2268
2269
2270/** @copydoc PDMDEVHLP::pfnSTAMRegisterV */
2271static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
2272 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args)
2273{
2274 PDMDEV_ASSERT_DEVINS(pDevIns);
2275 PVM pVM = pDevIns->Internal.s.pVMHC;
2276 VM_ASSERT_EMT(pVM);
2277
2278 int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
2279 AssertRC(rc);
2280
2281 NOREF(pVM);
2282}
2283
2284
2285/** @copydoc PDMDEVHLP::pfnRTCRegister */
2286static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
2287{
2288 PDMDEV_ASSERT_DEVINS(pDevIns);
2289 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
2290 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
2291 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
2292 pRtcReg->pfnWrite, ppRtcHlp));
2293
2294 /*
2295 * Validate input.
2296 */
2297 if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
2298 {
2299 AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
2300 PDM_RTCREG_VERSION));
2301 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (version)\n",
2302 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2303 return VERR_INVALID_PARAMETER;
2304 }
2305 if ( !pRtcReg->pfnWrite
2306 || !pRtcReg->pfnRead)
2307 {
2308 Assert(pRtcReg->pfnWrite);
2309 Assert(pRtcReg->pfnRead);
2310 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
2311 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2312 return VERR_INVALID_PARAMETER;
2313 }
2314
2315 if (!ppRtcHlp)
2316 {
2317 Assert(ppRtcHlp);
2318 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (ppRtcHlp)\n",
2319 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2320 return VERR_INVALID_PARAMETER;
2321 }
2322
2323 /*
2324 * Only one DMA device.
2325 */
2326 PVM pVM = pDevIns->Internal.s.pVMHC;
2327 if (pVM->pdm.s.pRtc)
2328 {
2329 AssertMsgFailed(("Only one RTC device is supported!\n"));
2330 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
2331 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2332 return VERR_INVALID_PARAMETER;
2333 }
2334
2335 /*
2336 * Allocate and initialize pci bus structure.
2337 */
2338 int rc = VINF_SUCCESS;
2339 PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMHC, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
2340 if (pRtc)
2341 {
2342 pRtc->pDevIns = pDevIns;
2343 pRtc->Reg = *pRtcReg;
2344 pVM->pdm.s.pRtc = pRtc;
2345
2346 /* set the helper pointer. */
2347 *ppRtcHlp = &g_pdmR3DevRtcHlp;
2348 Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
2349 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
2350 }
2351 else
2352 rc = VERR_NO_MEMORY;
2353
2354 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
2355 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2356 return rc;
2357}
2358
2359
2360/** @copydoc PDMDEVHLP::pfnPDMQueueCreate */
2361static DECLCALLBACK(int) pdmR3DevHlp_PDMQueueCreate(PPDMDEVINS pDevIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval,
2362 PFNPDMQUEUEDEV pfnCallback, bool fGCEnabled, PPDMQUEUE *ppQueue)
2363{
2364 PDMDEV_ASSERT_DEVINS(pDevIns);
2365 LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fGCEnabled=%RTbool ppQueue=%p\n",
2366 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue));
2367
2368 PVM pVM = pDevIns->Internal.s.pVMHC;
2369 VM_ASSERT_EMT(pVM);
2370 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue);
2371
2372 LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: returns %Vrc *ppQueue=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *ppQueue));
2373 return rc;
2374}
2375
2376
2377/** @copydoc PDMDEVHLP::pfnCritSectInit */
2378static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, const char *pszName)
2379{
2380 PDMDEV_ASSERT_DEVINS(pDevIns);
2381 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszName=%p:{%s}\n",
2382 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pCritSect, pszName, pszName));
2383
2384 PVM pVM = pDevIns->Internal.s.pVMHC;
2385 VM_ASSERT_EMT(pVM);
2386 int rc = pdmR3CritSectInitDevice(pVM, pDevIns, pCritSect, pszName);
2387
2388 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2389 return rc;
2390}
2391
2392
2393/** @copydoc PDMDEVHLP::pfnUTCNow */
2394static DECLCALLBACK(PRTTIMESPEC) pdmR3DevHlp_UTCNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime)
2395{
2396 PDMDEV_ASSERT_DEVINS(pDevIns);
2397 LogFlow(("pdmR3DevHlp_UTCNow: caller='%s'/%d: pTime=%p\n",
2398 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pTime));
2399
2400 pTime = TMR3UTCNow(pDevIns->Internal.s.pVMHC, pTime);
2401
2402 LogFlow(("pdmR3DevHlp_UTCNow: caller='%s'/%d: returns %RU64\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, RTTimeSpecGetNano(pTime)));
2403 return pTime;
2404}
2405
2406
2407/** @copydoc PDMDEVHLP::pfnPDMThreadCreate */
2408static DECLCALLBACK(int) pdmR3DevHlp_PDMThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
2409 PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
2410{
2411 PDMDEV_ASSERT_DEVINS(pDevIns);
2412 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
2413 LogFlow(("pdmR3DevHlp_PDMThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
2414 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
2415
2416 int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMHC, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
2417
2418 LogFlow(("pdmR3DevHlp_PDMThreadCreate: caller='%s'/%d: returns %Vrc *ppThread=%RTthrd\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
2419 rc, *ppThread));
2420 return rc;
2421}
2422
2423
2424/** @copydoc PDMDEVHLP::pfnGetVM */
2425static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
2426{
2427 PDMDEV_ASSERT_DEVINS(pDevIns);
2428 LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns->Internal.s.pVMHC));
2429 return pDevIns->Internal.s.pVMHC;
2430}
2431
2432
2433/** @copydoc PDMDEVHLP::pfnPCIBusRegister */
2434static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
2435{
2436 PDMDEV_ASSERT_DEVINS(pDevIns);
2437 PVM pVM = pDevIns->Internal.s.pVMHC;
2438 VM_ASSERT_EMT(pVM);
2439 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterHC=%p, .pfnIORegionRegisterHC=%p, .pfnSetIrqHC=%p, "
2440 ".pfnSaveExecHC=%p, .pfnLoadExecHC=%p, .pfnFakePCIBIOSHC=%p, .pszSetIrqGC=%p:{%s}} ppPciHlpR3=%p\n",
2441 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterHC,
2442 pPciBusReg->pfnIORegionRegisterHC, pPciBusReg->pfnSetIrqHC, pPciBusReg->pfnSaveExecHC, pPciBusReg->pfnLoadExecHC,
2443 pPciBusReg->pfnFakePCIBIOSHC, pPciBusReg->pszSetIrqGC, pPciBusReg->pszSetIrqGC, ppPciHlpR3));
2444
2445 /*
2446 * Validate the structure.
2447 */
2448 if (pPciBusReg->u32Version != PDM_PCIBUSREG_VERSION)
2449 {
2450 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREG_VERSION));
2451 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2452 return VERR_INVALID_PARAMETER;
2453 }
2454 if ( !pPciBusReg->pfnRegisterHC
2455 || !pPciBusReg->pfnIORegionRegisterHC
2456 || !pPciBusReg->pfnSetIrqHC
2457 || !pPciBusReg->pfnSaveExecHC
2458 || !pPciBusReg->pfnLoadExecHC
2459 || !pPciBusReg->pfnFakePCIBIOSHC)
2460 {
2461 Assert(pPciBusReg->pfnRegisterHC);
2462 Assert(pPciBusReg->pfnIORegionRegisterHC);
2463 Assert(pPciBusReg->pfnSetIrqHC);
2464 Assert(pPciBusReg->pfnSaveExecHC);
2465 Assert(pPciBusReg->pfnLoadExecHC);
2466 Assert(pPciBusReg->pfnFakePCIBIOSHC);
2467 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2468 return VERR_INVALID_PARAMETER;
2469 }
2470 if ( pPciBusReg->pszSetIrqGC
2471 && !VALID_PTR(pPciBusReg->pszSetIrqGC))
2472 {
2473 Assert(VALID_PTR(pPciBusReg->pszSetIrqGC));
2474 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2475 return VERR_INVALID_PARAMETER;
2476 }
2477 if ( pPciBusReg->pszSetIrqR0
2478 && !VALID_PTR(pPciBusReg->pszSetIrqR0))
2479 {
2480 Assert(VALID_PTR(pPciBusReg->pszSetIrqR0));
2481 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2482 return VERR_INVALID_PARAMETER;
2483 }
2484 if (!ppPciHlpR3)
2485 {
2486 Assert(ppPciHlpR3);
2487 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (ppPciHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2488 return VERR_INVALID_PARAMETER;
2489 }
2490
2491 /*
2492 * Find free PCI bus entry.
2493 */
2494 unsigned iBus = 0;
2495 for (iBus = 0; iBus < ELEMENTS(pVM->pdm.s.aPciBuses); iBus++)
2496 if (!pVM->pdm.s.aPciBuses[iBus].pDevInsR3)
2497 break;
2498 if (iBus >= ELEMENTS(pVM->pdm.s.aPciBuses))
2499 {
2500 AssertMsgFailed(("Too many PCI buses. Max=%u\n", ELEMENTS(pVM->pdm.s.aPciBuses)));
2501 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (pci bus)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2502 return VERR_INVALID_PARAMETER;
2503 }
2504 PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
2505
2506 /*
2507 * Resolve and init the GC bits.
2508 */
2509 if (pPciBusReg->pszSetIrqGC)
2510 {
2511 int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pPciBusReg->pszSetIrqGC, &pPciBus->pfnSetIrqGC);
2512 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pPciBusReg->pszSetIrqGC, rc));
2513 if (VBOX_FAILURE(rc))
2514 {
2515 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2516 return rc;
2517 }
2518 pPciBus->pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
2519 }
2520 else
2521 {
2522 pPciBus->pfnSetIrqGC = 0;
2523 pPciBus->pDevInsGC = 0;
2524 }
2525
2526 /*
2527 * Resolve and init the R0 bits.
2528 */
2529 if (pPciBusReg->pszSetIrqR0)
2530 {
2531 int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPciBusReg->pszSetIrqR0, &pPciBus->pfnSetIrqR0);
2532 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPciBusReg->pszSetIrqR0, rc));
2533 if (VBOX_FAILURE(rc))
2534 {
2535 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2536 return rc;
2537 }
2538 pPciBus->pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
2539 }
2540 else
2541 {
2542 pPciBus->pfnSetIrqR0 = 0;
2543 pPciBus->pDevInsR0 = 0;
2544 }
2545
2546 /*
2547 * Init the HC bits.
2548 */
2549 pPciBus->iBus = iBus;
2550 pPciBus->pDevInsR3 = pDevIns;
2551 pPciBus->pfnRegisterR3 = pPciBusReg->pfnRegisterHC;
2552 pPciBus->pfnIORegionRegisterR3 = pPciBusReg->pfnIORegionRegisterHC;
2553 pPciBus->pfnSetConfigCallbacksR3 = pPciBusReg->pfnSetConfigCallbacksHC;
2554 pPciBus->pfnSetIrqR3 = pPciBusReg->pfnSetIrqHC;
2555 pPciBus->pfnSaveExecR3 = pPciBusReg->pfnSaveExecHC;
2556 pPciBus->pfnLoadExecR3 = pPciBusReg->pfnLoadExecHC;
2557 pPciBus->pfnFakePCIBIOSR3 = pPciBusReg->pfnFakePCIBIOSHC;
2558
2559 Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
2560
2561 /* set the helper pointer and return. */
2562 *ppPciHlpR3 = &g_pdmR3DevPciHlp;
2563 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
2564 return VINF_SUCCESS;
2565}
2566
2567
2568/** @copydoc PDMDEVHLP::pfnPICRegister */
2569static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
2570{
2571 PDMDEV_ASSERT_DEVINS(pDevIns);
2572 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
2573 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrqHC=%p, .pfnGetInterruptHC=%p, .pszGetIrqGC=%p:{%s}, .pszGetInterruptGC=%p:{%s}} ppPicHlpR3=%p\n",
2574 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrqHC, pPicReg->pfnGetInterruptHC,
2575 pPicReg->pszSetIrqGC, pPicReg->pszSetIrqGC, pPicReg->pszGetInterruptGC, pPicReg->pszGetInterruptGC, ppPicHlpR3));
2576
2577 /*
2578 * Validate input.
2579 */
2580 if (pPicReg->u32Version != PDM_PICREG_VERSION)
2581 {
2582 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPicReg->u32Version, PDM_PICREG_VERSION));
2583 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2584 return VERR_INVALID_PARAMETER;
2585 }
2586 if ( !pPicReg->pfnSetIrqHC
2587 || !pPicReg->pfnGetInterruptHC)
2588 {
2589 Assert(pPicReg->pfnSetIrqHC);
2590 Assert(pPicReg->pfnGetInterruptHC);
2591 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2592 return VERR_INVALID_PARAMETER;
2593 }
2594 if ( ( pPicReg->pszSetIrqGC
2595 || pPicReg->pszGetInterruptGC)
2596 && ( !VALID_PTR(pPicReg->pszSetIrqGC)
2597 || !VALID_PTR(pPicReg->pszGetInterruptGC))
2598 )
2599 {
2600 Assert(VALID_PTR(pPicReg->pszSetIrqGC));
2601 Assert(VALID_PTR(pPicReg->pszGetInterruptGC));
2602 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2603 return VERR_INVALID_PARAMETER;
2604 }
2605 if ( pPicReg->pszSetIrqGC
2606 && !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_GC))
2607 {
2608 Assert(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_GC);
2609 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (GC flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2610 return VERR_INVALID_PARAMETER;
2611 }
2612 if ( pPicReg->pszSetIrqR0
2613 && !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
2614 {
2615 Assert(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0);
2616 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (R0 flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2617 return VERR_INVALID_PARAMETER;
2618 }
2619 if (!ppPicHlpR3)
2620 {
2621 Assert(ppPicHlpR3);
2622 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (ppPicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2623 return VERR_INVALID_PARAMETER;
2624 }
2625
2626 /*
2627 * Only one PIC device.
2628 */
2629 PVM pVM = pDevIns->Internal.s.pVMHC;
2630 if (pVM->pdm.s.Pic.pDevInsR3)
2631 {
2632 AssertMsgFailed(("Only one pic device is supported!\n"));
2633 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2634 return VERR_INVALID_PARAMETER;
2635 }
2636
2637 /*
2638 * GC stuff.
2639 */
2640 if (pPicReg->pszSetIrqGC)
2641 {
2642 int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pPicReg->pszSetIrqGC, &pVM->pdm.s.Pic.pfnSetIrqGC);
2643 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pPicReg->pszSetIrqGC, rc));
2644 if (VBOX_SUCCESS(rc))
2645 {
2646 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pPicReg->pszGetInterruptGC, &pVM->pdm.s.Pic.pfnGetInterruptGC);
2647 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pPicReg->pszGetInterruptGC, rc));
2648 }
2649 if (VBOX_FAILURE(rc))
2650 {
2651 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2652 return rc;
2653 }
2654 pVM->pdm.s.Pic.pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
2655 }
2656 else
2657 {
2658 pVM->pdm.s.Pic.pDevInsGC = 0;
2659 pVM->pdm.s.Pic.pfnSetIrqGC = 0;
2660 pVM->pdm.s.Pic.pfnGetInterruptGC = 0;
2661 }
2662
2663 /*
2664 * R0 stuff.
2665 */
2666 if (pPicReg->pszSetIrqR0)
2667 {
2668 int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszSetIrqR0, &pVM->pdm.s.Pic.pfnSetIrqR0);
2669 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPicReg->pszSetIrqR0, rc));
2670 if (VBOX_SUCCESS(rc))
2671 {
2672 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszGetInterruptR0, &pVM->pdm.s.Pic.pfnGetInterruptR0);
2673 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPicReg->pszGetInterruptR0, rc));
2674 }
2675 if (VBOX_FAILURE(rc))
2676 {
2677 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2678 return rc;
2679 }
2680 pVM->pdm.s.Pic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
2681 Assert(pVM->pdm.s.Pic.pDevInsR0);
2682 }
2683 else
2684 {
2685 pVM->pdm.s.Pic.pfnSetIrqR0 = 0;
2686 pVM->pdm.s.Pic.pfnGetInterruptR0 = 0;
2687 pVM->pdm.s.Pic.pDevInsR0 = 0;
2688 }
2689
2690 /*
2691 * HC stuff.
2692 */
2693 pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
2694 pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrqHC;
2695 pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterruptHC;
2696 Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
2697
2698 /* set the helper pointer and return. */
2699 *ppPicHlpR3 = &g_pdmR3DevPicHlp;
2700 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
2701 return VINF_SUCCESS;
2702}
2703
2704
2705/** @copydoc PDMDEVHLP::pfnAPICRegister */
2706static DECLCALLBACK(int) pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
2707{
2708 PDMDEV_ASSERT_DEVINS(pDevIns);
2709 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
2710 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: pApicReg=%p:{.u32Version=%#x, .pfnGetInterruptHC=%p, .pfnSetBaseHC=%p, .pfnGetBaseHC=%p, "
2711 ".pfnSetTPRHC=%p, .pfnGetTPRHC=%p, .pfnBusDeliverHC=%p, pszGetInterruptGC=%p:{%s}, pszSetBaseGC=%p:{%s}, pszGetBaseGC=%p:{%s}, "
2712 ".pszSetTPRGC=%p:{%s}, .pszGetTPRGC=%p:{%s}, .pszBusDeliverGC=%p:{%s}} ppApicHlpR3=%p\n",
2713 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pApicReg, pApicReg->u32Version, pApicReg->pfnGetInterruptHC, pApicReg->pfnSetBaseHC,
2714 pApicReg->pfnGetBaseHC, pApicReg->pfnSetTPRHC, pApicReg->pfnGetTPRHC, pApicReg->pfnBusDeliverHC, pApicReg->pszGetInterruptGC,
2715 pApicReg->pszGetInterruptGC, pApicReg->pszSetBaseGC, pApicReg->pszSetBaseGC, pApicReg->pszGetBaseGC, pApicReg->pszGetBaseGC,
2716 pApicReg->pszSetTPRGC, pApicReg->pszSetTPRGC, pApicReg->pszGetTPRGC, pApicReg->pszGetTPRGC, pApicReg->pszBusDeliverGC,
2717 pApicReg->pszBusDeliverGC, ppApicHlpR3));
2718
2719 /*
2720 * Validate input.
2721 */
2722 if (pApicReg->u32Version != PDM_APICREG_VERSION)
2723 {
2724 AssertMsgFailed(("u32Version=%#x expected %#x\n", pApicReg->u32Version, PDM_APICREG_VERSION));
2725 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2726 return VERR_INVALID_PARAMETER;
2727 }
2728 if ( !pApicReg->pfnGetInterruptHC
2729 || !pApicReg->pfnSetBaseHC
2730 || !pApicReg->pfnGetBaseHC
2731 || !pApicReg->pfnSetTPRHC
2732 || !pApicReg->pfnGetTPRHC
2733 || !pApicReg->pfnBusDeliverHC)
2734 {
2735 Assert(pApicReg->pfnGetInterruptHC);
2736 Assert(pApicReg->pfnSetBaseHC);
2737 Assert(pApicReg->pfnGetBaseHC);
2738 Assert(pApicReg->pfnSetTPRHC);
2739 Assert(pApicReg->pfnGetTPRHC);
2740 Assert(pApicReg->pfnBusDeliverHC);
2741 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2742 return VERR_INVALID_PARAMETER;
2743 }
2744 if ( ( pApicReg->pszGetInterruptGC
2745 || pApicReg->pszSetBaseGC
2746 || pApicReg->pszGetBaseGC
2747 || pApicReg->pszSetTPRGC
2748 || pApicReg->pszGetTPRGC
2749 || pApicReg->pszBusDeliverGC)
2750 && ( !VALID_PTR(pApicReg->pszGetInterruptGC)
2751 || !VALID_PTR(pApicReg->pszSetBaseGC)
2752 || !VALID_PTR(pApicReg->pszGetBaseGC)
2753 || !VALID_PTR(pApicReg->pszSetTPRGC)
2754 || !VALID_PTR(pApicReg->pszGetTPRGC)
2755 || !VALID_PTR(pApicReg->pszBusDeliverGC))
2756 )
2757 {
2758 Assert(VALID_PTR(pApicReg->pszGetInterruptGC));
2759 Assert(VALID_PTR(pApicReg->pszSetBaseGC));
2760 Assert(VALID_PTR(pApicReg->pszGetBaseGC));
2761 Assert(VALID_PTR(pApicReg->pszSetTPRGC));
2762 Assert(VALID_PTR(pApicReg->pszGetTPRGC));
2763 Assert(VALID_PTR(pApicReg->pszBusDeliverGC));
2764 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2765 return VERR_INVALID_PARAMETER;
2766 }
2767 if ( ( pApicReg->pszGetInterruptR0
2768 || pApicReg->pszSetBaseR0
2769 || pApicReg->pszGetBaseR0
2770 || pApicReg->pszSetTPRR0
2771 || pApicReg->pszGetTPRR0
2772 || pApicReg->pszBusDeliverR0)
2773 && ( !VALID_PTR(pApicReg->pszGetInterruptR0)
2774 || !VALID_PTR(pApicReg->pszSetBaseR0)
2775 || !VALID_PTR(pApicReg->pszGetBaseR0)
2776 || !VALID_PTR(pApicReg->pszSetTPRR0)
2777 || !VALID_PTR(pApicReg->pszGetTPRR0)
2778 || !VALID_PTR(pApicReg->pszBusDeliverR0))
2779 )
2780 {
2781 Assert(VALID_PTR(pApicReg->pszGetInterruptR0));
2782 Assert(VALID_PTR(pApicReg->pszSetBaseR0));
2783 Assert(VALID_PTR(pApicReg->pszGetBaseR0));
2784 Assert(VALID_PTR(pApicReg->pszSetTPRR0));
2785 Assert(VALID_PTR(pApicReg->pszGetTPRR0));
2786 Assert(VALID_PTR(pApicReg->pszBusDeliverR0));
2787 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (R0 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2788 return VERR_INVALID_PARAMETER;
2789 }
2790 if (!ppApicHlpR3)
2791 {
2792 Assert(ppApicHlpR3);
2793 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (ppApicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2794 return VERR_INVALID_PARAMETER;
2795 }
2796
2797 /*
2798 * Only one APIC device. (malc: only in UP case actually)
2799 */
2800 PVM pVM = pDevIns->Internal.s.pVMHC;
2801 if (pVM->pdm.s.Apic.pDevInsR3)
2802 {
2803 AssertMsgFailed(("Only one apic device is supported!\n"));
2804 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2805 return VERR_INVALID_PARAMETER;
2806 }
2807
2808 /*
2809 * Resolve & initialize the GC bits.
2810 */
2811 if (pApicReg->pszGetInterruptGC)
2812 {
2813 int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszGetInterruptGC, &pVM->pdm.s.Apic.pfnGetInterruptGC);
2814 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszGetInterruptGC, rc));
2815 if (RT_SUCCESS(rc))
2816 {
2817 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszSetBaseGC, &pVM->pdm.s.Apic.pfnSetBaseGC);
2818 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszSetBaseGC, rc));
2819 }
2820 if (RT_SUCCESS(rc))
2821 {
2822 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszGetBaseGC, &pVM->pdm.s.Apic.pfnGetBaseGC);
2823 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszGetBaseGC, rc));
2824 }
2825 if (RT_SUCCESS(rc))
2826 {
2827 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszSetTPRGC, &pVM->pdm.s.Apic.pfnSetTPRGC);
2828 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszSetTPRGC, rc));
2829 }
2830 if (RT_SUCCESS(rc))
2831 {
2832 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszGetTPRGC, &pVM->pdm.s.Apic.pfnGetTPRGC);
2833 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszGetTPRGC, rc));
2834 }
2835 if (RT_SUCCESS(rc))
2836 {
2837 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszBusDeliverGC, &pVM->pdm.s.Apic.pfnBusDeliverGC);
2838 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszBusDeliverGC, rc));
2839 }
2840 if (VBOX_FAILURE(rc))
2841 {
2842 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2843 return rc;
2844 }
2845 pVM->pdm.s.Apic.pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
2846 }
2847 else
2848 {
2849 pVM->pdm.s.Apic.pDevInsGC = 0;
2850 pVM->pdm.s.Apic.pfnGetInterruptGC = 0;
2851 pVM->pdm.s.Apic.pfnSetBaseGC = 0;
2852 pVM->pdm.s.Apic.pfnGetBaseGC = 0;
2853 pVM->pdm.s.Apic.pfnSetTPRGC = 0;
2854 pVM->pdm.s.Apic.pfnGetTPRGC = 0;
2855 pVM->pdm.s.Apic.pfnBusDeliverGC = 0;
2856 }
2857
2858 /*
2859 * Resolve & initialize the R0 bits.
2860 */
2861 if (pApicReg->pszGetInterruptR0)
2862 {
2863 int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, &pVM->pdm.s.Apic.pfnGetInterruptR0);
2864 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, rc));
2865 if (RT_SUCCESS(rc))
2866 {
2867 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, &pVM->pdm.s.Apic.pfnSetBaseR0);
2868 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, rc));
2869 }
2870 if (RT_SUCCESS(rc))
2871 {
2872 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, &pVM->pdm.s.Apic.pfnGetBaseR0);
2873 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, rc));
2874 }
2875 if (RT_SUCCESS(rc))
2876 {
2877 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, &pVM->pdm.s.Apic.pfnSetTPRR0);
2878 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, rc));
2879 }
2880 if (RT_SUCCESS(rc))
2881 {
2882 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, &pVM->pdm.s.Apic.pfnGetTPRR0);
2883 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, rc));
2884 }
2885 if (RT_SUCCESS(rc))
2886 {
2887 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, &pVM->pdm.s.Apic.pfnBusDeliverR0);
2888 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, rc));
2889 }
2890 if (VBOX_FAILURE(rc))
2891 {
2892 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2893 return rc;
2894 }
2895 pVM->pdm.s.Apic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
2896 Assert(pVM->pdm.s.Apic.pDevInsR0);
2897 }
2898 else
2899 {
2900 pVM->pdm.s.Apic.pfnGetInterruptR0 = 0;
2901 pVM->pdm.s.Apic.pfnSetBaseR0 = 0;
2902 pVM->pdm.s.Apic.pfnGetBaseR0 = 0;
2903 pVM->pdm.s.Apic.pfnSetTPRR0 = 0;
2904 pVM->pdm.s.Apic.pfnGetTPRR0 = 0;
2905 pVM->pdm.s.Apic.pfnBusDeliverR0 = 0;
2906 pVM->pdm.s.Apic.pDevInsR0 = 0;
2907 }
2908
2909 /*
2910 * Initialize the HC bits.
2911 */
2912 pVM->pdm.s.Apic.pDevInsR3 = pDevIns;
2913 pVM->pdm.s.Apic.pfnGetInterruptR3 = pApicReg->pfnGetInterruptHC;
2914 pVM->pdm.s.Apic.pfnSetBaseR3 = pApicReg->pfnSetBaseHC;
2915 pVM->pdm.s.Apic.pfnGetBaseR3 = pApicReg->pfnGetBaseHC;
2916 pVM->pdm.s.Apic.pfnSetTPRR3 = pApicReg->pfnSetTPRHC;
2917 pVM->pdm.s.Apic.pfnGetTPRR3 = pApicReg->pfnGetTPRHC;
2918 pVM->pdm.s.Apic.pfnBusDeliverR3 = pApicReg->pfnBusDeliverHC;
2919 Log(("PDM: Registered APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
2920
2921 /* set the helper pointer and return. */
2922 *ppApicHlpR3 = &g_pdmR3DevApicHlp;
2923 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
2924 return VINF_SUCCESS;
2925}
2926
2927
2928/** @copydoc PDMDEVHLP::pfnIOAPICRegister */
2929static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
2930{
2931 PDMDEV_ASSERT_DEVINS(pDevIns);
2932 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
2933 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrqHC=%p, .pszSetIrqGC=%p:{%s}} ppIoApicHlpR3=%p\n",
2934 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrqHC, pIoApicReg->pszSetIrqGC,
2935 pIoApicReg->pszSetIrqGC, ppIoApicHlpR3));
2936
2937 /*
2938 * Validate input.
2939 */
2940 if (pIoApicReg->u32Version != PDM_IOAPICREG_VERSION)
2941 {
2942 AssertMsgFailed(("u32Version=%#x expected %#x\n", pIoApicReg->u32Version, PDM_IOAPICREG_VERSION));
2943 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2944 return VERR_INVALID_PARAMETER;
2945 }
2946 if (!pIoApicReg->pfnSetIrqHC)
2947 {
2948 Assert(pIoApicReg->pfnSetIrqHC);
2949 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2950 return VERR_INVALID_PARAMETER;
2951 }
2952 if ( pIoApicReg->pszSetIrqGC
2953 && !VALID_PTR(pIoApicReg->pszSetIrqGC))
2954 {
2955 Assert(VALID_PTR(pIoApicReg->pszSetIrqGC));
2956 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2957 return VERR_INVALID_PARAMETER;
2958 }
2959 if ( pIoApicReg->pszSetIrqR0
2960 && !VALID_PTR(pIoApicReg->pszSetIrqR0))
2961 {
2962 Assert(VALID_PTR(pIoApicReg->pszSetIrqR0));
2963 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2964 return VERR_INVALID_PARAMETER;
2965 }
2966 if (!ppIoApicHlpR3)
2967 {
2968 Assert(ppIoApicHlpR3);
2969 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (ppApicHlp)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2970 return VERR_INVALID_PARAMETER;
2971 }
2972
2973 /*
2974 * The I/O APIC requires the APIC to be present (hacks++).
2975 * If the I/O APIC does GC stuff so must the APIC.
2976 */
2977 PVM pVM = pDevIns->Internal.s.pVMHC;
2978 if (!pVM->pdm.s.Apic.pDevInsR3)
2979 {
2980 AssertMsgFailed(("Configuration error / Init order error! No APIC!\n"));
2981 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2982 return VERR_INVALID_PARAMETER;
2983 }
2984 if ( pIoApicReg->pszSetIrqGC
2985 && !pVM->pdm.s.Apic.pDevInsGC)
2986 {
2987 AssertMsgFailed(("Configuration error! APIC doesn't do GC, I/O APIC does!\n"));
2988 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no GC APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2989 return VERR_INVALID_PARAMETER;
2990 }
2991
2992 /*
2993 * Only one I/O APIC device.
2994 */
2995 if (pVM->pdm.s.IoApic.pDevInsR3)
2996 {
2997 AssertMsgFailed(("Only one ioapic device is supported!\n"));
2998 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (only one)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2999 return VERR_INVALID_PARAMETER;
3000 }
3001
3002 /*
3003 * Resolve & initialize the GC bits.
3004 */
3005 if (pIoApicReg->pszSetIrqGC)
3006 {
3007 int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pIoApicReg->pszSetIrqGC, &pVM->pdm.s.IoApic.pfnSetIrqGC);
3008 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pIoApicReg->pszSetIrqGC, rc));
3009 if (VBOX_FAILURE(rc))
3010 {
3011 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3012 return rc;
3013 }
3014 pVM->pdm.s.IoApic.pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
3015 }
3016 else
3017 {
3018 pVM->pdm.s.IoApic.pDevInsGC = 0;
3019 pVM->pdm.s.IoApic.pfnSetIrqGC = 0;
3020 }
3021
3022 /*
3023 * Resolve & initialize the R0 bits.
3024 */
3025 if (pIoApicReg->pszSetIrqR0)
3026 {
3027 int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, &pVM->pdm.s.IoApic.pfnSetIrqR0);
3028 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, rc));
3029 if (VBOX_FAILURE(rc))
3030 {
3031 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3032 return rc;
3033 }
3034 pVM->pdm.s.IoApic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
3035 Assert(pVM->pdm.s.IoApic.pDevInsR0);
3036 }
3037 else
3038 {
3039 pVM->pdm.s.IoApic.pfnSetIrqR0 = 0;
3040 pVM->pdm.s.IoApic.pDevInsR0 = 0;
3041 }
3042
3043 /*
3044 * Initialize the HC bits.
3045 */
3046 pVM->pdm.s.IoApic.pDevInsR3 = pDevIns;
3047 pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrqHC;
3048 Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
3049
3050 /* set the helper pointer and return. */
3051 *ppIoApicHlpR3 = &g_pdmR3DevIoApicHlp;
3052 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
3053 return VINF_SUCCESS;
3054}
3055
3056
3057/** @copydoc PDMDEVHLP::pfnDMACRegister */
3058static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
3059{
3060 PDMDEV_ASSERT_DEVINS(pDevIns);
3061 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3062 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",
3063 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
3064 pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
3065
3066 /*
3067 * Validate input.
3068 */
3069 if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
3070 {
3071 AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
3072 PDM_DMACREG_VERSION));
3073 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (version)\n",
3074 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3075 return VERR_INVALID_PARAMETER;
3076 }
3077 if ( !pDmacReg->pfnRun
3078 || !pDmacReg->pfnRegister
3079 || !pDmacReg->pfnReadMemory
3080 || !pDmacReg->pfnWriteMemory
3081 || !pDmacReg->pfnSetDREQ
3082 || !pDmacReg->pfnGetChannelMode)
3083 {
3084 Assert(pDmacReg->pfnRun);
3085 Assert(pDmacReg->pfnRegister);
3086 Assert(pDmacReg->pfnReadMemory);
3087 Assert(pDmacReg->pfnWriteMemory);
3088 Assert(pDmacReg->pfnSetDREQ);
3089 Assert(pDmacReg->pfnGetChannelMode);
3090 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
3091 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3092 return VERR_INVALID_PARAMETER;
3093 }
3094
3095 if (!ppDmacHlp)
3096 {
3097 Assert(ppDmacHlp);
3098 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (ppDmacHlp)\n",
3099 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3100 return VERR_INVALID_PARAMETER;
3101 }
3102
3103 /*
3104 * Only one DMA device.
3105 */
3106 PVM pVM = pDevIns->Internal.s.pVMHC;
3107 if (pVM->pdm.s.pDmac)
3108 {
3109 AssertMsgFailed(("Only one DMA device is supported!\n"));
3110 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
3111 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3112 return VERR_INVALID_PARAMETER;
3113 }
3114
3115 /*
3116 * Allocate and initialize pci bus structure.
3117 */
3118 int rc = VINF_SUCCESS;
3119 PPDMDMAC pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMHC, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
3120 if (pDmac)
3121 {
3122 pDmac->pDevIns = pDevIns;
3123 pDmac->Reg = *pDmacReg;
3124 pVM->pdm.s.pDmac = pDmac;
3125
3126 /* set the helper pointer. */
3127 *ppDmacHlp = &g_pdmR3DevDmacHlp;
3128 Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
3129 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
3130 }
3131 else
3132 rc = VERR_NO_MEMORY;
3133
3134 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
3135 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3136 return rc;
3137}
3138
3139
3140/** @copydoc PDMDEVHLP::pfnPhysRead */
3141static DECLCALLBACK(void) pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
3142{
3143 PDMDEV_ASSERT_DEVINS(pDevIns);
3144 LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbRead=%#x\n",
3145 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
3146
3147 /*
3148 * For the convenience of the device we put no thread restriction on this interface.
3149 * That means we'll have to check which thread we're in and choose our path.
3150 */
3151#ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
3152 PGMPhysRead(pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbRead);
3153#else
3154 if (VM_IS_EMT(pDevIns->Internal.s.pVMHC) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMHC))
3155 PGMPhysRead(pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbRead);
3156 else
3157 {
3158 Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3159 PVMREQ pReq;
3160 int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMHC, &pReq, RT_INDEFINITE_WAIT,
3161 (PFNRT)PGMPhysRead, 4, pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbRead);
3162 while (rc == VERR_TIMEOUT)
3163 rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
3164 AssertReleaseRC(rc);
3165 VMR3ReqFree(pReq);
3166 }
3167#endif
3168 Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3169}
3170
3171
3172/** @copydoc PDMDEVHLP::pfnPhysWrite */
3173static DECLCALLBACK(void) pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
3174{
3175 PDMDEV_ASSERT_DEVINS(pDevIns);
3176 LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbWrite=%#x\n",
3177 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
3178
3179 /*
3180 * For the convenience of the device we put no thread restriction on this interface.
3181 * That means we'll have to check which thread we're in and choose our path.
3182 */
3183#ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
3184 PGMPhysWrite(pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbWrite);
3185#else
3186 if (VM_IS_EMT(pDevIns->Internal.s.pVMHC) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMHC))
3187 PGMPhysWrite(pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbWrite);
3188 else
3189 {
3190 Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3191 PVMREQ pReq;
3192 int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMHC, &pReq, RT_INDEFINITE_WAIT,
3193 (PFNRT)PGMPhysWrite, 4, pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbWrite);
3194 while (rc == VERR_TIMEOUT)
3195 rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
3196 AssertReleaseRC(rc);
3197 VMR3ReqFree(pReq);
3198 }
3199#endif
3200 Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3201}
3202
3203
3204/** @copydoc PDMDEVHLP::pfnPhysReadGCVirt */
3205static DECLCALLBACK(int) pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
3206{
3207 PDMDEV_ASSERT_DEVINS(pDevIns);
3208 PVM pVM = pDevIns->Internal.s.pVMHC;
3209 VM_ASSERT_EMT(pVM);
3210 LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: pvDst=%p GCVirt=%VGv cb=%#x\n",
3211 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pvDst, GCVirtSrc, cb));
3212
3213 if (!VM_IS_EMT(pVM))
3214 return VERR_ACCESS_DENIED;
3215
3216 int rc = PGMPhysReadGCPtr(pVM, pvDst, GCVirtSrc, cb);
3217
3218 LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3219
3220 return rc;
3221}
3222
3223
3224/** @copydoc PDMDEVHLP::pfnPhysWriteGCVirt */
3225static DECLCALLBACK(int) pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
3226{
3227 PDMDEV_ASSERT_DEVINS(pDevIns);
3228 PVM pVM = pDevIns->Internal.s.pVMHC;
3229 VM_ASSERT_EMT(pVM);
3230 LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: GCVirtDst=%VGv pvSrc=%p cb=%#x\n",
3231 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCVirtDst, pvSrc, cb));
3232
3233 if (!VM_IS_EMT(pVM))
3234 return VERR_ACCESS_DENIED;
3235
3236 int rc = PGMPhysWriteGCPtr(pVM, GCVirtDst, pvSrc, cb);
3237
3238 LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3239
3240 return rc;
3241}
3242
3243
3244/** @copydoc PDMDEVHLP::pfnPhysReserve */
3245static DECLCALLBACK(int) pdmR3DevHlp_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
3246{
3247 PDMDEV_ASSERT_DEVINS(pDevIns);
3248 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3249 LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: GCPhys=%VGp cbRange=%#x pszDesc=%p:{%s}\n",
3250 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, cbRange, pszDesc, pszDesc));
3251
3252 int rc = MMR3PhysReserve(pDevIns->Internal.s.pVMHC, GCPhys, cbRange, pszDesc);
3253
3254 LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3255
3256 return rc;
3257}
3258
3259/** @copydoc PDMDEVHLP::pfnPhysGCPtr2GCPhys */
3260static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys)
3261{
3262 PDMDEV_ASSERT_DEVINS(pDevIns);
3263 PVM pVM = pDevIns->Internal.s.pVMHC;
3264 VM_ASSERT_EMT(pVM);
3265 LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: GCPtr=%VGv pGCPhys=%p\n",
3266 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPtr, pGCPhys));
3267
3268 if (!VM_IS_EMT(pVM))
3269 return VERR_ACCESS_DENIED;
3270
3271 int rc = PGMPhysGCPtr2GCPhys(pVM, GCPtr, pGCPhys);
3272
3273 LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: returns %Vrc *pGCPhys=%VGp\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *pGCPhys));
3274
3275 return rc;
3276}
3277
3278
3279/** @copydoc PDMDEVHLP::pfnA20IsEnabled */
3280static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
3281{
3282 PDMDEV_ASSERT_DEVINS(pDevIns);
3283 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3284
3285 bool fRc = PGMPhysIsA20Enabled(pDevIns->Internal.s.pVMHC);
3286
3287 LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fRc));
3288 return fRc;
3289}
3290
3291
3292/** @copydoc PDMDEVHLP::pfnA20Set */
3293static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
3294{
3295 PDMDEV_ASSERT_DEVINS(pDevIns);
3296 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3297 LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fEnable));
3298 //Assert(*(unsigned *)&fEnable <= 1);
3299 PGMR3PhysSetA20(pDevIns->Internal.s.pVMHC, fEnable);
3300}
3301
3302
3303/** @copydoc PDMDEVHLP::pfnVMReset */
3304static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns)
3305{
3306 PDMDEV_ASSERT_DEVINS(pDevIns);
3307 PVM pVM = pDevIns->Internal.s.pVMHC;
3308 VM_ASSERT_EMT(pVM);
3309 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: VM_FF_RESET %d -> 1\n",
3310 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_RESET)));
3311
3312 /*
3313 * We postpone this operation because we're likely to be inside a I/O instruction
3314 * and the EIP will be updated when we return.
3315 * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
3316 */
3317 bool fHaltOnReset;
3318 int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
3319 if (VBOX_SUCCESS(rc) && fHaltOnReset)
3320 {
3321 Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
3322 rc = VINF_EM_HALT;
3323 }
3324 else
3325 {
3326 VM_FF_SET(pVM, VM_FF_RESET);
3327 rc = VINF_EM_RESET;
3328 }
3329
3330 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3331 return rc;
3332}
3333
3334
3335/** @copydoc PDMDEVHLP::pfnVMSuspend */
3336static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
3337{
3338 PDMDEV_ASSERT_DEVINS(pDevIns);
3339 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3340 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
3341 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3342
3343 int rc = VMR3Suspend(pDevIns->Internal.s.pVMHC);
3344
3345 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3346 return rc;
3347}
3348
3349
3350/** @copydoc PDMDEVHLP::pfnVMPowerOff */
3351static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
3352{
3353 PDMDEV_ASSERT_DEVINS(pDevIns);
3354 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3355 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
3356 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3357
3358 int rc = VMR3PowerOff(pDevIns->Internal.s.pVMHC);
3359
3360 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3361 return rc;
3362}
3363
3364
3365/** @copydoc PDMDEVHLP::pfnLockVM */
3366static DECLCALLBACK(int) pdmR3DevHlp_LockVM(PPDMDEVINS pDevIns)
3367{
3368 return VMMR3Lock(pDevIns->Internal.s.pVMHC);
3369}
3370
3371
3372/** @copydoc PDMDEVHLP::pfnUnlockVM */
3373static DECLCALLBACK(int) pdmR3DevHlp_UnlockVM(PPDMDEVINS pDevIns)
3374{
3375 return VMMR3Unlock(pDevIns->Internal.s.pVMHC);
3376}
3377
3378
3379/** @copydoc PDMDEVHLP::pfnAssertVMLock */
3380static DECLCALLBACK(bool) pdmR3DevHlp_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3381{
3382 PVM pVM = pDevIns->Internal.s.pVMHC;
3383 if (VMMR3LockIsOwner(pVM))
3384 return true;
3385
3386 RTNATIVETHREAD NativeThreadOwner = VMMR3LockGetOwner(pVM);
3387 RTTHREAD ThreadOwner = RTThreadFromNative(NativeThreadOwner);
3388 char szMsg[100];
3389 RTStrPrintf(szMsg, sizeof(szMsg), "AssertVMLocked '%s'/%d ThreadOwner=%RTnthrd/%RTthrd/'%s' Self='%s'\n",
3390 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
3391 NativeThreadOwner, ThreadOwner, RTThreadGetName(ThreadOwner), RTThreadSelfName());
3392 AssertMsg1(szMsg, iLine, pszFile, pszFunction);
3393 AssertBreakpoint();
3394 return false;
3395}
3396
3397/** @copydoc PDMDEVHLP::pfnDMARegister */
3398static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
3399{
3400 PDMDEV_ASSERT_DEVINS(pDevIns);
3401 PVM pVM = pDevIns->Internal.s.pVMHC;
3402 VM_ASSERT_EMT(pVM);
3403 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
3404 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
3405 int rc = VINF_SUCCESS;
3406 if (pVM->pdm.s.pDmac)
3407 pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pfnTransferHandler, pvUser);
3408 else
3409 {
3410 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3411 rc = VERR_PDM_NO_DMAC_INSTANCE;
3412 }
3413 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Vrc\n",
3414 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3415 return rc;
3416}
3417
3418/** @copydoc PDMDEVHLP::pfnDMAReadMemory */
3419static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
3420{
3421 PDMDEV_ASSERT_DEVINS(pDevIns);
3422 PVM pVM = pDevIns->Internal.s.pVMHC;
3423 VM_ASSERT_EMT(pVM);
3424 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
3425 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
3426 int rc = VINF_SUCCESS;
3427 if (pVM->pdm.s.pDmac)
3428 {
3429 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
3430 if (pcbRead)
3431 *pcbRead = cb;
3432 }
3433 else
3434 {
3435 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3436 rc = VERR_PDM_NO_DMAC_INSTANCE;
3437 }
3438 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Vrc\n",
3439 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3440 return rc;
3441}
3442
3443/** @copydoc PDMDEVHLP::pfnDMAWriteMemory */
3444static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
3445{
3446 PDMDEV_ASSERT_DEVINS(pDevIns);
3447 PVM pVM = pDevIns->Internal.s.pVMHC;
3448 VM_ASSERT_EMT(pVM);
3449 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
3450 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
3451 int rc = VINF_SUCCESS;
3452 if (pVM->pdm.s.pDmac)
3453 {
3454 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
3455 if (pcbWritten)
3456 *pcbWritten = cb;
3457 }
3458 else
3459 {
3460 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3461 rc = VERR_PDM_NO_DMAC_INSTANCE;
3462 }
3463 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Vrc\n",
3464 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3465 return rc;
3466}
3467
3468/** @copydoc PDMDEVHLP::pfnDMASetDREQ */
3469static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
3470{
3471 PDMDEV_ASSERT_DEVINS(pDevIns);
3472 PVM pVM = pDevIns->Internal.s.pVMHC;
3473 VM_ASSERT_EMT(pVM);
3474 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
3475 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, uLevel));
3476 int rc = VINF_SUCCESS;
3477 if (pVM->pdm.s.pDmac)
3478 pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
3479 else
3480 {
3481 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3482 rc = VERR_PDM_NO_DMAC_INSTANCE;
3483 }
3484 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Vrc\n",
3485 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3486 return rc;
3487}
3488
3489/** @copydoc PDMDEVHLP::pfnDMAGetChannelMode */
3490static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
3491{
3492 PDMDEV_ASSERT_DEVINS(pDevIns);
3493 PVM pVM = pDevIns->Internal.s.pVMHC;
3494 VM_ASSERT_EMT(pVM);
3495 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
3496 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel));
3497 uint8_t u8Mode;
3498 if (pVM->pdm.s.pDmac)
3499 u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
3500 else
3501 {
3502 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3503 u8Mode = 3 << 2 /* illegal mode type */;
3504 }
3505 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
3506 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, u8Mode));
3507 return u8Mode;
3508}
3509
3510/** @copydoc PDMDEVHLP::pfnDMASchedule */
3511static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
3512{
3513 PDMDEV_ASSERT_DEVINS(pDevIns);
3514 PVM pVM = pDevIns->Internal.s.pVMHC;
3515 VM_ASSERT_EMT(pVM);
3516 LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
3517 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_PDM_DMA)));
3518
3519 AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3520 VM_FF_SET(pVM, VM_FF_PDM_DMA);
3521 REMR3NotifyDmaPending(pVM);
3522 VMR3NotifyFF(pVM, true);
3523}
3524
3525
3526/** @copydoc PDMDEVHLP::pfnCMOSWrite */
3527static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
3528{
3529 PDMDEV_ASSERT_DEVINS(pDevIns);
3530 PVM pVM = pDevIns->Internal.s.pVMHC;
3531 VM_ASSERT_EMT(pVM);
3532
3533 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
3534 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, u8Value));
3535 int rc;
3536 if (pVM->pdm.s.pRtc)
3537 rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pVM->pdm.s.pRtc->pDevIns, iReg, u8Value);
3538 else
3539 rc = VERR_PDM_NO_RTC_INSTANCE;
3540
3541 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
3542 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3543 return rc;
3544}
3545
3546
3547/** @copydoc PDMDEVHLP::pfnCMOSRead */
3548static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
3549{
3550 PDMDEV_ASSERT_DEVINS(pDevIns);
3551 PVM pVM = pDevIns->Internal.s.pVMHC;
3552 VM_ASSERT_EMT(pVM);
3553
3554 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
3555 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, pu8Value));
3556 int rc;
3557 if (pVM->pdm.s.pRtc)
3558 rc = pVM->pdm.s.pRtc->Reg.pfnRead(pVM->pdm.s.pRtc->pDevIns, iReg, pu8Value);
3559 else
3560 rc = VERR_PDM_NO_RTC_INSTANCE;
3561
3562 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
3563 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3564 return rc;
3565}
3566
3567
3568/** @copydoc PDMDEVHLP::pfnGetCpuId */
3569static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
3570 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
3571{
3572 PDMDEV_ASSERT_DEVINS(pDevIns);
3573 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
3574 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
3575 AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
3576
3577 CPUMGetGuestCpuId(pDevIns->Internal.s.pVMHC, iLeaf, pEax, pEbx, pEcx, pEdx);
3578
3579 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
3580 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
3581}
3582
3583
3584/** @copydoc PDMDEVHLP::pfnROMProtectShadow */
3585static DECLCALLBACK(int) pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
3586{
3587 PDMDEV_ASSERT_DEVINS(pDevIns);
3588 LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x\n",
3589 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange));
3590
3591 int rc = MMR3PhysRomProtect(pDevIns->Internal.s.pVMHC, GCPhysStart, cbRange);
3592
3593 LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3594 return rc;
3595}
3596
3597
3598
3599/** @copydoc PDMDEVHLP::pfnGetVM */
3600static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
3601{
3602 PDMDEV_ASSERT_DEVINS(pDevIns);
3603 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3604 return NULL;
3605}
3606
3607
3608/** @copydoc PDMDEVHLP::pfnPCIBusRegister */
3609static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
3610{
3611 PDMDEV_ASSERT_DEVINS(pDevIns);
3612 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3613 NOREF(pPciBusReg);
3614 NOREF(ppPciHlpR3);
3615 return VERR_ACCESS_DENIED;
3616}
3617
3618
3619/** @copydoc PDMDEVHLP::pfnPICRegister */
3620static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
3621{
3622 PDMDEV_ASSERT_DEVINS(pDevIns);
3623 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3624 NOREF(pPicReg);
3625 NOREF(ppPicHlpR3);
3626 return VERR_ACCESS_DENIED;
3627}
3628
3629
3630/** @copydoc PDMDEVHLP::pfnAPICRegister */
3631static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
3632{
3633 PDMDEV_ASSERT_DEVINS(pDevIns);
3634 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3635 NOREF(pApicReg);
3636 NOREF(ppApicHlpR3);
3637 return VERR_ACCESS_DENIED;
3638}
3639
3640
3641/** @copydoc PDMDEVHLP::pfnIOAPICRegister */
3642static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
3643{
3644 PDMDEV_ASSERT_DEVINS(pDevIns);
3645 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3646 NOREF(pIoApicReg);
3647 NOREF(ppIoApicHlpR3);
3648 return VERR_ACCESS_DENIED;
3649}
3650
3651
3652/** @copydoc PDMDEVHLP::pfnDMACRegister */
3653static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
3654{
3655 PDMDEV_ASSERT_DEVINS(pDevIns);
3656 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3657 NOREF(pDmacReg);
3658 NOREF(ppDmacHlp);
3659 return VERR_ACCESS_DENIED;
3660}
3661
3662
3663/** @copydoc PDMDEVHLP::pfnPhysRead */
3664static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
3665{
3666 PDMDEV_ASSERT_DEVINS(pDevIns);
3667 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3668 NOREF(GCPhys);
3669 NOREF(pvBuf);
3670 NOREF(cbRead);
3671}
3672
3673
3674/** @copydoc PDMDEVHLP::pfnPhysWrite */
3675static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
3676{
3677 PDMDEV_ASSERT_DEVINS(pDevIns);
3678 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3679 NOREF(GCPhys);
3680 NOREF(pvBuf);
3681 NOREF(cbWrite);
3682}
3683
3684
3685/** @copydoc PDMDEVHLP::pfnPhysReadGCVirt */
3686static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
3687{
3688 PDMDEV_ASSERT_DEVINS(pDevIns);
3689 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3690 NOREF(pvDst);
3691 NOREF(GCVirtSrc);
3692 NOREF(cb);
3693 return VERR_ACCESS_DENIED;
3694}
3695
3696
3697/** @copydoc PDMDEVHLP::pfnPhysWriteGCVirt */
3698static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
3699{
3700 PDMDEV_ASSERT_DEVINS(pDevIns);
3701 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3702 NOREF(GCVirtDst);
3703 NOREF(pvSrc);
3704 NOREF(cb);
3705 return VERR_ACCESS_DENIED;
3706}
3707
3708
3709/** @copydoc PDMDEVHLP::pfnPhysReserve */
3710static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
3711{
3712 PDMDEV_ASSERT_DEVINS(pDevIns);
3713 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3714 NOREF(GCPhys);
3715 NOREF(cbRange);
3716 return VERR_ACCESS_DENIED;
3717}
3718
3719
3720/** @copydoc PDMDEVHLP::pfnPhys2HCVirt */
3721static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC)
3722{
3723 PDMDEV_ASSERT_DEVINS(pDevIns);
3724 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3725 NOREF(GCPhys);
3726 NOREF(cbRange);
3727 NOREF(ppvHC);
3728 return VERR_ACCESS_DENIED;
3729}
3730
3731
3732/** @copydoc PDMDEVHLP::pfnPhysGCPtr2HCPtr */
3733static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr)
3734{
3735 PDMDEV_ASSERT_DEVINS(pDevIns);
3736 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3737 NOREF(GCPtr);
3738 NOREF(pHCPtr);
3739 return VERR_ACCESS_DENIED;
3740}
3741
3742
3743/** @copydoc PDMDEVHLP::pfnA20IsEnabled */
3744static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
3745{
3746 PDMDEV_ASSERT_DEVINS(pDevIns);
3747 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3748 return false;
3749}
3750
3751
3752/** @copydoc PDMDEVHLP::pfnA20Set */
3753static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
3754{
3755 PDMDEV_ASSERT_DEVINS(pDevIns);
3756 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3757 NOREF(fEnable);
3758}
3759
3760
3761/** @copydoc PDMDEVHLP::pfnVMReset */
3762static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns)
3763{
3764 PDMDEV_ASSERT_DEVINS(pDevIns);
3765 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3766 return VERR_ACCESS_DENIED;
3767}
3768
3769
3770/** @copydoc PDMDEVHLP::pfnVMSuspend */
3771static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
3772{
3773 PDMDEV_ASSERT_DEVINS(pDevIns);
3774 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3775 return VERR_ACCESS_DENIED;
3776}
3777
3778
3779/** @copydoc PDMDEVHLP::pfnVMPowerOff */
3780static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
3781{
3782 PDMDEV_ASSERT_DEVINS(pDevIns);
3783 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3784 return VERR_ACCESS_DENIED;
3785}
3786
3787
3788/** @copydoc PDMDEVHLP::pfnLockVM */
3789static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_LockVM(PPDMDEVINS pDevIns)
3790{
3791 PDMDEV_ASSERT_DEVINS(pDevIns);
3792 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3793 return VERR_ACCESS_DENIED;
3794}
3795
3796
3797/** @copydoc PDMDEVHLP::pfnUnlockVM */
3798static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_UnlockVM(PPDMDEVINS pDevIns)
3799{
3800 PDMDEV_ASSERT_DEVINS(pDevIns);
3801 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3802 return VERR_ACCESS_DENIED;
3803}
3804
3805
3806/** @copydoc PDMDEVHLP::pfnAssertVMLock */
3807static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3808{
3809 PDMDEV_ASSERT_DEVINS(pDevIns);
3810 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3811 return false;
3812}
3813
3814
3815/** @copydoc PDMDEVHLP::pfnDMARegister */
3816static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
3817{
3818 PDMDEV_ASSERT_DEVINS(pDevIns);
3819 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3820 return VERR_ACCESS_DENIED;
3821}
3822
3823
3824/** @copydoc PDMDEVHLP::pfnDMAReadMemory */
3825static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
3826{
3827 PDMDEV_ASSERT_DEVINS(pDevIns);
3828 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3829 if (pcbRead)
3830 *pcbRead = 0;
3831 return VERR_ACCESS_DENIED;
3832}
3833
3834
3835/** @copydoc PDMDEVHLP::pfnDMAWriteMemory */
3836static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
3837{
3838 PDMDEV_ASSERT_DEVINS(pDevIns);
3839 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3840 if (pcbWritten)
3841 *pcbWritten = 0;
3842 return VERR_ACCESS_DENIED;
3843}
3844
3845
3846/** @copydoc PDMDEVHLP::pfnDMASetDREQ */
3847static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
3848{
3849 PDMDEV_ASSERT_DEVINS(pDevIns);
3850 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3851 return VERR_ACCESS_DENIED;
3852}
3853
3854
3855/** @copydoc PDMDEVHLP::pfnDMAGetChannelMode */
3856static DECLCALLBACK(uint8_t) pdmR3DevHlp_Untrusted_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
3857{
3858 PDMDEV_ASSERT_DEVINS(pDevIns);
3859 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3860 return 3 << 2 /* illegal mode type */;
3861}
3862
3863
3864/** @copydoc PDMDEVHLP::pfnDMASchedule */
3865static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_DMASchedule(PPDMDEVINS pDevIns)
3866{
3867 PDMDEV_ASSERT_DEVINS(pDevIns);
3868 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3869}
3870
3871
3872/** @copydoc PDMDEVHLP::pfnCMOSWrite */
3873static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
3874{
3875 PDMDEV_ASSERT_DEVINS(pDevIns);
3876 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3877 return VERR_ACCESS_DENIED;
3878}
3879
3880
3881/** @copydoc PDMDEVHLP::pfnCMOSRead */
3882static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
3883{
3884 PDMDEV_ASSERT_DEVINS(pDevIns);
3885 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3886 return VERR_ACCESS_DENIED;
3887}
3888
3889
3890/** @copydoc PDMDEVHLP::pfnQueryCPUId */
3891static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_QueryCPUId(PPDMDEVINS pDevIns, uint32_t iLeaf,
3892 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
3893{
3894 PDMDEV_ASSERT_DEVINS(pDevIns);
3895 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3896}
3897
3898
3899/** @copydoc PDMDEVHLP::pfnROMProtectShadow */
3900static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
3901{
3902 PDMDEV_ASSERT_DEVINS(pDevIns);
3903 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3904 return VERR_ACCESS_DENIED;
3905}
3906
3907
3908/** @copydoc PDMPICHLPR3::pfnSetInterruptFF */
3909static DECLCALLBACK(void) pdmR3PicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
3910{
3911 PDMDEV_ASSERT_DEVINS(pDevIns);
3912 PVM pVM = pDevIns->Internal.s.pVMHC;
3913 LogFlow(("pdmR3PicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 1\n",
3914 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_INTERRUPT_PIC)));
3915 VM_FF_SET(pVM, VM_FF_INTERRUPT_PIC);
3916 REMR3NotifyInterruptSet(pVM);
3917#ifdef VBOX_WITH_PDM_LOCK
3918 VMR3NotifyFF(pVM, true);
3919#endif
3920}
3921
3922
3923/** @copydoc PDMPICHLPR3::pfnClearInterruptFF */
3924static DECLCALLBACK(void) pdmR3PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
3925{
3926 PDMDEV_ASSERT_DEVINS(pDevIns);
3927 LogFlow(("pdmR3PicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 0\n",
3928 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_PIC)));
3929 VM_FF_CLEAR(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_PIC);
3930 REMR3NotifyInterruptClear(pDevIns->Internal.s.pVMHC);
3931}
3932
3933
3934#ifdef VBOX_WITH_PDM_LOCK
3935/** @copydoc PDMPICHLPR3::pfnLock */
3936static DECLCALLBACK(int) pdmR3PicHlp_Lock(PPDMDEVINS pDevIns, int rc)
3937{
3938 PDMDEV_ASSERT_DEVINS(pDevIns);
3939 return pdmLockEx(pDevIns->Internal.s.pVMHC, rc);
3940}
3941
3942
3943/** @copydoc PDMPICHLPR3::pfnUnlock */
3944static DECLCALLBACK(void) pdmR3PicHlp_Unlock(PPDMDEVINS pDevIns)
3945{
3946 PDMDEV_ASSERT_DEVINS(pDevIns);
3947 pdmUnlock(pDevIns->Internal.s.pVMHC);
3948}
3949#endif /* VBOX_WITH_PDM_LOCK */
3950
3951
3952/** @copydoc PDMPICHLPR3::pfnGetGCHelpers */
3953static DECLCALLBACK(PCPDMPICHLPGC) pdmR3PicHlp_GetGCHelpers(PPDMDEVINS pDevIns)
3954{
3955 PDMDEV_ASSERT_DEVINS(pDevIns);
3956 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3957 RTGCPTR pGCHelpers = 0;
3958 int rc = PDMR3GetSymbolGC(pDevIns->Internal.s.pVMHC, NULL, "g_pdmGCPicHlp", &pGCHelpers);
3959 AssertReleaseRC(rc);
3960 AssertRelease(pGCHelpers);
3961 LogFlow(("pdmR3PicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
3962 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pGCHelpers));
3963 return pGCHelpers;
3964}
3965
3966
3967/** @copydoc PDMPICHLPR3::pfnGetR0Helpers */
3968static DECLCALLBACK(PCPDMPICHLPR0) pdmR3PicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
3969{
3970 PDMDEV_ASSERT_DEVINS(pDevIns);
3971 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3972 PCPDMPICHLPR0 pR0Helpers = 0;
3973 int rc = PDMR3GetSymbolR0(pDevIns->Internal.s.pVMHC, NULL, "g_pdmR0PicHlp", &pR0Helpers);
3974 AssertReleaseRC(rc);
3975 AssertRelease(pR0Helpers);
3976 LogFlow(("pdmR3PicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
3977 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
3978 return pR0Helpers;
3979}
3980
3981
3982/** @copydoc PDMAPICHLPR3::pfnSetInterruptFF */
3983static DECLCALLBACK(void) pdmR3ApicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
3984{
3985 PDMDEV_ASSERT_DEVINS(pDevIns);
3986 PVM pVM = pDevIns->Internal.s.pVMHC;
3987 LogFlow(("pdmR3ApicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT %d -> 1\n",
3988 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_INTERRUPT_APIC)));
3989 VM_FF_SET(pVM, VM_FF_INTERRUPT_APIC);
3990 REMR3NotifyInterruptSet(pVM);
3991#ifdef VBOX_WITH_PDM_LOCK
3992 VMR3NotifyFF(pVM, true);
3993#endif
3994}
3995
3996
3997/** @copydoc PDMAPICHLPR3::pfnClearInterruptFF */
3998static DECLCALLBACK(void) pdmR3ApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
3999{
4000 PDMDEV_ASSERT_DEVINS(pDevIns);
4001 LogFlow(("pdmR3ApicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT %d -> 0\n",
4002 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_APIC)));
4003 VM_FF_CLEAR(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_APIC);
4004 REMR3NotifyInterruptClear(pDevIns->Internal.s.pVMHC);
4005}
4006
4007
4008/** @copydoc PDMAPICHLPR3::pfnChangeFeature */
4009static DECLCALLBACK(void) pdmR3ApicHlp_ChangeFeature(PPDMDEVINS pDevIns, bool fEnabled)
4010{
4011 PDMDEV_ASSERT_DEVINS(pDevIns);
4012 LogFlow(("pdmR3ApicHlp_ClearInterruptFF: caller='%s'/%d: fEnabled=%RTbool\n",
4013 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fEnabled));
4014 if (fEnabled)
4015 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMHC, CPUMCPUIDFEATURE_APIC);
4016 else
4017 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMHC, CPUMCPUIDFEATURE_APIC);
4018}
4019
4020#ifdef VBOX_WITH_PDM_LOCK
4021/** @copydoc PDMAPICHLPR3::pfnLock */
4022static DECLCALLBACK(int) pdmR3ApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
4023{
4024 PDMDEV_ASSERT_DEVINS(pDevIns);
4025 return pdmLockEx(pDevIns->Internal.s.pVMHC, rc);
4026}
4027
4028
4029/** @copydoc PDMAPICHLPR3::pfnUnlock */
4030static DECLCALLBACK(void) pdmR3ApicHlp_Unlock(PPDMDEVINS pDevIns)
4031{
4032 PDMDEV_ASSERT_DEVINS(pDevIns);
4033 pdmUnlock(pDevIns->Internal.s.pVMHC);
4034}
4035#endif /* VBOX_WITH_PDM_LOCK */
4036
4037
4038/** @copydoc PDMAPICHLPR3::pfnGetGCHelpers */
4039static DECLCALLBACK(PCPDMAPICHLPGC) pdmR3ApicHlp_GetGCHelpers(PPDMDEVINS pDevIns)
4040{
4041 PDMDEV_ASSERT_DEVINS(pDevIns);
4042 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4043 RTGCPTR pGCHelpers = 0;
4044 int rc = PDMR3GetSymbolGC(pDevIns->Internal.s.pVMHC, NULL, "g_pdmGCApicHlp", &pGCHelpers);
4045 AssertReleaseRC(rc);
4046 AssertRelease(pGCHelpers);
4047 LogFlow(("pdmR3ApicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
4048 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pGCHelpers));
4049 return pGCHelpers;
4050}
4051
4052
4053/** @copydoc PDMAPICHLPR3::pfnGetR0Helpers */
4054static DECLCALLBACK(PCPDMAPICHLPR0) pdmR3ApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
4055{
4056 PDMDEV_ASSERT_DEVINS(pDevIns);
4057 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4058 PCPDMAPICHLPR0 pR0Helpers = 0;
4059 int rc = PDMR3GetSymbolR0(pDevIns->Internal.s.pVMHC, NULL, "g_pdmR0ApicHlp", &pR0Helpers);
4060 AssertReleaseRC(rc);
4061 AssertRelease(pR0Helpers);
4062 LogFlow(("pdmR3ApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
4063 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
4064 return pR0Helpers;
4065}
4066
4067
4068/** @copydoc PDMIOAPICHLPR3::pfnApicBusDeliver */
4069static DECLCALLBACK(void) pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
4070 uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode)
4071{
4072 PDMDEV_ASSERT_DEVINS(pDevIns);
4073 PVM pVM = pDevIns->Internal.s.pVMHC;
4074#ifndef VBOX_WITH_PDM_LOCK
4075 VM_ASSERT_EMT(pVM);
4076#endif
4077 LogFlow(("pdmR3IoApicHlp_ApicBusDeliver: caller='%s'/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8\n",
4078 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode));
4079 if (pVM->pdm.s.Apic.pfnBusDeliverR3)
4080 pVM->pdm.s.Apic.pfnBusDeliverR3(pVM->pdm.s.Apic.pDevInsR3, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode);
4081}
4082
4083
4084#ifdef VBOX_WITH_PDM_LOCK
4085/** @copydoc PDMIOAPICHLPR3::pfnLock */
4086static DECLCALLBACK(int) pdmR3IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
4087{
4088 PDMDEV_ASSERT_DEVINS(pDevIns);
4089 return pdmLockEx(pDevIns->Internal.s.pVMHC, rc);
4090}
4091
4092
4093/** @copydoc PDMIOAPICHLPR3::pfnUnlock */
4094static DECLCALLBACK(void) pdmR3IoApicHlp_Unlock(PPDMDEVINS pDevIns)
4095{
4096 PDMDEV_ASSERT_DEVINS(pDevIns);
4097 pdmUnlock(pDevIns->Internal.s.pVMHC);
4098}
4099#endif /* VBOX_WITH_PDM_LOCK */
4100
4101
4102/** @copydoc PDMIOAPICHLPR3::pfnGetGCHelpers */
4103static DECLCALLBACK(PCPDMIOAPICHLPGC) pdmR3IoApicHlp_GetGCHelpers(PPDMDEVINS pDevIns)
4104{
4105 PDMDEV_ASSERT_DEVINS(pDevIns);
4106 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4107 RTGCPTR pGCHelpers = 0;
4108 int rc = PDMR3GetSymbolGC(pDevIns->Internal.s.pVMHC, NULL, "g_pdmGCIoApicHlp", &pGCHelpers);
4109 AssertReleaseRC(rc);
4110 AssertRelease(pGCHelpers);
4111 LogFlow(("pdmR3IoApicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
4112 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pGCHelpers));
4113 return pGCHelpers;
4114}
4115
4116
4117/** @copydoc PDMIOAPICHLPR3::pfnGetR0Helpers */
4118static DECLCALLBACK(PCPDMIOAPICHLPR0) pdmR3IoApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
4119{
4120 PDMDEV_ASSERT_DEVINS(pDevIns);
4121 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4122 PCPDMIOAPICHLPR0 pR0Helpers = 0;
4123 int rc = PDMR3GetSymbolR0(pDevIns->Internal.s.pVMHC, NULL, "g_pdmR0IoApicHlp", &pR0Helpers);
4124 AssertReleaseRC(rc);
4125 AssertRelease(pR0Helpers);
4126 LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
4127 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
4128 return pR0Helpers;
4129}
4130
4131
4132/** @copydoc PDMPCIHLPR3::pfnIsaSetIrq */
4133static DECLCALLBACK(void) pdmR3PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
4134{
4135 PDMDEV_ASSERT_DEVINS(pDevIns);
4136#ifndef VBOX_WITH_PDM_LOCK
4137 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4138#endif
4139 Log4(("pdmR3PciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
4140 PDMIsaSetIrq(pDevIns->Internal.s.pVMHC, iIrq, iLevel);
4141}
4142
4143
4144/** @copydoc PDMPCIHLPR3::pfnIoApicSetIrq */
4145static DECLCALLBACK(void) pdmR3PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
4146{
4147 PDMDEV_ASSERT_DEVINS(pDevIns);
4148#ifndef VBOX_WITH_PDM_LOCK
4149 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4150#endif
4151 Log4(("pdmR3PciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
4152 PDMIoApicSetIrq(pDevIns->Internal.s.pVMHC, iIrq, iLevel);
4153}
4154
4155
4156#ifdef VBOX_WITH_PDM_LOCK
4157/** @copydoc PDMPCIHLPR3::pfnLock */
4158static DECLCALLBACK(int) pdmR3PciHlp_Lock(PPDMDEVINS pDevIns, int rc)
4159{
4160 PDMDEV_ASSERT_DEVINS(pDevIns);
4161 return pdmLockEx(pDevIns->Internal.s.pVMHC, rc);
4162}
4163
4164
4165/** @copydoc PDMPCIHLPR3::pfnUnlock */
4166static DECLCALLBACK(void) pdmR3PciHlp_Unlock(PPDMDEVINS pDevIns)
4167{
4168 PDMDEV_ASSERT_DEVINS(pDevIns);
4169 pdmUnlock(pDevIns->Internal.s.pVMHC);
4170}
4171#endif /* VBOX_WITH_PDM_LOCK */
4172
4173
4174/** @copydoc PDMPCIHLPR3::pfnGetGCHelpers */
4175static DECLCALLBACK(PCPDMPCIHLPGC) pdmR3PciHlp_GetGCHelpers(PPDMDEVINS pDevIns)
4176{
4177 PDMDEV_ASSERT_DEVINS(pDevIns);
4178 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4179 RTGCPTR pGCHelpers = 0;
4180 int rc = PDMR3GetSymbolGC(pDevIns->Internal.s.pVMHC, NULL, "g_pdmGCPciHlp", &pGCHelpers);
4181 AssertReleaseRC(rc);
4182 AssertRelease(pGCHelpers);
4183 LogFlow(("pdmR3IoApicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
4184 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pGCHelpers));
4185 return pGCHelpers;
4186}
4187
4188
4189/** @copydoc PDMPCIHLPR3::pfnGetR0Helpers */
4190static DECLCALLBACK(PCPDMPCIHLPR0) pdmR3PciHlp_GetR0Helpers(PPDMDEVINS pDevIns)
4191{
4192 PDMDEV_ASSERT_DEVINS(pDevIns);
4193 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4194 PCPDMPCIHLPR0 pR0Helpers = 0;
4195 int rc = PDMR3GetSymbolR0(pDevIns->Internal.s.pVMHC, NULL, "g_pdmR0PciHlp", &pR0Helpers);
4196 AssertReleaseRC(rc);
4197 AssertRelease(pR0Helpers);
4198 LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
4199 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
4200 return pR0Helpers;
4201}
4202
4203
4204/**
4205 * Locates a LUN.
4206 *
4207 * @returns VBox status code.
4208 * @param pVM VM Handle.
4209 * @param pszDevice Device name.
4210 * @param iInstance Device instance.
4211 * @param iLun The Logical Unit to obtain the interface of.
4212 * @param ppLun Where to store the pointer to the LUN if found.
4213 * @thread Try only do this in EMT...
4214 */
4215int pdmR3DevFindLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMLUN *ppLun)
4216{
4217 /*
4218 * Iterate registered devices looking for the device.
4219 */
4220 RTUINT cchDevice = strlen(pszDevice);
4221 for (PPDMDEV pDev = pVM->pdm.s.pDevs; pDev; pDev = pDev->pNext)
4222 {
4223 if ( pDev->cchName == cchDevice
4224 && !memcmp(pDev->pDevReg->szDeviceName, pszDevice, cchDevice))
4225 {
4226 /*
4227 * Iterate device instances.
4228 */
4229 for (PPDMDEVINS pDevIns = pDev->pInstances; pDevIns; pDevIns = pDevIns->Internal.s.pPerDeviceNextHC)
4230 {
4231 if (pDevIns->iInstance == iInstance)
4232 {
4233 /*
4234 * Iterate luns.
4235 */
4236 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsHC; pLun; pLun = pLun->pNext)
4237 {
4238 if (pLun->iLun == iLun)
4239 {
4240 *ppLun = pLun;
4241 return VINF_SUCCESS;
4242 }
4243 }
4244 return VERR_PDM_LUN_NOT_FOUND;
4245 }
4246 }
4247 return VERR_PDM_DEVICE_INSTANCE_NOT_FOUND;
4248 }
4249 }
4250 return VERR_PDM_DEVICE_NOT_FOUND;
4251}
4252
4253
4254/**
4255 * Attaches a preconfigured driver to an existing device instance.
4256 *
4257 * This is used to change drivers and suchlike at runtime.
4258 *
4259 * @returns VBox status code.
4260 * @param pVM VM Handle.
4261 * @param pszDevice Device name.
4262 * @param iInstance Device instance.
4263 * @param iLun The Logical Unit to obtain the interface of.
4264 * @param ppBase Where to store the base interface pointer. Optional.
4265 * @thread EMT
4266 */
4267PDMR3DECL(int) PDMR3DeviceAttach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMIBASE *ppBase)
4268{
4269 VM_ASSERT_EMT(pVM);
4270 LogFlow(("PDMR3DeviceAttach: pszDevice=%p:{%s} iInstance=%d iLun=%d ppBase=%p\n",
4271 pszDevice, pszDevice, iInstance, iLun, ppBase));
4272
4273 /*
4274 * Find the LUN in question.
4275 */
4276 PPDMLUN pLun;
4277 int rc = pdmR3DevFindLun(pVM, pszDevice, iInstance, iLun, &pLun);
4278 if (VBOX_SUCCESS(rc))
4279 {
4280 /*
4281 * Can we attach anything at runtime?
4282 */
4283 PPDMDEVINS pDevIns = pLun->pDevIns;
4284 if (pDevIns->pDevReg->pfnAttach)
4285 {
4286 if (!pLun->pTop)
4287 {
4288 rc = pDevIns->pDevReg->pfnAttach(pDevIns, iLun);
4289
4290 }
4291 else
4292 rc = VERR_PDM_DRIVER_ALREADY_ATTACHED;
4293 }
4294 else
4295 rc = VERR_PDM_DEVICE_NO_RT_ATTACH;
4296
4297 if (ppBase)
4298 *ppBase = pLun->pTop ? &pLun->pTop->IBase : NULL;
4299 }
4300 else if (ppBase)
4301 *ppBase = NULL;
4302
4303 if (ppBase)
4304 LogFlow(("PDMR3DeviceAttach: returns %Vrc *ppBase=%p\n", rc, *ppBase));
4305 else
4306 LogFlow(("PDMR3DeviceAttach: returns %Vrc\n", rc));
4307 return rc;
4308}
4309
4310
4311/**
4312 * Detaches a driver chain from an existing device instance.
4313 *
4314 * This is used to change drivers and suchlike at runtime.
4315 *
4316 * @returns VBox status code.
4317 * @param pVM VM Handle.
4318 * @param pszDevice Device name.
4319 * @param iInstance Device instance.
4320 * @param iLun The Logical Unit to obtain the interface of.
4321 * @thread EMT
4322 */
4323PDMR3DECL(int) PDMR3DeviceDetach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun)
4324{
4325 VM_ASSERT_EMT(pVM);
4326 LogFlow(("PDMR3DeviceDetach: pszDevice=%p:{%s} iInstance=%d iLun=%d\n",
4327 pszDevice, pszDevice, iInstance, iLun));
4328
4329 /*
4330 * Find the LUN in question.
4331 */
4332 PPDMLUN pLun;
4333 int rc = pdmR3DevFindLun(pVM, pszDevice, iInstance, iLun, &pLun);
4334 if (VBOX_SUCCESS(rc))
4335 {
4336 /*
4337 * Can we detach anything at runtime?
4338 */
4339 PPDMDEVINS pDevIns = pLun->pDevIns;
4340 if (pDevIns->pDevReg->pfnDetach)
4341 {
4342 if (pLun->pTop)
4343 rc = pdmR3DrvDetach(pLun->pTop);
4344 else
4345 rc = VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN;
4346 }
4347 else
4348 rc = VERR_PDM_DEVICE_NO_RT_DETACH;
4349 }
4350
4351 LogFlow(("PDMR3DeviceDetach: returns %Vrc\n", rc));
4352 return rc;
4353}
4354
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette