VirtualBox

source: vbox/trunk/src/VBox/VMM/PDMDriver.cpp@ 6861

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

Fixed init problems wrt. VM ownership by implementing the UVM structure (U = user mode) and moving problematic ring-3 stuff over there (emt+reqs, r3heap, stam, loader[VMMR0.r0]). Big change, but it works fine here... :-)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 42.3 KB
Line 
1/* $Id: PDMDriver.cpp 6796 2008-02-04 18:19:58Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, Driver parts.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_PDM_DRIVER
23#include "PDMInternal.h"
24#include <VBox/pdm.h>
25#include <VBox/mm.h>
26#include <VBox/cfgm.h>
27#include <VBox/vmm.h>
28#include <VBox/sup.h>
29#include <VBox/vm.h>
30#include <VBox/version.h>
31#include <VBox/err.h>
32
33#include <VBox/log.h>
34#include <iprt/assert.h>
35#include <iprt/thread.h>
36#include <iprt/string.h>
37#include <iprt/asm.h>
38#include <iprt/alloc.h>
39#include <iprt/path.h>
40
41
42/*******************************************************************************
43* Structures and Typedefs *
44*******************************************************************************/
45/**
46 * Internal callback structure pointer.
47 *
48 * The main purpose is to define the extra data we associate
49 * with PDMDRVREGCB so we can find the VM instance and so on.
50 */
51typedef struct PDMDRVREGCBINT
52{
53 /** The callback structure. */
54 PDMDRVREGCB Core;
55 /** A bit of padding. */
56 uint32_t u32[4];
57 /** VM Handle. */
58 PVM pVM;
59} PDMDRVREGCBINT, *PPDMDRVREGCBINT;
60typedef const PDMDRVREGCBINT *PCPDMDRVREGCBINT;
61
62
63/*******************************************************************************
64* Internal Functions *
65*******************************************************************************/
66/** @name Driver Helpers
67 * @{
68 */
69static DECLCALLBACK(int) pdmR3DrvHlp_Attach(PPDMDRVINS pDrvIns, PPDMIBASE *ppBaseInterface);
70static DECLCALLBACK(int) pdmR3DrvHlp_Detach(PPDMDRVINS pDrvIns);
71static DECLCALLBACK(int) pdmR3DrvHlp_DetachSelf(PPDMDRVINS pDrvIns);
72static DECLCALLBACK(int) pdmR3DrvHlp_MountPrepare(PPDMDRVINS pDrvIns, const char *pszFilename, const char *pszCoreDriver);
73static DECLCALLBACK(int) pdmR3DrvHlp_VMSetError(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...);
74static DECLCALLBACK(int) pdmR3DrvHlp_VMSetErrorV(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va);
75static DECLCALLBACK(int) pdmR3DrvHlp_VMSetRuntimeError(PPDMDRVINS pDrvIns, bool fFatal, const char *pszErrorID, const char *pszFormat, ...);
76static DECLCALLBACK(int) pdmR3DrvHlp_VMSetRuntimeErrorV(PPDMDRVINS pDrvIns, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list va);
77static DECLCALLBACK(bool) pdmR3DrvHlp_AssertEMT(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction);
78static DECLCALLBACK(bool) pdmR3DrvHlp_AssertOther(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction);
79static DECLCALLBACK(int) pdmR3DrvHlp_PDMQueueCreate(PPDMDRVINS pDrvIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval, PFNPDMQUEUEDRV pfnCallback, PPDMQUEUE *ppQueue);
80static DECLCALLBACK(int) pdmR3DrvHlp_PDMPollerRegister(PPDMDRVINS pDrvIns, PFNPDMDRVPOLLER pfnPoller);
81static DECLCALLBACK(uint64_t) pdmR3DrvHlp_TMGetVirtualFreq(PPDMDRVINS pDrvIns);
82static DECLCALLBACK(uint64_t) pdmR3DrvHlp_TMGetVirtualTime(PPDMDRVINS pDrvIns);
83static DECLCALLBACK(int) pdmR3DrvHlp_TMTimerCreate(PPDMDRVINS pDrvIns, TMCLOCK enmClock, PFNTMTIMERDRV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer);
84static DECLCALLBACK(int) pdmR3DrvHlp_SSMRegister(PPDMDRVINS pDrvIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
85 PFNSSMDRVSAVEPREP pfnSavePrep, PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVSAVEDONE pfnSaveDone,
86 PFNSSMDRVLOADPREP pfnLoadPrep, PFNSSMDRVLOADEXEC pfnLoadExec, PFNSSMDRVLOADDONE pfnLoadDone);
87static DECLCALLBACK(int) pdmR3DrvHlp_SSMDeregister(PPDMDRVINS pDrvIns, const char *pszName, uint32_t u32Instance);
88static DECLCALLBACK(void) pdmR3DrvHlp_STAMRegister(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
89static DECLCALLBACK(void) pdmR3DrvHlp_STAMRegisterF(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...);
90static DECLCALLBACK(void) pdmR3DrvHlp_STAMRegisterV(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args);
91static DECLCALLBACK(int) pdmR3DrvHlp_SUPCallVMMR0Ex(PPDMDRVINS pDrvIns, unsigned uOperation, void *pvArg, unsigned cbArg);
92static DECLCALLBACK(int) pdmR3DrvHlp_USBRegisterHub(PPDMDRVINS pDrvIns, uint32_t fVersions, uint32_t cPorts, PCPDMUSBHUBREG pUsbHubReg, PPCPDMUSBHUBHLP ppUsbHubHlp);
93static DECLCALLBACK(int) pdmR3DrvHlp_PDMThreadCreate(PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
94 PFNPDMTHREADWAKEUPDRV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
95
96#ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
97static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
98 PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc);
99#endif
100
101/** @def PDMDRV_ASSERT_DRVINS
102 * Asserts the validity of the driver instance.
103 */
104#ifdef VBOX_STRICT
105# define PDMDRV_ASSERT_DRVINS(pDrvIns) do { Assert(pDrvIns); Assert(pDrvIns->u32Version == PDM_DRVINS_VERSION); Assert(pDrvIns->pvInstanceData == (void *)&pDrvIns->achInstanceData[0]); } while (0)
106#else
107# define PDMDRV_ASSERT_DRVINS(pDrvIns) do { } while (0)
108#endif
109/** @} */
110
111static DECLCALLBACK(int) pdmR3DrvRegister(PCPDMDRVREGCB pCallbacks, PCPDMDRVREG pDrvReg);
112static int pdmR3DrvLoad(PVM pVM, PPDMDRVREGCBINT pRegCB, const char *pszFilename, const char *pszName);
113
114
115/*******************************************************************************
116* Global Variables *
117*******************************************************************************/
118/**
119 * The driver helper structure.
120 */
121const PDMDRVHLP g_pdmR3DrvHlp =
122{
123 PDM_DRVHLP_VERSION,
124 pdmR3DrvHlp_Attach,
125 pdmR3DrvHlp_Detach,
126 pdmR3DrvHlp_DetachSelf,
127 pdmR3DrvHlp_MountPrepare,
128 pdmR3DrvHlp_AssertEMT,
129 pdmR3DrvHlp_AssertOther,
130 pdmR3DrvHlp_VMSetError,
131 pdmR3DrvHlp_VMSetErrorV,
132 pdmR3DrvHlp_VMSetRuntimeError,
133 pdmR3DrvHlp_VMSetRuntimeErrorV,
134 pdmR3DrvHlp_PDMQueueCreate,
135 pdmR3DrvHlp_PDMPollerRegister,
136 pdmR3DrvHlp_TMGetVirtualFreq,
137 pdmR3DrvHlp_TMGetVirtualTime,
138 pdmR3DrvHlp_TMTimerCreate,
139 pdmR3DrvHlp_SSMRegister,
140 pdmR3DrvHlp_SSMDeregister,
141 pdmR3DrvHlp_STAMRegister,
142 pdmR3DrvHlp_STAMRegisterF,
143 pdmR3DrvHlp_STAMRegisterV,
144 pdmR3DrvHlp_SUPCallVMMR0Ex,
145 pdmR3DrvHlp_USBRegisterHub,
146 pdmR3DrvHlp_PDMThreadCreate,
147#ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
148 pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate,
149#endif
150 0 /* the end */
151};
152
153
154/**
155 * Register external drivers
156 *
157 * @returns VBox status code.
158 * @param pVM The VM to operate on.
159 * @param pfnCallback Driver registration callback
160 */
161PDMR3DECL(int) PDMR3RegisterDrivers(PVM pVM, FNPDMVBOXDRIVERSREGISTER pfnCallback)
162{
163 /*
164 * The registration callbacks.
165 */
166 PDMDRVREGCBINT RegCB;
167 RegCB.Core.u32Version = PDM_DRVREG_CB_VERSION;
168 RegCB.Core.pfnRegister = pdmR3DrvRegister;
169 RegCB.pVM = pVM;
170
171 int rc = pfnCallback(&RegCB.Core, VBOX_VERSION);
172 if (VBOX_FAILURE(rc))
173 AssertMsgFailed(("VBoxDriversRegister failed with rc=%Vrc\n"));
174
175 return rc;
176}
177
178/**
179 * This function will initialize the drivers for this VM instance.
180 *
181 * First of all this mean loading the builtin drivers and letting them
182 * register themselves. Beyond that any additional driver modules are
183 * loaded and called for registration.
184 *
185 * @returns VBox status code.
186 * @param pVM VM Handle.
187 */
188int pdmR3DrvInit(PVM pVM)
189{
190 LogFlow(("pdmR3DrvInit:\n"));
191
192 AssertRelease(!(RT_OFFSETOF(PDMDRVINS, achInstanceData) & 15));
193 PPDMDRVINS pDrvInsAssert;
194 AssertRelease(sizeof(pDrvInsAssert->Internal.s) <= sizeof(pDrvInsAssert->Internal.padding));
195
196 /*
197 * The registration callbacks.
198 */
199 PDMDRVREGCBINT RegCB;
200 RegCB.Core.u32Version = PDM_DRVREG_CB_VERSION;
201 RegCB.Core.pfnRegister = pdmR3DrvRegister;
202 RegCB.pVM = pVM;
203
204 /*
205 * Load the builtin module
206 */
207 PCFGMNODE pDriversNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM/Drivers");
208 bool fLoadBuiltin;
209 int rc = CFGMR3QueryBool(pDriversNode, "LoadBuiltin", &fLoadBuiltin);
210 if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
211 fLoadBuiltin = true;
212 else if (VBOX_FAILURE(rc))
213 {
214 AssertMsgFailed(("Configuration error: Querying boolean \"LoadBuiltin\" failed with %Vrc\n", rc));
215 return rc;
216 }
217 if (fLoadBuiltin)
218 {
219 /* make filename */
220 char *pszFilename = pdmR3FileR3("VBoxDD", /*fShared=*/true);
221 if (!pszFilename)
222 return VERR_NO_TMP_MEMORY;
223 rc = pdmR3DrvLoad(pVM, &RegCB, pszFilename, "VBoxDD");
224 RTMemTmpFree(pszFilename);
225 if (VBOX_FAILURE(rc))
226 return rc;
227 }
228
229 /*
230 * Load additional driver modules.
231 */
232 for (PCFGMNODE pCur = CFGMR3GetFirstChild(pDriversNode); pCur; pCur = CFGMR3GetNextChild(pCur))
233 {
234 /*
235 * Get the name and path.
236 */
237 char szName[PDMMOD_NAME_LEN];
238 rc = CFGMR3GetName(pCur, &szName[0], sizeof(szName));
239 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
240 {
241 AssertMsgFailed(("configuration error: The module name is too long, cchName=%d.\n", CFGMR3GetNameLen(pCur)));
242 return VERR_PDM_MODULE_NAME_TOO_LONG;
243 }
244 else if (VBOX_FAILURE(rc))
245 {
246 AssertMsgFailed(("CFGMR3GetName -> %Vrc.\n", rc));
247 return rc;
248 }
249
250 /* the path is optional, if no path the module name + path is used. */
251 char szFilename[RTPATH_MAX];
252 rc = CFGMR3QueryString(pCur, "Path", &szFilename[0], sizeof(szFilename));
253 if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
254 strcpy(szFilename, szName);
255 else if (VBOX_FAILURE(rc))
256 {
257 AssertMsgFailed(("configuration error: Failure to query the module path, rc=%Vrc.\n", rc));
258 return rc;
259 }
260
261 /* prepend path? */
262 if (!RTPathHavePath(szFilename))
263 {
264 char *psz = pdmR3FileR3(szFilename);
265 if (!psz)
266 return VERR_NO_TMP_MEMORY;
267 size_t cch = strlen(psz) + 1;
268 if (cch > sizeof(szFilename))
269 {
270 RTMemTmpFree(psz);
271 AssertMsgFailed(("Filename too long! cch=%d '%s'\n", cch, psz));
272 return VERR_FILENAME_TOO_LONG;
273 }
274 memcpy(szFilename, psz, cch);
275 RTMemTmpFree(psz);
276 }
277
278 /*
279 * Load the module and register it's drivers.
280 */
281 rc = pdmR3DrvLoad(pVM, &RegCB, szFilename, szName);
282 if (VBOX_FAILURE(rc))
283 return rc;
284 }
285
286 LogFlow(("pdmR3DrvInit: returns VINF_SUCCESS\n"));
287 return VINF_SUCCESS;
288}
289
290
291/**
292 * Loads one driver module and call the registration entry point.
293 *
294 * @returns VBox status code.
295 * @param pVM VM handle.
296 * @param pRegCB The registration callback stuff.
297 * @param pszFilename Module filename.
298 * @param pszName Module name.
299 */
300static int pdmR3DrvLoad(PVM pVM, PPDMDRVREGCBINT pRegCB, const char *pszFilename, const char *pszName)
301{
302 /*
303 * Load it.
304 */
305 int rc = pdmR3LoadR3U(pVM->pUVM, pszFilename, pszName);
306 if (VBOX_SUCCESS(rc))
307 {
308 /*
309 * Get the registration export and call it.
310 */
311 FNPDMVBOXDRIVERSREGISTER *pfnVBoxDriversRegister;
312 rc = PDMR3GetSymbolR3(pVM, pszName, "VBoxDriversRegister", (void **)&pfnVBoxDriversRegister);
313 if (VBOX_SUCCESS(rc))
314 {
315 Log(("PDM: Calling VBoxDriversRegister (%p) of %s (%s)\n", pfnVBoxDriversRegister, pszName, pszFilename));
316 rc = pfnVBoxDriversRegister(&pRegCB->Core, VBOX_VERSION);
317 if (VBOX_SUCCESS(rc))
318 Log(("PDM: Successfully loaded driver module %s (%s).\n", pszName, pszFilename));
319 else
320 AssertMsgFailed(("VBoxDriversRegister failed with rc=%Vrc\n"));
321 }
322 else
323 {
324 AssertMsgFailed(("Failed to locate 'VBoxDriversRegister' in %s (%s) rc=%Vrc\n", pszName, pszFilename, rc));
325 if (rc == VERR_SYMBOL_NOT_FOUND)
326 rc = VERR_PDM_NO_REGISTRATION_EXPORT;
327 }
328 }
329 else
330 AssertMsgFailed(("Failed to load %s (%s) rc=%Vrc!\n", pszName, pszFilename, rc));
331 return rc;
332}
333
334
335/** @copydoc PDMDRVREGCB::pfnRegister */
336static DECLCALLBACK(int) pdmR3DrvRegister(PCPDMDRVREGCB pCallbacks, PCPDMDRVREG pDrvReg)
337{
338 /*
339 * Validate the registration structure.
340 */
341 Assert(pDrvReg);
342 if (pDrvReg->u32Version != PDM_DRVREG_VERSION)
343 {
344 AssertMsgFailed(("Unknown struct version %#x!\n", pDrvReg->u32Version));
345 return VERR_PDM_UNKNOWN_DRVREG_VERSION;
346 }
347 if ( !pDrvReg->szDriverName[0]
348 || strlen(pDrvReg->szDriverName) >= sizeof(pDrvReg->szDriverName))
349 {
350 AssertMsgFailed(("Invalid name '%s'\n", pDrvReg->szDriverName));
351 return VERR_PDM_INVALID_DRIVER_REGISTRATION;
352 }
353 if ((pDrvReg->fFlags & PDM_DRVREG_FLAGS_HOST_BITS_MASK) != PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT)
354 {
355 AssertMsgFailed(("Invalid host bits flags! fFlags=%#x (Driver %s)\n", pDrvReg->fFlags, pDrvReg->szDriverName));
356 return VERR_PDM_INVALID_DRIVER_HOST_BITS;
357 }
358 if (pDrvReg->cMaxInstances <= 0)
359 {
360 AssertMsgFailed(("Max instances %u! (Driver %s)\n", pDrvReg->cMaxInstances, pDrvReg->szDriverName));
361 return VERR_PDM_INVALID_DRIVER_REGISTRATION;
362 }
363 if (pDrvReg->cbInstance > _1M)
364 {
365 AssertMsgFailed(("Instance size above 1MB, %d bytes! (Driver %s)\n", pDrvReg->cbInstance, pDrvReg->szDriverName));
366 return VERR_PDM_INVALID_DRIVER_REGISTRATION;
367 }
368 if (!pDrvReg->pfnConstruct)
369 {
370 AssertMsgFailed(("No constructore! (Driver %s)\n", pDrvReg->szDriverName));
371 return VERR_PDM_INVALID_DRIVER_REGISTRATION;
372 }
373
374 /*
375 * Check for duplicate and find FIFO entry at the same time.
376 */
377 PCPDMDRVREGCBINT pRegCB = (PCPDMDRVREGCBINT)pCallbacks;
378 PPDMDRV pDrvPrev = NULL;
379 PPDMDRV pDrv = pRegCB->pVM->pdm.s.pDrvs;
380 for (; pDrv; pDrvPrev = pDrv, pDrv = pDrv->pNext)
381 {
382 if (!strcmp(pDrv->pDrvReg->szDriverName, pDrvReg->szDriverName))
383 {
384 AssertMsgFailed(("Driver '%s' already exists\n", pDrvReg->szDriverName));
385 return VERR_PDM_DRIVER_NAME_CLASH;
386 }
387 }
388
389 /*
390 * Allocate new driver structure and insert it into the list.
391 */
392 pDrv = (PPDMDRV)MMR3HeapAlloc(pRegCB->pVM, MM_TAG_PDM_DRIVER, sizeof(*pDrv));
393 if (pDrv)
394 {
395 pDrv->pNext = NULL;
396 pDrv->cInstances = 0;
397 pDrv->pDrvReg = pDrvReg;
398
399 if (pDrvPrev)
400 pDrvPrev->pNext = pDrv;
401 else
402 pRegCB->pVM->pdm.s.pDrvs = pDrv;
403 Log(("PDM: Registered driver '%s'\n", pDrvReg->szDriverName));
404 return VINF_SUCCESS;
405 }
406 return VERR_NO_MEMORY;
407}
408
409
410/**
411 * Lookups a driver structure by name.
412 * @internal
413 */
414PPDMDRV pdmR3DrvLookup(PVM pVM, const char *pszName)
415{
416 for (PPDMDRV pDrv = pVM->pdm.s.pDrvs; pDrv; pDrv = pDrv->pNext)
417 if (!strcmp(pDrv->pDrvReg->szDriverName, pszName))
418 return pDrv;
419 return NULL;
420}
421
422
423/**
424 * Detaches a driver from whatever it's attached to.
425 * This will of course lead to the destruction of the driver and all drivers below it in the chain.
426 *
427 * @returns VINF_SUCCESS
428 * @param pDrvIns The driver instance to detach.
429 */
430int pdmR3DrvDetach(PPDMDRVINS pDrvIns)
431{
432 PDMDRV_ASSERT_DRVINS(pDrvIns);
433 LogFlow(("pdmR3DrvDetach: pDrvIns=%p '%s'/%d\n", pDrvIns, pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
434 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
435
436 /*
437 * Check that we're not doing this recursively, that could have unwanted sideeffects!
438 */
439 if (pDrvIns->Internal.s.fDetaching)
440 {
441 AssertMsgFailed(("Recursive detach! '%s'/%d\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
442 return VINF_SUCCESS;
443 }
444
445 /*
446 * Check that we actually can detach this instance.
447 * The requirement is that the driver/device above has a detach method.
448 */
449 if (pDrvIns->Internal.s.pUp
450 ? !pDrvIns->Internal.s.pUp->pDrvReg->pfnDetach
451 : !pDrvIns->Internal.s.pLun->pDevIns->pDevReg->pfnDetach)
452 {
453 AssertMsgFailed(("Cannot detach driver instance because the driver/device above doesn't support it!\n"));
454 return VERR_PDM_DRIVER_DETACH_NOT_POSSIBLE;
455 }
456
457 /*
458 * Join paths with pdmR3DrvDestroyChain.
459 */
460 pdmR3DrvDestroyChain(pDrvIns);
461 return VINF_SUCCESS;
462}
463
464
465/**
466 * Destroys a driver chain starting with the specified driver.
467 *
468 * This is used when unplugging a device at run time.
469 *
470 * @param pDrvIns Pointer to the driver instance to start with.
471 */
472void pdmR3DrvDestroyChain(PPDMDRVINS pDrvIns)
473{
474 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
475
476 /*
477 * Detach the bottommost driver until we've detached pDrvIns.
478 */
479 pDrvIns->Internal.s.fDetaching = true;
480 PPDMDRVINS pCur;
481 do
482 {
483 /* find the driver to detach. */
484 pCur = pDrvIns;
485 while (pCur->Internal.s.pDown)
486 pCur = pCur->Internal.s.pDown;
487 LogFlow(("pdmR3DrvDetach: pCur=%p '%s'/%d\n", pCur, pCur->pDrvReg->szDriverName, pCur->iInstance));
488
489 /*
490 * Unlink it and notify parent.
491 */
492 pCur->Internal.s.fDetaching = true;
493
494 PPDMLUN pLun = pCur->Internal.s.pLun;
495 Assert(pLun->pBottom == pCur);
496 pLun->pBottom = pCur->Internal.s.pUp;
497
498 if (pCur->Internal.s.pUp)
499 {
500 /* driver parent */
501 PPDMDRVINS pParent = pCur->Internal.s.pUp;
502 pCur->Internal.s.pUp = NULL;
503 pParent->Internal.s.pDown = NULL;
504
505 if (pParent->pDrvReg->pfnDetach)
506 pParent->pDrvReg->pfnDetach(pParent);
507
508 pParent->pDownBase = NULL;
509 }
510 else
511 {
512 /* device parent */
513 Assert(pLun->pTop == pCur);
514 pLun->pTop = NULL;
515 if (pLun->pDevIns->pDevReg->pfnDetach)
516 pLun->pDevIns->pDevReg->pfnDetach(pLun->pDevIns, pLun->iLun);
517 }
518
519 /*
520 * Call destructor.
521 */
522 pCur->pUpBase = NULL;
523 if (pCur->pDrvReg->pfnDestruct)
524 pCur->pDrvReg->pfnDestruct(pCur);
525
526 /*
527 * Free all resources allocated by the driver.
528 */
529 /* Queues. */
530 int rc = PDMR3QueueDestroyDriver(pCur->Internal.s.pVM, pCur);
531 AssertRC(rc);
532 /* Timers. */
533 rc = TMR3TimerDestroyDriver(pCur->Internal.s.pVM, pCur);
534 AssertRC(rc);
535 /* SSM data units. */
536 rc = SSMR3DeregisterDriver(pCur->Internal.s.pVM, pCur, NULL, 0);
537 AssertRC(rc);
538 /* PDM threads. */
539 rc = pdmR3ThreadDestroyDriver(pCur->Internal.s.pVM, pCur);
540 AssertRC(rc);
541 /* Finally, the driver it self. */
542 ASMMemFill32(pCur, RT_OFFSETOF(PDMDRVINS, achInstanceData[pCur->pDrvReg->cbInstance]), 0xdeadd0d0);
543 MMR3HeapFree(pCur);
544
545 } while (pCur != pDrvIns);
546}
547
548
549/** @copydoc PDMDRVHLP::pfnAttach */
550static DECLCALLBACK(int) pdmR3DrvHlp_Attach(PPDMDRVINS pDrvIns, PPDMIBASE *ppBaseInterface)
551{
552 PDMDRV_ASSERT_DRVINS(pDrvIns);
553 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
554 LogFlow(("pdmR3DrvHlp_Attach: caller='%s'/%d:\n",
555 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
556
557 /*
558 * Check that there isn't anything attached already.
559 */
560 int rc;
561 if (!pDrvIns->Internal.s.pDown)
562 {
563 Assert(pDrvIns->Internal.s.pLun->pBottom == pDrvIns);
564
565 /*
566 * Get the attached driver configuration.
567 */
568 PCFGMNODE pNode = CFGMR3GetChild(pDrvIns->Internal.s.pCfgHandle, "AttachedDriver");
569 if (pNode)
570 {
571 char *pszName;
572 rc = CFGMR3QueryStringAlloc(pNode, "Driver", &pszName);
573 if (VBOX_SUCCESS(rc))
574 {
575 /*
576 * Find the driver and allocate instance data.
577 */
578 PVM pVM = pDrvIns->Internal.s.pVM;
579 PPDMDRV pDrv = pdmR3DrvLookup(pVM, pszName);
580 if (pDrv)
581 {
582 /* config node */
583 PCFGMNODE pConfigNode = CFGMR3GetChild(pNode, "Config");
584 if (!pConfigNode)
585 rc = CFGMR3InsertNode(pNode, "Config", &pConfigNode);
586 if (VBOX_SUCCESS(rc))
587 {
588 CFGMR3SetRestrictedRoot(pConfigNode);
589
590 size_t cb = RT_OFFSETOF(PDMDRVINS, achInstanceData[pDrv->pDrvReg->cbInstance]);
591 cb = RT_ALIGN_Z(cb, 16);
592 PPDMDRVINS pNew = (PPDMDRVINS)MMR3HeapAllocZ(pVM, MM_TAG_PDM_DRIVER, cb);
593 if (pNew)
594 {
595 /*
596 * Initialize the instance structure (declaration order).
597 */
598 pNew->u32Version = PDM_DRVINS_VERSION;
599 pNew->Internal.s.pUp = pDrvIns;
600 pNew->Internal.s.pDown = NULL;
601 pNew->Internal.s.pLun = pDrvIns->Internal.s.pLun;
602 pNew->Internal.s.pDrv = pDrv;
603 pNew->Internal.s.pVM = pVM;
604 pNew->Internal.s.fDetaching = false;
605 pNew->Internal.s.pCfgHandle = pNode;
606 pNew->pDrvHlp = &g_pdmR3DrvHlp;
607 pNew->pDrvReg = pDrv->pDrvReg;
608 pNew->pCfgHandle = pConfigNode;
609 pNew->iInstance = pDrv->cInstances++;
610 pNew->pUpBase = &pDrvIns->IBase; /* This ain't safe, you can calc the pDrvIns of the up/down driver! */
611 pNew->pDownBase = NULL;
612 pNew->IBase.pfnQueryInterface = NULL;
613 pNew->pvInstanceData = &pNew->achInstanceData[0];
614
615 /*
616 * Hook it onto the chain and call the constructor.
617 */
618 pDrvIns->Internal.s.pDown = pNew;
619 pDrvIns->Internal.s.pLun->pBottom = pNew;
620
621 Log(("PDM: Constructing driver '%s' instance %d...\n", pNew->pDrvReg->szDriverName, pNew->iInstance));
622 rc = pDrv->pDrvReg->pfnConstruct(pNew, pNew->pCfgHandle);
623 if (VBOX_SUCCESS(rc))
624 {
625 *ppBaseInterface = &pNew->IBase;
626 rc = VINF_SUCCESS;
627 }
628 else
629 {
630 /*
631 * Unlink and free the data.
632 */
633 Assert(pDrvIns->Internal.s.pLun->pBottom == pNew);
634 pDrvIns->Internal.s.pLun->pBottom = pDrvIns;
635 pDrvIns->Internal.s.pDown = NULL;
636 ASMMemFill32(pNew, cb, 0xdeadd0d0);
637 MMR3HeapFree(pNew);
638 pDrv->cInstances--;
639 }
640 }
641 else
642 {
643 AssertMsgFailed(("Failed to allocate %d bytes for instantiating driver '%s'\n", cb, pszName));
644 rc = VERR_NO_MEMORY;
645 }
646 }
647 else
648 AssertMsgFailed(("Failed to create Config node! rc=%Vrc\n", rc));
649 }
650 else
651 {
652 AssertMsgFailed(("Driver '%s' wasn't found!\n", pszName));
653 rc = VERR_PDM_DRIVER_NOT_FOUND;
654 }
655 MMR3HeapFree(pszName);
656 }
657 else
658 {
659 AssertMsgFailed(("Query for string value of \"Driver\" -> %Vrc\n", rc));
660 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
661 rc = VERR_PDM_CFG_MISSING_DRIVER_NAME;
662 }
663 }
664 else
665 rc = VERR_PDM_NO_ATTACHED_DRIVER;
666 }
667 else
668 {
669 AssertMsgFailed(("Already got a driver attached. The driver should keep track of such things!\n"));
670 rc = VERR_PDM_DRIVER_ALREADY_ATTACHED;
671 }
672
673 LogFlow(("pdmR3DrvHlp_Attach: caller='%s'/%d: return %Vrc\n",
674 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
675 return rc;
676}
677
678
679/** @copydoc PDMDRVHLP::pfnDetach */
680static DECLCALLBACK(int) pdmR3DrvHlp_Detach(PPDMDRVINS pDrvIns)
681{
682 PDMDRV_ASSERT_DRVINS(pDrvIns);
683 LogFlow(("pdmR3DrvHlp_Detach: caller='%s'/%d:\n",
684 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
685 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
686
687 /*
688 * Anything attached?
689 */
690 int rc;
691 if (pDrvIns->Internal.s.pDown)
692 {
693 rc = pdmR3DrvDetach(pDrvIns->Internal.s.pDown);
694 }
695 else
696 {
697 AssertMsgFailed(("Nothing attached!\n"));
698 rc = VERR_PDM_NO_DRIVER_ATTACHED;
699 }
700
701 LogFlow(("pdmR3DrvHlp_Detach: caller='%s'/%d: returns %Vrc\n",
702 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
703 return rc;
704}
705
706
707/** @copydoc PDMDRVHLP::pfnDetachSelf */
708static DECLCALLBACK(int) pdmR3DrvHlp_DetachSelf(PPDMDRVINS pDrvIns)
709{
710 PDMDRV_ASSERT_DRVINS(pDrvIns);
711 LogFlow(("pdmR3DrvHlp_DetachSelf: caller='%s'/%d:\n",
712 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
713 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
714
715 int rc = pdmR3DrvDetach(pDrvIns);
716
717 LogFlow(("pdmR3DrvHlp_Detach: returns %Vrc\n", rc)); /* pDrvIns is freed by now. */
718 return rc;
719}
720
721
722/** @copydoc PDMDRVHLP::pfnMountPrepare */
723static DECLCALLBACK(int) pdmR3DrvHlp_MountPrepare(PPDMDRVINS pDrvIns, const char *pszFilename, const char *pszCoreDriver)
724{
725 PDMDRV_ASSERT_DRVINS(pDrvIns);
726 LogFlow(("pdmR3DrvHlp_MountPrepare: caller='%s'/%d: pszFilename=%p:{%s} pszCoreDriver=%p:{%s}\n",
727 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pszFilename, pszFilename, pszCoreDriver, pszCoreDriver));
728 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
729
730 /*
731 * Do the caller have anything attached below itself?
732 */
733 if (pDrvIns->Internal.s.pDown)
734 {
735 AssertMsgFailed(("Cannot prepare a mount when something's attached to you!\n"));
736 return VERR_PDM_DRIVER_ALREADY_ATTACHED;
737 }
738
739 /*
740 * We're asked to prepare, so we'll start off by nuking the
741 * attached configuration tree.
742 */
743 PCFGMNODE pNode = CFGMR3GetChild(pDrvIns->Internal.s.pCfgHandle, "AttachedDriver");
744 if (pNode)
745 CFGMR3RemoveNode(pNode);
746
747 /*
748 * If there is no core driver, we'll have to probe for it.
749 */
750 if (!pszCoreDriver)
751 {
752 /** @todo implement image probing. */
753 AssertReleaseMsgFailed(("Not implemented!\n"));
754 return VERR_NOT_IMPLEMENTED;
755 }
756
757 /*
758 * Construct the basic attached driver configuration.
759 */
760 int rc = CFGMR3InsertNode(pDrvIns->Internal.s.pCfgHandle, "AttachedDriver", &pNode);
761 if (VBOX_SUCCESS(rc))
762 {
763 rc = CFGMR3InsertString(pNode, "Driver", pszCoreDriver);
764 if (VBOX_SUCCESS(rc))
765 {
766 PCFGMNODE pCfg;
767 rc = CFGMR3InsertNode(pNode, "Config", &pCfg);
768 if (VBOX_SUCCESS(rc))
769 {
770 rc = CFGMR3InsertString(pCfg, "Path", pszFilename);
771 if (VBOX_SUCCESS(rc))
772 {
773 LogFlow(("pdmR3DrvHlp_MountPrepare: caller='%s'/%d: returns %Vrc (Driver=%s)\n",
774 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc, pszCoreDriver));
775 return rc;
776 }
777 else
778 AssertMsgFailed(("Path string insert failed, rc=%Vrc\n", rc));
779 }
780 else
781 AssertMsgFailed(("Config node failed, rc=%Vrc\n", rc));
782 }
783 else
784 AssertMsgFailed(("Driver string insert failed, rc=%Vrc\n", rc));
785 CFGMR3RemoveNode(pNode);
786 }
787 else
788 AssertMsgFailed(("AttachedDriver node insert failed, rc=%Vrc\n", rc));
789
790 LogFlow(("pdmR3DrvHlp_MountPrepare: caller='%s'/%d: returns %Vrc\n",
791 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
792 return rc;
793}
794
795
796/** @copydoc PDMDRVHLP::pfnAssertEMT */
797static DECLCALLBACK(bool) pdmR3DrvHlp_AssertEMT(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
798{
799 PDMDRV_ASSERT_DRVINS(pDrvIns);
800 if (VM_IS_EMT(pDrvIns->Internal.s.pVM))
801 return true;
802
803 char szMsg[100];
804 RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance);
805 AssertMsg1(szMsg, iLine, pszFile, pszFunction);
806 AssertBreakpoint();
807 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
808 return false;
809}
810
811
812/** @copydoc PDMDRVHLP::pfnAssertOther */
813static DECLCALLBACK(bool) pdmR3DrvHlp_AssertOther(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction)
814{
815 PDMDRV_ASSERT_DRVINS(pDrvIns);
816 if (!VM_IS_EMT(pDrvIns->Internal.s.pVM))
817 return true;
818
819 char szMsg[100];
820 RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance);
821 AssertMsg1(szMsg, iLine, pszFile, pszFunction);
822 AssertBreakpoint();
823 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
824 return false;
825}
826
827
828/** @copydoc PDMDRVHLP::pfnVMSetError */
829static DECLCALLBACK(int) pdmR3DrvHlp_VMSetError(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
830{
831 PDMDRV_ASSERT_DRVINS(pDrvIns);
832 va_list args;
833 va_start(args, pszFormat);
834 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVM, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
835 va_end(args);
836 return rc;
837}
838
839
840/** @copydoc PDMDRVHLP::pfnVMSetErrorV */
841static DECLCALLBACK(int) pdmR3DrvHlp_VMSetErrorV(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
842{
843 PDMDRV_ASSERT_DRVINS(pDrvIns);
844 int rc2 = VMSetErrorV(pDrvIns->Internal.s.pVM, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
845 return rc;
846}
847
848
849/** @copydoc PDMDRVHLP::pfnVMSetRuntimeError */
850static DECLCALLBACK(int) pdmR3DrvHlp_VMSetRuntimeError(PPDMDRVINS pDrvIns, bool fFatal, const char *pszErrorID, const char *pszFormat, ...)
851{
852 PDMDRV_ASSERT_DRVINS(pDrvIns);
853 va_list args;
854 va_start(args, pszFormat);
855 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVM, fFatal, pszErrorID, pszFormat, args);
856 va_end(args);
857 return rc;
858}
859
860
861/** @copydoc PDMDRVHLP::pfnVMSetRuntimeErrorV */
862static DECLCALLBACK(int) pdmR3DrvHlp_VMSetRuntimeErrorV(PPDMDRVINS pDrvIns, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list va)
863{
864 PDMDRV_ASSERT_DRVINS(pDrvIns);
865 int rc = VMSetRuntimeErrorV(pDrvIns->Internal.s.pVM, fFatal, pszErrorID, pszFormat, va);
866 return rc;
867}
868
869
870/** @copydoc PDMDRVHLP::pfnPDMQueueCreate */
871static DECLCALLBACK(int) pdmR3DrvHlp_PDMQueueCreate(PPDMDRVINS pDrvIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval, PFNPDMQUEUEDRV pfnCallback, PPDMQUEUE *ppQueue)
872{
873 PDMDRV_ASSERT_DRVINS(pDrvIns);
874 LogFlow(("pdmR3DrvHlp_PDMQueueCreate: caller='%s'/%d: cbItem=%d cItems=%d cMilliesInterval=%d pfnCallback=%p ppQueue=%p\n",
875 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, ppQueue, ppQueue));
876 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
877
878 int rc = PDMR3QueueCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, cbItem, cItems, cMilliesInterval, pfnCallback, ppQueue);
879
880 LogFlow(("pdmR3DrvHlp_PDMQueueCreate: caller='%s'/%d: returns %Vrc *ppQueue=%p\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc, *ppQueue));
881 return rc;
882}
883
884
885
886/** @copydoc PDMDRVHLP::pfnPDMPollerRegister */
887static DECLCALLBACK(int) pdmR3DrvHlp_PDMPollerRegister(PPDMDRVINS pDrvIns, PFNPDMDRVPOLLER pfnPoller)
888{
889 PDMDRV_ASSERT_DRVINS(pDrvIns);
890 LogFlow(("pdmR3DrvHlp_PDMPollerRegister: caller='%s'/%d: pfnPoller=%p\n",
891 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pfnPoller));
892 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
893
894 int rc = VINF_SUCCESS;
895 PVM pVM = pDrvIns->Internal.s.pVM;
896 if (pVM->pdm.s.cPollers < ELEMENTS(pVM->pdm.s.apfnPollers))
897 {
898 pVM->pdm.s.apfnPollers[pVM->pdm.s.cPollers] = pfnPoller;
899 pVM->pdm.s.aDrvInsPollers[pVM->pdm.s.cPollers] = pDrvIns;
900 pVM->pdm.s.cPollers++;
901 if (pVM->pdm.s.cPollers == 1)
902 TMTimerSetMillies(pVM->pdm.s.pTimerPollers, 5);
903 }
904 else
905 {
906 AssertMsgFailed(("Too many pollers!\n"));
907 rc = VERR_INTERNAL_ERROR;
908 }
909
910 LogFlow(("pdmR3DrvHlp_PDMPollerRegister: caller='%s'/%d: returns %Vrc\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
911 return rc;
912}
913
914
915/** @copydoc PDMDRVHLP::pfnTMGetVirtualFreq */
916static DECLCALLBACK(uint64_t) pdmR3DrvHlp_TMGetVirtualFreq(PPDMDRVINS pDrvIns)
917{
918 PDMDRV_ASSERT_DRVINS(pDrvIns);
919
920 return TMVirtualGetFreq(pDrvIns->Internal.s.pVM);
921}
922
923
924/** @copydoc PDMDRVHLP::pfnTMGetVirtualTime */
925static DECLCALLBACK(uint64_t) pdmR3DrvHlp_TMGetVirtualTime(PPDMDRVINS pDrvIns)
926{
927 PDMDRV_ASSERT_DRVINS(pDrvIns);
928
929 return TMVirtualGet(pDrvIns->Internal.s.pVM);
930}
931
932/** @copydoc PDMDRVHLP::pfnTMTimerCreate */
933static DECLCALLBACK(int) pdmR3DrvHlp_TMTimerCreate(PPDMDRVINS pDrvIns, TMCLOCK enmClock, PFNTMTIMERDRV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer)
934{
935 PDMDRV_ASSERT_DRVINS(pDrvIns);
936 LogFlow(("pdmR3DrvHlp_TMTimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pszDesc=%p:{%s} ppTimer=%p\n",
937 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, enmClock, pfnCallback, pszDesc, pszDesc, ppTimer));
938
939 int rc = TMR3TimerCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, enmClock, pfnCallback, pszDesc, ppTimer);
940
941 LogFlow(("pdmR3DrvHlp_TMTimerCreate: caller='%s'/%d: returns %Vrc *ppTimer=%p\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc, *ppTimer));
942 return rc;
943}
944
945
946
947/** @copydoc PDMDRVHLP::pfnSSMRegister */
948static DECLCALLBACK(int) pdmR3DrvHlp_SSMRegister(PPDMDRVINS pDrvIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
949 PFNSSMDRVSAVEPREP pfnSavePrep, PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVSAVEDONE pfnSaveDone,
950 PFNSSMDRVLOADPREP pfnLoadPrep, PFNSSMDRVLOADEXEC pfnLoadExec, PFNSSMDRVLOADDONE pfnLoadDone)
951{
952 PDMDRV_ASSERT_DRVINS(pDrvIns);
953 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
954 LogFlow(("pdmR3DrvHlp_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",
955 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pszName, pszName, u32Instance, u32Version, cbGuess, pfnSavePrep, pfnSaveExec, pfnSaveDone, pfnLoadPrep, pfnLoadExec, pfnLoadDone));
956
957 int rc = SSMR3RegisterDriver(pDrvIns->Internal.s.pVM, pDrvIns, pszName, u32Instance, u32Version, cbGuess,
958 pfnSavePrep, pfnSaveExec, pfnSaveDone,
959 pfnLoadPrep, pfnLoadExec, pfnLoadDone);
960
961 LogFlow(("pdmR3DrvHlp_SSMRegister: caller='%s'/%d: returns %Vrc\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
962 return rc;
963}
964
965
966/** @copydoc PDMDRVHLP::pfnSSMDeregister */
967static DECLCALLBACK(int) pdmR3DrvHlp_SSMDeregister(PPDMDRVINS pDrvIns, const char *pszName, uint32_t u32Instance)
968{
969 PDMDRV_ASSERT_DRVINS(pDrvIns);
970 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
971 LogFlow(("pdmR3DrvHlp_SSMDeregister: caller='%s'/%d: pszName=%p:{%s} u32Instance=%#x\n",
972 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pszName, pszName, u32Instance));
973
974 int rc = SSMR3DeregisterDriver(pDrvIns->Internal.s.pVM, pDrvIns, pszName, u32Instance);
975
976 LogFlow(("pdmR3DrvHlp_SSMDeregister: caller='%s'/%d: returns %Vrc\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
977 return rc;
978}
979
980
981/** @copydoc PDMDRVHLP::pfnSTAMRegister */
982static DECLCALLBACK(void) pdmR3DrvHlp_STAMRegister(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
983{
984 PDMDRV_ASSERT_DRVINS(pDrvIns);
985 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
986
987 STAM_REG(pDrvIns->Internal.s.pVM, pvSample, enmType, pszName, enmUnit, pszDesc);
988 /** @todo track the samples so they can be dumped & deregistered when the driver instance is destroyed.
989 * For now we just have to be careful not to use this call for drivers which can be unloaded. */
990}
991
992
993/** @copydoc PDMDRVHLP::pfnSTAMRegisterF */
994static DECLCALLBACK(void) pdmR3DrvHlp_STAMRegisterF(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
995 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...)
996{
997 PDMDRV_ASSERT_DRVINS(pDrvIns);
998 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
999
1000 va_list args;
1001 va_start(args, pszName);
1002 int rc = STAMR3RegisterV(pDrvIns->Internal.s.pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
1003 va_end(args);
1004 AssertRC(rc);
1005}
1006
1007
1008/** @copydoc PDMDRVHLP::pfnSTAMRegisterV */
1009static DECLCALLBACK(void) pdmR3DrvHlp_STAMRegisterV(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
1010 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args)
1011{
1012 PDMDRV_ASSERT_DRVINS(pDrvIns);
1013 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
1014
1015 int rc = STAMR3RegisterV(pDrvIns->Internal.s.pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
1016 AssertRC(rc);
1017}
1018
1019
1020/** @copydoc PDMDRVHLP::pfnSUPCallVMMR0Ex */
1021static DECLCALLBACK(int) pdmR3DrvHlp_SUPCallVMMR0Ex(PPDMDRVINS pDrvIns, unsigned uOperation, void *pvArg, unsigned cbArg)
1022{
1023 PDMDRV_ASSERT_DRVINS(pDrvIns);
1024 LogFlow(("pdmR3DrvHlp_SSMCallVMMR0Ex: caller='%s'/%d: uOperation=%u pvArg=%p cbArg=%d\n",
1025 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, uOperation, pvArg, cbArg));
1026 int rc;
1027 if ( uOperation >= VMMR0_DO_SRV_START
1028 && uOperation < VMMR0_DO_SRV_END)
1029 rc = SUPCallVMMR0Ex(pDrvIns->Internal.s.pVM->pVMR0, uOperation, 0, (PSUPVMMR0REQHDR)pvArg);
1030 else
1031 {
1032 AssertMsgFailed(("Invalid uOperation=%u\n", uOperation));
1033 rc = VERR_INVALID_PARAMETER;
1034 }
1035
1036 LogFlow(("pdmR3DrvHlp_SUPCallVMMR0Ex: caller='%s'/%d: returns %Vrc\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
1037 return rc;
1038}
1039
1040
1041/** @copydoc PDMDRVHLP::pfnUSBRegisterHub */
1042static DECLCALLBACK(int) pdmR3DrvHlp_USBRegisterHub(PPDMDRVINS pDrvIns, uint32_t fVersions, uint32_t cPorts, PCPDMUSBHUBREG pUsbHubReg, PPCPDMUSBHUBHLP ppUsbHubHlp)
1043{
1044 PDMDRV_ASSERT_DRVINS(pDrvIns);
1045 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
1046 LogFlow(("pdmR3DrvHlp_USBRegisterHub: caller='%s'/%d: fVersions=%#x cPorts=%#x pUsbHubReg=%p ppUsbHubHlp=%p\n",
1047 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, fVersions, cPorts, pUsbHubReg, ppUsbHubHlp));
1048
1049#ifdef VBOX_WITH_USB
1050 int rc = pdmR3UsbRegisterHub(pDrvIns->Internal.s.pVM, pDrvIns, fVersions, cPorts, pUsbHubReg, ppUsbHubHlp);
1051#else
1052 int rc = VERR_NOT_SUPPORTED;
1053#endif
1054
1055 LogFlow(("pdmR3DrvHlp_USBRegisterHub: caller='%s'/%d: returns %Vrc\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
1056 return rc;
1057}
1058
1059
1060/** @copydoc PDMDRVHLP::pfnPDMThreadCreate */
1061static DECLCALLBACK(int) pdmR3DrvHlp_PDMThreadCreate(PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
1062 PFNPDMTHREADWAKEUPDRV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
1063{
1064 PDMDRV_ASSERT_DRVINS(pDrvIns);
1065 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
1066 LogFlow(("pdmR3DrvHlp_PDMThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
1067 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
1068
1069 int rc = pdmR3ThreadCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
1070
1071 LogFlow(("pdmR3DrvHlp_PDMThreadCreate: caller='%s'/%d: returns %Vrc *ppThread=%RTthrd\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance,
1072 rc, *ppThread));
1073 return rc;
1074}
1075
1076#ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
1077static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
1078 PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc)
1079{
1080 PDMDRV_ASSERT_DRVINS(pDrvIns);
1081 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
1082 LogFlow(("pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate: caller='%s'/%d: ppTemplate=%p pfnCompleted=%p pszDesc=%p:{%s}\n",
1083 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, ppTemplate, pfnCompleted, pszDesc));
1084
1085 int rc = PDMR3AsyncCompletionTemplateCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, ppTemplate, pfnCompleted, pszDesc);
1086
1087 LogFlow(("pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate: caller='%s'/%d: returns %Vrc *ppThread=%p\n", pDrvIns->pDrvReg->szDriverName,
1088 pDrvIns->iInstance, rc, *ppTemplate));
1089 return rc;
1090}
1091#endif
1092
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