VirtualBox

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

Last change on this file since 11976 was 11311, checked in by vboxsync, 16 years ago

VMM: ELEMENTS -> RT_ELEMENTS.

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