VirtualBox

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

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

tweaks

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