VirtualBox

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

Last change on this file since 4514 was 4388, checked in by vboxsync, 18 years ago

Shadow ROM emulation. Clear the RESERVED flag for ROM.

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

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