VirtualBox

source: vbox/trunk/src/VBox/VMM/PDM.cpp@ 7821

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

The new MMIO2 code.
WARNING! This changes the pci mapping protocol for MMIO2 so it's working the same way as I/O ports and normal MMIO memory. External users of the interface will have to update their mapping routines.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 39.8 KB
Line 
1/* $Id: PDM.cpp 7635 2008-03-28 17:15:38Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device Manager.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/** @page pg_pdm PDM - The Pluggable Device Manager
20 *
21 * VBox is designed to be very configurable, i.e. the ability to select
22 * virtual devices and configure them uniquely for a VM. For this reason
23 * virtual devices are not statically linked with the VMM but loaded and
24 * linked at runtime thru the Configuration Manager (CFGM). PDM will use
25 * CFGM to enumerate devices which needs loading and instantiation.
26 *
27 *
28 * @section sec_pdm_dev The Pluggable Device
29 *
30 * Devices register themselves when the module containing them is loaded.
31 * PDM will call an entry point 'VBoxDevicesRegister' when loading a device
32 * module. The device module will then use the supplied callback table to
33 * check the VMM version and to register its devices. Each device have an
34 * unique (for the configured VM) name (string). The name is not only used
35 * in PDM but in CFGM - to organize device and device instance settings - and
36 * by anyone who wants to do ioctls to the device.
37 *
38 * When all device modules have been successfully loaded PDM will instantiate
39 * those devices which are configured for the VM. Mark that this might mean
40 * creating several instances of some devices. When instantiating a device
41 * PDM provides device instance memory and a callback table with the VM APIs
42 * which the device instance is trusted with.
43 *
44 * Some devices are trusted devices, most are not. The trusted devices are
45 * an integrated part of the VM and can obtain the VM handle from their
46 * device instance handles, thus enabling them to call any VM api. Untrusted
47 * devices are can only use the callbacks provided during device
48 * instantiation.
49 *
50 * The guest context extention (optional) of a device is initialized as part
51 * of the GC init. A device marks in it's registration structure that it have
52 * a GC part, in which module and which name the entry point have. PDM will
53 * use its loader facilities to load this module into GC and to find the
54 * specified entry point.
55 *
56 * When writing a GC extention the programmer must keep in mind that this
57 * code will be relocated, so that using global/static pointer variables
58 * won't work.
59 *
60 *
61 * @section sec_pdm_drv The Pluggable Drivers
62 *
63 * The VM devices are often accessing host hardware or OS facilities. For
64 * most devices these facilities can be abstracted in one or more levels.
65 * These abstractions are called drivers.
66 *
67 * For instance take a DVD/CD drive. This can be connected to a SCSI
68 * controller, EIDE controller or SATA controller. The basics of the
69 * DVD/CD drive implementation remains the same - eject, insert,
70 * read, seek, and such. (For the scsi case, you might wanna speak SCSI
71 * directly to, but that can of course be fixed.) So, it makes much sense to
72 * have a generic CD/DVD driver which implements this.
73 *
74 * Then the media 'inserted' into the DVD/CD drive can be a ISO image, or
75 * it can be read from a real CD or DVD drive (there are probably other
76 * custom formats someone could desire to read or construct too). So, it
77 * would make sense to have abstracted interfaces for dealing with this
78 * in a generic way so the cdrom unit doesn't have to implement it all.
79 * Thus we have created the CDROM/DVD media driver family.
80 *
81 * So, for this example the IDE controller #1 (i.e. secondary) will have
82 * the DVD/CD Driver attached to it's LUN #0 (master). When a media is mounted
83 * the DVD/CD Driver will have a ISO, NativeCD, NativeDVD or RAW (media) Driver
84 * attached.
85 *
86 * It is possible to configure many levels of drivers inserting filters, loggers,
87 * or whatever you desire into the chain.
88 *
89 *
90 * @subsection sec_pdm_drv_interfaces Interfaces
91 *
92 * The pluggable drivers exposes one standard interface (callback table) which
93 * is used to construct, destruct, attach, detach, and query other interfaces.
94 * A device will query the interfaces required for it's operation during init
95 * and hotplug. PDM will query some interfaces during runtime mounting too.
96 *
97 * ... list interfaces ...
98 *
99 */
100
101
102/*******************************************************************************
103* Header Files *
104*******************************************************************************/
105#define LOG_GROUP LOG_GROUP_PDM
106#include "PDMInternal.h"
107#include <VBox/pdm.h>
108#include <VBox/mm.h>
109#include <VBox/pgm.h>
110#include <VBox/ssm.h>
111#include <VBox/vm.h>
112#include <VBox/uvm.h>
113#include <VBox/vmm.h>
114#include <VBox/param.h>
115#include <VBox/err.h>
116#include <VBox/sup.h>
117
118#include <VBox/log.h>
119#include <iprt/asm.h>
120#include <iprt/assert.h>
121#include <iprt/alloc.h>
122#include <iprt/ldr.h>
123#include <iprt/path.h>
124#include <iprt/string.h>
125
126
127/*******************************************************************************
128* Defined Constants And Macros *
129*******************************************************************************/
130/** The PDM saved state version. */
131#define PDM_SAVED_STATE_VERSION 3
132
133
134/*******************************************************************************
135* Internal Functions *
136*******************************************************************************/
137static DECLCALLBACK(int) pdmR3Save(PVM pVM, PSSMHANDLE pSSM);
138static DECLCALLBACK(int) pdmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
139static DECLCALLBACK(int) pdmR3LoadPrep(PVM pVM, PSSMHANDLE pSSM);
140static DECLCALLBACK(void) pdmR3PollerTimer(PVM pVM, PTMTIMER pTimer, void *pvUser);
141
142
143
144/**
145 * Initializes the PDM part of the UVM.
146 *
147 * This doesn't really do much right now but has to be here for the sake
148 * of completeness.
149 *
150 * @returns VBox status code.
151 * @param pUVM Pointer to the user mode VM structure.
152 */
153PDMR3DECL(int) PDMR3InitUVM(PUVM pUVM)
154{
155 AssertCompile(sizeof(pUVM->pdm.s) <= sizeof(pUVM->pdm.padding));
156 AssertRelease(sizeof(pUVM->pdm.s) <= sizeof(pUVM->pdm.padding));
157 pUVM->pdm.s.pModules = NULL;
158 return VINF_SUCCESS;
159}
160
161
162/**
163 * Initializes the PDM.
164 *
165 * @returns VBox status code.
166 * @param pVM The VM to operate on.
167 */
168PDMR3DECL(int) PDMR3Init(PVM pVM)
169{
170 LogFlow(("PDMR3Init\n"));
171
172 /*
173 * Assert alignment and sizes.
174 */
175 AssertRelease(!(RT_OFFSETOF(VM, pdm.s) & 31));
176 AssertRelease(sizeof(pVM->pdm.s) <= sizeof(pVM->pdm.padding));
177
178 /*
179 * Init the structure.
180 */
181 pVM->pdm.s.offVM = RT_OFFSETOF(VM, pdm.s);
182
183 int rc = TMR3TimerCreateInternal(pVM, TMCLOCK_VIRTUAL, pdmR3PollerTimer, NULL, "PDM Poller", &pVM->pdm.s.pTimerPollers);
184 AssertRC(rc);
185
186 /*
187 * Initialize sub compontents.
188 */
189 rc = pdmR3CritSectInit(pVM);
190 if (VBOX_SUCCESS(rc))
191 {
192#ifdef VBOX_WITH_PDM_LOCK
193 rc = PDMR3CritSectInit(pVM, &pVM->pdm.s.CritSect, "PDM");
194 if (VBOX_SUCCESS(rc))
195#endif
196 rc = pdmR3LdrInitU(pVM->pUVM);
197 if (VBOX_SUCCESS(rc))
198 {
199 rc = pdmR3DrvInit(pVM);
200 if (VBOX_SUCCESS(rc))
201 {
202 rc = pdmR3DevInit(pVM);
203 if (VBOX_SUCCESS(rc))
204 {
205#ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
206 rc = pdmR3AsyncCompletionInit(pVM);
207 if (VBOX_SUCCESS(rc))
208#endif
209 {
210 /*
211 * Register the saved state data unit.
212 */
213 rc = SSMR3RegisterInternal(pVM, "pdm", 1, PDM_SAVED_STATE_VERSION, 128,
214 NULL, pdmR3Save, NULL,
215 pdmR3LoadPrep, pdmR3Load, NULL);
216 if (VBOX_SUCCESS(rc))
217 {
218 LogFlow(("PDM: Successfully initialized\n"));
219 return rc;
220 }
221
222 }
223 }
224 }
225 }
226 }
227
228 /*
229 * Cleanup and return failure.
230 */
231 PDMR3Term(pVM);
232 LogFlow(("PDMR3Init: returns %Vrc\n", rc));
233 return rc;
234}
235
236
237/**
238 * Applies relocations to data and code managed by this
239 * component. This function will be called at init and
240 * whenever the VMM need to relocate it self inside the GC.
241 *
242 * @param pVM VM handle.
243 * @param offDelta Relocation delta relative to old location.
244 * @remark The loader subcomponent is relocated by PDMR3LdrRelocate() very
245 * early in the relocation phase.
246 */
247PDMR3DECL(void) PDMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
248{
249 LogFlow(("PDMR3Relocate\n"));
250
251 /*
252 * Queues.
253 */
254 pdmR3QueueRelocate(pVM, offDelta);
255 pVM->pdm.s.pDevHlpQueueGC = PDMQueueGCPtr(pVM->pdm.s.pDevHlpQueueHC);
256
257 /*
258 * Critical sections.
259 */
260 pdmR3CritSectRelocate(pVM);
261
262 /*
263 * The registered PIC.
264 */
265 if (pVM->pdm.s.Pic.pDevInsGC)
266 {
267 pVM->pdm.s.Pic.pDevInsGC += offDelta;
268 pVM->pdm.s.Pic.pfnSetIrqGC += offDelta;
269 pVM->pdm.s.Pic.pfnGetInterruptGC += offDelta;
270 }
271
272 /*
273 * The registered APIC.
274 */
275 if (pVM->pdm.s.Apic.pDevInsGC)
276 {
277 pVM->pdm.s.Apic.pDevInsGC += offDelta;
278 pVM->pdm.s.Apic.pfnGetInterruptGC += offDelta;
279 pVM->pdm.s.Apic.pfnSetBaseGC += offDelta;
280 pVM->pdm.s.Apic.pfnGetBaseGC += offDelta;
281 pVM->pdm.s.Apic.pfnSetTPRGC += offDelta;
282 pVM->pdm.s.Apic.pfnGetTPRGC += offDelta;
283 pVM->pdm.s.Apic.pfnBusDeliverGC += offDelta;
284 }
285
286 /*
287 * The registered I/O APIC.
288 */
289 if (pVM->pdm.s.IoApic.pDevInsGC)
290 {
291 pVM->pdm.s.IoApic.pDevInsGC += offDelta;
292 pVM->pdm.s.IoApic.pfnSetIrqGC += offDelta;
293 }
294
295 /*
296 * The register PCI Buses.
297 */
298 for (unsigned i = 0; i < ELEMENTS(pVM->pdm.s.aPciBuses); i++)
299 {
300 if (pVM->pdm.s.aPciBuses[i].pDevInsGC)
301 {
302 pVM->pdm.s.aPciBuses[i].pDevInsGC += offDelta;
303 pVM->pdm.s.aPciBuses[i].pfnSetIrqGC += offDelta;
304 }
305 }
306
307 /*
308 * Devices.
309 */
310 GCPTRTYPE(PCPDMDEVHLPGC) pDevHlpGC;
311 int rc = PDMR3GetSymbolGC(pVM, NULL, "g_pdmGCDevHlp", &pDevHlpGC);
312 AssertReleaseMsgRC(rc, ("rc=%Vrc when resolving g_pdmGCDevHlp\n", rc));
313 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextHC)
314 {
315 if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_GC)
316 {
317 pDevIns->pDevHlpGC = pDevHlpGC;
318 pDevIns->pvInstanceDataGC = MMHyperR3ToGC(pVM, pDevIns->pvInstanceDataR3);
319 pDevIns->pvInstanceDataR0 = MMHyperR3ToR0(pVM, pDevIns->pvInstanceDataR3);
320 pDevIns->Internal.s.pVMGC = pVM->pVMGC;
321 if (pDevIns->Internal.s.pPciBusHC)
322 pDevIns->Internal.s.pPciBusGC = MMHyperR3ToGC(pVM, pDevIns->Internal.s.pPciBusHC);
323 if (pDevIns->Internal.s.pPciDeviceHC)
324 pDevIns->Internal.s.pPciDeviceGC = MMHyperR3ToGC(pVM, pDevIns->Internal.s.pPciDeviceHC);
325 if (pDevIns->pDevReg->pfnRelocate)
326 {
327 LogFlow(("PDMR3Relocate: Relocating device '%s'/%d\n",
328 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
329 pDevIns->pDevReg->pfnRelocate(pDevIns, offDelta);
330 }
331 }
332 }
333}
334
335
336/**
337 * Worker for pdmR3Term that terminates a LUN chain.
338 *
339 * @param pVM Pointer to the shared VM structure.
340 * @param pLun The head of the chain.
341 * @param pszDevice The name of the device (for logging).
342 * @param iInstance The device instance number (for logging).
343 */
344static void pdmR3TermLuns(PVM pVM, PPDMLUN pLun, const char *pszDevice, unsigned iInstance)
345{
346 for (; pLun; pLun = pLun->pNext)
347 {
348 /*
349 * Destroy them one at a time from the bottom up.
350 * (The serial device/drivers depends on this - bad.)
351 */
352 PPDMDRVINS pDrvIns = pLun->pBottom;
353 pLun->pBottom = pLun->pTop = NULL;
354 while (pDrvIns)
355 {
356 PPDMDRVINS pDrvNext = pDrvIns->Internal.s.pUp;
357
358 if (pDrvIns->pDrvReg->pfnDestruct)
359 {
360 LogFlow(("pdmR3DevTerm: Destroying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
361 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pszDevice, iInstance));
362 pDrvIns->pDrvReg->pfnDestruct(pDrvIns);
363 }
364
365 TMR3TimerDestroyDriver(pVM, pDrvIns);
366 //PDMR3QueueDestroyDriver(pVM, pDrvIns);
367 //pdmR3ThreadDestroyDriver(pVM, pDrvIns);
368 SSMR3DeregisterDriver(pVM, pDrvIns, NULL, 0);
369
370 pDrvIns = pDrvNext;
371 }
372 }
373}
374
375
376/**
377 * Terminates the PDM.
378 *
379 * Termination means cleaning up and freeing all resources,
380 * the VM it self is at this point powered off or suspended.
381 *
382 * @returns VBox status code.
383 * @param pVM The VM to operate on.
384 */
385PDMR3DECL(int) PDMR3Term(PVM pVM)
386{
387 LogFlow(("PDMR3Term:\n"));
388 AssertMsg(pVM->pdm.s.offVM, ("bad init order!\n"));
389
390 /*
391 * Iterate the device instances and attach drivers, doing
392 * relevant destruction processing.
393 *
394 * N.B. There is no need to mess around freeing memory allocated
395 * from any MM heap since MM will do that in its Term function.
396 */
397 /* usb ones first. */
398 for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
399 {
400 pdmR3TermLuns(pVM, pUsbIns->Internal.s.pLuns, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance);
401
402 if (pUsbIns->pUsbReg->pfnDestruct)
403 {
404 LogFlow(("pdmR3DevTerm: Destroying - device '%s'/%d\n",
405 pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
406 pUsbIns->pUsbReg->pfnDestruct(pUsbIns);
407 }
408
409 //TMR3TimerDestroyUsb(pVM, pUsbIns);
410 //SSMR3DeregisterUsb(pVM, pUsbIns, NULL, 0);
411 pdmR3ThreadDestroyUsb(pVM, pUsbIns);
412 }
413
414 /* then the 'normal' ones. */
415 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextHC)
416 {
417 pdmR3TermLuns(pVM, pDevIns->Internal.s.pLunsHC, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
418
419 if (pDevIns->pDevReg->pfnDestruct)
420 {
421 LogFlow(("pdmR3DevTerm: Destroying - device '%s'/%d\n",
422 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
423 pDevIns->pDevReg->pfnDestruct(pDevIns);
424 }
425
426 TMR3TimerDestroyDevice(pVM, pDevIns);
427 //SSMR3DeregisterDriver(pVM, pDevIns, NULL, 0);
428 pdmR3CritSectDeleteDevice(pVM, pDevIns);
429 //pdmR3ThreadDestroyDevice(pVM, pDevIns);
430 //PDMR3QueueDestroyDevice(pVM, pDevIns);
431 PGMR3PhysMMIO2Deregister(pVM, pDevIns, UINT32_MAX);
432 }
433
434 /*
435 * Destroy all threads.
436 */
437 pdmR3ThreadDestroyAll(pVM);
438
439#ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
440 /*
441 * Free async completion managers.
442 */
443 pdmR3AsyncCompletionTerm(pVM);
444#endif
445
446 /*
447 * Free modules.
448 */
449 pdmR3LdrTermU(pVM->pUVM);
450
451#ifdef VBOX_WITH_PDM_LOCK
452 /*
453 * Destroy the PDM lock.
454 */
455 PDMR3CritSectDelete(&pVM->pdm.s.CritSect);
456#endif
457
458 LogFlow(("PDMR3Term: returns %Vrc\n", VINF_SUCCESS));
459 return VINF_SUCCESS;
460}
461
462
463/**
464 * Terminates the PDM part of the UVM.
465 *
466 * This will unload any modules left behind.
467 *
468 * @param pUVM Pointer to the user mode VM structure.
469 */
470PDMR3DECL(void) PDMR3TermUVM(PUVM pUVM)
471{
472 /*
473 * In the normal cause of events we will now call pdmR3LdrTermU for
474 * the second time. In the case of init failure however, this might
475 * the first time, which is why we do it.
476 */
477 pdmR3LdrTermU(pUVM);
478}
479
480
481
482
483
484/**
485 * Execute state save operation.
486 *
487 * @returns VBox status code.
488 * @param pVM VM Handle.
489 * @param pSSM SSM operation handle.
490 */
491static DECLCALLBACK(int) pdmR3Save(PVM pVM, PSSMHANDLE pSSM)
492{
493 LogFlow(("pdmR3Save:\n"));
494
495 /*
496 * Save interrupt and DMA states.
497 */
498 SSMR3PutUInt(pSSM, VM_FF_ISSET(pVM, VM_FF_INTERRUPT_APIC));
499 SSMR3PutUInt(pSSM, VM_FF_ISSET(pVM, VM_FF_INTERRUPT_PIC));
500 SSMR3PutUInt(pSSM, VM_FF_ISSET(pVM, VM_FF_PDM_DMA));
501
502 /*
503 * Save the list of device instances so we can check that
504 * they're all still there when we load the state and that
505 * nothing new have been added.
506 */
507 /** @todo We might have to filter out some device classes, like USB attached devices. */
508 uint32_t i = 0;
509 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextHC, i++)
510 {
511 SSMR3PutU32(pSSM, i);
512 SSMR3PutStrZ(pSSM, pDevIns->pDevReg->szDeviceName);
513 SSMR3PutU32(pSSM, pDevIns->iInstance);
514 }
515 return SSMR3PutU32(pSSM, ~0); /* terminator */
516}
517
518
519/**
520 * Prepare state load operation.
521 *
522 * This will dispatch pending operations and clear the FFs governed by PDM and its devices.
523 *
524 * @returns VBox status code.
525 * @param pVM The VM handle.
526 * @param pSSM The SSM handle.
527 */
528static DECLCALLBACK(int) pdmR3LoadPrep(PVM pVM, PSSMHANDLE pSSM)
529{
530 LogFlow(("pdmR3LoadPrep: %s%s%s%s\n",
531 VM_FF_ISSET(pVM, VM_FF_PDM_QUEUES) ? " VM_FF_PDM_QUEUES" : "",
532 VM_FF_ISSET(pVM, VM_FF_PDM_DMA) ? " VM_FF_PDM_DMA" : "",
533 VM_FF_ISSET(pVM, VM_FF_INTERRUPT_APIC) ? " VM_FF_INTERRUPT_APIC" : "",
534 VM_FF_ISSET(pVM, VM_FF_INTERRUPT_PIC) ? " VM_FF_INTERRUPT_PIC" : ""
535 ));
536
537 /*
538 * In case there is work pending that will raise an interrupt,
539 * start a DMA transfer, or release a lock. (unlikely)
540 */
541 if (VM_FF_ISSET(pVM, VM_FF_PDM_QUEUES))
542 PDMR3QueueFlushAll(pVM);
543
544 /* Clear the FFs. */
545 VM_FF_CLEAR(pVM, VM_FF_INTERRUPT_APIC);
546 VM_FF_CLEAR(pVM, VM_FF_INTERRUPT_PIC);
547 VM_FF_CLEAR(pVM, VM_FF_PDM_DMA);
548
549 return VINF_SUCCESS;
550}
551
552
553/**
554 * Execute state load operation.
555 *
556 * @returns VBox status code.
557 * @param pVM VM Handle.
558 * @param pSSM SSM operation handle.
559 * @param u32Version Data layout version.
560 */
561static DECLCALLBACK(int) pdmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version)
562{
563 LogFlow(("pdmR3Load:\n"));
564
565 /*
566 * Validate version.
567 */
568 if (u32Version != PDM_SAVED_STATE_VERSION)
569 {
570 Log(("pdmR3Load: Invalid version u32Version=%d!\n", u32Version));
571 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
572 }
573
574 /*
575 * Load the interrupt and DMA states.
576 */
577 /* APIC interrupt */
578 RTUINT fInterruptPending = 0;
579 int rc = SSMR3GetUInt(pSSM, &fInterruptPending);
580 if (VBOX_FAILURE(rc))
581 return rc;
582 if (fInterruptPending & ~1)
583 {
584 AssertMsgFailed(("fInterruptPending=%#x (APIC)\n", fInterruptPending));
585 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
586 }
587 AssertRelease(!VM_FF_ISSET(pVM, VM_FF_INTERRUPT_APIC));
588 if (fInterruptPending)
589 VM_FF_SET(pVM, VM_FF_INTERRUPT_APIC);
590
591 /* PIC interrupt */
592 fInterruptPending = 0;
593 rc = SSMR3GetUInt(pSSM, &fInterruptPending);
594 if (VBOX_FAILURE(rc))
595 return rc;
596 if (fInterruptPending & ~1)
597 {
598 AssertMsgFailed(("fInterruptPending=%#x (PIC)\n", fInterruptPending));
599 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
600 }
601 AssertRelease(!VM_FF_ISSET(pVM, VM_FF_INTERRUPT_PIC));
602 if (fInterruptPending)
603 VM_FF_SET(pVM, VM_FF_INTERRUPT_PIC);
604
605 /* DMA pending */
606 RTUINT fDMAPending = 0;
607 rc = SSMR3GetUInt(pSSM, &fDMAPending);
608 if (VBOX_FAILURE(rc))
609 return rc;
610 if (fDMAPending & ~1)
611 {
612 AssertMsgFailed(("fDMAPending=%#x\n", fDMAPending));
613 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
614 }
615 AssertRelease(!VM_FF_ISSET(pVM, VM_FF_PDM_DMA));
616 if (fDMAPending)
617 VM_FF_SET(pVM, VM_FF_PDM_DMA);
618
619 /*
620 * Load the list of devices and verify that they are all there.
621 *
622 * We boldly ASSUME that the order is fixed and that it's a good, this
623 * makes it way easier to validate...
624 */
625 uint32_t i = 0;
626 PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances;
627 for (;;pDevIns = pDevIns->Internal.s.pNextHC, i++)
628 {
629 /* Get the separator / terminator. */
630 uint32_t u32Sep;
631 int rc = SSMR3GetU32(pSSM, &u32Sep);
632 if (VBOX_FAILURE(rc))
633 return rc;
634 if (u32Sep == (uint32_t)~0)
635 break;
636 if (u32Sep != i)
637 AssertMsgFailedReturn(("Out of seqence. u32Sep=%#x i=%#x\n", u32Sep, i), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
638
639 /* get the name and instance number. */
640 char szDeviceName[sizeof(pDevIns->pDevReg->szDeviceName)];
641 rc = SSMR3GetStrZ(pSSM, szDeviceName, sizeof(szDeviceName));
642 if (VBOX_FAILURE(rc))
643 return rc;
644 RTUINT iInstance;
645 rc = SSMR3GetUInt(pSSM, &iInstance);
646 if (VBOX_FAILURE(rc))
647 return rc;
648
649 /* compare */
650 if (!pDevIns)
651 {
652 LogRel(("Device '%s'/%d not found in current config\n", szDeviceName, iInstance));
653 if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
654 AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH);
655 break;
656 }
657 if ( strcmp(szDeviceName, pDevIns->pDevReg->szDeviceName)
658 || pDevIns->iInstance != iInstance)
659 {
660 LogRel(("u32Sep=%d loaded '%s'/%d configured '%s'/%d\n",
661 u32Sep, szDeviceName, iInstance, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
662 if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
663 AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH);
664 }
665 }
666
667 /*
668 * Too many devices?
669 */
670 if (pDevIns)
671 {
672 LogRel(("Device '%s'/%d not found in saved state\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
673 if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
674 AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH);
675 }
676
677 return VINF_SUCCESS;
678}
679
680
681/**
682 * This function will notify all the devices and their
683 * attached drivers about the VM now being powered on.
684 *
685 * @param pVM VM Handle.
686 */
687PDMR3DECL(void) PDMR3PowerOn(PVM pVM)
688{
689 LogFlow(("PDMR3PowerOn:\n"));
690
691 /*
692 * Iterate the device instances.
693 * The attached drivers are processed first.
694 */
695 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextHC)
696 {
697 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsHC; pLun; pLun = pLun->pNext)
698 /** @todo Inverse the order here? */
699 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
700 if (pDrvIns->pDrvReg->pfnPowerOn)
701 {
702 LogFlow(("PDMR3PowerOn: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
703 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
704 pDrvIns->pDrvReg->pfnPowerOn(pDrvIns);
705 }
706
707 if (pDevIns->pDevReg->pfnPowerOn)
708 {
709 LogFlow(("PDMR3PowerOn: Notifying - device '%s'/%d\n",
710 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
711 pDevIns->pDevReg->pfnPowerOn(pDevIns);
712 }
713 }
714
715#ifdef VBOX_WITH_USB
716 for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
717 {
718 for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
719 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
720 if (pDrvIns->pDrvReg->pfnPowerOn)
721 {
722 LogFlow(("PDMR3PowerOn: Notifying - driver '%s'/%d on LUN#%d of usb device '%s'/%d\n",
723 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
724 pDrvIns->pDrvReg->pfnPowerOn(pDrvIns);
725 }
726
727 if (pUsbIns->pUsbReg->pfnVMPowerOn)
728 {
729 LogFlow(("PDMR3PowerOn: Notifying - device '%s'/%d\n",
730 pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
731 pUsbIns->pUsbReg->pfnVMPowerOn(pUsbIns);
732 }
733 }
734#endif
735
736 /*
737 * Resume all threads.
738 */
739 pdmR3ThreadResumeAll(pVM);
740
741 LogFlow(("PDMR3PowerOn: returns void\n"));
742}
743
744
745
746
747/**
748 * This function will notify all the devices and their
749 * attached drivers about the VM now being reset.
750 *
751 * @param pVM VM Handle.
752 */
753PDMR3DECL(void) PDMR3Reset(PVM pVM)
754{
755 LogFlow(("PDMR3Reset:\n"));
756
757 /*
758 * Clear all pending interrupts and DMA operations.
759 */
760 VM_FF_CLEAR(pVM, VM_FF_INTERRUPT_APIC);
761 VM_FF_CLEAR(pVM, VM_FF_INTERRUPT_PIC);
762 VM_FF_CLEAR(pVM, VM_FF_PDM_DMA);
763
764 /*
765 * Iterate the device instances.
766 * The attached drivers are processed first.
767 */
768 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextHC)
769 {
770 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsHC; pLun; pLun = pLun->pNext)
771 /** @todo Inverse the order here? */
772 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
773 if (pDrvIns->pDrvReg->pfnReset)
774 {
775 LogFlow(("PDMR3Reset: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
776 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
777 pDrvIns->pDrvReg->pfnReset(pDrvIns);
778 }
779
780 if (pDevIns->pDevReg->pfnReset)
781 {
782 LogFlow(("PDMR3Reset: Notifying - device '%s'/%d\n",
783 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
784 pDevIns->pDevReg->pfnReset(pDevIns);
785 }
786 }
787
788#ifdef VBOX_WITH_USB
789 for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
790 {
791 for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
792 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
793 if (pDrvIns->pDrvReg->pfnReset)
794 {
795 LogFlow(("PDMR3Reset: Notifying - driver '%s'/%d on LUN#%d of usb device '%s'/%d\n",
796 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
797 pDrvIns->pDrvReg->pfnReset(pDrvIns);
798 }
799
800 if (pUsbIns->pUsbReg->pfnVMReset)
801 {
802 LogFlow(("PDMR3Reset: Notifying - device '%s'/%d\n",
803 pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
804 pUsbIns->pUsbReg->pfnVMReset(pUsbIns);
805 }
806 }
807#endif
808
809 LogFlow(("PDMR3Reset: returns void\n"));
810}
811
812
813/**
814 * This function will notify all the devices and their
815 * attached drivers about the VM now being reset.
816 *
817 * @param pVM VM Handle.
818 */
819PDMR3DECL(void) PDMR3Suspend(PVM pVM)
820{
821 LogFlow(("PDMR3Suspend:\n"));
822
823 /*
824 * Iterate the device instances.
825 * The attached drivers are processed first.
826 */
827 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextHC)
828 {
829 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsHC; pLun; pLun = pLun->pNext)
830 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
831 if (pDrvIns->pDrvReg->pfnSuspend)
832 {
833 LogFlow(("PDMR3Suspend: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
834 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
835 pDrvIns->pDrvReg->pfnSuspend(pDrvIns);
836 }
837
838 if (pDevIns->pDevReg->pfnSuspend)
839 {
840 LogFlow(("PDMR3Suspend: Notifying - device '%s'/%d\n",
841 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
842 pDevIns->pDevReg->pfnSuspend(pDevIns);
843 }
844 }
845
846#ifdef VBOX_WITH_USB
847 for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
848 {
849 for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
850 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
851 if (pDrvIns->pDrvReg->pfnSuspend)
852 {
853 LogFlow(("PDMR3Suspend: Notifying - driver '%s'/%d on LUN#%d of usb device '%s'/%d\n",
854 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
855 pDrvIns->pDrvReg->pfnSuspend(pDrvIns);
856 }
857
858 if (pUsbIns->pUsbReg->pfnVMSuspend)
859 {
860 LogFlow(("PDMR3Suspend: Notifying - device '%s'/%d\n",
861 pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
862 pUsbIns->pUsbReg->pfnVMSuspend(pUsbIns);
863 }
864 }
865#endif
866
867 /*
868 * Suspend all threads.
869 */
870 pdmR3ThreadSuspendAll(pVM);
871
872 LogFlow(("PDMR3Suspend: returns void\n"));
873}
874
875
876/**
877 * This function will notify all the devices and their
878 * attached drivers about the VM now being resumed.
879 *
880 * @param pVM VM Handle.
881 */
882PDMR3DECL(void) PDMR3Resume(PVM pVM)
883{
884 LogFlow(("PDMR3Resume:\n"));
885
886 /*
887 * Iterate the device instances.
888 * The attached drivers are processed first.
889 */
890 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextHC)
891 {
892 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsHC; pLun; pLun = pLun->pNext)
893 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
894 if (pDrvIns->pDrvReg->pfnResume)
895 {
896 LogFlow(("PDMR3Resume: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
897 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
898 pDrvIns->pDrvReg->pfnResume(pDrvIns);
899 }
900
901 if (pDevIns->pDevReg->pfnResume)
902 {
903 LogFlow(("PDMR3Resume: Notifying - device '%s'/%d\n",
904 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
905 pDevIns->pDevReg->pfnResume(pDevIns);
906 }
907 }
908
909#ifdef VBOX_WITH_USB
910 for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
911 {
912 for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
913 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
914 if (pDrvIns->pDrvReg->pfnResume)
915 {
916 LogFlow(("PDMR3Resume: Notifying - driver '%s'/%d on LUN#%d of usb device '%s'/%d\n",
917 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
918 pDrvIns->pDrvReg->pfnResume(pDrvIns);
919 }
920
921 if (pUsbIns->pUsbReg->pfnVMResume)
922 {
923 LogFlow(("PDMR3Resume: Notifying - device '%s'/%d\n",
924 pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
925 pUsbIns->pUsbReg->pfnVMResume(pUsbIns);
926 }
927 }
928#endif
929
930 /*
931 * Resume all threads.
932 */
933 pdmR3ThreadResumeAll(pVM);
934
935 LogFlow(("PDMR3Resume: returns void\n"));
936}
937
938
939/**
940 * This function will notify all the devices and their
941 * attached drivers about the VM being powered off.
942 *
943 * @param pVM VM Handle.
944 */
945PDMR3DECL(void) PDMR3PowerOff(PVM pVM)
946{
947 LogFlow(("PDMR3PowerOff:\n"));
948
949 /*
950 * Iterate the device instances.
951 * The attached drivers are processed first.
952 */
953 for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextHC)
954 {
955 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsHC; pLun; pLun = pLun->pNext)
956 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
957 if (pDrvIns->pDrvReg->pfnPowerOff)
958 {
959 LogFlow(("PDMR3PowerOff: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
960 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
961 pDrvIns->pDrvReg->pfnPowerOff(pDrvIns);
962 }
963
964 if (pDevIns->pDevReg->pfnPowerOff)
965 {
966 LogFlow(("PDMR3PowerOff: Notifying - device '%s'/%d\n",
967 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
968 pDevIns->pDevReg->pfnPowerOff(pDevIns);
969 }
970 }
971
972#ifdef VBOX_WITH_USB
973 for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
974 {
975 for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
976 for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
977 if (pDrvIns->pDrvReg->pfnPowerOff)
978 {
979 LogFlow(("PDMR3PowerOff: Notifying - driver '%s'/%d on LUN#%d of usb device '%s'/%d\n",
980 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
981 pDrvIns->pDrvReg->pfnPowerOff(pDrvIns);
982 }
983
984 if (pUsbIns->pUsbReg->pfnVMPowerOff)
985 {
986 LogFlow(("PDMR3PowerOff: Notifying - device '%s'/%d\n",
987 pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
988 pUsbIns->pUsbReg->pfnVMPowerOff(pUsbIns);
989 }
990 }
991#endif
992
993 /*
994 * Suspend all threads.
995 */
996 pdmR3ThreadSuspendAll(pVM);
997
998 LogFlow(("PDMR3PowerOff: returns void\n"));
999}
1000
1001
1002/**
1003 * Queries the base interace of a device instance.
1004 *
1005 * The caller can use this to query other interfaces the device implements
1006 * and use them to talk to the device.
1007 *
1008 * @returns VBox status code.
1009 * @param pVM VM handle.
1010 * @param pszDevice Device name.
1011 * @param iInstance Device instance.
1012 * @param ppBase Where to store the pointer to the base device interface on success.
1013 * @remark We're not doing any locking ATM, so don't try call this at times when the
1014 * device chain is known to be updated.
1015 */
1016PDMR3DECL(int) PDMR3QueryDevice(PVM pVM, const char *pszDevice, unsigned iInstance, PPDMIBASE *ppBase)
1017{
1018 LogFlow(("PDMR3DeviceQuery: pszDevice=%p:{%s} iInstance=%u ppBase=%p\n", pszDevice, pszDevice, iInstance, ppBase));
1019
1020 /*
1021 * Iterate registered devices looking for the device.
1022 */
1023 RTUINT cchDevice = strlen(pszDevice);
1024 for (PPDMDEV pDev = pVM->pdm.s.pDevs; pDev; pDev = pDev->pNext)
1025 {
1026 if ( pDev->cchName == cchDevice
1027 && !memcmp(pDev->pDevReg->szDeviceName, pszDevice, cchDevice))
1028 {
1029 /*
1030 * Iterate device instances.
1031 */
1032 for (PPDMDEVINS pDevIns = pDev->pInstances; pDevIns; pDevIns = pDevIns->Internal.s.pPerDeviceNextHC)
1033 {
1034 if (pDevIns->iInstance == iInstance)
1035 {
1036 if (pDevIns->IBase.pfnQueryInterface)
1037 {
1038 *ppBase = &pDevIns->IBase;
1039 LogFlow(("PDMR3DeviceQuery: return VINF_SUCCESS and *ppBase=%p\n", *ppBase));
1040 return VINF_SUCCESS;
1041 }
1042
1043 LogFlow(("PDMR3DeviceQuery: returns VERR_PDM_DEVICE_INSTANCE_NO_IBASE\n"));
1044 return VERR_PDM_DEVICE_INSTANCE_NO_IBASE;
1045 }
1046 }
1047
1048 LogFlow(("PDMR3DeviceQuery: returns VERR_PDM_DEVICE_INSTANCE_NOT_FOUND\n"));
1049 return VERR_PDM_DEVICE_INSTANCE_NOT_FOUND;
1050 }
1051 }
1052
1053 LogFlow(("PDMR3QueryDevice: returns VERR_PDM_DEVICE_NOT_FOUND\n"));
1054 return VERR_PDM_DEVICE_NOT_FOUND;
1055}
1056
1057
1058/**
1059 * Queries the base interface of a device LUN.
1060 *
1061 * This differs from PDMR3QueryLun by that it returns the interface on the
1062 * device and not the top level driver.
1063 *
1064 * @returns VBox status code.
1065 * @param pVM VM Handle.
1066 * @param pszDevice Device name.
1067 * @param iInstance Device instance.
1068 * @param iLun The Logical Unit to obtain the interface of.
1069 * @param ppBase Where to store the base interface pointer.
1070 * @remark We're not doing any locking ATM, so don't try call this at times when the
1071 * device chain is known to be updated.
1072 */
1073PDMR3DECL(int) PDMR3QueryDeviceLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMIBASE *ppBase)
1074{
1075 LogFlow(("PDMR3QueryLun: pszDevice=%p:{%s} iInstance=%u iLun=%u ppBase=%p\n",
1076 pszDevice, pszDevice, iInstance, iLun, ppBase));
1077
1078 /*
1079 * Find the LUN.
1080 */
1081 PPDMLUN pLun;
1082 int rc = pdmR3DevFindLun(pVM, pszDevice, iInstance, iLun, &pLun);
1083 if (VBOX_SUCCESS(rc))
1084 {
1085 *ppBase = pLun->pBase;
1086 LogFlow(("PDMR3QueryDeviceLun: return VINF_SUCCESS and *ppBase=%p\n", *ppBase));
1087 return VINF_SUCCESS;
1088 }
1089 LogFlow(("PDMR3QueryDeviceLun: returns %Vrc\n", rc));
1090 return rc;
1091}
1092
1093
1094/**
1095 * Query the interface of the top level driver on a LUN.
1096 *
1097 * @returns VBox status code.
1098 * @param pVM VM Handle.
1099 * @param pszDevice Device name.
1100 * @param iInstance Device instance.
1101 * @param iLun The Logical Unit to obtain the interface of.
1102 * @param ppBase Where to store the base interface pointer.
1103 * @remark We're not doing any locking ATM, so don't try call this at times when the
1104 * device chain is known to be updated.
1105 */
1106PDMR3DECL(int) PDMR3QueryLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMIBASE *ppBase)
1107{
1108 LogFlow(("PDMR3QueryLun: pszDevice=%p:{%s} iInstance=%u iLun=%u ppBase=%p\n",
1109 pszDevice, pszDevice, iInstance, iLun, ppBase));
1110
1111 /*
1112 * Find the LUN.
1113 */
1114 PPDMLUN pLun;
1115 int rc = pdmR3DevFindLun(pVM, pszDevice, iInstance, iLun, &pLun);
1116 if (VBOX_SUCCESS(rc))
1117 {
1118 if (pLun->pTop)
1119 {
1120 *ppBase = &pLun->pTop->IBase;
1121 LogFlow(("PDMR3QueryLun: return %Vrc and *ppBase=%p\n", VINF_SUCCESS, *ppBase));
1122 return VINF_SUCCESS;
1123 }
1124 rc = VERR_PDM_NO_DRIVER_ATTACHED_TO_LUN;
1125 }
1126 LogFlow(("PDMR3QueryLun: returns %Vrc\n", rc));
1127 return rc;
1128}
1129
1130/**
1131 * Executes pending DMA transfers.
1132 * Forced Action handler.
1133 *
1134 * @param pVM VM handle.
1135 */
1136PDMR3DECL(void) PDMR3DmaRun(PVM pVM)
1137{
1138 VM_FF_CLEAR(pVM, VM_FF_PDM_DMA);
1139 if (pVM->pdm.s.pDmac)
1140 {
1141 bool fMore = pVM->pdm.s.pDmac->Reg.pfnRun(pVM->pdm.s.pDmac->pDevIns);
1142 if (fMore)
1143 VM_FF_SET(pVM, VM_FF_PDM_DMA);
1144 }
1145}
1146
1147
1148/**
1149 * Call polling function.
1150 *
1151 * @param pVM VM handle.
1152 */
1153PDMR3DECL(void) PDMR3Poll(PVM pVM)
1154{
1155 /* This is temporary hack and shall be removed ASAP! */
1156 unsigned iPoller = pVM->pdm.s.cPollers;
1157 if (iPoller)
1158 {
1159 while (iPoller-- > 0)
1160 pVM->pdm.s.apfnPollers[iPoller](pVM->pdm.s.aDrvInsPollers[iPoller]);
1161 TMTimerSetMillies(pVM->pdm.s.pTimerPollers, 3);
1162 }
1163}
1164
1165
1166/**
1167 * Internal timer callback function.
1168 *
1169 * @param pVM The VM.
1170 * @param pTimer The timer handle.
1171 * @param pvUser User argument specified upon timer creation.
1172 */
1173static DECLCALLBACK(void) pdmR3PollerTimer(PVM pVM, PTMTIMER pTimer, void *pvUser)
1174{
1175 PDMR3Poll(pVM);
1176}
1177
1178
1179/**
1180 * Serivce a VMMCALLHOST_PDM_LOCK call.
1181 *
1182 * @returns VBox status code.
1183 * @param pVM The VM handle.
1184 */
1185PDMR3DECL(int) PDMR3LockCall(PVM pVM)
1186{
1187 return pdmLockEx(pVM, VERR_INTERNAL_ERROR);
1188}
1189
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