Index: /trunk/include/VBox/rawpci.h
===================================================================
--- /trunk/include/VBox/rawpci.h	(revision 35945)
+++ /trunk/include/VBox/rawpci.h	(revision 35946)
@@ -189,4 +189,85 @@
 } PCIRAWR0OPERATION;
 
+/** Forward declarations. */
+typedef struct RAWPCIFACTORY *PRAWPCIFACTORY;
+typedef struct RAWPCIDEVPORT *PRAWPCIDEVPORT;
+
+/**
+ * This is the port on the device interface, i.e. the driver side which the
+ * host device is connected to.
+ *
+ * This is only used for the in-kernel PCI device connections.
+ */
+typedef struct RAWPCIDEVPORT
+{
+    /** Structure version number. (RAWPCIDEVPORT_VERSION) */
+    uint32_t u32Version;
+
+    /**
+     * Retain the object.
+     *
+     * It will normally be called while owning the internal semaphore.
+     *
+     * @param   pPort     Pointer to this structure.
+     */
+    DECLR0CALLBACKMEMBER(void, pfnRetain,(PRAWPCIDEVPORT pPort));
+
+    /**
+     * Releases the object.
+     *
+     * This must be called for every pfnRetain call.
+     *
+     *
+     * @param   pPort     Pointer to this structure.
+     */
+    DECLR0CALLBACKMEMBER(void, pfnRelease,(PRAWPCIDEVPORT pPort));
+    
+    /** Structure version number. (RAWPCIDEVPORT_VERSION) */
+    uint32_t u32VersionEnd;
+} RAWPCIDEVPORT;
+/** Version number for the RAWPCIDEVPORT::u32Version and RAWPCIIFPORT::u32VersionEnd fields. */
+#define RAWPCIDEVPORT_VERSION   UINT32_C(0xAFBDCC01)
+
+/**
+ * The component factory interface for create a raw PCI interfaces.
+ */
+typedef struct RAWPCIFACTORY
+{
+    /**
+     * Release this factory.
+     *
+     * SUPR0ComponentQueryFactory (SUPDRVFACTORY::pfnQueryFactoryInterface to be precise)
+     * will retain a reference to the factory and the caller has to call this method to
+     * release it once the pfnCreateAndConnect call(s) has been done.
+     *
+     * @param   pIfFactory          Pointer to this structure.
+     */
+    DECLR0CALLBACKMEMBER(void, pfnRelease,(PRAWPCIFACTORY pFactory));
+
+    /**
+     * Create an instance for the specfied host PCI card and connects it
+     * to the driver.
+     *
+     *
+     * @returns VBox status code.
+     *
+     * @param   pIfFactory          Pointer to this structure.
+     * @param   u32HostAddress      Address of PCI device on the host.
+     * @param   fFlags              Creation flags.
+     * @param   ppDevPort           Where to store the pointer to the device port
+     *                              on success.
+     *
+     */
+    DECLR0CALLBACKMEMBER(int, pfnCreateAndConnect,(PRAWPCIFACTORY       pFactory, 
+                                                   uint32_t             u32HostAddress, 
+                                                   uint32_t             fFlags,
+                                                   PRAWPCIDEVPORT       *ppDevPort));
+
+
+} RAWPCIFACTORY;
+
+
+#define RAWPCIFACTORY_UUID_STR "c0268f49-e1e4-402b-b7e0-eb8d09659a9b"
+
 RT_C_DECLS_END
 
Index: /trunk/src/VBox/HostDrivers/VBoxPci/VBoxPci.c
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxPci/VBoxPci.c	(revision 35945)
+++ /trunk/src/VBox/HostDrivers/VBoxPci/VBoxPci.c	(revision 35946)
@@ -18,20 +18,297 @@
 /** @page pg_rawpci     VBoxPci - host PCI support
  *
- * This is a kernel module that works as host proxy between guest and 
+ * This is a kernel module that works as host proxy between guest and
  * PCI hardware.
  *
  */
 
-#define LOG_GROUP LOG_GROUP_PCI_RAW
-#include "VBoxPciInternal.h"
-
+#define LOG_GROUP LOG_GROUP_DEV_PCI_RAW
 #include <VBox/log.h>
 #include <VBox/err.h>
