VirtualBox

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

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