VirtualBox

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

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

Biggest check-in ever. New source code headers for all (C) innotek files.

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

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