+#include <VBox/sup.h>
+#include <VBox/version.h>
+
 #include <iprt/string.h>
-
-#include <VBox/sup.h>
 #include <iprt/assert.h>
 #include <iprt/spinlock.h>
 #include <iprt/uuid.h>
-#include <VBox/version.h>
-
+#include <iprt/asm.h>
+#include <iprt/mem.h>
+
+#include "VBoxPciInternal.h"
+
+
+/**
+ * Implements the SUPDRV component factor interface query method.
+ *
+ * @returns Pointer to an interface. NULL if not supported.
+ *
+ * @param   pSupDrvFactory      Pointer to the component factory registration structure.
+ * @param   pSession            The session - unused.
+ * @param   pszInterfaceUuid    The factory interface id.
+ */
+static DECLCALLBACK(void *) vboxPciQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid)
+{
+    PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, SupDrvFactory));
+
+    /*
+     * Convert the UUID strings and compare them.
+     */
+    RTUUID UuidReq;
+    int rc = RTUuidFromStr(&UuidReq, pszInterfaceUuid);
+    if (RT_SUCCESS(rc))
+    {
+        if (!RTUuidCompareStr(&UuidReq, RAWPCIFACTORY_UUID_STR))
+        {
+            ASMAtomicIncS32(&pGlobals->cFactoryRefs);
+            return &pGlobals->RawPciFactory;
+        }
+    }
+    else
+        Log(("VBoxRawPci: rc=%Rrc, uuid=%s\n", rc, pszInterfaceUuid));
+
+    return NULL;
+}
+
+/**
+ * @copydoc RAWPCIDEVPORT:: pfnRetain
+ */
+DECLHIDDEN(void) vboxPciDevRetain(PRAWPCIDEVPORT pThis)
+{
+}
+
+/**
+ * @copydoc RAWPCIDEVPORT:: pfnRelease
+ */
+DECLHIDDEN(void) vboxPciDevRelease(PRAWPCIDEVPORT pThis)
+{
+}
+
+
+/**
+ * Creates a new instance.
+ *
+ * @returns VBox status code.
+ * @param   pGlobals            The globals.
+ * @param   pszName             The instance name.
+ * @param   ppDevPort           Where to store the pointer to our port interface.
+ */
+static int vboxPciNewInstance(PVBOXRAWPCIGLOBALS pGlobals, 
+                              uint32_t           u32HostAddress, 
+                              uint32_t           fFlags,
+                              PRAWPCIDEVPORT     *ppDevPort)
+{
+    int             rc;
+    PVBOXRAWPCIINS  pNew = (PVBOXRAWPCIINS)RTMemAllocZ(sizeof(*pNew));
+    if (!pNew)
+        return VERR_NO_MEMORY;
+
+    pNew->pGlobals                      = pGlobals;
+    pNew->hSpinlock                     = NIL_RTSPINLOCK;
+    pNew->cRefs                         = 1;    
+    pNew->pNext                         = NULL;
+    pNew->HostPciAddress                = u32HostAddress;
+
+    pNew->DevPort.u32Version            = RAWPCIDEVPORT_VERSION;
+    pNew->DevPort.pfnRetain             = vboxPciDevRetain;
+    pNew->DevPort.pfnRelease            = vboxPciDevRelease;
+    pNew->DevPort.u32VersionEnd         = RAWPCIDEVPORT_VERSION;
+    
+    rc = RTSpinlockCreate(&pNew->hSpinlock);
+    if (RT_SUCCESS(rc))
+    {
+        *ppDevPort = &pNew->DevPort;
+        return rc;
+    }
+
+    return rc;
+}
+
+
+/**
+ * @copydoc RAWPCIFACTORY::pfnCreateAndConnect
+ */
+static DECLCALLBACK(int) vboxPciFactoryCreateAndConnect(PRAWPCIFACTORY       pFactory, 
+                                                        uint32_t             u32HostAddress, 
+                                                        uint32_t             fFlags,
+                                                        PRAWPCIDEVPORT       *ppDevPort)
+{
+    PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
+    int rc;
+
+    LogFlow(("vboxPciFactoryCreateAndConnect: PCI=%x fFlags=%#x\n", u32HostAddress, fFlags));
+    Assert(pGlobals->cFactoryRefs > 0);
+    rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
+    AssertRCReturn(rc, rc);
+
+    rc = vboxPciNewInstance(pGlobals, u32HostAddress, fFlags, ppDevPort);
+
+    RTSemFastMutexRelease(pGlobals->hFastMtx);
+
+    return rc;
+}
+
+/**
+ * @copydoc RAWPCIFACTORY::pfnRelease
+ */
+static DECLCALLBACK(void) vboxPciFactoryRelease(PRAWPCIFACTORY pFactory)
+{
+    PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
+
+    int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
+    Assert(cRefs >= 0); NOREF(cRefs);
+    LogFlow(("vboxPciFactoryRelease: cRefs=%d (new)\n", cRefs));
+}
+
+
+
+
+static DECLHIDDEN(bool) vboxPciCanUnload(PVBOXRAWPCIGLOBALS pGlobals)
+{
+    int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
+    bool fRc = !pGlobals->pInstanceHead
+            && pGlobals->cFactoryRefs <= 0;
+    RTSemFastMutexRelease(pGlobals->hFastMtx);
+    AssertRC(rc);
+    return fRc;
+}
+
+
+static DECLHIDDEN(int) vboxPciInitIdc(PVBOXRAWPCIGLOBALS pGlobals)
+{
+    int rc;
+    Assert(!pGlobals->fIDCOpen);
+
+    /*
+     * Establish a connection to SUPDRV and register our component factory.
+     */
+    rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
+    if (RT_SUCCESS(rc))
+    {
+        rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
+        if (RT_SUCCESS(rc))
+        {
+            pGlobals->fIDCOpen = true;
+            Log(("VBoxRawPci: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
+            return rc;
+        }
+
+        /* bail out. */
+        LogRel(("VBoxRawPci: Failed to register component factory, rc=%Rrc\n", rc));
+        SUPR0IdcClose(&pGlobals->SupDrvIDC);
+    }
+
+    return rc;
+}
+
+/**
+ * Try to close the IDC connection to SUPDRV if established.
+ *
+ * @returns VBox status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_WRONG_ORDER if we're busy.
+ *
+ * @param   pGlobals        Pointer to the globals.
+ */
+DECLHIDDEN(int) vboxPciDeleteIdc(PVBOXRAWPCIGLOBALS pGlobals)
+{
+    int rc;
+
+    Assert(pGlobals->hFastMtx != NIL_RTSEMFASTMUTEX);
+
+    /*
+     * Check before trying to deregister the factory.
+     */
+    if (!vboxPciCanUnload(pGlobals))
+        return VERR_WRONG_ORDER;
+
+    if (!pGlobals->fIDCOpen)
+        rc = VINF_SUCCESS;
+    else
+    {
+        /*
+         * Disconnect from SUPDRV.
+         */
+        rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
+        AssertRC(rc);
+        SUPR0IdcClose(&pGlobals->SupDrvIDC);
+        pGlobals->fIDCOpen = false;
+    }
+
+    return rc;
+}
+
+
+/**
+ * Initializes the globals.
+ *
+ * @returns VBox status code.
+ * @param   pGlobals        Pointer to the globals.
+ */
+DECLHIDDEN(int) vboxPciInitGlobals(PVBOXRAWPCIGLOBALS pGlobals)
+{
+    /*
+     * Initialize the common portions of the structure.
+     */
+    int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
+    if (RT_SUCCESS(rc))
+    {
+        pGlobals->pInstanceHead = NULL;
+        pGlobals->RawPciFactory.pfnRelease = vboxPciFactoryRelease;
+        pGlobals->RawPciFactory.pfnCreateAndConnect = vboxPciFactoryCreateAndConnect;
+        memcpy(pGlobals->SupDrvFactory.szName, "VBoxRawPci", sizeof("VBoxRawPci"));
+        pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxPciQueryFactoryInterface;
+        pGlobals->fIDCOpen = false;
+    }
+    return rc;
+}
+
+
+/**
+ * Deletes the globals.
+ *
+ *
+ * @param   pGlobals        Pointer to the globals.
+ */
+DECLHIDDEN(void) vboxPciDeleteGlobals(PVBOXRAWPCIGLOBALS pGlobals)
+{
+    Assert(!pGlobals->fIDCOpen);
+
+    /*
+     * Release resources.
+     */
+    if (pGlobals->hFastMtx)
+    {
+        RTSemFastMutexDestroy(pGlobals->hFastMtx);
+        pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;
+    }
+}
+
+
+int  vboxPciInit(PVBOXRAWPCIGLOBALS pGlobals)
+{
+
+    /*
+     * Initialize the common portions of the structure.
+     */
+    int rc = vboxPciInitGlobals(pGlobals);
+    if (RT_SUCCESS(rc))
+    {     
+        rc = vboxPciInitIdc(pGlobals);
+        if (RT_SUCCESS(rc))
+            return rc;
+
+        /* bail out. */
+        vboxPciDeleteGlobals(pGlobals);
+    }
+
+    return rc;
+}
+
+void vboxPciShutdown(PVBOXRAWPCIGLOBALS pGlobals)
+{
+    int rc = vboxPciDeleteIdc(pGlobals);
+    
+    if (RT_SUCCESS(rc))
+        vboxPciDeleteGlobals(pGlobals);
+}
Index: /trunk/src/VBox/HostDrivers/VBoxPci/VBoxPciInternal.h
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxPci/VBoxPciInternal.h	(revision 35945)
+++ /trunk/src/VBox/HostDrivers/VBoxPci/VBoxPciInternal.h	(revision 35946)
@@ -24,4 +24,69 @@
 #include <iprt/assert.h>
 
+
+RT_C_DECLS_BEGIN
+
+/* Forward declaration. */
+typedef struct VBOXRAWPCIGLOBALS *PVBOXRAWPCIGLOBALS;
+typedef struct VBOXRAWPCIINS     *PVBOXRAWPCIINS;
+
+/**
+ * The per-instance data of the VBox raw PCI interface.
+ *
+ * This is data associated with a host PCI card which
+ * the filter driver has been or may be attached to. When possible it is
+ * attached dynamically, but this may not be possible on all OSes so we have
+ * to be flexible about things.
+ *
+ */
+typedef struct VBOXRAWPCIINS
+{
+    /** Pointer to the globals. */
+    PVBOXRAWPCIGLOBALS pGlobals;
+    /** The spinlock protecting the state variables and host interface handle. */
+    RTSPINLOCK         hSpinlock;
+    /** Pointer to the next device in the list. */
+    PVBOXRAWPCIINS     pNext;
+    /** Reference count. */
+    uint32_t volatile cRefs;
+
+    /* Host PCI address of this device. */
+    uint32_t           HostPciAddress;
+
+    /** Port, given to the outside world. */
+    RAWPCIDEVPORT      DevPort;
+} VBOXRAWPCIINS;
+
+/**
+ * The global data of the VBox PCI driver.
+ *
+ * This contains the bit required for communicating with support driver, VBoxDrv
+ * (start out as SupDrv).
+ */
+typedef struct VBOXRAWPCIGLOBALS
+{
+    /** Mutex protecting the list of instances and state changes. */
+    RTSEMFASTMUTEX hFastMtx;
+
+    /** Pointer to a list of instance data. */
+    PVBOXRAWPCIINS pInstanceHead;
+
+    /** The raw PCI interface factory. */
+    RAWPCIFACTORY RawPciFactory;
+    /** The SUPDRV component factory registration. */
+    SUPDRVFACTORY SupDrvFactory;
+    /** The number of current factory references. */
+    int32_t volatile cFactoryRefs;
+    /** Whether the IDC connection is open or not.
+     * This is only for cleaning up correctly after the separate IDC init on Windows. */
+    bool fIDCOpen;
+    /** The SUPDRV IDC handle (opaque struct). */
+    SUPDRVIDCHANDLE SupDrvIDC;
+} VBOXRAWPCIGLOBALS;
+
+DECLHIDDEN(int)  vboxPciInit(PVBOXRAWPCIGLOBALS pGlobals);
+DECLHIDDEN(void) vboxPciShutdown(PVBOXRAWPCIGLOBALS pGlobals);
+
+RT_C_DECLS_END
+
 #endif
-
