VirtualBox

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

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

PCI: fixed init-order issue

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.2 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, uint64_t *pu64Param)
387{
388 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
389 int rc;
390
391 vboxPciDevLock(pThis);
392
393 rc = vboxPciOsDevPowerStateChange(pThis, aState);
394
395 if (aState == PCIRAW_POWER_ON)
396 {
397 /*
398 * Let virtual device know about VM caps.
399 */
400 *pu64Param = VBOX_DRV_VMDATA(pThis)->pPerVmData->fVmCaps;
401 }
402 else
403 pu64Param = 0;
404
405
406 vboxPciDevUnlock(pThis);
407
408 return rc;
409}
410
411/**
412 * Creates a new instance.
413 *
414 * @returns VBox status code.
415 * @param pGlobals The globals.
416 * @param pszName The instance name.
417 * @param ppDevPort Where to store the pointer to our port interface.
418 */
419static int vboxPciNewInstance(PVBOXRAWPCIGLOBALS pGlobals,
420 uint32_t u32HostAddress,
421 uint32_t fFlags,
422 PRAWPCIPERVM pVmCtx,
423 PRAWPCIDEVPORT *ppDevPort,
424 uint32_t *pfDevFlags)
425{
426 int rc;
427 PVBOXRAWPCIINS pNew = (PVBOXRAWPCIINS)RTMemAllocZ(sizeof(*pNew));
428 if (!pNew)
429 return VERR_NO_MEMORY;
430
431 pNew->pGlobals = pGlobals;
432 pNew->hSpinlock = NIL_RTSPINLOCK;
433 pNew->cRefs = 1;
434 pNew->pNext = NULL;
435 pNew->HostPciAddress = u32HostAddress;
436 pNew->iHostIrq = -1;
437 pNew->pVmCtx = pVmCtx;
438
439 pNew->DevPort.u32Version = RAWPCIDEVPORT_VERSION;
440
441 pNew->DevPort.pfnInit = vboxPciDevInit;
442 pNew->DevPort.pfnDeinit = vboxPciDevDeinit;
443 pNew->DevPort.pfnDestroy = vboxPciDevDestroy;
444 pNew->DevPort.pfnGetRegionInfo = vboxPciDevGetRegionInfo;
445 pNew->DevPort.pfnMapRegion = vboxPciDevMapRegion;
446 pNew->DevPort.pfnUnmapRegion = vboxPciDevUnmapRegion;
447 pNew->DevPort.pfnPciCfgRead = vboxPciDevPciCfgRead;
448 pNew->DevPort.pfnPciCfgWrite = vboxPciDevPciCfgWrite;
449 pNew->DevPort.pfnPciCfgRead = vboxPciDevPciCfgRead;
450 pNew->DevPort.pfnPciCfgWrite = vboxPciDevPciCfgWrite;
451 pNew->DevPort.pfnRegisterIrqHandler = vboxPciDevRegisterIrqHandler;
452 pNew->DevPort.pfnUnregisterIrqHandler = vboxPciDevUnregisterIrqHandler;
453 pNew->DevPort.pfnPowerStateChange = vboxPciDevPowerStateChange;
454 pNew->DevPort.u32VersionEnd = RAWPCIDEVPORT_VERSION;
455
456 rc = RTSpinlockCreate(&pNew->hSpinlock);
457
458 if (RT_SUCCESS(rc))
459 {
460 rc = RTSemFastMutexCreate(&pNew->hFastMtx);
461 if (RT_SUCCESS(rc))
462 {
463 rc = pNew->DevPort.pfnInit(&pNew->DevPort, fFlags);
464 if (RT_SUCCESS(rc))
465 {
466 *ppDevPort = &pNew->DevPort;
467
468 pNew->pNext = pGlobals->pInstanceHead;
469 pGlobals->pInstanceHead = pNew;
470 }
471 else
472 {
473 RTSemFastMutexDestroy(pNew->hFastMtx);
474 RTSpinlockDestroy(pNew->hSpinlock);
475 RTMemFree(pNew);
476 }
477 return rc;
478 }
479 }
480
481 return rc;
482}
483
484/**
485 * @copydoc RAWPCIFACTORY::pfnCreateAndConnect
486 */
487static DECLCALLBACK(int) vboxPciFactoryCreateAndConnect(PRAWPCIFACTORY pFactory,
488 uint32_t u32HostAddress,
489 uint32_t fFlags,
490 PRAWPCIPERVM pVmCtx,
491 PRAWPCIDEVPORT *ppDevPort,
492 uint32_t *pfDevFlags)
493{
494 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
495 int rc;
496
497 LogFlow(("vboxPciFactoryCreateAndConnect: PCI=%x fFlags=%#x\n", u32HostAddress, fFlags));
498 Assert(pGlobals->cFactoryRefs > 0);
499 rc = vboxPciGlobalsLock(pGlobals);
500 AssertRCReturn(rc, rc);
501
502 /* First search if there's no existing instance with same host device
503 * address - if so - we cannot continue.
504 */
505 if (vboxPciFindInstanceLocked(pGlobals, u32HostAddress) != NULL)
506 {
507 rc = VERR_RESOURCE_BUSY;
508 goto unlock;
509 }
510
511 rc = vboxPciNewInstance(pGlobals, u32HostAddress, fFlags, pVmCtx, ppDevPort, pfDevFlags);
512
513unlock:
514 vboxPciGlobalsUnlock(pGlobals);
515
516 return rc;
517}
518
519/**
520 * @copydoc RAWPCIFACTORY::pfnRelease
521 */
522static DECLCALLBACK(void) vboxPciFactoryRelease(PRAWPCIFACTORY pFactory)
523{
524 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
525
526 int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
527 Assert(cRefs >= 0); NOREF(cRefs);
528 LogFlow(("vboxPciFactoryRelease: cRefs=%d (new)\n", cRefs));
529}
530
531/**
532 * @copydoc RAWPCIFACTORY::pfnInitVm
533 */
534static DECLCALLBACK(int) vboxPciFactoryInitVm(PRAWPCIFACTORY pFactory,
535 PVM pVM,
536 PRAWPCIPERVM pVmData)
537{
538 PVBOXRAWPCIDRVVM pThis = (PVBOXRAWPCIDRVVM)RTMemAllocZ(sizeof(VBOXRAWPCIDRVVM));
539 int rc;
540
541 if (!pThis)
542 return VERR_NO_MEMORY;
543
544 rc = RTSemFastMutexCreate(&pThis->hFastMtx);
545 if (RT_SUCCESS(rc))
546 {
547 rc = vboxPciOsInitVm(pThis, pVM, pVmData);
548
549 if (RT_SUCCESS(rc))
550 {
551#ifdef VBOX_WITH_IOMMU
552 /* If IOMMU notification routine in pVmData->pfnContigMemInfo
553 is set - we have functional IOMMU hardware. */
554 if (pVmData->pfnContigMemInfo)
555 pVmData->fVmCaps |= PCIRAW_VMFLAGS_HAS_IOMMU;
556#endif
557 pThis->pPerVmData = pVmData;
558 pVmData->pDriverData = pThis;
559 return VINF_SUCCESS;
560 }
561
562 RTSemFastMutexDestroy(pThis->hFastMtx);
563 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
564 RTMemFree(pThis);
565 }
566
567 return rc;
568}
569
570/**
571 * @copydoc RAWPCIFACTORY::pfnDeinitVm
572 */
573static DECLCALLBACK(void) vboxPciFactoryDeinitVm(PRAWPCIFACTORY pFactory,
574 PVM pVM,
575 PRAWPCIPERVM pPciData)
576{
577 if (pPciData->pDriverData)
578 {
579 PVBOXRAWPCIDRVVM pThis = (PVBOXRAWPCIDRVVM)pPciData->pDriverData;
580
581#ifdef VBOX_WITH_IOMMU
582 /* If we have IOMMU, need to unmap all guest's physical pages from IOMMU on VM termination. */
583#endif
584
585 vboxPciOsDeinitVm(pThis, pVM);
586
587 if (pThis->hFastMtx)
588 {
589 RTSemFastMutexDestroy(pThis->hFastMtx);
590 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
591 }
592
593 RTMemFree(pThis);
594 pPciData->pDriverData = NULL;
595 }
596}
597
598
599static DECLHIDDEN(bool) vboxPciCanUnload(PVBOXRAWPCIGLOBALS pGlobals)
600{
601 int rc = vboxPciGlobalsLock(pGlobals);
602 bool fRc = !pGlobals->pInstanceHead
603 && pGlobals->cFactoryRefs <= 0;
604 vboxPciGlobalsUnlock(pGlobals);
605 AssertRC(rc);
606 return fRc;
607}
608
609
610static DECLHIDDEN(int) vboxPciInitIdc(PVBOXRAWPCIGLOBALS pGlobals)
611{
612 int rc;
613 Assert(!pGlobals->fIDCOpen);
614
615 /*
616 * Establish a connection to SUPDRV and register our component factory.
617 */
618 rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
619 if (RT_SUCCESS(rc))
620 {
621 rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
622 if (RT_SUCCESS(rc))
623 {
624 pGlobals->fIDCOpen = true;
625 Log(("VBoxRawPci: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
626 return rc;
627 }
628
629 /* bail out. */
630 LogRel(("VBoxRawPci: Failed to register component factory, rc=%Rrc\n", rc));
631 SUPR0IdcClose(&pGlobals->SupDrvIDC);
632 }
633
634 return rc;
635}
636
637/**
638 * Try to close the IDC connection to SUPDRV if established.
639 *
640 * @returns VBox status code.
641 * @retval VINF_SUCCESS on success.
642 * @retval VERR_WRONG_ORDER if we're busy.
643 *
644 * @param pGlobals Pointer to the globals.
645 */
646DECLHIDDEN(int) vboxPciDeleteIdc(PVBOXRAWPCIGLOBALS pGlobals)
647{
648 int rc;
649
650 Assert(pGlobals->hFastMtx != NIL_RTSEMFASTMUTEX);
651
652 /*
653 * Check before trying to deregister the factory.
654 */
655 if (!vboxPciCanUnload(pGlobals))
656 return VERR_WRONG_ORDER;
657
658 if (!pGlobals->fIDCOpen)
659 rc = VINF_SUCCESS;
660 else
661 {
662 /*
663 * Disconnect from SUPDRV.
664 */
665 rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
666 AssertRC(rc);
667 SUPR0IdcClose(&pGlobals->SupDrvIDC);
668 pGlobals->fIDCOpen = false;
669 }
670
671 return rc;
672}
673
674
675/**
676 * Initializes the globals.
677 *
678 * @returns VBox status code.
679 * @param pGlobals Pointer to the globals.
680 */
681DECLHIDDEN(int) vboxPciInitGlobals(PVBOXRAWPCIGLOBALS pGlobals)
682{
683 /*
684 * Initialize the common portions of the structure.
685 */
686 int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
687 if (RT_SUCCESS(rc))
688 {
689 pGlobals->pInstanceHead = NULL;
690 pGlobals->RawPciFactory.pfnRelease = vboxPciFactoryRelease;
691 pGlobals->RawPciFactory.pfnCreateAndConnect = vboxPciFactoryCreateAndConnect;
692 pGlobals->RawPciFactory.pfnInitVm = vboxPciFactoryInitVm;
693 pGlobals->RawPciFactory.pfnDeinitVm = vboxPciFactoryDeinitVm;
694 memcpy(pGlobals->SupDrvFactory.szName, "VBoxRawPci", sizeof("VBoxRawPci"));
695 pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxPciQueryFactoryInterface;
696 pGlobals->fIDCOpen = false;
697 }
698 return rc;
699}
700
701
702/**
703 * Deletes the globals.
704 *
705 *
706 * @param pGlobals Pointer to the globals.
707 */
708DECLHIDDEN(void) vboxPciDeleteGlobals(PVBOXRAWPCIGLOBALS pGlobals)
709{
710 Assert(!pGlobals->fIDCOpen);
711
712 /*
713 * Release resources.
714 */
715 if (pGlobals->hFastMtx)
716 {
717 RTSemFastMutexDestroy(pGlobals->hFastMtx);
718 pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;
719 }
720}
721
722
723int vboxPciInit(PVBOXRAWPCIGLOBALS pGlobals)
724{
725
726 /*
727 * Initialize the common portions of the structure.
728 */
729 int rc = vboxPciInitGlobals(pGlobals);
730 if (RT_SUCCESS(rc))
731 {
732 rc = vboxPciInitIdc(pGlobals);
733 if (RT_SUCCESS(rc))
734 return rc;
735
736 /* bail out. */
737 vboxPciDeleteGlobals(pGlobals);
738 }
739
740 return rc;
741}
742
743void vboxPciShutdown(PVBOXRAWPCIGLOBALS pGlobals)
744{
745 int rc = vboxPciDeleteIdc(pGlobals);
746
747 if (RT_SUCCESS(rc))
748 vboxPciDeleteGlobals(pGlobals);
749}
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