VBoxPci.c revision 1fff175c9a0fea173ee52a209224dc6ecbd39572
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * VBoxPci - PCI card passthrough support (Host), Common Code.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * Copyright (C) 2011 Oracle Corporation
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * available from http://www.virtualbox.org. This file is free software;
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * you can redistribute it and/or modify it under the terms of the GNU
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * General Public License (GPL) as published by the Free Software
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync/** @page pg_rawpci VBoxPci - host PCI support
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * This is a kernel module that works as host proxy between guest and
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * PCI hardware.
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync ( (PVBOXRAWPCIINS)((uint8_t *)pPort - RT_OFFSETOF(VBOXRAWPCIINS, DevPort)) )
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync * Implements the SUPDRV component factor interface query method.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * @returns Pointer to an interface. NULL if not supported.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * @param pSupDrvFactory Pointer to the component factory registration structure.
5c1381fc884d30a749517579368ff6cb4b43e809vboxsync * @param pSession The session - unused.
5c1381fc884d30a749517579368ff6cb4b43e809vboxsync * @param pszInterfaceUuid The factory interface id.
1df297ea8319f3f3afddb73e6ea2fd9c7f0e5eb4vboxsyncstatic DECLCALLBACK(void *) vboxPciQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid)
5c1381fc884d30a749517579368ff6cb4b43e809vboxsync PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, SupDrvFactory));
5c1381fc884d30a749517579368ff6cb4b43e809vboxsync * Convert the UUID strings and compare them.
3fd65c821ad93f378baf8c75b30dcb6a17a5dd77vboxsync int rc = RTUuidFromStr(&UuidReq, pszInterfaceUuid);
2a560b28131ee7efa5b73a9e9cbfdb08eae28624vboxsync if (!RTUuidCompareStr(&UuidReq, RAWPCIFACTORY_UUID_STR))
3fd65c821ad93f378baf8c75b30dcb6a17a5dd77vboxsync Log(("VBoxRawPci: rc=%Rrc, uuid=%s\n", rc, pszInterfaceUuid));
3fd65c821ad93f378baf8c75b30dcb6a17a5dd77vboxsync * @copydoc RAWPCIDEVPORT:: pfnRetain
3fd65c821ad93f378baf8c75b30dcb6a17a5dd77vboxsyncDECLHIDDEN(void) vboxPciDevRetain(PRAWPCIDEVPORT pPort)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync * @copydoc RAWPCIDEVPORT:: pfnRelease
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsyncDECLHIDDEN(void) vboxPciDevRelease(PRAWPCIDEVPORT pPort)
e3e8bde164b5715114ebf596187b5512fa9b75advboxsync * @copydoc RAWPCIDEVPORT:: pfnInit
2a560b28131ee7efa5b73a9e9cbfdb08eae28624vboxsyncDECLHIDDEN(int) vboxPciDevInit(PRAWPCIDEVPORT pPort, uint32_t fFlags)
5e5603ae40c7a0a884fe91e269b7d6d6c0ba56f5vboxsync PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync * @copydoc RAWPCIDEVPORT:: pfnDeinit
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsyncDECLHIDDEN(int) vboxPciDevDeinit(PRAWPCIDEVPORT pPort, uint32_t fFlags)
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync * @copydoc RAWPCIDEVPORT:: pfnGetRegionInfo
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsyncDECLHIDDEN(int) vboxPciDevGetRegionInfo(PRAWPCIDEVPORT pPort,
6a5bc4dc98789eb202e249b189f036e5ff9129ccvboxsync PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsync * @copydoc RAWPCIDEVPORT:: pfnMapRegion
ab7139411cba3600213877c953b69fc11a7ef0cfvboxsyncDECLHIDDEN(int) vboxPciDevMapRegion(PRAWPCIDEVPORT pPort,
04bce18d27791abed8346aba0de41c53a2acd81avboxsync PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
04bce18d27791abed8346aba0de41c53a2acd81avboxsync int rc = vboxPciOsDevMapRegion(pThis, iRegion, RegionStart, u64RegionSize, fFlags, pRegionBase);
2a560b28131ee7efa5b73a9e9cbfdb08eae28624vboxsync * @copydoc RAWPCIDEVPORT:: pfnUnapRegion
2a560b28131ee7efa5b73a9e9cbfdb08eae28624vboxsyncDECLHIDDEN(int) vboxPciDevUnmapRegion(PRAWPCIDEVPORT pPort,
e3e8bde164b5715114ebf596187b5512fa9b75advboxsync PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
e3e8bde164b5715114ebf596187b5512fa9b75advboxsync int rc = vboxPciOsDevUnmapRegion(pThis, iRegion, RegionStart, u64RegionSize, RegionBase);
e3e8bde164b5715114ebf596187b5512fa9b75advboxsync * @copydoc RAWPCIDEVPORT:: pfnPciCfgRead
e3e8bde164b5715114ebf596187b5512fa9b75advboxsyncDECLHIDDEN(int) vboxPciDevPciCfgRead(PRAWPCIDEVPORT pPort, uint32_t Register, PCIRAWMEMLOC *pValue)
e3e8bde164b5715114ebf596187b5512fa9b75advboxsync PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
04bce18d27791abed8346aba0de41c53a2acd81avboxsync rc = vboxPciOsDevPciCfgRead(pThis, Register, pValue);
e3e8bde164b5715114ebf596187b5512fa9b75advboxsync * @copydoc RAWPCIDEVPORT:: pfnPciCfgWrite
e3e8bde164b5715114ebf596187b5512fa9b75advboxsyncDECLHIDDEN(int) vboxPciDevPciCfgWrite(PRAWPCIDEVPORT pPort, uint32_t Register, PCIRAWMEMLOC *pValue)
e3e8bde164b5715114ebf596187b5512fa9b75advboxsync PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
e3e8bde164b5715114ebf596187b5512fa9b75advboxsync int rc = vboxPciOsDevPciCfgWrite(pThis, Register, pValue);
5a7d67754026bd3654a2464799f0db1790ecf183vboxsyncDECLHIDDEN(int) vboxPciDevRegisterIrqHandler(PRAWPCIDEVPORT pPort, PFNRAWPCIISR pfnHandler, void* pIrqContext, int32_t *piHostIrq)
5a7d67754026bd3654a2464799f0db1790ecf183vboxsync PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
1df297ea8319f3f3afddb73e6ea2fd9c7f0e5eb4vboxsync rc = vboxPciOsDevRegisterIrqHandler(pThis, pfnHandler, pIrqContext, piHostIrq);
1df297ea8319f3f3afddb73e6ea2fd9c7f0e5eb4vboxsyncDECLHIDDEN(int) vboxPciDevUnregisterIrqHandler(PRAWPCIDEVPORT pPort, int32_t iHostIrq)
c00fd08041e14ed8ad7733165f855bfbbc818a0evboxsync PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
c00fd08041e14ed8ad7733165f855bfbbc818a0evboxsync int rc = vboxPciOsDevUnregisterIrqHandler(pThis, iHostIrq);
c00fd08041e14ed8ad7733165f855bfbbc818a0evboxsync * Creates a new instance.
c00fd08041e14ed8ad7733165f855bfbbc818a0evboxsync * @returns VBox status code.
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync * @param pGlobals The globals.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * @param pszName The instance name.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * @param ppDevPort Where to store the pointer to our port interface.
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsyncstatic int vboxPciNewInstance(PVBOXRAWPCIGLOBALS pGlobals,
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync PVBOXRAWPCIINS pNew = (PVBOXRAWPCIINS)RTMemAllocZ(sizeof(*pNew));
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync pNew->DevPort.pfnGetRegionInfo = vboxPciDevGetRegionInfo;
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync pNew->DevPort.pfnUnmapRegion = vboxPciDevUnmapRegion;
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync pNew->DevPort.pfnPciCfgRead = vboxPciDevPciCfgRead;
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync pNew->DevPort.pfnPciCfgWrite = vboxPciDevPciCfgWrite;
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync pNew->DevPort.pfnPciCfgRead = vboxPciDevPciCfgRead;
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync pNew->DevPort.pfnPciCfgWrite = vboxPciDevPciCfgWrite;
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync pNew->DevPort.pfnRegisterIrqHandler = vboxPciDevRegisterIrqHandler;
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync pNew->DevPort.pfnUnregisterIrqHandler = vboxPciDevUnregisterIrqHandler;
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync pNew->DevPort.u32VersionEnd = RAWPCIDEVPORT_VERSION;
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsync rc = pNew->DevPort.pfnInit(&pNew->DevPort, fFlags);
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * @copydoc RAWPCIFACTORY::pfnCreateAndConnect
2c19fa7a35e93931f995c196426585b16f8bf2c0vboxsyncstatic DECLCALLBACK(int) vboxPciFactoryCreateAndConnect(PRAWPCIFACTORY pFactory,
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync LogFlow(("vboxPciFactoryCreateAndConnect: PCI=%x fFlags=%#x\n", u32HostAddress, fFlags));
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync rc = vboxPciNewInstance(pGlobals, u32HostAddress, fFlags, ppDevPort);
1d8f69ceb39fecbf9a7c95dbac083f3ce5c4efd9vboxsync * @copydoc RAWPCIFACTORY::pfnRelease
1d8f69ceb39fecbf9a7c95dbac083f3ce5c4efd9vboxsyncstatic DECLCALLBACK(void) vboxPciFactoryRelease(PRAWPCIFACTORY pFactory)
1d8f69ceb39fecbf9a7c95dbac083f3ce5c4efd9vboxsync PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
1d8f69ceb39fecbf9a7c95dbac083f3ce5c4efd9vboxsync int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
1d8f69ceb39fecbf9a7c95dbac083f3ce5c4efd9vboxsync LogFlow(("vboxPciFactoryRelease: cRefs=%d (new)\n", cRefs));
1d8f69ceb39fecbf9a7c95dbac083f3ce5c4efd9vboxsyncstatic DECLHIDDEN(bool) vboxPciCanUnload(PVBOXRAWPCIGLOBALS pGlobals)
0aaf889969ebdaba8a310db13adcec8c10174796vboxsync int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
0aaf889969ebdaba8a310db13adcec8c10174796vboxsyncstatic DECLHIDDEN(int) vboxPciInitIdc(PVBOXRAWPCIGLOBALS pGlobals)
0aaf889969ebdaba8a310db13adcec8c10174796vboxsync * Establish a connection to SUPDRV and register our component factory.
0aaf889969ebdaba8a310db13adcec8c10174796vboxsync rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
0aaf889969ebdaba8a310db13adcec8c10174796vboxsync rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
0aaf889969ebdaba8a310db13adcec8c10174796vboxsync Log(("VBoxRawPci: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
0aaf889969ebdaba8a310db13adcec8c10174796vboxsync /* bail out. */
0aaf889969ebdaba8a310db13adcec8c10174796vboxsync LogRel(("VBoxRawPci: Failed to register component factory, rc=%Rrc\n", rc));
0aaf889969ebdaba8a310db13adcec8c10174796vboxsync * Try to close the IDC connection to SUPDRV if established.
0aaf889969ebdaba8a310db13adcec8c10174796vboxsync * @returns VBox status code.
0aaf889969ebdaba8a310db13adcec8c10174796vboxsync * @retval VINF_SUCCESS on success.
0aaf889969ebdaba8a310db13adcec8c10174796vboxsync * @retval VERR_WRONG_ORDER if we're busy.
0aaf889969ebdaba8a310db13adcec8c10174796vboxsync * @param pGlobals Pointer to the globals.
0aaf889969ebdaba8a310db13adcec8c10174796vboxsyncDECLHIDDEN(int) vboxPciDeleteIdc(PVBOXRAWPCIGLOBALS pGlobals)
0aaf889969ebdaba8a310db13adcec8c10174796vboxsync * Check before trying to deregister the factory.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync * Disconnect from SUPDRV.
165b506f4c024dabd5a4caaeda31c66712d154eavboxsync rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
return rc;
return rc;
return rc;
return rc;