VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxPci/VBoxPci.c@ 36400

Last change on this file since 36400 was 36400, checked in by vboxsync, 14 years ago

PCI: work on IOMMU notifications

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.4 KB
Line 
1/* $Id $ */
2/** @file
3 * VBoxPci - PCI card passthrough support (Host), Common Code.
4 */
5
6/*
7 * Copyright (C) 2011 Oracle Corporation
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/** @page pg_rawpci VBoxPci - host PCI support
19 *
20 * This is a kernel module that works as host proxy between guest and
21 * PCI hardware.
22 *
23 */
24
25#define LOG_GROUP LOG_GROUP_DEV_PCI_RAW
26#include <VBox/log.h>
27#include <VBox/err.h>
28#include <VBox/sup.h>
29#include <VBox/version.h>
30
31#include <iprt/string.h>
32#include <iprt/assert.h>
33#include <iprt/spinlock.h>
34#include <iprt/uuid.h>
35#include <iprt/asm.h>
36#include <iprt/mem.h>
37
38#include "VBoxPciInternal.h"
39
40
41#define DEVPORT_2_VBOXRAWPCIINS(pPort) \
42 ( (PVBOXRAWPCIINS)((uint8_t *)pPort - RT_OFFSETOF(VBOXRAWPCIINS, DevPort)) )
43
44
45/**
46 * Implements the SUPDRV component factor interface query method.
47 *
48 * @returns Pointer to an interface. NULL if not supported.
49 *
50 * @param pSupDrvFactory Pointer to the component factory registration structure.
51 * @param pSession The session - unused.
52 * @param pszInterfaceUuid The factory interface id.
53 */
54static DECLCALLBACK(void *) vboxPciQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid)
55{
56 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, SupDrvFactory));
57
58 /*
59 * Convert the UUID strings and compare them.
60 */
61 RTUUID UuidReq;
62 int rc = RTUuidFromStr(&UuidReq, pszInterfaceUuid);
63 if (RT_SUCCESS(rc))
64 {
65 if (!RTUuidCompareStr(&UuidReq, RAWPCIFACTORY_UUID_STR))
66 {
67 ASMAtomicIncS32(&pGlobals->cFactoryRefs);
68 return &pGlobals->RawPciFactory;
69 }
70 }
71 else
72 Log(("VBoxRawPci: rc=%Rrc, uuid=%s\n", rc, pszInterfaceUuid));
73
74 return NULL;
75}
76
77DECLINLINE(int) vboxPciDevLock(PVBOXRAWPCIINS pThis)
78{
79 int rc = RTSemFastMutexRequest(pThis->hFastMtx);
80 AssertRC(rc);
81 return rc;
82}
83
84DECLINLINE(void) vboxPciDevUnlock(PVBOXRAWPCIINS pThis)
85{
86 RTSemFastMutexRelease(pThis->hFastMtx);
87}
88
89DECLINLINE(int) vboxPciVmLock(PVBOXRAWPCIDRVVM pThis)
90{
91 int rc = RTSemFastMutexRequest(pThis->hFastMtx);
92 AssertRC(rc);
93 return rc;
94}
95
96DECLINLINE(void) vboxPciVmUnlock(PVBOXRAWPCIDRVVM pThis)
97{
98 RTSemFastMutexRelease(pThis->hFastMtx);
99}
100
101DECLINLINE(int) vboxPciGlobalsLock(PVBOXRAWPCIGLOBALS pGlobals)
102{
103 int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
104 AssertRC(rc);
105 return rc;
106}
107
108DECLINLINE(void) vboxPciGlobalsUnlock(PVBOXRAWPCIGLOBALS pGlobals)
109{
110 RTSemFastMutexRelease(pGlobals->hFastMtx);
111}
112
113static PVBOXRAWPCIINS vboxPciFindInstanceLocked(PVBOXRAWPCIGLOBALS pGlobals, uint32_t iHostAddress)
114{
115 PVBOXRAWPCIINS pCur;
116 for (pCur = pGlobals->pInstanceHead; pCur != NULL; pCur = pCur->pNext)
117 {
118 if (iHostAddress == pCur->HostPciAddress)
119 return pCur;
120 }
121 return NULL;
122}
123
124static void vboxPciUnlinkInstanceLocked(PVBOXRAWPCIGLOBALS pGlobals, PVBOXRAWPCIINS pToUnlink)
125{
126 if (pGlobals->pInstanceHead == pToUnlink)
127 pGlobals->pInstanceHead = pToUnlink->pNext;
128 else
129 {
130 PVBOXRAWPCIINS pCur;
131 for (pCur = pGlobals->pInstanceHead; pCur != NULL; pCur = pCur->pNext)
132 {
133 if (pCur->pNext == pToUnlink)
134 {
135 pCur->pNext = pToUnlink->pNext;
136 break;
137 }
138 }
139 }
140 pToUnlink->pNext = NULL;
141}
142
143
144DECLHIDDEN(void) vboxPciDevCleanup(PVBOXRAWPCIINS pThis)
145{
146 pThis->DevPort.pfnDeinit(&pThis->DevPort, 0);
147
148 if (pThis->hFastMtx)
149 {
150 RTSemFastMutexDestroy(pThis->hFastMtx);
151 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
152 }
153
154 if (pThis->hSpinlock)
155 {
156 RTSpinlockDestroy(pThis->hSpinlock);
157 pThis->hSpinlock = NIL_RTSPINLOCK;
158 }
159
160 vboxPciGlobalsLock(pThis->pGlobals);
161 vboxPciUnlinkInstanceLocked(pThis->pGlobals, pThis);
162 vboxPciGlobalsUnlock(pThis->pGlobals);
163}
164
165
166/**
167 * @copydoc RAWPCIDEVPORT:: pfnInit
168 */
169DECLHIDDEN(int) vboxPciDevInit(PRAWPCIDEVPORT pPort, uint32_t fFlags)
170{
171 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
172 int rc;
173
174 vboxPciDevLock(pThis);
175
176 rc = vboxPciOsDevInit(pThis, fFlags);
177
178 vboxPciDevUnlock(pThis);
179
180 return rc;
181}
182
183/**
184 * @copydoc RAWPCIDEVPORT:: pfnDeinit
185 */
186DECLHIDDEN(int) vboxPciDevDeinit(PRAWPCIDEVPORT pPort, uint32_t fFlags)
187{
188 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
189 int rc;
190
191 /* Bit racy, better check under lock. */
192 if (pThis->iHostIrq != -1)
193 {
194 pPort->pfnUnregisterIrqHandler(pPort, pThis->iHostIrq);
195 pThis->iHostIrq = -1;
196 }
197
198 vboxPciDevLock(pThis);
199
200 rc = vboxPciOsDevDeinit(pThis, fFlags);
201
202 vboxPciDevUnlock(pThis);
203
204 return rc;
205}
206
207
208/**
209 * @copydoc RAWPCIDEVPORT:: pfnDestroy
210 */
211DECLHIDDEN(int) vboxPciDevDestroy(PRAWPCIDEVPORT pPort)
212{
213 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
214 int rc;
215
216 rc = vboxPciOsDevDestroy(pThis);
217 if (rc == VINF_SUCCESS)
218 {
219 if (pThis->hFastMtx)
220 {
221 RTSemFastMutexDestroy(pThis->hFastMtx);
222 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
223 }
224
225 if (pThis->hSpinlock)
226 {
227 RTSpinlockDestroy(pThis->hSpinlock);
228 pThis->hSpinlock = NIL_RTSPINLOCK;
229 }
230
231 vboxPciGlobalsLock(pThis->pGlobals);
232 vboxPciUnlinkInstanceLocked(pThis->pGlobals, pThis);
233 vboxPciGlobalsUnlock(pThis->pGlobals);
234
235 RTMemFree(pThis);
236 }
237
238 return rc;
239}
240/**
241 * @copydoc RAWPCIDEVPORT:: pfnGetRegionInfo
242 */
243DECLHIDDEN(int) vboxPciDevGetRegionInfo(PRAWPCIDEVPORT pPort,
244 int32_t iRegion,
245 RTHCPHYS *pRegionStart,
246 uint64_t *pu64RegionSize,
247 bool *pfPresent,
248 uint32_t *pfFlags)
249{
250 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
251 int rc;
252
253 vboxPciDevLock(pThis);
254
255 rc = vboxPciOsDevGetRegionInfo(pThis, iRegion,
256 pRegionStart, pu64RegionSize,
257 pfPresent, pfFlags);
258 vboxPciDevUnlock(pThis);
259
260 return rc;
261}
262
263/**
264 * @copydoc RAWPCIDEVPORT:: pfnMapRegion
265 */
266DECLHIDDEN(int) vboxPciDevMapRegion(PRAWPCIDEVPORT pPort,
267 int32_t iRegion,
268 RTHCPHYS RegionStart,
269 uint64_t u64RegionSize,
270 int32_t fFlags,
271 RTR0PTR *pRegionBase)
272{
273 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
274 int rc;
275
276 vboxPciDevLock(pThis);
277
278 rc = vboxPciOsDevMapRegion(pThis, iRegion, RegionStart, u64RegionSize, fFlags, pRegionBase);
279
280 vboxPciDevUnlock(pThis);
281
282 return rc;
283}
284
285/**
286 * @copydoc RAWPCIDEVPORT:: pfnUnapRegion
287 */
288DECLHIDDEN(int) vboxPciDevUnmapRegion(PRAWPCIDEVPORT pPort,
289 int32_t iRegion,
290 RTHCPHYS RegionStart,
291 uint64_t u64RegionSize,
292 RTR0PTR RegionBase)
293{
294 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
295 int rc;
296
297 vboxPciDevLock(pThis);
298
299 rc = vboxPciOsDevUnmapRegion(pThis, iRegion, RegionStart, u64RegionSize, RegionBase);
300
301 vboxPciDevUnlock(pThis);
302
303 return rc;
304}
305
306/**
307 * @copydoc RAWPCIDEVPORT:: pfnPciCfgRead
308 */
309DECLHIDDEN(int) vboxPciDevPciCfgRead(PRAWPCIDEVPORT pPort, uint32_t Register, PCIRAWMEMLOC *pValue)
310{
311 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
312
313 int rc;
314
315 vboxPciDevLock(pThis);
316
317 rc = vboxPciOsDevPciCfgRead(pThis, Register, pValue);
318
319 vboxPciDevUnlock(pThis);
320
321 return rc;
322}
323
324/**
325 * @copydoc RAWPCIDEVPORT:: pfnPciCfgWrite
326 */
327DECLHIDDEN(int) vboxPciDevPciCfgWrite(PRAWPCIDEVPORT pPort, uint32_t Register, PCIRAWMEMLOC *pValue)
328{
329 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
330 int rc;
331
332 vboxPciDevLock(pThis);
333
334 rc = vboxPciOsDevPciCfgWrite(pThis, Register, pValue);
335
336 vboxPciDevUnlock(pThis);
337
338 return rc;
339}
340
341DECLHIDDEN(int) vboxPciDevRegisterIrqHandler(PRAWPCIDEVPORT pPort, PFNRAWPCIISR pfnHandler, void* pIrqContext, int32_t *piHostIrq)
342{
343 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
344 int rc;
345
346 vboxPciDevLock(pThis);
347
348 pThis->pfnIrqHandler = pfnHandler;
349 pThis->pIrqContext = pIrqContext;
350 rc = vboxPciOsDevRegisterIrqHandler(pThis, pfnHandler, pIrqContext, piHostIrq);
351 if (RT_FAILURE(rc))
352 {
353 pThis->pfnIrqHandler = NULL;
354 pThis->pIrqContext = NULL;
355 pThis->iHostIrq = -1;
356 *piHostIrq = -1;
357 }
358 else
359 pThis->iHostIrq = *piHostIrq;
360
361 vboxPciDevUnlock(pThis);
362
363 return rc;
364}
365
366DECLHIDDEN(int) vboxPciDevUnregisterIrqHandler(PRAWPCIDEVPORT pPort, int32_t iHostIrq)
367{
368 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
369 int rc;
370
371 vboxPciDevLock(pThis);
372
373 Assert(iHostIrq == pThis->iHostIrq);
374 rc = vboxPciOsDevUnregisterIrqHandler(pThis, iHostIrq);
375 if (RT_SUCCESS(rc))
376 {
377 pThis->pfnIrqHandler = NULL;
378 pThis->pIrqContext = NULL;
379 pThis->iHostIrq = -1;
380 }
381 vboxPciDevUnlock(pThis);
382
383 return rc;
384}
385
386DECLHIDDEN(int) vboxPciDevPowerStateChange(PRAWPCIDEVPORT pPort, PCIRAWPOWERSTATE aState)
387{
388 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
389 int rc;
390
391 vboxPciDevLock(pThis);
392
393 rc = vboxPciOsDevPowerStateChange(pThis, aState);
394
395 vboxPciDevUnlock(pThis);
396
397 return rc;
398}
399
400/**
401 * Creates a new instance.
402 *
403 * @returns VBox status code.
404 * @param pGlobals The globals.
405 * @param pszName The instance name.
406 * @param ppDevPort Where to store the pointer to our port interface.
407 */
408static int vboxPciNewInstance(PVBOXRAWPCIGLOBALS pGlobals,
409 uint32_t u32HostAddress,
410 uint32_t fFlags,
411 PRAWPCIVM pVmCtx,
412 PRAWPCIDEVPORT *ppDevPort)
413{
414 int rc;
415 PVBOXRAWPCIINS pNew = (PVBOXRAWPCIINS)RTMemAllocZ(sizeof(*pNew));
416 if (!pNew)
417 return VERR_NO_MEMORY;
418
419 pNew->pGlobals = pGlobals;
420 pNew->hSpinlock = NIL_RTSPINLOCK;
421 pNew->cRefs = 1;
422 pNew->pNext = NULL;
423 pNew->HostPciAddress = u32HostAddress;
424 pNew->iHostIrq = -1;
425 pNew->pVmCtx = pVmCtx;
426
427 pNew->DevPort.u32Version = RAWPCIDEVPORT_VERSION;
428
429 pNew->DevPort.pfnInit = vboxPciDevInit;
430 pNew->DevPort.pfnDeinit = vboxPciDevDeinit;
431 pNew->DevPort.pfnDestroy = vboxPciDevDestroy;
432 pNew->DevPort.pfnGetRegionInfo = vboxPciDevGetRegionInfo;
433 pNew->DevPort.pfnMapRegion = vboxPciDevMapRegion;
434 pNew->DevPort.pfnUnmapRegion = vboxPciDevUnmapRegion;
435 pNew->DevPort.pfnPciCfgRead = vboxPciDevPciCfgRead;
436 pNew->DevPort.pfnPciCfgWrite = vboxPciDevPciCfgWrite;
437 pNew->DevPort.pfnPciCfgRead = vboxPciDevPciCfgRead;
438 pNew->DevPort.pfnPciCfgWrite = vboxPciDevPciCfgWrite;
439 pNew->DevPort.pfnRegisterIrqHandler = vboxPciDevRegisterIrqHandler;
440 pNew->DevPort.pfnUnregisterIrqHandler = vboxPciDevUnregisterIrqHandler;
441 pNew->DevPort.pfnPowerStateChange = vboxPciDevPowerStateChange;
442 pNew->DevPort.u32VersionEnd = RAWPCIDEVPORT_VERSION;
443
444 rc = RTSpinlockCreate(&pNew->hSpinlock);
445
446 if (RT_SUCCESS(rc))
447 {
448 rc = RTSemFastMutexCreate(&pNew->hFastMtx);
449 if (RT_SUCCESS(rc))
450 {
451 rc = pNew->DevPort.pfnInit(&pNew->DevPort, fFlags);
452 if (RT_SUCCESS(rc))
453 {
454 *ppDevPort = &pNew->DevPort;
455
456 pNew->pNext = pGlobals->pInstanceHead;
457 pGlobals->pInstanceHead = pNew;
458 }
459 else
460 {
461 RTSemFastMutexDestroy(pNew->hFastMtx);
462 RTSpinlockDestroy(pNew->hSpinlock);
463 RTMemFree(pNew);
464 }
465 return rc;
466 }
467 }
468
469 return rc;
470}
471
472/**
473 * @copydoc RAWPCIFACTORY::pfnCreateAndConnect
474 */
475static DECLCALLBACK(int) vboxPciFactoryCreateAndConnect(PRAWPCIFACTORY pFactory,
476 uint32_t u32HostAddress,
477 uint32_t fFlags,
478 PRAWPCIVM pVmCtx,
479 PRAWPCIDEVPORT *ppDevPort)
480{
481 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
482 int rc;
483
484 LogFlow(("vboxPciFactoryCreateAndConnect: PCI=%x fFlags=%#x\n", u32HostAddress, fFlags));
485 Assert(pGlobals->cFactoryRefs > 0);
486 rc = vboxPciGlobalsLock(pGlobals);
487 AssertRCReturn(rc, rc);
488
489 /* First search if there's no existing instance with same host device
490 * address - if so - we cannot continue.
491 */
492 if (vboxPciFindInstanceLocked(pGlobals, u32HostAddress) != NULL)
493 {
494 rc = VERR_RESOURCE_BUSY;
495 goto unlock;
496 }
497
498 rc = vboxPciNewInstance(pGlobals, u32HostAddress, fFlags, pVmCtx, ppDevPort);
499
500unlock:
501 vboxPciGlobalsUnlock(pGlobals);
502
503 return rc;
504}
505
506/**
507 * @copydoc RAWPCIFACTORY::pfnRelease
508 */
509static DECLCALLBACK(void) vboxPciFactoryRelease(PRAWPCIFACTORY pFactory)
510{
511 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
512
513 int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
514 Assert(cRefs >= 0); NOREF(cRefs);
515 LogFlow(("vboxPciFactoryRelease: cRefs=%d (new)\n", cRefs));
516}
517
518/**
519 * @copydoc RAWPCIFACTORY::pfnInitVm
520 */
521static DECLCALLBACK(int) vboxPciFactoryInitVm(PRAWPCIFACTORY pFactory,
522 PVM pVM,
523 PRAWPCIVM pPciData)
524{
525 PVBOXRAWPCIDRVVM pThis = (PVBOXRAWPCIDRVVM)RTMemAllocZ(sizeof(VBOXRAWPCIDRVVM));
526 int rc;
527
528 if (!pThis)
529 return VERR_NO_MEMORY;
530
531 rc = RTSemFastMutexCreate(&pThis->hFastMtx);
532 if (RT_SUCCESS(rc))
533 {
534 rc = vboxPciOsInitVm(pThis, pVM);
535
536 if (RT_SUCCESS(rc))
537 {
538 pPciData->pDriverData = pThis;
539 return VINF_SUCCESS;
540 }
541
542 RTSemFastMutexDestroy(pThis->hFastMtx);
543 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
544 RTMemFree(pThis);
545 }
546
547 return rc;
548}
549
550/**
551 * @copydoc RAWPCIFACTORY::pfnDeinitVm
552 */
553static DECLCALLBACK(void) vboxPciFactoryDeinitVm(PRAWPCIFACTORY pFactory,
554 PVM pVM,
555 PRAWPCIVM pPciData)
556{
557 if (pPciData->pDriverData)
558 {
559 PVBOXRAWPCIDRVVM pThis = (PVBOXRAWPCIDRVVM)pPciData->pDriverData;
560
561 vboxPciOsDeinitVm(pThis, pVM);
562
563 if (pThis->hFastMtx)
564 {
565 RTSemFastMutexDestroy(pThis->hFastMtx);
566 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
567 }
568
569 RTMemFree(pThis);
570 pPciData->pDriverData = NULL;
571 }
572}
573
574
575static DECLHIDDEN(bool) vboxPciCanUnload(PVBOXRAWPCIGLOBALS pGlobals)
576{
577 int rc = vboxPciGlobalsLock(pGlobals);
578 bool fRc = !pGlobals->pInstanceHead
579 && pGlobals->cFactoryRefs <= 0;
580 vboxPciGlobalsUnlock(pGlobals);
581 AssertRC(rc);
582 return fRc;
583}
584
585
586static DECLHIDDEN(int) vboxPciInitIdc(PVBOXRAWPCIGLOBALS pGlobals)
587{
588 int rc;
589 Assert(!pGlobals->fIDCOpen);
590
591 /*
592 * Establish a connection to SUPDRV and register our component factory.
593 */
594 rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
595 if (RT_SUCCESS(rc))
596 {
597 rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
598 if (RT_SUCCESS(rc))
599 {
600 pGlobals->fIDCOpen = true;
601 Log(("VBoxRawPci: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
602 return rc;
603 }
604
605 /* bail out. */
606 LogRel(("VBoxRawPci: Failed to register component factory, rc=%Rrc\n", rc));
607 SUPR0IdcClose(&pGlobals->SupDrvIDC);
608 }
609
610 return rc;
611}
612
613/**
614 * Try to close the IDC connection to SUPDRV if established.
615 *
616 * @returns VBox status code.
617 * @retval VINF_SUCCESS on success.
618 * @retval VERR_WRONG_ORDER if we're busy.
619 *
620 * @param pGlobals Pointer to the globals.
621 */
622DECLHIDDEN(int) vboxPciDeleteIdc(PVBOXRAWPCIGLOBALS pGlobals)
623{
624 int rc;
625
626 Assert(pGlobals->hFastMtx != NIL_RTSEMFASTMUTEX);
627
628 /*
629 * Check before trying to deregister the factory.
630 */
631 if (!vboxPciCanUnload(pGlobals))
632 return VERR_WRONG_ORDER;
633
634 if (!pGlobals->fIDCOpen)
635 rc = VINF_SUCCESS;
636 else
637 {
638 /*
639 * Disconnect from SUPDRV.
640 */
641 rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
642 AssertRC(rc);
643 SUPR0IdcClose(&pGlobals->SupDrvIDC);
644 pGlobals->fIDCOpen = false;
645 }
646
647 return rc;
648}
649
650
651/**
652 * Initializes the globals.
653 *
654 * @returns VBox status code.
655 * @param pGlobals Pointer to the globals.
656 */
657DECLHIDDEN(int) vboxPciInitGlobals(PVBOXRAWPCIGLOBALS pGlobals)
658{
659 /*
660 * Initialize the common portions of the structure.
661 */
662 int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
663 if (RT_SUCCESS(rc))
664 {
665 pGlobals->pInstanceHead = NULL;
666 pGlobals->RawPciFactory.pfnRelease = vboxPciFactoryRelease;
667 pGlobals->RawPciFactory.pfnCreateAndConnect = vboxPciFactoryCreateAndConnect;
668 pGlobals->RawPciFactory.pfnInitVm = vboxPciFactoryInitVm;
669 pGlobals->RawPciFactory.pfnDeinitVm = vboxPciFactoryDeinitVm;
670 memcpy(pGlobals->SupDrvFactory.szName, "VBoxRawPci", sizeof("VBoxRawPci"));
671 pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxPciQueryFactoryInterface;
672 pGlobals->fIDCOpen = false;
673 }
674 return rc;
675}
676
677
678/**
679 * Deletes the globals.
680 *
681 *
682 * @param pGlobals Pointer to the globals.
683 */
684DECLHIDDEN(void) vboxPciDeleteGlobals(PVBOXRAWPCIGLOBALS pGlobals)
685{
686 Assert(!pGlobals->fIDCOpen);
687
688 /*
689 * Release resources.
690 */
691 if (pGlobals->hFastMtx)
692 {
693 RTSemFastMutexDestroy(pGlobals->hFastMtx);
694 pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;
695 }
696}
697
698
699int vboxPciInit(PVBOXRAWPCIGLOBALS pGlobals)
700{
701
702 /*
703 * Initialize the common portions of the structure.
704 */
705 int rc = vboxPciInitGlobals(pGlobals);
706 if (RT_SUCCESS(rc))
707 {
708 rc = vboxPciInitIdc(pGlobals);
709 if (RT_SUCCESS(rc))
710 return rc;
711
712 /* bail out. */
713 vboxPciDeleteGlobals(pGlobals);
714 }
715
716 return rc;
717}
718
719void vboxPciShutdown(PVBOXRAWPCIGLOBALS pGlobals)
720{
721 int rc = vboxPciDeleteIdc(pGlobals);
722
723 if (RT_SUCCESS(rc))
724 vboxPciDeleteGlobals(pGlobals);
725}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette