VirtualBox

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

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

PCI: fully reworked interrupts, now HDA audio device can be reasonably passed to the guest

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.5 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 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 */
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, 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
373DECLHIDDEN(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
395DECLHIDDEN(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 return rc;
489 }
490 }
491
492 return rc;
493}
494
495/**
496 * @copydoc RAWPCIFACTORY::pfnCreateAndConnect
497 */
498static DECLCALLBACK(int) vboxPciFactoryCreateAndConnect(PRAWPCIFACTORY pFactory,
499 uint32_t u32HostAddress,
500 uint32_t fFlags,
501 PRAWPCIPERVM pVmCtx,
502 PRAWPCIDEVPORT *ppDevPort,
503 uint32_t *pfDevFlags)
504{
505 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
506 int rc;
507
508 LogFlow(("vboxPciFactoryCreateAndConnect: PCI=%x fFlags=%#x\n", u32HostAddress, fFlags));
509 Assert(pGlobals->cFactoryRefs > 0);
510 rc = vboxPciGlobalsLock(pGlobals);
511 AssertRCReturn(rc, rc);
512
513 /* First search if there's no existing instance with same host device
514 * address - if so - we cannot continue.
515 */
516 if (vboxPciFindInstanceLocked(pGlobals, u32HostAddress) != NULL)
517 {
518 rc = VERR_RESOURCE_BUSY;
519 goto unlock;
520 }
521
522 rc = vboxPciNewInstance(pGlobals, u32HostAddress, fFlags, pVmCtx, ppDevPort, pfDevFlags);
523
524unlock:
525 vboxPciGlobalsUnlock(pGlobals);
526
527 return rc;
528}
529
530/**
531 * @copydoc RAWPCIFACTORY::pfnRelease
532 */
533static DECLCALLBACK(void) vboxPciFactoryRelease(PRAWPCIFACTORY pFactory)
534{
535 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
536
537 int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
538 Assert(cRefs >= 0); NOREF(cRefs);
539 LogFlow(("vboxPciFactoryRelease: cRefs=%d (new)\n", cRefs));
540}
541
542/**
543 * @copydoc RAWPCIFACTORY::pfnInitVm
544 */
545static DECLCALLBACK(int) vboxPciFactoryInitVm(PRAWPCIFACTORY pFactory,
546 PVM pVM,
547 PRAWPCIPERVM pVmData)
548{
549 PVBOXRAWPCIDRVVM pThis = (PVBOXRAWPCIDRVVM)RTMemAllocZ(sizeof(VBOXRAWPCIDRVVM));
550 int rc;
551
552 if (!pThis)
553 return VERR_NO_MEMORY;
554
555 rc = RTSemFastMutexCreate(&pThis->hFastMtx);
556 if (RT_SUCCESS(rc))
557 {
558 rc = vboxPciOsInitVm(pThis, pVM, pVmData);
559
560 if (RT_SUCCESS(rc))
561 {
562#ifdef VBOX_WITH_IOMMU
563 /* If IOMMU notification routine in pVmData->pfnContigMemInfo
564 is set - we have functional IOMMU hardware. */
565 if (pVmData->pfnContigMemInfo)
566 pVmData->fVmCaps |= PCIRAW_VMFLAGS_HAS_IOMMU;
567#endif
568 pThis->pPerVmData = pVmData;
569 pVmData->pDriverData = pThis;
570 return VINF_SUCCESS;
571 }
572
573 RTSemFastMutexDestroy(pThis->hFastMtx);
574 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
575 RTMemFree(pThis);
576 }
577
578 return rc;
579}
580
581/**
582 * @copydoc RAWPCIFACTORY::pfnDeinitVm
583 */
584static DECLCALLBACK(void) vboxPciFactoryDeinitVm(PRAWPCIFACTORY pFactory,
585 PVM pVM,
586 PRAWPCIPERVM pPciData)
587{
588 if (pPciData->pDriverData)
589 {
590 PVBOXRAWPCIDRVVM pThis = (PVBOXRAWPCIDRVVM)pPciData->pDriverData;
591
592#ifdef VBOX_WITH_IOMMU
593 /* If we have IOMMU, need to unmap all guest's physical pages from IOMMU on VM termination. */
594#endif
595
596 vboxPciOsDeinitVm(pThis, pVM);
597
598 if (pThis->hFastMtx)
599 {
600 RTSemFastMutexDestroy(pThis->hFastMtx);
601 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
602 }
603
604 RTMemFree(pThis);
605 pPciData->pDriverData = NULL;
606 }
607}
608
609
610static DECLHIDDEN(bool) vboxPciCanUnload(PVBOXRAWPCIGLOBALS pGlobals)
611{
612 int rc = vboxPciGlobalsLock(pGlobals);
613 bool fRc = !pGlobals->pInstanceHead
614 && pGlobals->cFactoryRefs <= 0;
615 vboxPciGlobalsUnlock(pGlobals);
616 AssertRC(rc);
617 return fRc;
618}
619
620
621static DECLHIDDEN(int) vboxPciInitIdc(PVBOXRAWPCIGLOBALS pGlobals)
622{
623 int rc;
624 Assert(!pGlobals->fIDCOpen);
625
626 /*
627 * Establish a connection to SUPDRV and register our component factory.
628 */
629 rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
630 if (RT_SUCCESS(rc))
631 {
632 rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
633 if (RT_SUCCESS(rc))
634 {
635 pGlobals->fIDCOpen = true;
636 Log(("VBoxRawPci: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
637 return rc;
638 }
639
640 /* bail out. */
641 LogRel(("VBoxRawPci: Failed to register component factory, rc=%Rrc\n", rc));
642 SUPR0IdcClose(&pGlobals->SupDrvIDC);
643 }
644
645 return rc;
646}
647
648/**
649 * Try to close the IDC connection to SUPDRV if established.
650 *
651 * @returns VBox status code.
652 * @retval VINF_SUCCESS on success.
653 * @retval VERR_WRONG_ORDER if we're busy.
654 *
655 * @param pGlobals Pointer to the globals.
656 */
657DECLHIDDEN(int) vboxPciDeleteIdc(PVBOXRAWPCIGLOBALS pGlobals)
658{
659 int rc;
660
661 Assert(pGlobals->hFastMtx != NIL_RTSEMFASTMUTEX);
662
663 /*
664 * Check before trying to deregister the factory.
665 */
666 if (!vboxPciCanUnload(pGlobals))
667 return VERR_WRONG_ORDER;
668
669 if (!pGlobals->fIDCOpen)
670 rc = VINF_SUCCESS;
671 else
672 {
673 /*
674 * Disconnect from SUPDRV.
675 */
676 rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
677 AssertRC(rc);
678 SUPR0IdcClose(&pGlobals->SupDrvIDC);
679 pGlobals->fIDCOpen = false;
680 }
681
682 return rc;
683}
684
685
686/**
687 * Initializes the globals.
688 *
689 * @returns VBox status code.
690 * @param pGlobals Pointer to the globals.
691 */
692DECLHIDDEN(int) vboxPciInitGlobals(PVBOXRAWPCIGLOBALS pGlobals)
693{
694 /*
695 * Initialize the common portions of the structure.
696 */
697 int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
698 if (RT_SUCCESS(rc))
699 {
700 pGlobals->pInstanceHead = NULL;
701 pGlobals->RawPciFactory.pfnRelease = vboxPciFactoryRelease;
702 pGlobals->RawPciFactory.pfnCreateAndConnect = vboxPciFactoryCreateAndConnect;
703 pGlobals->RawPciFactory.pfnInitVm = vboxPciFactoryInitVm;
704 pGlobals->RawPciFactory.pfnDeinitVm = vboxPciFactoryDeinitVm;
705 memcpy(pGlobals->SupDrvFactory.szName, "VBoxRawPci", sizeof("VBoxRawPci"));
706 pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxPciQueryFactoryInterface;
707 pGlobals->fIDCOpen = false;
708 }
709 return rc;
710}
711
712
713/**
714 * Deletes the globals.
715 *
716 *
717 * @param pGlobals Pointer to the globals.
718 */
719DECLHIDDEN(void) vboxPciDeleteGlobals(PVBOXRAWPCIGLOBALS pGlobals)
720{
721 Assert(!pGlobals->fIDCOpen);
722
723 /*
724 * Release resources.
725 */
726 if (pGlobals->hFastMtx)
727 {
728 RTSemFastMutexDestroy(pGlobals->hFastMtx);
729 pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;
730 }
731}
732
733
734int vboxPciInit(PVBOXRAWPCIGLOBALS pGlobals)
735{
736
737 /*
738 * Initialize the common portions of the structure.
739 */
740 int rc = vboxPciInitGlobals(pGlobals);
741 if (RT_SUCCESS(rc))
742 {
743 rc = vboxPciInitIdc(pGlobals);
744 if (RT_SUCCESS(rc))
745 return rc;
746
747 /* bail out. */
748 vboxPciDeleteGlobals(pGlobals);
749 }
750
751 return rc;
752}
753
754void vboxPciShutdown(PVBOXRAWPCIGLOBALS pGlobals)
755{
756 int rc = vboxPciDeleteIdc(pGlobals);
757
758 if (RT_SUCCESS(rc))
759 vboxPciDeleteGlobals(pGlobals);
760}
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