VirtualBox

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

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

Redid the supdrv interface. works on windows and linux while the other OSes still needs some adjusting/testing. internal networking is temporarily broken as the SUPCallVMMR0Ex interface is being reworked (this is what all this is really about).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 40.2 KB
Line 
1/* $Id: PDMDriver.cpp 4800 2007-09-14 14:59:15Z 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, 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, 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, PPTMTIMERR3 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#if 0 /** @todo fix internal networking */
994 rc = SUPCallVMMR0Ex(pDrvIns->Internal.s.pVM->pVMR0, uOperation, pvArg, cbArg);
995#else
996{
997LogRel(("Sorry, internal networking is currently broken in the devlopment tree. Will be fixed in a bit, no time right now.\n"));
998rc = VERR_NOT_IMPLEMENTED;
999}
1000#endif
1001 else
1002 {
1003 AssertMsgFailed(("Invalid uOperation=%u\n", uOperation));
1004 rc = VERR_INVALID_PARAMETER;
1005 }
1006
1007 LogFlow(("pdmR3DrvHlp_SUPCallVMMR0Ex: caller='%s'/%d: returns %Vrc\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
1008 return rc;
1009}
1010
1011
1012/** @copydoc PDMDRVHLP::pfnUSBRegisterHub */
1013static DECLCALLBACK(int) pdmR3DrvHlp_USBRegisterHub(PPDMDRVINS pDrvIns, void *pvReservedIn, void **ppvReservedHlp)
1014{
1015 PDMDRV_ASSERT_DRVINS(pDrvIns);
1016 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
1017 LogFlow(("pdmR3DrvHlp_USBRegisterHub: caller='%s'/%d: pvReservedIn=%p ppvReservedHlp=%p\n",
1018 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pvReservedIn, ppvReservedHlp));
1019
1020/// @todo int rc = PDMUSBRegisterHub(pDrvIns->Internal.s.pVM, pvReservedIn, ppvReservedHlp);
1021 int rc = VINF_SUCCESS;
1022
1023 LogFlow(("pdmR3DrvHlp_USBRegisterHub: caller='%s'/%d: returns %Vrc\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
1024 return rc;
1025}
1026
1027
1028/** @copydoc PDMDRVHLP::pfnPDMThreadCreate */
1029static DECLCALLBACK(int) pdmR3DrvHlp_PDMThreadCreate(PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
1030 PFNPDMTHREADWAKEUPDRV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
1031{
1032 PDMDRV_ASSERT_DRVINS(pDrvIns);
1033 VM_ASSERT_EMT(pDrvIns->Internal.s.pVM);
1034 LogFlow(("pdmR3DrvHlp_PDMThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
1035 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
1036
1037 int rc = pdmR3ThreadCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
1038
1039 LogFlow(("pdmR3DrvHlp_PDMThreadCreate: caller='%s'/%d: returns %Vrc *ppThread=%RTthrd\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance,
1040 rc, *ppThread));
1041 return rc;
1042}
1043
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