]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
[IBBUS] ibbus as a filter driver. tested for mthca, see etc\ for mthca.inf example...
authorstansmith <stansmith@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sat, 2 Aug 2008 00:43:15 +0000 (00:43 +0000)
committerstansmith <stansmith@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sat, 2 Aug 2008 00:43:15 +0000 (00:43 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1@1453 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

branches/winverbs/core/bus/kernel/bus_driver.c
branches/winverbs/core/bus/kernel/bus_driver.h
branches/winverbs/core/bus/kernel/bus_iou_mgr.c
branches/winverbs/core/bus/kernel/bus_iou_mgr.h
branches/winverbs/core/bus/kernel/bus_pnp.c
branches/winverbs/core/bus/kernel/bus_port_mgr.c
branches/winverbs/core/bus/kernel/bus_port_mgr.h
branches/winverbs/core/bus/kernel/etc/ib_iou.inf [new file with mode: 0644]
branches/winverbs/core/bus/kernel/etc/mthca.cdf [new file with mode: 0644]
branches/winverbs/core/bus/kernel/etc/mthca.inx [new file with mode: 0644]

index b39d2965035d06e6ba4b3905214e41d400400b68..98e5a1e045cee837bb82e2f1dabe76b6bf126644 100644 (file)
@@ -191,7 +191,8 @@ __read_machine_name( void )
 * output:      pkey_array\r
 * return:      uint16_t number of pkey(s) found\r
 *************************************************************************************/\r
-static uint16_t __prepare_pKey_array(IN const UNICODE_STRING *str, OUT uint16_t *pkey_array)\r
+static uint16_t\r
+__prepare_pKey_array(IN const UNICODE_STRING *str, OUT uint16_t *pkey_array)\r
 {\r
        uint16_t i, num_pKeys, cur_pkey_length;\r
        NTSTATUS status;\r
@@ -320,6 +321,7 @@ static uint16_t __prepare_pKey_array(IN const UNICODE_STRING *str, OUT uint16_t
        BUS_EXIT( BUS_DBG_DRV );\r
        return num_pKeys;\r
 }\r
+\r
 static NTSTATUS\r
 __read_registry(\r
        IN                              UNICODE_STRING* const           p_registry_path )\r
@@ -440,6 +442,8 @@ __read_registry(
 #if DBG\r
        if( g_al_dbg_flags & AL_DBG_ERR )\r
                g_al_dbg_flags |= CL_DBG_ERROR;\r
+\r
+       bus_globals.dbg_lvl |= BUS_DBG_DRV | BUS_DBG_PNP;\r
 #endif\r
 \r
        BUS_TRACE(BUS_DBG_DRV ,\r
@@ -667,7 +671,7 @@ DriverEntry(
        IN                              DRIVER_OBJECT                           *p_driver_obj,\r
        IN                              UNICODE_STRING                          *p_registry_path )\r
 {\r
-       NTSTATUS                        status;\r
+       NTSTATUS                status;\r
 \r
        BUS_ENTER( BUS_DBG_DRV );\r
 \r
@@ -707,6 +711,15 @@ DriverEntry(
        p_driver_obj->DriverUnload = bus_drv_unload;\r
        p_driver_obj->DriverExtension->AddDevice = bus_add_device;\r
 \r
+    // Mutex to synchronize multiple threads creating & deleting \r
+    // control deviceobjects. \r
+\r
+    ExInitializeFastMutex(&ControlMutex);\r
+       bfi_InstanceCount = 0;\r
+       memset(  __out_bcount(sizeof(bus_filters)) (void*)bus_filters, 0,\r
+                       sizeof(bus_filters) );\r
+\r
        BUS_EXIT( BUS_DBG_DRV );\r
        return STATUS_SUCCESS;\r
 }\r
+\r
index bee33af542dd26ca288ec8e12bf44a114c7778d4..e4ff16e091a436d1f26f2cfe732950b44827b474 100644 (file)
        CL_TRACE_EXIT( lvl, bus_globals.dbg_lvl, msg )\r
 \r
 #define BUS_PRINT( lvl, msg )          \\r
-       CL_PRINT( lvl, bus_globals.dbl_lvl, msg )\r
+       CL_PRINT( lvl, bus_globals.dbg_lvl, msg )\r
+\r
+/* single character Macro elemination */\r
+#define XBUS_PRINT( lvl, msg )\r
+#define XBUS_ENTER( lvl )\r
+#define XBUS_EXIT( lvl )\r
 \r
 #define BUS_DBG_ERROR  CL_DBG_ERROR\r
 #define BUS_DBG_DRV            (1 << 0)\r
@@ -93,7 +98,6 @@
  *             in the paging, crash dump, or hibernation path.\r
  */\r
 \r
-\r
 /*\r
  * Device extension for the device object that serves as entry point for \r
  * the interface and IOCTL requests.\r
@@ -112,15 +116,13 @@ typedef struct _bus_fdo_ext
        port_mgr_t                              *p_port_mgr;\r
        iou_mgr_t                               *p_iou_mgr;\r
 \r
-       /* Interface names are generated by IoRegisterDeviceInterface. */\r
-       UNICODE_STRING                  al_ifc_name;\r
-       UNICODE_STRING                  ci_ifc_name;\r
-\r
        /* Number of references on the upper interface. */\r
        atomic32_t                              n_al_ifc_ref;\r
        /* Number of references on the CI interface. */\r
        atomic32_t                              n_ci_ifc_ref;\r
 \r
+       struct _bus_filter_instance *bus_filter;\r
+\r
 }      bus_fdo_ext_t;\r
 \r
 \r
@@ -174,7 +176,7 @@ typedef struct _bus_pdo_ext
        boolean_t                               b_reported_missing;\r
 \r
        /* Flag to control the behaviour of the driver during hibernation */\r
-       uint32_t                                        b_hibernating;\r
+       uint32_t                                b_hibernating;\r
 \r
        /* work item for handling Power Management request */\r
        PIO_WORKITEM                    p_po_work_item;\r
@@ -196,13 +198,62 @@ typedef struct _bus_globals
        /* Driver object.  Used for registering of Plug and Play notifications. */\r
        DRIVER_OBJECT                   *p_driver_obj;\r
 \r
-       /* Pointer to the one and only bus root. */\r
-       bus_fdo_ext_t                   *p_bus_ext;\r
+       /* IBAL PNP event register handles */\r
+       ib_pnp_handle_t                 h_pnp_port;\r
+       ib_pnp_handle_t                 h_pnp_iou;\r
 \r
 }      bus_globals_t;\r
 \r
 \r
 extern bus_globals_t   bus_globals;\r
 \r
+/*\r
+ * Each instance of a bus filter on an HCA device stack (InfiniBandController)\r
+ * populates a bus_filter_t slot in bus_filters[MAX_BUS_FILTERS]; see\r
+ * bus_add_device(). Therefore MAX_BUS_FILTERS represents the MAX number of\r
+ * HCA's supported in a single system.\r
+ */\r
+#define MAX_BUS_FILTERS        16\r
+#define BFI_MAGIC              0xcafebabe\r
+\r
+#define BFI_PORT_MGR_OBJ       1\r
+#define BFI_IOU_MGR_OBJ                2\r
+\r
+\r
+typedef struct _bus_filter_instance\r
+{\r
+       /* Pointer to the bus filter instance FDO extention.\r
+        * if p_bus_ext is NULL, then it's an empty slot available for allocation\r
+        */\r
+       bus_fdo_ext_t                   *p_bus_ext;\r
+\r
+       /* HCA guid for which this bus filter is servicing */\r
+       ib_net64_t                              ca_guid;\r
+\r
+       /* PORT management - on a per HCA basis */\r
+       port_mgr_t                              *p_port_mgr;\r
+       cl_obj_t                                *p_port_mgr_obj;\r
+\r
+       /* IOU management - on a per HCA basis */\r
+       iou_mgr_t                               *p_iou_mgr;\r
+       cl_obj_t                                *p_iou_mgr_obj;\r
+#if DBG\r
+       ULONG                                   magic; // initial/temp debug\r
+       char                                    whoami[8];\r
+#endif\r
+\r
+}      bus_filter_t;\r
+\r
+extern bus_filter_t    bus_filters[MAX_BUS_FILTERS];\r
+extern ULONG bfi_InstanceCount;\r
+extern FAST_MUTEX ControlMutex;        // serializes InstanceCount & bus_filters\r
+\r
+extern bus_filter_t *alloc_bfi( IN DRIVER_OBJECT *, OUT int * );\r
+extern int free_bfi( IN bus_filter_t *p_bfi );\r
+extern int get_bfi_count( void );\r
+extern bus_filter_t *get_bfi_by_obj( IN int obj_type, IN cl_obj_t *p_obj );\r
+extern bus_filter_t *get_bfi_by_ca_guid( IN net64_t ca_guid );\r
+extern bus_filter_t *get_set_bfi_by_ca_guid( IN net64_t ca_guid );\r
+extern char *get_obj_state_str(cl_state_t state);\r
 \r
 #endif /* !defined _BUS_DRIVER_H_ */\r
index 277730f8a7d0368f5e4cac84467d0d5f89ae3181..d53917406be3127af6f587ecb37057ae64b6ca2f 100644 (file)
@@ -83,7 +83,12 @@ typedef struct _bus_iou_ext
 }      bus_iou_ext_t;\r
 \r
 \r
-iou_mgr_t*                                             gp_iou_mgr = NULL;\r
+typedef struct _iou_pnp_context\r
+{\r
+       bus_filter_t    *p_bus_filter;\r
+       void                    *p_pdo_ext;\r
+\r
+}      iou_pnp_ctx_t;\r
 \r
 \r
 /*\r
@@ -98,7 +103,8 @@ free_iou_mgr(
        IN                              cl_obj_t*                                       p_obj );\r
 \r
 ib_api_status_t\r
-bus_reg_iou_pnp( void );\r
+bus_reg_iou_pnp(\r
+       IN                              bus_filter_t*                           p_bfi );\r
 \r
 ib_api_status_t\r
 iou_mgr_pnp_cb(\r
@@ -278,25 +284,29 @@ static const cl_vfptr_query_txt_t         vfptr_iou_query_txt = {
  */\r
 ib_api_status_t\r
 create_iou_mgr(\r
+       IN                              bus_filter_t*                           p_bfi,\r
                OUT                     iou_mgr_t** const                       pp_iou_mgr )\r
 {\r
        ib_api_status_t         status;\r
        cl_status_t                     cl_status;\r
+       iou_mgr_t                       *gp_iou_mgr;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
-       CL_ASSERT( !gp_iou_mgr );\r
+       CL_ASSERT( p_bfi->p_iou_mgr == NULL );\r
 \r
        gp_iou_mgr = cl_zalloc( sizeof(iou_mgr_t) );\r
        if( !gp_iou_mgr )\r
        {\r
                BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
-                       ("Failed to allocate port manager.\n") );\r
+                       ("Failed to allocate IOU manager.\n") );\r
                return IB_INSUFFICIENT_MEMORY;\r
        }\r
+       p_bfi->p_iou_mgr = gp_iou_mgr;\r
 \r
        /* Construct the load service. */\r
        cl_obj_construct( &gp_iou_mgr->obj, AL_OBJ_TYPE_LOADER );\r
+       p_bfi->p_iou_mgr_obj = &p_bfi->p_iou_mgr->obj; // save for destroy & free\r
        cl_mutex_construct( &gp_iou_mgr->pdo_mutex );\r
        cl_qlist_init( &gp_iou_mgr->iou_list );\r
 \r
@@ -311,7 +321,7 @@ create_iou_mgr(
 \r
        /* Initialize the load service object. */\r
        cl_status = cl_obj_init( &gp_iou_mgr->obj, CL_DESTROY_SYNC,\r
-               destroying_iou_mgr, NULL, free_iou_mgr );\r
+                                                        destroying_iou_mgr, NULL, free_iou_mgr );\r
        if( cl_status != CL_SUCCESS )\r
        {\r
                free_iou_mgr( &gp_iou_mgr->obj );\r
@@ -320,11 +330,12 @@ create_iou_mgr(
                return ib_convert_cl_status( cl_status );\r
        }\r
 \r
-       /* Register for port PnP events. */\r
-       status = bus_reg_iou_pnp();\r
+       /* Register for IOU PnP events. */\r
+       status = bus_reg_iou_pnp( p_bfi );\r
        if( status != IB_SUCCESS )\r
        {\r
-               cl_obj_destroy( &gp_iou_mgr->obj );\r
+//             cl_obj_destroy( &gp_iou_mgr->obj );\r
+               free_iou_mgr( &gp_iou_mgr->obj );\r
                BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
                        ("bus_reg_iou_pnp returned %s.\n", ib_get_err_str(status)) );\r
                return status;\r
@@ -337,6 +348,26 @@ create_iou_mgr(
 }\r
 \r
 \r
+void\r
+destroy_iou_mgr_cb( IN  void  *context )\r
+{\r
+       iou_pnp_ctx_t   *p_ctx = context;\r
+       bus_filter_t    *p_bfi;\r
+\r
+       CL_ASSERT( p_ctx );\r
+       CL_ASSERT( p_ctx->p_bus_filter->magic == BFI_MAGIC );\r
+\r
+       p_bfi = p_ctx->p_bus_filter;\r
+       BUS_PRINT(BUS_DBG_PNP, ("%s() Enter: obj %p?\n", __FUNCTION__,\r
+                               p_bfi->p_iou_mgr_obj));\r
+\r
+       cl_obj_deref( p_bfi->p_iou_mgr_obj );\r
+       \r
+       BUS_PRINT(BUS_DBG_PNP, ("%s() Exit: obj %p?\n", __FUNCTION__,\r
+                               p_bfi->p_iou_mgr_obj));\r
+}\r
+\r
+\r
 /*\r
  * Pre-destroy the load service.\r
  */\r
@@ -345,20 +376,34 @@ destroying_iou_mgr(
        IN                              cl_obj_t*                                       p_obj )\r
 {\r
        ib_api_status_t                 status;\r
+       bus_filter_t                    *p_bfi;\r
+       iou_mgr_t                               *gp_iou_mgr;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
        CL_ASSERT( p_obj );\r
+       p_bfi = get_bfi_by_obj( BFI_IOU_MGR_OBJ, p_obj );\r
+       if (p_bfi == NULL) {\r
+               BUS_PRINT(BUS_DBG_PNP, ("%s() failed to find p_bfi by obj %p?\n",\r
+                       __FUNCTION__,p_obj));\r
+               return;\r
+       }\r
+       gp_iou_mgr = p_bfi->p_iou_mgr;\r
+\r
+       BUS_PRINT(BUS_DBG_PNP, ("%s(%s) obj %p port_mgr %p\n",\r
+                       __FUNCTION__, p_bfi->whoami, p_obj, gp_iou_mgr));\r
+\r
        CL_ASSERT( gp_iou_mgr == PARENT_STRUCT( p_obj, iou_mgr_t, obj ) );\r
-       UNUSED_PARAM( p_obj );\r
 \r
-       /* Deregister for port PnP events. */\r
-       if( gp_iou_mgr->h_pnp )\r
+       /* Deregister for iou PnP events. */\r
+       if( get_bfi_count() == 1 && bus_globals.h_pnp_iou )\r
        {\r
-               status = ib_dereg_pnp( gp_iou_mgr->h_pnp,\r
-                       (ib_pfn_destroy_cb_t)cl_obj_deref );\r
+               status = ib_dereg_pnp( bus_globals.h_pnp_iou, NULL );\r
+               bus_globals.h_pnp_iou = NULL;\r
                CL_ASSERT( status == IB_SUCCESS );\r
        }\r
+       cl_obj_deref( p_bfi->p_iou_mgr_obj );\r
+\r
        BUS_EXIT( BUS_DBG_PNP );\r
 }\r
 \r
@@ -372,14 +417,30 @@ free_iou_mgr(
 {\r
        bus_pdo_ext_t   *p_ext;\r
        cl_list_item_t  *p_list_item;\r
+       bus_filter_t    *p_bfi;\r
+       iou_mgr_t               *gp_iou_mgr;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
        CL_ASSERT( p_obj );\r
+       p_bfi = get_bfi_by_obj( BFI_IOU_MGR_OBJ, p_obj );\r
+       if ( p_bfi == NULL ) {\r
+               BUS_PRINT( BUS_DBG_PNP, ("%s: unable to get p_bfi iou_obj %p?\n",\r
+                                       __FUNCTION__,p_obj) );\r
+               return;\r
+       }\r
+       gp_iou_mgr = p_bfi->p_iou_mgr;\r
+       if ( !gp_iou_mgr ) {\r
+               // if create fails & then free is called, p_bfi->p_iou_mgr == NULL\r
+               return;\r
+       }\r
+\r
        CL_ASSERT( gp_iou_mgr == PARENT_STRUCT( p_obj, iou_mgr_t, obj ) );\r
 \r
+       BUS_PRINT( BUS_DBG_PNP, ("%s(%s) Mark all IOU PDOs as no longer present\n",\r
+                               __FUNCTION__, p_bfi->whoami));\r
        /*\r
-        * Mark all IPoIB PDOs as no longer present.  This will cause them\r
+        * Mark all IOU PDOs as no longer present.  This will cause them\r
         * to be removed when they process the IRP_MN_REMOVE_DEVICE.\r
         */\r
        p_list_item = cl_qlist_remove_head( &gp_iou_mgr->iou_list );\r
@@ -391,8 +452,10 @@ free_iou_mgr(
                {\r
                        CL_ASSERT( !p_ext->b_present );\r
                        p_ext->b_reported_missing = TRUE;\r
-                       BUS_TRACE( BUS_DBG_PNP, ("%s: ext %p, present %d, missing %d .\n",\r
-                               p_ext->cl_ext.vfptr_pnp_po->identity, p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
+                       BUS_TRACE( BUS_DBG_PNP, ("%s %s: ext %p, present %d, missing %d\n",\r
+                                               p_bfi->whoami,\r
+                                               p_ext->cl_ext.vfptr_pnp_po->identity, p_ext,\r
+                                               p_ext->b_present, p_ext->b_reported_missing ) );\r
                        continue;\r
                }\r
                if( p_ext->h_ca )\r
@@ -404,13 +467,25 @@ free_iou_mgr(
                        /* Release the reference on the CA object. */\r
                        deref_al_obj( &p_ext->h_ca->obj );\r
                }\r
+               BUS_TRACE( BUS_DBG_PNP, ("Deleted device %s %s: PDO %p, ext %p\n",\r
+                                       p_bfi->whoami, p_ext->cl_ext.vfptr_pnp_po->identity,\r
+                                       p_ext->cl_ext.p_self_do, p_ext ) );\r
+\r
+               BUS_TRACE( BUS_DBG_PNP,("%s(%s) p_ext->h_ca->obj.state %d ref_cnt %d\n",\r
+                                       __FUNCTION__, p_bfi->whoami,\r
+                                       p_ext->h_ca->obj.state,\r
+                                       p_ext->h_ca->obj.ref_cnt));//XXX\r
+\r
                IoDeleteDevice( p_ext->cl_ext.p_self_do );\r
        }\r
 \r
        cl_mutex_destroy( &gp_iou_mgr->pdo_mutex );\r
        cl_obj_deinit( p_obj );\r
        cl_free( gp_iou_mgr );\r
-       gp_iou_mgr = NULL;\r
+\r
+       p_bfi->p_iou_mgr = NULL;\r
+       p_bfi->p_iou_mgr_obj = NULL;\r
+\r
        BUS_EXIT( BUS_DBG_PNP );\r
 }\r
 \r
@@ -419,22 +494,24 @@ free_iou_mgr(
  * Register the load service for the given PnP class events.\r
  */\r
 ib_api_status_t\r
-bus_reg_iou_pnp( void )\r
+bus_reg_iou_pnp( IN bus_filter_t *p_bfi )\r
 {\r
        ib_pnp_req_t                    pnp_req;\r
-       ib_api_status_t                 status;\r
+       ib_api_status_t                 status = IB_SUCCESS;\r
 \r
-       cl_memclr( &pnp_req, sizeof( ib_pnp_req_t ) );\r
-       pnp_req.pnp_class       = IB_PNP_IOU | IB_PNP_FLAG_REG_SYNC;\r
-       pnp_req.pnp_context = gp_iou_mgr;\r
-       pnp_req.pfn_pnp_cb      = iou_mgr_pnp_cb;\r
+       /* only need to register for PNP once */\r
+       if ( get_bfi_count() == 1 ) {\r
+               cl_memclr( &pnp_req, sizeof( ib_pnp_req_t ) );\r
+               pnp_req.pnp_class       = IB_PNP_IOU | IB_PNP_FLAG_REG_SYNC;\r
+               pnp_req.pnp_context = NULL;\r
+               pnp_req.pfn_pnp_cb      = iou_mgr_pnp_cb;\r
 \r
-       status = ib_reg_pnp( gh_al, &pnp_req, &gp_iou_mgr->h_pnp );\r
+               status = ib_reg_pnp( gh_al, &pnp_req, &bus_globals.h_pnp_iou );\r
+       }\r
 \r
-       if( status == IB_SUCCESS )\r
-       {\r
+       if( status == IB_SUCCESS ) {\r
                /* Reference the load service on behalf of the ib_reg_pnp call. */\r
-               cl_obj_ref( &gp_iou_mgr->obj );\r
+               cl_obj_ref( &p_bfi->p_iou_mgr->obj );\r
        }\r
 \r
        return status;\r
@@ -448,12 +525,11 @@ ib_api_status_t
 iou_mgr_pnp_cb(\r
        IN                              ib_pnp_rec_t*                           p_pnp_rec )\r
 {\r
-       ib_api_status_t         status;\r
+       ib_api_status_t         status=IB_SUCCESS;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
        CL_ASSERT( p_pnp_rec );\r
-       CL_ASSERT( gp_iou_mgr == p_pnp_rec->pnp_context );\r
 \r
        switch( p_pnp_rec->pnp_event )\r
        {\r
@@ -463,9 +539,11 @@ iou_mgr_pnp_cb(
 \r
        case IB_PNP_IOU_REMOVE:\r
                iou_mgr_iou_remove( (ib_pnp_iou_rec_t*)p_pnp_rec );\r
+               break;\r
 \r
        default:\r
-               status = IB_SUCCESS;\r
+               BUS_PRINT( BUS_DBG_PNP, ("%s() Unhandled PNP Event %s\n",\r
+                                       __FUNCTION__, ib_get_pnp_event_str(p_pnp_rec->pnp_event) ));\r
                break;\r
        }\r
        BUS_EXIT( BUS_DBG_PNP );\r
@@ -482,9 +560,47 @@ iou_mgr_get_bus_relations(
        IN                              IRP* const                                      p_irp )\r
 {\r
        NTSTATUS                        status;\r
+       bus_filter_t            *p_bfi;\r
+       iou_mgr_t                       *gp_iou_mgr;\r
+       DEVICE_RELATIONS        *p_rel;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
+       BUS_PRINT(BUS_DBG_PNP, ("%s() ca_guid %I64x\n",__FUNCTION__,ca_guid));\r
+\r
+       /* special case guid == 0 - walk all bus filter instances */\r
+       if ( ca_guid == 0ULL ) {\r
+               for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++) {\r
+                       gp_iou_mgr = p_bfi->p_iou_mgr;\r
+                       if ( !gp_iou_mgr )\r
+                               continue;\r
+                       cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
+                       status = bus_get_relations( &gp_iou_mgr->iou_list, ca_guid, p_irp );\r
+                       cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
+               }\r
+               p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
+               if ( p_rel ) {\r
+                       BUS_PRINT(BUS_DBG_PNP, ("%s() ca_guid 0 Reports %d\n",\r
+                                               __FUNCTION__,p_rel->Count));\r
+               }\r
+               BUS_EXIT( BUS_DBG_PNP );\r
+               return STATUS_SUCCESS;\r
+       }\r
+\r
+       p_bfi = get_bfi_by_ca_guid(ca_guid);\r
+       if (p_bfi == NULL) {\r
+               BUS_PRINT(BUS_DBG_PNP,\r
+                       ("%s() Null p_bfi from ca_guid %I64x ?\n",__FUNCTION__,ca_guid));\r
+               BUS_EXIT( BUS_DBG_PNP );\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+       gp_iou_mgr = p_bfi->p_iou_mgr;\r
+\r
+       BUS_PRINT(BUS_DBG_PNP, ("%s(%s) for ca_guid %I64x iou_mgr %p\n",\r
+                               __FUNCTION__, p_bfi->whoami, ca_guid, gp_iou_mgr) );\r
+       if (!gp_iou_mgr)\r
+               return STATUS_NO_SUCH_DEVICE;\r
+\r
        cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
        status = bus_get_relations( &gp_iou_mgr->iou_list, ca_guid, p_irp );\r
        cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
@@ -496,14 +612,17 @@ iou_mgr_get_bus_relations(
 \r
 static ib_api_status_t\r
 __iou_was_hibernated(\r
-       IN                              ib_pnp_iou_rec_t*                       p_pnp_rec )\r
+       IN                              ib_pnp_iou_rec_t*                       p_pnp_rec,\r
+       IN                              bus_filter_t*                           p_bfi )\r
 {\r
        NTSTATUS                status;\r
-       cl_list_item_t          *p_list_item;\r
-       bus_iou_ext_t           *p_iou_ext;\r
+       cl_list_item_t  *p_list_item;\r
+       bus_iou_ext_t   *p_iou_ext;\r
        bus_pdo_ext_t   *p_pdo_ext = NULL;\r
        size_t                  n_devs = 0;\r
+       iou_mgr_t               *gp_iou_mgr = p_bfi->p_iou_mgr;\r
        cl_qlist_t*             p_pdo_list = &gp_iou_mgr->iou_list;\r
+       iou_pnp_ctx_t   *p_ctx = p_pnp_rec->pnp_rec.context;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
        \r
@@ -525,9 +644,11 @@ __iou_was_hibernated(
                        break;\r
                }\r
 \r
-               BUS_TRACE( BUS_DBG_PNP, \r
-                       ("Skipped PDO for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
-                       p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
+               BUS_TRACE( BUS_DBG_PNP, ("%s Skipped PDO for %s: PDO %p, ext %p, "\r
+                       "present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
+                       p_bfi->whoami,\r
+                       p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
+                       p_pdo_ext->cl_ext.p_self_do, \r
                        p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
                        p_pdo_ext->b_hibernating, p_iou_ext->guid ) );\r
        }\r
@@ -545,20 +666,23 @@ __iou_was_hibernated(
                else \r
                {\r
                        p_pdo_ext->b_hibernating = FALSE;\r
-                       p_pnp_rec->pnp_rec.context = p_pdo_ext;\r
+                       p_ctx->p_pdo_ext = p_pdo_ext; // for iou_mgr_iou_remove()\r
+\r
                        status = IB_SUCCESS;\r
                        p_iou_ext = (bus_iou_ext_t*)p_pdo_ext;\r
-                       BUS_TRACE( BUS_DBG_PNP, \r
-                               ("Found PDO for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
-                               p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
+                       BUS_TRACE( BUS_DBG_PNP, ("%s Found PDO for %s: PDO %p, ext %p, "\r
+                               "present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
+                               p_bfi->whoami,\r
+                               p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
+                               p_pdo_ext->cl_ext.p_self_do, \r
                                p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
                                p_pdo_ext->b_hibernating, p_iou_ext->guid ) );\r
                }\r
        }\r
        else \r
        {\r
-               BUS_TRACE( BUS_DBG_PNP, ("Failed to find PDO for guid  %I64x .\n",\r
-                       p_pnp_rec->pnp_rec.guid ) );\r
+               BUS_TRACE( BUS_DBG_PNP, ("%s Failed to find PDO for guid  %I64x .\n",\r
+                                       p_bfi->whoami, p_pnp_rec->pnp_rec.guid ) );\r
                status = IB_NOT_FOUND;\r
        }\r
 \r
@@ -575,13 +699,48 @@ iou_mgr_iou_add(
        NTSTATUS                status;\r
        DEVICE_OBJECT   *p_pdo;\r
        bus_iou_ext_t   *p_iou_ext;\r
+       bus_filter_t    *p_bfi;\r
+       iou_mgr_t               *gp_iou_mgr;\r
+       iou_pnp_ctx_t   *p_ctx = p_pnp_rec->pnp_rec.context;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
-       /* Upon hibernating of the computer IB_BUS driver doesn't remove PDO, but\r
+       p_bfi = get_set_bfi_by_ca_guid( p_pnp_rec->ca_guid );\r
+       if ( !p_bfi ) {\r
+               BUS_PRINT( BUS_DBG_PNP,("%s() NULL p_bfi? ca_guid 0x%I64x\n",\r
+                                                               __FUNCTION__, p_pnp_rec->ca_guid ) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       if ( !p_ctx ) {\r
+               /*\r
+                * Allocate a PNP context for this object. pnp_rec.context is object\r
+                * unique.\r
+                */\r
+               p_ctx = cl_zalloc( sizeof(*p_ctx) );\r
+               if( !p_ctx )\r
+               {\r
+                       BUS_PRINT(BUS_DBG_PNP, ("%s(%s) ca_guid 0x%I64x iou_guid(%I64x) "\r
+                                       "BAD alloc for PNP context\n", __FUNCTION__,\r
+                                       p_bfi->whoami, p_bfi->ca_guid, p_pnp_rec->guid ));\r
+\r
+                       return IB_ERROR;\r
+               }\r
+               p_ctx->p_bus_filter = p_bfi;\r
+               p_pnp_rec->pnp_rec.context = p_ctx;\r
+\r
+               BUS_PRINT(BUS_DBG_PNP,\r
+                                       ("%s(%s) ca_guid %I64x iou_guid(%I64x) ALLOC p_ctx @ %p\n",\r
+                                       __FUNCTION__, p_bfi->whoami, p_bfi->ca_guid, \r
+                                       p_pnp_rec->guid,p_ctx));\r
+       }\r
+       gp_iou_mgr = p_bfi->p_iou_mgr;\r
+\r
+       /* Upon hibernating the computer IB_BUS driver doesn't remove PDO, but\r
           marks with a flag. So we first try to find an existing PDO for this port,\r
-          marked with this flag. If it was found, we turn off the flag and use this PDO */\r
-       status = __iou_was_hibernated(p_pnp_rec);\r
+          marked with this flag. If it was found, we turn off the flag and use\r
+          this PDO */\r
+       status = __iou_was_hibernated( p_pnp_rec, p_bfi );\r
        if( status != IB_NOT_FOUND )\r
        {\r
                BUS_EXIT( BUS_DBG_PNP );\r
@@ -590,9 +749,11 @@ iou_mgr_iou_add(
 \r
        /* Create the PDO for the new port device. */\r
        status = IoCreateDevice( bus_globals.p_driver_obj, sizeof(bus_iou_ext_t),\r
-               NULL, FILE_DEVICE_CONTROLLER, \r
-               FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,\r
-               FALSE, &p_pdo );\r
+                                                        NULL, FILE_DEVICE_CONTROLLER, \r
+                                                        FILE_DEVICE_SECURE_OPEN |\r
+                                                                                       FILE_AUTOGENERATED_DEVICE_NAME,\r
+                                                        FALSE, &p_pdo );\r
+\r
        if( !NT_SUCCESS( status ) )\r
        {\r
                BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
@@ -602,18 +763,19 @@ iou_mgr_iou_add(
 \r
        /* Initialize the device extension. */\r
        cl_init_pnp_po_ext( p_pdo, NULL, p_pdo, bus_globals.dbg_lvl,\r
-               &vfptr_iou_pnp, &vfptr_iou_query_txt );\r
+                                               &vfptr_iou_pnp, &vfptr_iou_query_txt );\r
 \r
        /* Set the DO_BUS_ENUMERATED_DEVICE flag to mark it as a PDO. */\r
        p_pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;\r
        \r
        p_iou_ext = p_pdo->DeviceExtension;\r
        p_iou_ext->pdo.dev_po_state.DeviceState = PowerDeviceD0;\r
-       p_iou_ext->pdo.p_parent_ext = bus_globals.p_bus_ext;\r
+       p_iou_ext->pdo.p_parent_ext = p_bfi->p_bus_ext;\r
        p_iou_ext->pdo.b_present = TRUE;\r
        p_iou_ext->pdo.b_reported_missing = FALSE;\r
        BUS_TRACE( BUS_DBG_PNP, ("%s: ext %p, present %d, missing %d .\n",\r
-               p_iou_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_iou_ext, p_iou_ext->pdo.b_present, p_iou_ext->pdo.b_reported_missing ) );\r
+               p_iou_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_iou_ext,\r
+               p_iou_ext->pdo.b_present, p_iou_ext->pdo.b_reported_missing ) );\r
 \r
        p_iou_ext->guid = p_pnp_rec->guid;\r
        p_iou_ext->chassis_guid = p_pnp_rec->chassis_guid;\r
@@ -626,6 +788,7 @@ iou_mgr_iou_add(
        p_iou_ext->revision = cl_ntoh32( p_pnp_rec->revision );\r
        cl_memcpy( p_iou_ext->desc, p_pnp_rec->desc,\r
                IB_NODE_DESCRIPTION_SIZE + 1 );\r
+       p_iou_ext->n_ifc_ref = 0;\r
 \r
        /* Cache the CA GUID. */\r
        p_iou_ext->pdo.ca_guid = p_pnp_rec->ca_guid;\r
@@ -641,23 +804,26 @@ iou_mgr_iou_add(
 \r
        /* Store the device extension in the PDO list for future queries. */\r
        cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
-       cl_qlist_insert_tail( &gp_iou_mgr->iou_list,\r
-               &p_iou_ext->pdo.list_item );\r
+       cl_qlist_insert_tail( &gp_iou_mgr->iou_list, &p_iou_ext->pdo.list_item );\r
        cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
 \r
        /*\r
         * Set the context of the PNP event.  The context is passed in for future\r
         * events on the same port.\r
         */\r
-       p_pnp_rec->pnp_rec.context = p_iou_ext;\r
+       /* if not set in iou_was_hibernated(), set now */\r
+       if ( !p_ctx->p_pdo_ext )\r
+               p_ctx->p_pdo_ext = p_iou_ext;\r
 \r
        /* Tell the PnP Manager to rescan for the HCA's bus relations. */\r
        IoInvalidateDeviceRelations(\r
-               p_iou_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
+                       p_iou_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
 \r
+#if 0 // XXX\r
        /* Invalidate removal relations for the bus driver. */\r
        IoInvalidateDeviceRelations(\r
-               bus_globals.p_bus_ext->cl_ext.p_pdo, RemovalRelations );\r
+                       p_bfi->p_bus_ext->cl_ext.p_pdo, RemovalRelations );\r
+#endif\r
 \r
        BUS_EXIT( BUS_DBG_PNP );\r
 \r
@@ -670,13 +836,50 @@ iou_mgr_iou_remove(
        IN                              ib_pnp_iou_rec_t*                       p_pnp_rec )\r
 {\r
        bus_pdo_ext_t   *p_ext;\r
+       iou_mgr_t               *gp_iou_mgr;\r
+       bus_filter_t    *p_bfi;\r
+       iou_pnp_ctx_t   *p_ctx = p_pnp_rec->pnp_rec.context;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
-       /* The PNP record's context is the port extension. */\r
-       p_ext = p_pnp_rec->pnp_rec.context;\r
+       if ( !p_ctx ) {\r
+               BUS_EXIT( BUS_DBG_PNP );\r
+               return;\r
+       }\r
+\r
+       CL_ASSERT( p_ctx->p_bus_filter->magic == BFI_MAGIC );\r
+       p_bfi = p_ctx->p_bus_filter;\r
+       CL_ASSERT( p_bfi );\r
+\r
+       BUS_PRINT(BUS_DBG_PNP,("%s(%s) ca_guid 0x%I64x iou_mgr %p\n",\r
+                               __FUNCTION__, p_bfi->whoami, p_bfi->ca_guid, p_bfi->p_iou_mgr));\r
+\r
+       /* fdo_release_resources() has destroyed the IOU mgr, all that needs to be\r
+        * done is cleanup the PNP IOU context; one per port.\r
+        */\r
+       if ( p_bfi->ca_guid == 0ULL || !p_bfi->p_iou_mgr ) {\r
+               cl_free( p_ctx );\r
+               p_pnp_rec->pnp_rec.context = NULL;\r
+               BUS_EXIT( BUS_DBG_PNP );\r
+               return;\r
+       }\r
+\r
+       gp_iou_mgr = p_bfi->p_iou_mgr;\r
+\r
+       /* Within the Bus fabric instance is the port extension; see\r
+        * was_hibernated().\r
+        */\r
+       p_ext = p_ctx->p_pdo_ext;\r
        CL_ASSERT( p_ext );\r
 \r
+       if (p_bfi != p_ext->p_parent_ext->bus_filter) {\r
+               BUS_PRINT(BUS_DBG_PNP,\r
+                       ("%s() p_bfi(%p) != p_ext->bus_filter(%p) line %d file %s\n",\r
+                       __FUNCTION__,p_bfi,p_ext->p_parent_ext->bus_filter,\r
+                       __LINE__,__FILE__));\r
+               CL_ASSERT (p_bfi == p_ext->p_parent_ext->bus_filter);\r
+       }\r
+\r
        /*\r
         * Flag the port PDO as no longer being present.  We have to wait until\r
         * the PnP manager removes it to clean up.  However, we do release the\r
@@ -684,31 +887,48 @@ iou_mgr_iou_remove(
         * to proceed should it occur before the port's PDO is cleaned up.\r
         */\r
        cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
-       CL_ASSERT( p_ext->h_ca );\r
+       if ( !p_ext->h_ca )\r
+       {\r
+               BUS_TRACE( BUS_DBG_PNP, ("%s() NULL h_ca? p_ext %p\n",\r
+                                       __FUNCTION__, p_ext ) );\r
+               return;\r
+       }\r
 \r
        if( p_ext->b_hibernating )\r
        {\r
-               BUS_TRACE( BUS_DBG_PNP, ("Skip port removing for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d .\n",\r
-                       p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext, p_ext->b_present, \r
+               BUS_TRACE( BUS_DBG_PNP, ("%s Skip port removing for %s: PDO %p ext %p "\r
+                       "present %d missing %d hibernating %d\n",\r
+                       p_bfi->whoami,\r
+                       p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do,\r
+                       p_ext, p_ext->b_present, \r
                        p_ext->b_reported_missing, p_ext->b_hibernating ) );\r
                goto hca_deref;\r
        }\r
 \r
        p_ext->b_present = FALSE;\r
-       BUS_TRACE( BUS_DBG_PNP, ("%s: ext %p, present %d, missing %d .\n",\r
-               p_ext->cl_ext.vfptr_pnp_po->identity, p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
+       p_ext->b_reported_missing = TRUE;\r
+\r
+       BUS_TRACE( BUS_DBG_PNP, ("%s %s: ext %p, present %d, missing %d .\n",\r
+                               p_bfi->whoami,\r
+                               p_ext->cl_ext.vfptr_pnp_po->identity, p_ext, p_ext->b_present,\r
+                               p_ext->b_reported_missing ) );\r
 \r
+#if 0 // XXX\r
        /* Invalidate removal relations for the bus driver. */\r
-       IoInvalidateDeviceRelations( bus_globals.p_bus_ext->cl_ext.p_pdo,\r
-               RemovalRelations );\r
+       IoInvalidateDeviceRelations( p_bfi->p_bus_ext->cl_ext.p_pdo,\r
+                                                                RemovalRelations );\r
+#endif\r
 \r
        /* Invalidate bus relations for the HCA. */\r
        IoInvalidateDeviceRelations(\r
                p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
 \r
+       /* free PNP context */\r
+       cl_free( p_ctx );\r
+       p_pnp_rec->pnp_rec.context = NULL;\r
+\r
 hca_deref:\r
        deref_al_obj( &p_ext->h_ca->obj );\r
-       p_ext->h_ca = NULL;\r
        cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
 \r
        BUS_EXIT( BUS_DBG_PNP );\r
@@ -778,10 +998,12 @@ iou_release_resources(
 {\r
        bus_iou_ext_t   *p_ext;\r
        POWER_STATE             po_state;\r
+       iou_mgr_t               *gp_iou_mgr;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
        p_ext = p_dev_obj->DeviceExtension;\r
+       gp_iou_mgr = p_ext->pdo.p_parent_ext->bus_filter->p_iou_mgr;\r
 \r
        /* Remove this PDO from its list. */\r
        cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
index 2199be462dba44d624737cc520acb68190da3acc..bfe420f721a5e93fde961ef2ed797b58954047a5 100644 (file)
@@ -43,7 +43,6 @@
 typedef struct _iou_mgr\r
 {\r
        cl_obj_t                                        obj;\r
-       ib_pnp_handle_t                         h_pnp;  /* Handle for iou PnP events */\r
 \r
        /* Mutex protects both pointer vectors. */\r
        cl_mutex_t                                      pdo_mutex;\r
@@ -54,9 +53,12 @@ typedef struct _iou_mgr
 }      iou_mgr_t;\r
 \r
 \r
+struct _bus_filter_instance;\r
+\r
 ib_api_status_t\r
 create_iou_mgr(\r
-               OUT                     iou_mgr_t** const                       pp_iou_mgr );\r
+               IN                      struct _bus_filter_instance*    p_bfi,\r
+               OUT                     iou_mgr_t** const                               pp_iou_mgr );\r
 \r
 \r
 NTSTATUS\r
index e0188c53bf5141693b08465522c6277de0453009..8c2d61b71a3c6d87237d487c52859f7c7f125649 100644 (file)
@@ -36,7 +36,6 @@
  * Implemenation of all PnP functionality for FDO (power policy owners).\r
  */\r
 \r
-\r
 #include "bus_pnp.h"\r
 #include "al_ca.h"\r
 #include "al_init.h"\r
 #include "iba/ib_ci_ifc.h"\r
 \r
 \r
+/* Interface names are generated by IoRegisterDeviceInterface. */\r
+static UNICODE_STRING  al_ifc_name;\r
+static UNICODE_STRING  ci_ifc_name;\r
+\r
+FAST_MUTEX                             ControlMutex;\r
+ULONG                                  bfi_InstanceCount;\r
+bus_filter_t                   bus_filters[MAX_BUS_FILTERS];\r
+\r
+extern ib_al_handle_t  gh_al; // NULL if AL needs init.\r
+\r
+\r
 static NTSTATUS\r
 fdo_start(\r
        IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
@@ -71,7 +81,7 @@ fdo_query_capabilities(
                OUT                             cl_irp_action_t* const  p_action );\r
 \r
 static NTSTATUS\r
-fdo_query_remove_relations(\r
+fdo_query_bus_relations(\r
        IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
        IN                                      IRP* const                              p_irp, \r
                OUT                             cl_irp_action_t* const  p_action );\r
@@ -117,7 +127,7 @@ __fdo_set_power(
 #pragma alloc_text (PAGE, fdo_query_remove)\r
 #pragma alloc_text (PAGE, fdo_release_resources)\r
 #pragma alloc_text (PAGE, fdo_query_capabilities)\r
-#pragma alloc_text (PAGE, fdo_query_remove_relations)\r
+#pragma alloc_text (PAGE, fdo_query_bus_relations)\r
 #pragma alloc_text (PAGE, __query_al_ifc)\r
 #pragma alloc_text (PAGE, __query_ci_ifc)\r
 #pragma alloc_text (PAGE, __get_relations)\r
@@ -143,9 +153,9 @@ static const cl_vfptr_pnp_po_t              vfptr_fdo_pnp = {
        cl_irp_skip,\r
        cl_irp_skip,\r
        cl_do_sync_pnp,\r
+       fdo_query_bus_relations /*cl_irp_ignore*/ ,\r
        cl_irp_ignore,\r
-       cl_irp_ignore,\r
-       fdo_query_remove_relations,\r
+       cl_irp_skip     /*fdo_query_remove_relations now _bus_relations */ ,\r
        cl_irp_ignore,\r
        cl_irp_ignore,\r
        cl_irp_ignore,\r
@@ -170,58 +180,90 @@ bus_add_device(
 {\r
        NTSTATUS                status;\r
        DEVICE_OBJECT   *p_dev_obj, *p_next_do;\r
-       bus_fdo_ext_t   *p_ext;\r
+       bus_fdo_ext_t   *p_ext=NULL;\r
        UNICODE_STRING  dev_name, dos_name;\r
+       bus_filter_t    *p_bfi;\r
+       int                             ic;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
-       if( bus_globals.p_bus_ext )\r
+       /* allocate a Bus Filter Instance */\r
+       p_bfi = alloc_bfi( p_driver_obj, &ic );\r
+       if ( !p_bfi )\r
        {\r
-               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
-                       ("Bus root already exists.  Only one bus root allowed.\n") );\r
-               return STATUS_NO_SUCH_DEVICE;\r
+               BUS_PRINT( BUS_DBG_PNP,\r
+                       ("%s() Err - Exceeded MAX_BUS_FILTERS(%d)\n",MAX_BUS_FILTERS));\r
+               return STATUS_UNSUCCESSFUL;\r
        }\r
 \r
-       RtlInitUnicodeString( &dev_name, AL_DEVICE_NAME );\r
-       RtlInitUnicodeString( &dos_name, L"\\DosDevices\\Global\\ibal" );\r
-\r
        /* Create the FDO device object to attach to the stack. */\r
-       status = IoCreateDevice( p_driver_obj, sizeof(bus_fdo_ext_t),\r
-               &dev_name, FILE_DEVICE_BUS_EXTENDER,\r
-               FILE_DEVICE_SECURE_OPEN, FALSE, &p_dev_obj );\r
-       if( !NT_SUCCESS(status) )\r
+\r
+       /* if 1st Bus Filter Instance, then create device names for user ioctl */\r
+       if ( ic == 1 )\r
        {\r
-               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
-                       ("Failed to create bus root FDO device.\n") );\r
-               return status;\r
+               RtlInitUnicodeString( &dev_name, AL_DEVICE_NAME );\r
+               RtlInitUnicodeString( &dos_name, L"\\DosDevices\\Global\\ibal" );\r
+\r
+               status = IoCreateDevice( p_driver_obj, sizeof(bus_fdo_ext_t),\r
+                                                                &dev_name, FILE_DEVICE_BUS_EXTENDER,\r
+                                                                FILE_DEVICE_SECURE_OPEN, FALSE, &p_dev_obj );\r
+               if( !NT_SUCCESS(status) )\r
+               {\r
+                       BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                               ("Failed to create ControlDeviceObject, status %x.\n",status) );\r
+                       goto bail;\r
+               }\r
+               IoDeleteSymbolicLink( &dos_name );\r
+               status = IoCreateSymbolicLink( &dos_name, &dev_name );\r
+               if( !NT_SUCCESS(status) )\r
+               {\r
+                       IoDeleteDevice( p_dev_obj );\r
+                       BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                               ("Failed to create symlink for dos name.\n") );\r
+                       goto bail;\r
+               }\r
+       }\r
+       else {\r
+               status = IoCreateDevice( p_driver_obj, sizeof(bus_fdo_ext_t),\r
+                                                                NULL, FILE_DEVICE_BUS_EXTENDER,\r
+                                                                FILE_DEVICE_SECURE_OPEN, FALSE, &p_dev_obj );\r
        }\r
 \r
-       IoDeleteSymbolicLink( &dos_name );\r
-       status = IoCreateSymbolicLink( &dos_name, &dev_name );\r
        if( !NT_SUCCESS(status) )\r
        {\r
-               IoDeleteDevice( p_dev_obj );\r
-               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
-                       ("Failed to create symlink for dos name.\n") );\r
-               return status;\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("Failed to create bus root FDO device.\n") );\r
+               goto bail;\r
        }\r
 \r
        p_ext = p_dev_obj->DeviceExtension;\r
+       p_ext->n_al_ifc_ref = 0;\r
+       p_ext->n_ci_ifc_ref = 0;\r
 \r
        p_next_do = IoAttachDeviceToDeviceStack( p_dev_obj, p_pdo );\r
        if( !p_next_do )\r
        {\r
                IoDeleteDevice( p_dev_obj );\r
                BUS_TRACE_EXIT( BUS_DBG_ERROR, ("IoAttachToDeviceStack failed.\n") );\r
-               return STATUS_NO_SUCH_DEVICE;\r
+               status = STATUS_NO_SUCH_DEVICE;\r
+               goto bail;\r
        }\r
 \r
        cl_init_pnp_po_ext( p_dev_obj, p_next_do, p_pdo, bus_globals.dbg_lvl,\r
-               &vfptr_fdo_pnp, NULL );\r
+                                               &vfptr_fdo_pnp, NULL );\r
+\r
+       p_bfi->p_bus_ext = p_ext;\r
+       p_ext->bus_filter = p_bfi;\r
+\r
+       /*\r
+        * if not 1st Bus Filter Instance, then finished...\r
+        */\r
+       if ( ic > 1 )\r
+               goto adxit;\r
 \r
        /* Register the upper interface (the one used by clients). */\r
-       status = IoRegisterDeviceInterface( p_pdo, \r
-               &GUID_IB_AL_INTERFACE, NULL, &p_ext->al_ifc_name );\r
+       status = IoRegisterDeviceInterface( p_pdo, &GUID_IB_AL_INTERFACE, NULL,\r
+                                                                               &al_ifc_name );\r
        if( !NT_SUCCESS( status ) )\r
        {\r
                IoDetachDevice( p_ext->cl_ext.p_next_do );\r
@@ -229,27 +271,43 @@ bus_add_device(
                BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
                        ("IoRegisterDeviceInterface for upper interface returned %08x\n",\r
                        status) );\r
-               return STATUS_NO_SUCH_DEVICE;\r
+               status = STATUS_NO_SUCH_DEVICE;\r
+               goto bail;\r
        }\r
 \r
-       /* Register the lower interface (the one used by HCA VPDs). */\r
-       status = IoRegisterDeviceInterface( p_pdo, \r
-               &GUID_IB_CI_INTERFACE, NULL, &p_ext->ci_ifc_name );\r
+       /* Register the lower (CI) interface (the one used by HCA VPDs). */\r
+       status = IoRegisterDeviceInterface( p_pdo, &GUID_IB_CI_INTERFACE, NULL,\r
+                                                                               &ci_ifc_name );\r
        if( !NT_SUCCESS( status ) )\r
        {\r
-               RtlFreeUnicodeString( &p_ext->al_ifc_name );\r
                IoDetachDevice( p_ext->cl_ext.p_next_do );\r
                IoDeleteDevice( p_dev_obj );\r
                BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
                        ("IoRegisterDeviceInterface for lower interface returned %08x\n",\r
                        status) );\r
-               return STATUS_NO_SUCH_DEVICE;\r
+               status = STATUS_NO_SUCH_DEVICE;\r
+               goto bail;\r
        }\r
 \r
-       bus_globals.p_bus_ext = p_ext;\r
+adxit:\r
+       BUS_PRINT( BUS_DBG_PNP, ("%s(%s) exit status 0\n",\r
+                               __FUNCTION__, p_bfi->whoami) );\r
 \r
        BUS_EXIT( BUS_DBG_PNP );\r
        return STATUS_SUCCESS;\r
+\r
+bail:\r
+       BUS_PRINT( BUS_DBG_PNP, ("%s(%s) exit status %d\n",\r
+                                                               __FUNCTION__,p_bfi->whoami,status) );\r
+       ic = free_bfi(p_bfi);\r
+       /* if last Bus filter, then cleanup */\r
+       if ( ic == 0 )\r
+       {\r
+               IoDeleteSymbolicLink( &dos_name );\r
+               RtlFreeUnicodeString( &al_ifc_name );\r
+       }\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
 }\r
 \r
 \r
@@ -262,10 +320,13 @@ fdo_start(
        NTSTATUS                status;\r
        bus_fdo_ext_t   *p_ext;\r
        ib_api_status_t ib_status;\r
+       bus_filter_t    *p_bfi;\r
+       boolean_t               AL_init_here = FALSE;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
        p_ext = p_dev_obj->DeviceExtension;\r
+       p_bfi = p_ext->bus_filter;\r
 \r
        /* Handled on the way up. */\r
        status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
@@ -276,18 +337,24 @@ fdo_start(
                return status;\r
        }\r
 \r
-       /* Initialize AL */\r
-       ib_status = al_initialize();\r
-       if( ib_status != IB_SUCCESS )\r
-       {\r
-               al_cleanup();\r
-               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("al_initialize returned %s.\n",\r
-                       ib_get_err_str(ib_status)) );\r
-               return STATUS_UNSUCCESSFUL;\r
+       ExAcquireFastMutexUnsafe(&ControlMutex);\r
+       if ( !gh_al ) {\r
+               /* Initialize AL */\r
+               ib_status = al_initialize();\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       al_cleanup();\r
+                       BUS_TRACE_EXIT( BUS_DBG_ERROR, ("al_initialize returned %s.\n",\r
+                                                       ib_get_err_str(ib_status)) );\r
+                       ExReleaseFastMutexUnsafe(&ControlMutex);\r
+                       return STATUS_UNSUCCESSFUL;\r
+               }\r
+               AL_init_here = TRUE;\r
        }\r
+       ExReleaseFastMutexUnsafe(&ControlMutex);\r
 \r
        /* Initialize the port manager. */\r
-       ib_status = create_port_mgr( &p_ext->p_port_mgr );\r
+       ib_status = create_port_mgr( p_ext->bus_filter, &p_ext->p_port_mgr );\r
        if( ib_status != IB_SUCCESS )\r
        {\r
                BUS_TRACE_EXIT( BUS_DBG_ERROR, ("create_port_mgr returned %s.\n",\r
@@ -296,7 +363,7 @@ fdo_start(
        }\r
 \r
        /* Initialize the IOU manager. */\r
-       ib_status = create_iou_mgr( &p_ext->p_iou_mgr );\r
+       ib_status = create_iou_mgr( p_ext->bus_filter, &p_ext->p_iou_mgr );\r
        if( ib_status != IB_SUCCESS )\r
        {\r
                BUS_TRACE_EXIT( BUS_DBG_ERROR, ("create_iou_mgr returned %s.\n",\r
@@ -304,13 +371,18 @@ fdo_start(
                return STATUS_UNSUCCESSFUL;\r
        }\r
 \r
-       status = IoSetDeviceInterfaceState( &p_ext->al_ifc_name, TRUE );\r
-       ASSERT( NT_SUCCESS( status ) );\r
+       if ( AL_init_here ) {\r
+               status = IoSetDeviceInterfaceState( &al_ifc_name, TRUE );\r
+               ASSERT( NT_SUCCESS( status ) );\r
 \r
-       status = IoSetDeviceInterfaceState( &p_ext->ci_ifc_name, TRUE );\r
-       ASSERT( NT_SUCCESS( status ) );\r
+               status = IoSetDeviceInterfaceState( &ci_ifc_name, TRUE );\r
+               ASSERT( NT_SUCCESS( status ) );\r
+       }\r
 \r
+       BUS_PRINT(BUS_DBG_PNP,\r
+                               ("%s() %s exit %x\n",__FUNCTION__,p_bfi->whoami,status));\r
        BUS_EXIT( BUS_DBG_PNP );\r
+\r
        return status;\r
 }\r
 \r
@@ -327,6 +399,11 @@ fdo_query_remove(
 \r
        p_ext = p_dev_obj->DeviceExtension;\r
 \r
+       BUS_PRINT( BUS_DBG_PNP,\r
+               ("%s() IRP_MN_QUERY_REMOVE_DEVICE %s @ %p refs CI %d AL %d\n", \r
+               __FUNCTION__, p_ext->cl_ext.vfptr_pnp_po->identity, p_ext,\r
+               p_ext->n_ci_ifc_ref,p_ext->n_al_ifc_ref ) ); // XXX\r
+\r
        if( p_ext->n_ci_ifc_ref )\r
        {\r
                /*\r
@@ -363,30 +440,52 @@ fdo_release_resources(
 {\r
        bus_fdo_ext_t   *p_ext;\r
        NTSTATUS                status;\r
+       bus_filter_t    *p_bfi;\r
+       int                             ic;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
        p_ext = p_dev_obj->DeviceExtension;\r
+       ic = get_bfi_count();\r
 \r
        //TODO: Fail outstanding I/O operations.\r
 \r
+       if (p_ext->p_port_mgr)\r
+               cl_obj_destroy( &p_ext->p_port_mgr->obj );\r
+\r
+       if (p_ext->p_iou_mgr)\r
+               cl_obj_destroy( &p_ext->p_iou_mgr->obj );\r
+\r
+       p_bfi = p_ext->bus_filter;\r
+       CL_ASSERT( p_bfi );\r
+       BUS_PRINT( BUS_DBG_PNP, ("%s() Releasing BusFilter %s\n",\r
+                                                       __FUNCTION__, p_bfi->whoami ));\r
+       if (p_bfi) {\r
+               p_ext->bus_filter = NULL;\r
+               p_bfi->p_bus_ext = NULL;\r
+       }\r
+\r
+       ic = free_bfi( p_bfi );\r
+\r
+       /* if not last Buf Filter Instance, then exit, otherwise cleanup/shutdown */\r
+       if ( ic > 0 ) {\r
+               BUS_PRINT( BUS_DBG_PNP, ("%s() %d remaining BusFilters\n",\r
+                                               __FUNCTION__, ic ));\r
+               return;\r
+       }\r
+\r
        /* Disable any exported interfaces. */\r
-       status = IoSetDeviceInterfaceState( &p_ext->al_ifc_name, FALSE );\r
+       status = IoSetDeviceInterfaceState( &al_ifc_name, FALSE );\r
        ASSERT( NT_SUCCESS( status ) );\r
-       status = IoSetDeviceInterfaceState( &p_ext->ci_ifc_name, FALSE );\r
+       status = IoSetDeviceInterfaceState( &ci_ifc_name, FALSE );\r
        ASSERT( NT_SUCCESS( status ) );\r
 \r
        /* Release the memory allocated for the interface symbolic names. */\r
-       RtlFreeUnicodeString( &p_ext->ci_ifc_name );\r
-       RtlFreeUnicodeString( &p_ext->al_ifc_name );\r
-\r
-       cl_obj_destroy( &p_ext->p_port_mgr->obj );\r
-       cl_obj_destroy( &p_ext->p_iou_mgr->obj );\r
+       RtlFreeUnicodeString( &ci_ifc_name );\r
+       RtlFreeUnicodeString( &al_ifc_name );\r
 \r
        al_cleanup();\r
 \r
-       bus_globals.p_bus_ext = NULL;\r
-\r
        BUS_EXIT( BUS_DBG_PNP );\r
 }\r
 \r
@@ -431,18 +530,19 @@ fdo_query_capabilities(
 }\r
 \r
 \r
+#if 0 // XXX\r
+\r
 static NTSTATUS\r
-fdo_query_remove_relations(\r
+fdo_query_removal_relations(\r
        IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
        IN                                      IRP* const                              p_irp, \r
                OUT                             cl_irp_action_t* const  p_action )\r
 {\r
        NTSTATUS                        status;\r
+       UNUSED_PARAM( p_dev_obj );\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
-       UNUSED_PARAM( p_dev_obj );\r
-\r
        status = port_mgr_get_bus_relations( 0, p_irp );\r
        if( status == STATUS_SUCCESS || \r
                status == STATUS_NO_SUCH_DEVICE )\r
@@ -471,6 +571,67 @@ fdo_query_remove_relations(
        BUS_EXIT( BUS_DBG_PNP );\r
        return status;\r
 }\r
+#endif\r
+\r
+\r
+static NTSTATUS\r
+fdo_query_bus_relations(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
+       IN                                      IRP* const                              p_irp, \r
+               OUT                             cl_irp_action_t* const  p_action )\r
+{\r
+       NTSTATUS                        status;\r
+       bus_fdo_ext_t           *p_ext;\r
+       bus_filter_t            *p_bfi;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+       CL_ASSERT( p_ext->bus_filter );\r
+       p_bfi = p_ext->bus_filter;\r
+       CL_ASSERT( p_bfi->magic == BFI_MAGIC );\r
+\r
+       BUS_PRINT( BUS_DBG_PNP, ("%s(%s) ca_guid %I64x\n",\r
+                                                       __FUNCTION__,p_bfi->whoami, p_bfi->ca_guid) );\r
+\r
+       if ( p_bfi->ca_guid == 0ULL )\r
+       {\r
+               /* HCA not yet bound to a BFI slot (no PNP ADD event seen), no bus\r
+                * relations yet.\r
+                */\r
+               status = STATUS_SUCCESS;\r
+       }\r
+       else\r
+       {\r
+               status = port_mgr_get_bus_relations( p_bfi->ca_guid, p_irp );\r
+               if( status == STATUS_SUCCESS || \r
+                       status == STATUS_NO_SUCH_DEVICE )\r
+               {\r
+                       status = iou_mgr_get_bus_relations( p_bfi->ca_guid, p_irp );\r
+               }\r
+               if( status == STATUS_NO_SUCH_DEVICE )\r
+                       status = STATUS_SUCCESS;\r
+       }\r
+\r
+       switch( status )\r
+       {\r
+       case STATUS_NO_SUCH_DEVICE:\r
+               *p_action = IrpSkip;\r
+               status = STATUS_SUCCESS;\r
+               break;\r
+\r
+       case STATUS_SUCCESS:\r
+               *p_action = IrpPassDown;\r
+               break;\r
+\r
+       default:\r
+               *p_action = IrpComplete;\r
+               break;\r
+       }\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
 \r
 \r
 void\r
@@ -486,6 +647,8 @@ al_ref_ifc(
        cl_atomic_inc( &p_ext->n_al_ifc_ref );\r
        ObReferenceObject( p_dev_obj );\r
 \r
+       BUS_PRINT( BUS_DBG_PNP, ("  %p->n_al_ifc_ref %d\n",\r
+                               p_ext,p_ext->n_al_ifc_ref )); // XXX\r
        BUS_EXIT( BUS_DBG_PNP );\r
 }\r
 \r
@@ -503,6 +666,8 @@ al_deref_ifc(
        cl_atomic_dec( &p_ext->n_al_ifc_ref );\r
        ObDereferenceObject( p_dev_obj );\r
 \r
+       BUS_PRINT( BUS_DBG_PNP, ("  %p->n_al_ifc_ref %d\n",\r
+                               p_ext,p_ext->n_al_ifc_ref )); // XXX\r
        BUS_EXIT( BUS_DBG_PNP );\r
 }\r
 \r
@@ -520,6 +685,8 @@ al_ref_ci_ifc(
        cl_atomic_inc( &p_ext->n_ci_ifc_ref );\r
        ObReferenceObject( p_dev_obj );\r
 \r
+       BUS_PRINT( BUS_DBG_PNP, ("  %p->n_ci_ifc_ref %d\n",\r
+                               p_ext,p_ext->n_ci_ifc_ref )); // XXX\r
        BUS_EXIT( BUS_DBG_PNP );\r
 }\r
 \r
@@ -537,6 +704,8 @@ al_deref_ci_ifc(
        cl_atomic_dec( &p_ext->n_ci_ifc_ref );\r
        ObDereferenceObject( p_dev_obj );\r
 \r
+       BUS_PRINT( BUS_DBG_PNP, ("  %p->n_ci_ifc_ref %d\n",\r
+                               p_ext,p_ext->n_ci_ifc_ref )); // XXX\r
        BUS_EXIT( BUS_DBG_PNP );\r
 }\r
 \r
@@ -777,9 +946,7 @@ fdo_query_interface(
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
-#pragma warning( push, 3 )\r
        PAGED_CODE();\r
-#pragma warning( pop )\r
 \r
        p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
        \r
@@ -971,7 +1138,8 @@ __fdo_set_power(
        BUS_TRACE( BUS_DBG_POWER, \r
                ("SET_POWER for FDO %p (ext %p): type %s, state %d, action %d \n",\r
                p_dev_obj, p_ext,\r
-               (p_io_stack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",\r
+               (p_io_stack->Parameters.Power.Type)\r
+                       ? "DevicePowerState" : "SystemPowerState",\r
                p_io_stack->Parameters.Power.State.DeviceState, \r
                p_io_stack->Parameters.Power.ShutdownType ));\r
 \r
@@ -1073,16 +1241,18 @@ bus_get_relations(
                         * the PDO will get cleaned up.\r
                         */\r
                        p_pdo_ext->b_reported_missing = TRUE;\r
-                       BUS_TRACE( BUS_DBG_PNP, ("Don't report PDO! %s: PDO %p, ext %p, present %d, missing %d .\n",\r
-                               p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
-                               p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing ) );\r
+                       BUS_TRACE( BUS_DBG_PNP, ("Don't report PDO! %s: PDO %p, ext %p, "\r
+                               "present %d, missing %d .\n",\r
+                               p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
+                               p_pdo_ext->cl_ext.p_self_do, p_pdo_ext, p_pdo_ext->b_present,\r
+                               p_pdo_ext->b_reported_missing ) );\r
                        continue;\r
                }\r
 \r
                if( ca_guid && p_pdo_ext->ca_guid != ca_guid )\r
                        continue;\r
 \r
-               BUS_TRACE( BUS_DBG_PNP, ("Reported PDO %p(=%p), ext %p.\n", \r
+               BUS_TRACE( BUS_DBG_PNP, ("Reported PDO %p(=%p), ext %p\n", \r
                        p_pdo_ext->cl_ext.p_self_do, p_pdo_ext->cl_ext.p_pdo, p_pdo_ext ));\r
                \r
                p_rel->Objects[p_rel->Count] = p_pdo_ext->cl_ext.p_pdo;\r
@@ -1092,3 +1262,256 @@ bus_get_relations(
        BUS_EXIT( BUS_DBG_PNP );\r
        return STATUS_SUCCESS;\r
 }\r
+\r
+\r
+/*\r
+ * find a bus filter instance (p_bfi) given an *cl_obj: port_mgr or iou_mgr. \r
+ */\r
+\r
+bus_filter_t *\r
+get_bfi_by_obj(IN int obj_type, IN cl_obj_t *p_obj )\r
+{\r
+       bus_filter_t    *p_bfi;\r
+       bus_filter_t    *matched=NULL;\r
+\r
+       CL_ASSERT((obj_type == BFI_PORT_MGR_OBJ) || (obj_type == BFI_IOU_MGR_OBJ));\r
+\r
+    ExAcquireFastMutexUnsafe(&ControlMutex);\r
+\r
+       for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++) {\r
+\r
+               if ( !p_bfi->p_bus_ext )\r
+                       continue;\r
+\r
+               if ( obj_type == BFI_PORT_MGR_OBJ ) {\r
+                       if ( p_obj == p_bfi->p_port_mgr_obj ) {\r
+                               matched = p_bfi;\r
+                               break;\r
+                       }\r
+               }\r
+               else {\r
+                       if ( p_obj == p_bfi->p_iou_mgr_obj ) {\r
+                               matched = p_bfi;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       ExReleaseFastMutexUnsafe(&ControlMutex);\r
+\r
+       BUS_PRINT( BUS_DBG_PNP,\r
+                               ("%s() cl_obj %p type %s_MGR_OBJ --> bfi[%d] %p\n",\r
+                               __FUNCTION__,p_obj,\r
+                               (obj_type == BFI_PORT_MGR_OBJ ? "PORT": "IOU"),\r
+                               (matched ? (matched - bus_filters) : (-1)), matched ) );\r
+\r
+       return matched;\r
+}\r
+\r
+/*\r
+ * find a bus filter instance given an HCA guid.\r
+ */\r
+\r
+bus_filter_t *\r
+get_bfi_by_ca_guid( IN net64_t ca_guid )\r
+{\r
+       bus_filter_t    *p_bfi;\r
+       bus_filter_t    *matched=NULL;\r
+\r
+       if ( ca_guid == 0ULL )\r
+       {\r
+               matched = bus_filters;\r
+               BUS_PRINT( BUS_DBG_PNP, ("%s() ERR guid %I64x -> bfi[0] %p\n",\r
+                                                               __FUNCTION__, ca_guid, matched) );\r
+               CL_ASSERT( ca_guid ); // XXX\r
+               return matched;\r
+       }\r
+\r
+       ExAcquireFastMutexUnsafe(&ControlMutex);\r
+\r
+       for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
+       {\r
+               if ( !p_bfi->p_bus_ext )\r
+                       continue;\r
+\r
+               if ( ca_guid == p_bfi->ca_guid )\r
+               {\r
+                       matched = p_bfi;\r
+                       break;\r
+               }\r
+       }\r
+       ExReleaseFastMutexUnsafe(&ControlMutex);\r
+\r
+       BUS_PRINT( BUS_DBG_PNP,\r
+                               ("%s() guid 0x%I64x -> bfi[%d] %p\n",\r
+                               __FUNCTION__, ca_guid,\r
+                               (matched ? (matched - bus_filters) : (-1)), matched ) );\r
+\r
+       return matched;\r
+}\r
+\r
+\r
+/*\r
+ * find/bind the specified ca_guid to a bus filter instance.\r
+ * Called from PORT_ADD or IOU_ADD pnp callback routines with the ca_guid from\r
+ * the pnp event record.\r
+ * Assumption is a BFI slot has been allocated in add_device() although the\r
+ * ca_guid was not known at that time; hence !ca_bound. When PNP generates an\r
+ * 'ADD' event, the port_mgr/iou_mgr pnp callback routine calls here to match\r
+ * the input ca_guid which caused the PNP event to the BFI instance by ca_guid.\r
+ * In the 1st call after add_device() the BFI slot is allocated but not yet \r
+ * bound to a CA guid. If the input ca_guid is not matched, then the 1st\r
+ * allocated but not bound BFI slot is then 'bound' by setting\r
+ * bfi->ca_guid = input ca_guid.\r
+ */\r
+\r
+bus_filter_t *\r
+get_set_bfi_by_ca_guid( IN net64_t ca_guid )\r
+{\r
+       bus_filter_t    *p_bfi;\r
+       bus_filter_t    *matched=NULL;\r
+       boolean_t               ca_bound = FALSE;\r
+\r
+       if ( ca_guid == 0ULL )\r
+       {\r
+               matched = bus_filters;\r
+               BUS_PRINT( BUS_DBG_PNP, ("%s() ERR guid 0x%I64x -> bfi[0] %p\n",\r
+                                       __FUNCTION__, ca_guid, matched) );\r
+               CL_ASSERT( ca_guid ); // XXX\r
+               return matched;\r
+       }\r
+\r
+       for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
+       {\r
+               if ( !p_bfi->p_bus_ext )\r
+                       continue;\r
+\r
+               if ( ca_guid == p_bfi->ca_guid )\r
+               {\r
+                       matched = p_bfi;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       /*\r
+        * if no match, find an 'allocated' bfi slot which does not have a bound CA.\r
+        * Bound == ca_guid != 0ULL.\r
+        */\r
+       if ( !matched )\r
+       {\r
+               ExAcquireFastMutexUnsafe(&ControlMutex);\r
+\r
+               for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
+               {\r
+                       if ( !p_bfi->p_bus_ext )\r
+                               continue;       // not allocated.\r
+\r
+                       if ( p_bfi->ca_guid == 0ULL )\r
+                       {\r
+                               ca_bound = TRUE;\r
+                               p_bfi->ca_guid = ca_guid;       // bind CA & this BFI slot; RTU.\r
+                               matched = p_bfi;\r
+                               break;\r
+                       }\r
+               }\r
+               ExReleaseFastMutexUnsafe(&ControlMutex);\r
+       }\r
+\r
+       BUS_PRINT( BUS_DBG_PNP,\r
+                               ("%s()%sguid 0x%I64x @ bfi[%d] %p \n",\r
+                               __FUNCTION__, (ca_bound ? "SET ":" "), ca_guid,\r
+                               (matched ? (matched - bus_filters) : (-1)), matched ) );\r
+\r
+       return matched;\r
+}\r
+\r
+\r
+bus_filter_t *\r
+alloc_bfi( IN DRIVER_OBJECT  *p_driver_obj, OUT int *p_instance_count )\r
+{\r
+       bus_filter_t    *p_bfi;\r
+       bus_filter_t    *matched=NULL;\r
+\r
+    // Using unsafe function so that the IRQL remains at PASSIVE_LEVEL.\r
+    // IoCreateDeviceSecure & IoCreateSymbolicLink must be called at\r
+    // PASSIVE_LEVEL.\r
+\r
+       ExAcquireFastMutexUnsafe(&ControlMutex);\r
+\r
+       // find 1st unused bfi slot.\r
+       for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
+       {\r
+               if ( !p_bfi->p_bus_ext )\r
+               {\r
+                       /* temp setting until 'real' p_bus_ext is alloc; see bus_add_device.\r
+                        * If p_bus_ext is ! 0, then bfi slot is allocated, although it\r
+                        * may not yet have a bound CA guid; set set_get_\r
+                        */\r
+                       p_bfi->p_bus_ext = (bus_fdo_ext_t*)p_driver_obj;\r
+                       matched = p_bfi;\r
+                       *p_instance_count = ++bfi_InstanceCount; // record in-use\r
+                       break;\r
+               }\r
+       }\r
+       ExReleaseFastMutexUnsafe(&ControlMutex);\r
+\r
+#if DBG\r
+       RtlStringCbPrintfA ( p_bfi->whoami,\r
+                                                sizeof(p_bfi->whoami),\r
+                                                "bfi-%d",\r
+                                                (bfi_InstanceCount - 1) );\r
+\r
+       p_bfi->magic = BFI_MAGIC; // XXX debug\r
+#endif\r
+\r
+       BUS_PRINT( BUS_DBG_PNP, ("%s() %s %p\n",\r
+                               __FUNCTION__, (matched ? matched->whoami:"Nobody"), matched) );\r
+\r
+       return matched;\r
+}\r
+\r
+\r
+int\r
+free_bfi( IN  bus_filter_t  *p_bfi )\r
+{\r
+       int     remaining;\r
+\r
+       ExAcquireFastMutexUnsafe(&ControlMutex);\r
+       p_bfi->p_bus_ext = NULL;\r
+       p_bfi->ca_guid = 0ULL;\r
+       remaining = --bfi_InstanceCount; // one less bfi in-use\r
+       ExReleaseFastMutexUnsafe(&ControlMutex);\r
+\r
+       return remaining;\r
+}\r
+\r
+int\r
+get_bfi_count( void )\r
+{\r
+       int     ic;\r
+\r
+       ExAcquireFastMutexUnsafe(&ControlMutex);\r
+       ic = bfi_InstanceCount;\r
+       ExReleaseFastMutexUnsafe(&ControlMutex);\r
+\r
+       return ic;\r
+}\r
+\r
+#if DBG\r
+char *get_obj_state_str(cl_state_t state)\r
+{\r
+       switch( state ) {\r
+         case CL_UNINITIALIZED:\r
+               return "UNINITIALIZED";\r
+         case CL_INITIALIZED:\r
+               return "INITIALIZED";\r
+         case CL_DESTROYING:\r
+               return "DESTROYING";\r
+         case CL_DESTROYED:\r
+               return "DESTROYED";\r
+         default:\r
+               break;\r
+       }\r
+       return "Err - Bad obj state";\r
+}\r
+#endif\r
+\r
index 8d79576f6fa6f48eb5f086ec614f36f952905ae2..31837284ce0b3773104d4984c144e8e500d7161a 100644 (file)
@@ -71,7 +71,14 @@ typedef struct _bus_port_ext
 }      bus_port_ext_t;\r
 \r
 \r
-port_mgr_t*                                            gp_port_mgr = NULL;\r
+typedef struct _port_pnp_context\r
+{\r
+       bus_filter_t    *p_bus_filter;\r
+       void                    *p_pdo_ext;\r
+       int                             port_num;\r
+\r
+}      port_pnp_ctx_t;\r
+\r
 \r
 extern pkey_array_t  g_pkeys;\r
 \r
@@ -88,7 +95,8 @@ free_port_mgr(
        IN                              cl_obj_t*                                       p_obj );\r
 \r
 ib_api_status_t\r
-bus_reg_port_pnp( void );\r
+bus_reg_port_pnp(\r
+       IN                              bus_filter_t*                           p_bfi );\r
 \r
 ib_api_status_t\r
 port_mgr_pnp_cb(\r
@@ -274,14 +282,16 @@ static const cl_vfptr_query_txt_t         vfptr_port_query_txt = {
  */\r
 ib_api_status_t\r
 create_port_mgr(\r
+               IN                      bus_filter_t*                           p_bfi,\r
                OUT                     port_mgr_t** const                      pp_port_mgr )\r
 {\r
        ib_api_status_t         status;\r
        cl_status_t                     cl_status;\r
+       port_mgr_t                      *gp_port_mgr;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
-       CL_ASSERT( !gp_port_mgr );\r
+       CL_ASSERT( p_bfi->p_port_mgr == NULL );\r
 \r
        gp_port_mgr = cl_zalloc( sizeof( port_mgr_t ) );\r
        if( !gp_port_mgr )\r
@@ -290,9 +300,11 @@ create_port_mgr(
                        ("Failed to allocate port manager.\n") );\r
                return IB_INSUFFICIENT_MEMORY;\r
        }\r
+       p_bfi->p_port_mgr = gp_port_mgr;\r
 \r
        /* Construct the load service. */\r
        cl_obj_construct( &gp_port_mgr->obj, AL_OBJ_TYPE_LOADER );\r
+       p_bfi->p_port_mgr_obj = &gp_port_mgr->obj;\r
        cl_mutex_construct( &gp_port_mgr->pdo_mutex );\r
        cl_qlist_init( &gp_port_mgr->port_list );\r
 \r
@@ -307,7 +319,8 @@ create_port_mgr(
 \r
        /* Initialize the load service object. */\r
        cl_status = cl_obj_init( &gp_port_mgr->obj, CL_DESTROY_SYNC,\r
-               destroying_port_mgr, NULL, free_port_mgr );\r
+                                                        destroying_port_mgr, NULL, free_port_mgr );\r
+\r
        if( cl_status != CL_SUCCESS )\r
        {\r
                free_port_mgr( &gp_port_mgr->obj );\r
@@ -316,13 +329,13 @@ create_port_mgr(
                return ib_convert_cl_status( cl_status );\r
        }\r
 \r
-       /* Register for port PnP events. */\r
-       status = bus_reg_port_pnp();\r
+       /* Register for port PnP events */\r
+       status = bus_reg_port_pnp(p_bfi);\r
        if( status != IB_SUCCESS )\r
        {\r
-               cl_obj_destroy( &gp_port_mgr->obj );\r
                BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
                        ("bus_reg_port_pnp returned %s.\n", ib_get_err_str(status)) );\r
+               free_port_mgr( &gp_port_mgr->obj );\r
                return status;\r
        }\r
 \r
@@ -341,20 +354,35 @@ destroying_port_mgr(
        IN                              cl_obj_t*                                       p_obj )\r
 {\r
        ib_api_status_t                 status;\r
+       bus_filter_t                    *p_bfi;\r
+       port_mgr_t                              *gp_port_mgr;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
        CL_ASSERT( p_obj );\r
+       p_bfi = get_bfi_by_obj(BFI_PORT_MGR_OBJ, p_obj);\r
+       if (p_bfi == NULL) {\r
+               BUS_PRINT(BUS_DBG_PNP, ("%s() failed to find p_bfi by obj %p?\n",\r
+                       __FUNCTION__,p_obj));\r
+               return;\r
+       }\r
+       gp_port_mgr = p_bfi->p_port_mgr;\r
+\r
+       BUS_PRINT(BUS_DBG_PNP, ("%s(%s) obj %p port_mgr %p port_mgr_obj %p\n",\r
+                       __FUNCTION__,p_bfi->whoami,p_obj,gp_port_mgr,\r
+                       p_bfi->p_port_mgr_obj) );\r
+\r
+       CL_ASSERT( (void*)p_bfi->p_port_mgr == (void*)p_bfi->p_port_mgr_obj );\r
        CL_ASSERT( gp_port_mgr == PARENT_STRUCT( p_obj, port_mgr_t, obj ) );\r
-       UNUSED_PARAM( p_obj );\r
 \r
-       /* Deregister for port PnP events. */\r
-       if( gp_port_mgr->h_pnp )\r
-       {\r
-               status = ib_dereg_pnp( gp_port_mgr->h_pnp,\r
-                       (ib_pfn_destroy_cb_t)cl_obj_deref );\r
+       /* Deregister for port PnP events if this is the last Port manager. */\r
+       if ( get_bfi_count() == 1 && bus_globals.h_pnp_port ) {\r
+               status = ib_dereg_pnp( bus_globals.h_pnp_port, NULL );\r
+               bus_globals.h_pnp_port = NULL;\r
                CL_ASSERT( status == IB_SUCCESS );\r
        }\r
+       cl_obj_deref( p_bfi->p_port_mgr_obj );\r
+\r
        BUS_EXIT( BUS_DBG_PNP );\r
 }\r
 \r
@@ -368,12 +396,32 @@ free_port_mgr(
 {\r
        bus_pdo_ext_t   *p_ext;\r
        cl_list_item_t  *p_list_item;\r
+       bus_filter_t    *p_bfi;\r
+       port_mgr_t              *gp_port_mgr;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
        CL_ASSERT( p_obj );\r
+       p_bfi = get_bfi_by_obj(BFI_PORT_MGR_OBJ, p_obj);\r
+       if (p_bfi == NULL) {\r
+               BUS_PRINT(BUS_DBG_PNP, ("%s: unable to get p_bfi for port obj %p?\n",\r
+                       __FUNCTION__,p_obj));\r
+               return;\r
+       }\r
+       gp_port_mgr = p_bfi->p_port_mgr;\r
+       if ( !gp_port_mgr ) {\r
+               // if create fails & then free is called, p_bfi->p_port_mgr == NULL\r
+               return;\r
+       }\r
        CL_ASSERT( gp_port_mgr == PARENT_STRUCT( p_obj, port_mgr_t, obj ) );\r
 \r
+       BUS_PRINT(BUS_DBG_PNP, ("%s(%s) obj %p port_mgr %p port_mgr_obj %p\n",\r
+                       __FUNCTION__, p_bfi->whoami, p_obj,gp_port_mgr,\r
+                       p_bfi->p_port_mgr_obj) );\r
+\r
+       BUS_PRINT( BUS_DBG_PNP,\r
+                               ("%s(%s) Mark all IPoIB PDOs as no longer present\n",\r
+                               __FUNCTION__, p_bfi->whoami));\r
        /*\r
         * Mark all IPoIB PDOs as no longer present.  This will cause them\r
         * to be removed when they process the IRP_MN_REMOVE_DEVICE.\r
@@ -387,8 +435,11 @@ free_port_mgr(
                {\r
                        CL_ASSERT( !p_ext->b_present );\r
                        p_ext->b_reported_missing = TRUE;\r
-                       BUS_TRACE( BUS_DBG_PNP, ("%s: PDO %p, ext %p, present %d, missing %d .\n",\r
-                               p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
+                       BUS_TRACE( BUS_DBG_PNP,\r
+                               ("%s %s: PDO %p, ext %p, present %d, missing %d .\n",\r
+                               p_bfi->whoami,\r
+                               p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do,\r
+                               p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
                        continue;\r
                }\r
                if( p_ext->h_ca )\r
@@ -400,15 +451,26 @@ free_port_mgr(
                        /* Release the reference on the CA object. */\r
                        deref_al_obj( &p_ext->h_ca->obj );\r
                }\r
-               BUS_TRACE( BUS_DBG_PNP, ("Deleted device %s: PDO %p, ext %p\n",\r
-                       p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext ) );\r
+\r
+               BUS_TRACE( BUS_DBG_PNP, ("%s Deleted device %s: PDO %p, ext %p\n",\r
+                                       p_bfi->whoami, p_ext->cl_ext.vfptr_pnp_po->identity,\r
+                                       p_ext->cl_ext.p_self_do, p_ext ) );\r
+\r
+               BUS_TRACE( BUS_DBG_PNP,("%s(%s) h_ca->obj.state %s refs %d\n",\r
+                                               __FUNCTION__, p_bfi->whoami,\r
+                                               get_obj_state_str(p_ext->h_ca->obj.state),\r
+                                               p_ext->h_ca->obj.ref_cnt)); // XXX\r
+\r
                IoDeleteDevice( p_ext->cl_ext.p_self_do );\r
        }\r
 \r
        cl_mutex_destroy( &gp_port_mgr->pdo_mutex );\r
        cl_obj_deinit( p_obj );\r
        cl_free( gp_port_mgr );\r
-       gp_port_mgr = NULL;\r
+\r
+       p_bfi->p_port_mgr = NULL;\r
+       p_bfi->p_port_mgr_obj = NULL;\r
+\r
        BUS_EXIT( BUS_DBG_PNP );\r
 }\r
 \r
@@ -417,22 +479,26 @@ free_port_mgr(
  * Register the load service for the given PnP class events.\r
  */\r
 ib_api_status_t\r
-bus_reg_port_pnp( void )\r
+bus_reg_port_pnp( IN bus_filter_t *p_bfi )\r
 {\r
        ib_pnp_req_t                    pnp_req;\r
-       ib_api_status_t                 status;\r
+       ib_api_status_t                 status = IB_SUCCESS;\r
 \r
-       cl_memclr( &pnp_req, sizeof( ib_pnp_req_t ) );\r
-       pnp_req.pnp_class       = IB_PNP_PORT | IB_PNP_FLAG_REG_SYNC;\r
-       pnp_req.pnp_context = gp_port_mgr;\r
-       pnp_req.pfn_pnp_cb      = port_mgr_pnp_cb;\r
+       /* only need to register for PNP once */\r
+       ExAcquireFastMutexUnsafe(&ControlMutex);\r
+       if ( !bus_globals.h_pnp_port ) {\r
+               cl_memclr( &pnp_req, sizeof( ib_pnp_req_t ) );\r
+               pnp_req.pnp_class       = IB_PNP_PORT | IB_PNP_FLAG_REG_SYNC;\r
+               pnp_req.pnp_context = NULL;\r
+               pnp_req.pfn_pnp_cb      = port_mgr_pnp_cb;\r
 \r
-       status = ib_reg_pnp( gh_al, &pnp_req, &gp_port_mgr->h_pnp );\r
+               status = ib_reg_pnp( gh_al, &pnp_req, &bus_globals.h_pnp_port );\r
+       }\r
+       ExReleaseFastMutexUnsafe(&ControlMutex);\r
 \r
-       if( status == IB_SUCCESS )\r
-       {\r
-               /* Reference the load service on behalf of the ib_reg_pnp call. */\r
-               cl_obj_ref( &gp_port_mgr->obj );\r
+       if( status == IB_SUCCESS ) {\r
+               /* Reference this bus filter's port load service */\r
+               cl_obj_ref( &p_bfi->p_port_mgr->obj );\r
        }\r
 \r
        return status;\r
@@ -446,12 +512,11 @@ ib_api_status_t
 port_mgr_pnp_cb(\r
        IN                              ib_pnp_rec_t*                           p_pnp_rec )\r
 {\r
-       ib_api_status_t         status;\r
+       ib_api_status_t         status=IB_SUCCESS;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
        CL_ASSERT( p_pnp_rec );\r
-       CL_ASSERT( gp_port_mgr == p_pnp_rec->pnp_context );\r
 \r
        switch( p_pnp_rec->pnp_event )\r
        {\r
@@ -461,12 +526,15 @@ port_mgr_pnp_cb(
 \r
        case IB_PNP_PORT_REMOVE:\r
                port_mgr_port_remove( (ib_pnp_port_rec_t*)p_pnp_rec );\r
+               break;\r
 \r
        default:\r
-               status = IB_SUCCESS;\r
+               XBUS_PRINT( BUS_DBG_PNP, ("%s() Unhandled PNP Event %s\n",\r
+                                       __FUNCTION__, ib_get_pnp_event_str(p_pnp_rec->pnp_event) ));\r
                break;\r
        }\r
        BUS_EXIT( BUS_DBG_PNP );\r
+\r
        return status;\r
 }\r
 \r
@@ -480,9 +548,50 @@ port_mgr_get_bus_relations(
        IN                              IRP* const                                      p_irp )\r
 {\r
        NTSTATUS                        status;\r
+       bus_filter_t            *p_bfi;\r
+       port_mgr_t                      *gp_port_mgr;\r
+       DEVICE_RELATIONS        *p_rel;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
+       BUS_PRINT(BUS_DBG_PNP, ("%s() ca_guid %I64x\n",__FUNCTION__,ca_guid));\r
+\r
+       /* special case guid == 0 - walk all bus filter instances */\r
+       if ( ca_guid == 0ULL ) {\r
+               for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++) {\r
+                       gp_port_mgr = p_bfi->p_port_mgr;\r
+                       if ( !gp_port_mgr )\r
+                               continue;\r
+                       cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
+                       status = bus_get_relations( &gp_port_mgr->port_list,\r
+                                                                               ca_guid,\r
+                                                                               p_irp );\r
+                       cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
+               }\r
+\r
+               p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
+               if ( p_rel ) {\r
+                       BUS_PRINT(BUS_DBG_PNP, ("%s() ca_guid 0 Reports %d\n",\r
+                                               __FUNCTION__,p_rel->Count));\r
+               }\r
+               BUS_EXIT( BUS_DBG_PNP );\r
+               return STATUS_SUCCESS;\r
+       }\r
+\r
+       p_bfi = get_bfi_by_ca_guid(ca_guid);\r
+       if (p_bfi == NULL) {\r
+               BUS_PRINT(BUS_DBG_PNP,\r
+                       ("%s() Null *p_bfi from ca_guid %I64x\n",__FUNCTION__,ca_guid));\r
+               BUS_EXIT( BUS_DBG_PNP );\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+       gp_port_mgr = p_bfi->p_port_mgr;\r
+\r
+       BUS_PRINT(BUS_DBG_PNP, ("%s(%s) for ca_guid %I64x port_mgr %p\n",\r
+                               __FUNCTION__, p_bfi->whoami, ca_guid, gp_port_mgr) );\r
+       if (!gp_port_mgr)\r
+               return STATUS_NO_SUCH_DEVICE;\r
+\r
        cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
        status = bus_get_relations( &gp_port_mgr->port_list, ca_guid, p_irp );\r
        cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
@@ -493,15 +602,19 @@ port_mgr_get_bus_relations(
 \r
 static ib_api_status_t\r
 __port_was_hibernated(\r
-       IN                              ib_pnp_port_rec_t*                      p_pnp_rec )\r
+       IN                              ib_pnp_port_rec_t*                      p_pnp_rec,\r
+       IN                              bus_filter_t*                           p_bfi )\r
 {\r
        NTSTATUS                status;\r
-       cl_list_item_t          *p_list_item;\r
+       cl_list_item_t  *p_list_item;\r
        bus_port_ext_t  *p_port_ext;\r
        bus_pdo_ext_t   *p_pdo_ext = NULL;\r
        size_t                  n_devs = 0;\r
+       port_mgr_t              *gp_port_mgr = p_bfi->p_port_mgr;\r
        cl_qlist_t*             p_pdo_list = &gp_port_mgr->port_list;\r
 \r
+       port_pnp_ctx_t  *p_ctx = p_pnp_rec->pnp_rec.context;\r
+\r
        BUS_ENTER( BUS_DBG_PNP );\r
        \r
        cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
@@ -521,9 +634,11 @@ __port_was_hibernated(
                        break;\r
                }\r
 \r
-               BUS_TRACE( BUS_DBG_PNP, \r
-                       ("Skipped PDO for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
-                       p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
+               BUS_TRACE( BUS_DBG_PNP, ("%s Skipped PDO for %s: PDO %p, ext %p, "\r
+                       "present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
+                       p_bfi->whoami,\r
+                       p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
+                       p_pdo_ext->cl_ext.p_self_do, \r
                        p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
                        p_pdo_ext->b_hibernating, p_port_ext->port_guid.guid  ) );\r
        }\r
@@ -534,27 +649,33 @@ __port_was_hibernated(
                p_pdo_ext->h_ca = acquire_ca( p_pnp_rec->p_ca_attr->ca_guid );\r
                if( !p_pdo_ext->h_ca )\r
                {\r
-                       BUS_TRACE( BUS_DBG_ERROR, ("acquire_ca failed to find CA by guid %I64x\n",\r
-                               p_pnp_rec->p_ca_attr->ca_guid ) );\r
+                       BUS_TRACE( BUS_DBG_ERROR,\r
+                               ("%s acquire_ca failed to find CA by guid %I64x\n",\r
+                               p_bfi->whoami, p_pnp_rec->p_ca_attr->ca_guid ) );\r
                        status = IB_INVALID_GUID;\r
                }\r
                else \r
                {\r
                        p_pdo_ext->b_hibernating = FALSE;\r
-                       p_pnp_rec->pnp_rec.context = p_pdo_ext;\r
+\r
+                       CL_ASSERT( p_ctx );\r
+                       p_ctx->p_pdo_ext = p_pdo_ext; // save for port_mgr_port_remove\r
+\r
                        status = IB_SUCCESS;\r
                        p_port_ext = (bus_port_ext_t*)p_pdo_ext;\r
-                       BUS_TRACE( BUS_DBG_PNP, \r
-                               ("Found PDO for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
-                               p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
+                       BUS_TRACE( BUS_DBG_PNP, ("%s Found PDO for %s: PDO %p, ext %p, "\r
+                               "present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
+                               p_bfi->whoami,\r
+                               p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
+                               p_pdo_ext->cl_ext.p_self_do, \r
                                p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
                                p_pdo_ext->b_hibernating, p_port_ext->port_guid.guid ) );\r
                }\r
        }\r
        else \r
        {\r
-               BUS_TRACE( BUS_DBG_PNP, ("Failed to find PDO for guid  %I64x .\n",\r
-                       p_pnp_rec->p_ca_attr->ca_guid ) );\r
+               BUS_TRACE( BUS_DBG_PNP, ("%s Failed to find PDO for guid  %I64x .\n",\r
+                                       p_bfi->whoami, p_pnp_rec->p_ca_attr->ca_guid ) );\r
                status = IB_NOT_FOUND;\r
        }\r
 \r
@@ -564,6 +685,69 @@ __port_was_hibernated(
        return status;\r
 }\r
 \r
+\r
+void\r
+dump_pnp_port_rec( ib_pnp_port_rec_t*  pr )\r
+{\r
+       BUS_PRINT( BUS_DBG_PNP, ("%s() ib_pnp_port_rec_t* @ %p\nib_pnp_rec_t*:\n",\r
+                               __FUNCTION__,pr));\r
+\r
+\r
+       BUS_PRINT( BUS_DBG_PNP, ("  Event %s\n",\r
+                               ib_get_pnp_event_str(pr->pnp_rec.pnp_event) ));\r
+\r
+       BUS_PRINT( BUS_DBG_PNP, ("  pnp_context %p\n",pr->pnp_rec.pnp_context));\r
+       BUS_PRINT( BUS_DBG_PNP, ("  context %p\n",pr->pnp_rec.context));\r
+       BUS_PRINT( BUS_DBG_PNP, ("  guid %I64x\n",pr->pnp_rec.guid));\r
+       BUS_PRINT( BUS_DBG_PNP, ("  ca_guid %I64x\n",pr->pnp_rec.ca_guid));\r
+\r
+       if ( !pr->p_ca_attr ) {\r
+               BUS_PRINT( BUS_DBG_PNP, ("  NULL *p_ca_attr ?\n"));\r
+       }\r
+       else {\r
+               BUS_PRINT( BUS_DBG_PNP, ("*p_ca_attr\n"));\r
+               BUS_PRINT( BUS_DBG_PNP, ("  ca_guid 0x%I64x\n",\r
+                                                               pr->p_ca_attr->ca_guid ) );\r
+       }\r
+       if ( !pr->p_port_attr ) {\r
+               BUS_PRINT( BUS_DBG_PNP, ("  NULL *p_port_attr?\n"));\r
+       }\r
+       else {\r
+               BUS_PRINT( BUS_DBG_PNP, ("*p_port_attr:\n"));\r
+               BUS_PRINT( BUS_DBG_PNP, ("  port_guid 0x%I64x port_num %d\n",\r
+                                                               pr->p_port_attr->port_guid,\r
+                                                               pr->p_port_attr->port_num ));\r
+       }\r
+}\r
+\r
+void\r
+dump_pnp_iou_rec( ib_pnp_iou_rec_t*    pr )\r
+{\r
+       BUS_PRINT( BUS_DBG_PNP, ("%s() ib_pnp_iou_rec_t* @ %p\nib_pnp_rec_t*:\n",\r
+                               __FUNCTION__,pr));\r
+\r
+\r
+       BUS_PRINT( BUS_DBG_PNP, ("  Event %s\n",\r
+                               ib_get_pnp_event_str(pr->pnp_rec.pnp_event) ));\r
+\r
+       BUS_PRINT( BUS_DBG_PNP, ("  pnp_context %p\n",pr->pnp_rec.pnp_context));\r
+       BUS_PRINT( BUS_DBG_PNP, ("  context %p\n",pr->pnp_rec.context));\r
+       BUS_PRINT( BUS_DBG_PNP, ("  guid %I64x\n",pr->pnp_rec.guid));\r
+       BUS_PRINT( BUS_DBG_PNP, ("  ca_guid %I64x\n",pr->pnp_rec.ca_guid));\r
+\r
+       BUS_PRINT( BUS_DBG_PNP, ("pnp_iou_rec_t:\n" ));\r
+       BUS_PRINT( BUS_DBG_PNP,\r
+                               ("  guid 0x%I64x\n  ca_guid %I64x\n  chassis_guid %I64x\n",\r
+                               pr->guid, pr->ca_guid, pr->chassis_guid ));\r
+       BUS_PRINT( BUS_DBG_PNP,\r
+                               ("  slot 0x%x\n  vend_id 0x%x\n  dev_id 0x%x  revision 0x%x\n",\r
+                               pr->slot, pr->vend_id, pr->dev_id, pr->revision ));\r
+       if ( pr->desc[0] ) {\r
+               BUS_PRINT( BUS_DBG_PNP, ("  Desc %s\n",pr->desc ));\r
+       }\r
+}\r
+\r
+\r
 ib_api_status_t\r
 port_mgr_port_add(\r
        IN                              ib_pnp_port_rec_t*                      p_pnp_rec )\r
@@ -573,18 +757,56 @@ port_mgr_port_add(
     uint8_t         num_pdo;\r
        bus_port_ext_t  *p_port_ext;\r
        ib_net16_t      pdo_cnt;\r
+       bus_filter_t    *p_bfi;\r
+       port_mgr_t              *gp_port_mgr;\r
+       port_pnp_ctx_t  *p_ctx = p_pnp_rec->pnp_rec.context;\r
+\r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
+       CL_ASSERT( p_pnp_rec->p_ca_attr->ca_guid );\r
+\r
+       p_bfi = get_set_bfi_by_ca_guid( p_pnp_rec->p_ca_attr->ca_guid );\r
+       if ( !p_bfi ) {\r
+               BUS_PRINT( BUS_DBG_PNP,("%s() NULL p_bfi? ca_guid 0x%I64x\n",\r
+                                                               __FUNCTION__, p_pnp_rec->p_ca_attr->ca_guid ) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       /*\r
+        * Allocate a PNP context for this object. pnp_rec.context is obj unique.\r
+        */\r
+       if ( !p_ctx ) {\r
+               p_ctx = cl_zalloc( sizeof(*p_ctx) );\r
+               if( !p_ctx )\r
+               {\r
+                       BUS_PRINT(BUS_DBG_PNP,\r
+                                       ("%s(%s) ca_guid %I64x port(%d) BAD alloc PNP context\n",\r
+                                       __FUNCTION__, p_bfi->whoami, p_bfi->ca_guid, \r
+                                       p_pnp_rec->p_port_attr->port_num));\r
+                       return IB_ERROR;\r
+               }\r
+               p_ctx->p_bus_filter = p_bfi;\r
+               p_ctx->port_num = p_pnp_rec->p_port_attr->port_num;\r
+               p_pnp_rec->pnp_rec.context = p_ctx;\r
+\r
+               BUS_PRINT(BUS_DBG_PNP,\r
+                                       ("%s(%s) ca_guid %I64x port %d ALLOC p_ctx @ %p\n",\r
+                                       __FUNCTION__, p_bfi->whoami, p_bfi->ca_guid, \r
+                                       p_pnp_rec->p_port_attr->port_num,p_ctx));\r
+       }\r
+       gp_port_mgr = p_bfi->p_port_mgr;\r
+\r
        if( !bus_globals.b_report_port_nic )\r
        {\r
                BUS_EXIT( BUS_DBG_PNP );\r
                return IB_NOT_DONE;\r
        }\r
 \r
-       /* Upon hibernating of the computer IB_BUS driver doesn't remove PDO, but\r
+       /* Upon hibernating the computer IB_BUS driver doesn't remove PDO, but\r
           marks with a flag. So we first try to find an existing PDO for this port,\r
-          marked with this flag. If it was found, we turn off the flag and use this PDO */\r
-       status = __port_was_hibernated(p_pnp_rec);\r
+          marked with this flag. If it was found, we turn off the flag and use\r
+          this PDO */\r
+       status = __port_was_hibernated( p_pnp_rec, p_bfi );\r
        if( status != IB_NOT_FOUND )\r
        {\r
                BUS_EXIT( BUS_DBG_PNP );\r
@@ -600,73 +822,82 @@ port_mgr_port_add(
 \r
     for (num_pdo = 0; num_pdo < pdo_cnt; num_pdo++)\r
     {\r
-       /* Create the PDO for the new port device. */\r
-       status = IoCreateDevice( bus_globals.p_driver_obj, sizeof(bus_port_ext_t),\r
-               NULL, FILE_DEVICE_CONTROLLER,\r
-               FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,\r
-                       FALSE, &p_pdo[num_pdo] );\r
-       if( !NT_SUCCESS( status ) )\r
-       {\r
-               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
-                       ("IoCreateDevice returned %08x.\n", status) );\r
-               return IB_ERROR;\r
-       }\r
+               /* Create the PDO for the new port device. */\r
+               status = IoCreateDevice( bus_globals.p_driver_obj,\r
+                                                                sizeof(bus_port_ext_t),\r
+                                                                NULL, FILE_DEVICE_CONTROLLER,\r
+                                                                FILE_DEVICE_SECURE_OPEN |\r
+                                                                                       FILE_AUTOGENERATED_DEVICE_NAME,\r
+                                                                FALSE, &p_pdo[num_pdo] );\r
+               if( !NT_SUCCESS( status ) )\r
+               {\r
+                       BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                               ("IoCreateDevice returned %08x.\n", status) );\r
+                       return IB_ERROR;\r
+               }\r
 \r
-       /* Initialize the device extension. */\r
-               cl_init_pnp_po_ext( p_pdo[num_pdo], NULL, p_pdo[num_pdo], bus_globals.dbg_lvl,\r
-               &vfptr_port_pnp, &vfptr_port_query_txt );\r
+               /* Initialize the device extension. */\r
+               cl_init_pnp_po_ext( p_pdo[num_pdo], NULL, p_pdo[num_pdo],\r
+                                                       bus_globals.dbg_lvl, &vfptr_port_pnp,\r
+                                                       &vfptr_port_query_txt );\r
 \r
-       /* Set the DO_BUS_ENUMERATED_DEVICE flag to mark it as a PDO. */\r
+               /* Set the DO_BUS_ENUMERATED_DEVICE flag to mark it as a PDO. */\r
                p_pdo[num_pdo]->Flags |= DO_BUS_ENUMERATED_DEVICE;\r
 \r
                p_port_ext = p_pdo[num_pdo]->DeviceExtension;\r
-       p_port_ext->pdo.dev_po_state.DeviceState = PowerDeviceD0;\r
-       p_port_ext->pdo.p_parent_ext = bus_globals.p_bus_ext;\r
-       p_port_ext->pdo.b_present = TRUE;\r
-       p_port_ext->pdo.b_reported_missing = FALSE;\r
-       p_port_ext->pdo.b_hibernating = FALSE;\r
-       p_port_ext->pdo.p_po_work_item = NULL;\r
-       BUS_TRACE( BUS_DBG_PNP, ("Created device for %s: PDO %p,ext %p, present %d, missing %d .\n",\r
-                       p_port_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_pdo[num_pdo], p_port_ext, p_port_ext->pdo.b_present, \r
-               p_port_ext->pdo.b_reported_missing ) );\r
-\r
-       /* Cache the CA GUID. */\r
-       p_port_ext->pdo.ca_guid = p_pnp_rec->p_ca_attr->ca_guid;\r
-\r
-       /* Take a reference on the parent HCA. */\r
+               p_port_ext->pdo.dev_po_state.DeviceState = PowerDeviceD0;\r
+               p_port_ext->pdo.p_parent_ext = p_bfi->p_bus_ext;\r
+               p_port_ext->pdo.b_present = TRUE;\r
+               p_port_ext->pdo.b_reported_missing = FALSE;\r
+               p_port_ext->pdo.b_hibernating = FALSE;\r
+               p_port_ext->pdo.p_po_work_item = NULL;\r
+               BUS_TRACE( BUS_DBG_PNP,\r
+                       ("Created %s %s: PDO %p,ext %p, present %d, missing %d .\n",\r
+                       p_bfi->whoami,\r
+                       p_port_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_pdo[num_pdo],\r
+                       p_port_ext, p_port_ext->pdo.b_present,\r
+                       p_port_ext->pdo.b_reported_missing ) );\r
+\r
+               /* Cache the CA GUID. */\r
+               p_port_ext->pdo.ca_guid = p_pnp_rec->p_ca_attr->ca_guid;\r
+\r
+               /* Take a reference on the parent HCA. */\r
                if(num_pdo > 0)\r
                {\r
                        p_port_ext->pdo.h_ca = ((bus_port_ext_t*)p_pdo[0]->DeviceExtension)->pdo.h_ca;\r
                }\r
                else\r
-       p_port_ext->pdo.h_ca = acquire_ca( p_pnp_rec->p_ca_attr->ca_guid );\r
-       if( !p_port_ext->pdo.h_ca )\r
-       {\r
+                       p_port_ext->pdo.h_ca = acquire_ca( p_pnp_rec->p_ca_attr->ca_guid );\r
+\r
+               if( !p_port_ext->pdo.h_ca )\r
+               {\r
                        BUS_TRACE( BUS_DBG_PNP, ("Deleted device: PDO %p\n", p_pdo[num_pdo]));\r
                        IoDeleteDevice( p_pdo[num_pdo]);\r
-               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("acquire_ca failed to find CA.\n") );\r
-               return IB_INVALID_GUID;\r
-       }\r
+                       BUS_TRACE_EXIT( BUS_DBG_ERROR, ("acquire_ca failed to find CA.\n") );\r
+                       return IB_INVALID_GUID;\r
+               }\r
                p_port_ext->port_guid.guid = p_pnp_rec->p_port_attr->port_guid;\r
-       p_port_ext->n_port = p_pnp_rec->p_port_attr->port_num;\r
+               p_port_ext->n_port = p_pnp_rec->p_port_attr->port_num;\r
                p_port_ext->port_guid.pkey = IB_DEFAULT_PKEY;\r
+               p_port_ext->n_ifc_ref = 0;\r
 \r
                if(num_pdo > 0)\r
                {\r
                  p_port_ext->port_guid.pkey = g_pkeys.pkey_array[num_pdo -1];\r
                }\r
-       /* Store the device extension in the port vector for future queries. */\r
-       cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
-       cl_qlist_insert_tail( &gp_port_mgr->port_list,\r
-               &p_port_ext->pdo.list_item );\r
-       cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
 \r
-       /*\r
-        * Set the context of the PNP event.  The context is passed in for future\r
-        * events on the same port.\r
-        */\r
+               /* Store the device extension in the port vector for future queries. */\r
+               cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
+               cl_qlist_insert_tail( &gp_port_mgr->port_list,\r
+                                                         &p_port_ext->pdo.list_item );\r
+               cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
+\r
+               /*\r
+                * save the port_ext, as the context is passed in for future events on\r
+                * the same port.\r
+                */\r
                if(num_pdo == 0)\r
-                       p_pnp_rec->pnp_rec.context = p_port_ext;\r
+                       p_ctx->p_pdo_ext = p_port_ext;\r
        }\r
        pkeys_enumerated = TRUE;\r
 \r
@@ -674,9 +905,11 @@ port_mgr_port_add(
        IoInvalidateDeviceRelations(\r
                p_port_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
 \r
+#if 0 // XXX\r
        /* Invalidate removal relations for the bus driver. */\r
-       IoInvalidateDeviceRelations(\r
-               bus_globals.p_bus_ext->cl_ext.p_pdo, RemovalRelations );\r
+       IoInvalidateDeviceRelations( p_bfi->p_bus_ext->cl_ext.p_pdo,\r
+                                                                RemovalRelations );\r
+#endif\r
 \r
        BUS_EXIT( BUS_DBG_PNP );\r
        return IB_SUCCESS;\r
@@ -697,10 +930,14 @@ cl_status_t port_mgr_pkey_add(pkey_array_t *pkeys)
        bus_port_ext_t          *p_port_ext, *pkey_port_ext;\r
        DEVICE_OBJECT       *p_pdo[MAX_NUM_PKEY];\r
        bus_pdo_ext_t           *p_pdo_ext = NULL;\r
-       cl_qlist_t*                     p_pdo_list = &gp_port_mgr->port_list;\r
+       cl_qlist_t*                     p_pdo_list;\r
+       bus_filter_t            *p_bfi = &bus_filters[0];// pass in ca_guid? | all CA's?\r
+       port_mgr_t                      *gp_port_mgr;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
+       gp_port_mgr = p_bfi->p_port_mgr;        \r
+       p_pdo_list = &gp_port_mgr->port_list;\r
        p_port_ext = NULL;\r
        cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
        \r
@@ -720,18 +957,19 @@ cl_status_t port_mgr_pkey_add(pkey_array_t *pkeys)
        if (!p_port_ext)\r
        {\r
                BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
-                       ("No existed pdo found.\n") );\r
+                       ("No existing pdo found.\n") );\r
                return CL_ERROR;\r
        }\r
 \r
     for (cnt = 0; cnt < pkeys->pkey_num; cnt++)\r
     {\r
-\r
                /* Create the PDO for the new port device. */\r
-               status = IoCreateDevice( bus_globals.p_driver_obj, sizeof(bus_port_ext_t),\r
-                       NULL, FILE_DEVICE_CONTROLLER,\r
-                       FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,\r
-                       FALSE, &p_pdo[cnt] );\r
+               status = IoCreateDevice( bus_globals.p_driver_obj,\r
+                                                                sizeof(bus_port_ext_t),\r
+                                                                NULL, FILE_DEVICE_CONTROLLER,\r
+                                                                FILE_DEVICE_SECURE_OPEN\r
+                                                                                       | FILE_AUTOGENERATED_DEVICE_NAME,\r
+                                                                FALSE, &p_pdo[cnt] );\r
                if( !NT_SUCCESS( status ) )\r
                {\r
                        BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
@@ -741,20 +979,22 @@ cl_status_t port_mgr_pkey_add(pkey_array_t *pkeys)
        \r
                /* Initialize the device extension. */\r
                cl_init_pnp_po_ext( p_pdo[cnt], NULL, p_pdo[cnt], bus_globals.dbg_lvl,\r
-                       &vfptr_port_pnp, &vfptr_port_query_txt );\r
+                                                       &vfptr_port_pnp, &vfptr_port_query_txt );\r
        \r
                /* Set the DO_BUS_ENUMERATED_DEVICE flag to mark it as a PDO. */\r
                p_pdo[cnt]->Flags |= DO_BUS_ENUMERATED_DEVICE;\r
        \r
                pkey_port_ext = p_pdo[cnt]->DeviceExtension;\r
                pkey_port_ext->pdo.dev_po_state.DeviceState = PowerDeviceD0;\r
-               pkey_port_ext->pdo.p_parent_ext = bus_globals.p_bus_ext;\r
+               pkey_port_ext->pdo.p_parent_ext = p_bfi->p_bus_ext;\r
                pkey_port_ext->pdo.b_present = TRUE;\r
                pkey_port_ext->pdo.b_reported_missing = FALSE;\r
                pkey_port_ext->pdo.b_hibernating = FALSE;\r
                pkey_port_ext->pdo.p_po_work_item = NULL;\r
-               BUS_TRACE( BUS_DBG_PNP, ("Created device for %s: PDO %p,ext %p, present %d, missing %d .\n",\r
-                       pkey_port_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_pdo[cnt], pkey_port_ext, pkey_port_ext->pdo.b_present, \r
+               BUS_TRACE( BUS_DBG_PNP,\r
+                       ("Created device for %s: PDO %p,ext %p, present %d, missing %d\n",\r
+                       pkey_port_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_pdo[cnt],\r
+                       pkey_port_ext, pkey_port_ext->pdo.b_present, \r
                        pkey_port_ext->pdo.b_reported_missing ) );\r
        \r
                /* Cache the CA GUID. */\r
@@ -775,9 +1015,11 @@ cl_status_t port_mgr_pkey_add(pkey_array_t *pkeys)
        IoInvalidateDeviceRelations(\r
                p_port_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
 \r
+#if 0 // XXX\r
        /* Invalidate removal relations for the bus driver. */\r
-       IoInvalidateDeviceRelations(\r
-               bus_globals.p_bus_ext->cl_ext.p_pdo, RemovalRelations );\r
+       IoInvalidateDeviceRelations( p_bfi->p_bus_ext->cl_ext.p_pdo,\r
+                                                                RemovalRelations );\r
+#endif\r
 \r
        BUS_EXIT( BUS_DBG_PNP );\r
        return CL_SUCCESS;\r
@@ -785,48 +1027,108 @@ cl_status_t port_mgr_pkey_add(pkey_array_t *pkeys)
 \r
 void\r
 port_mgr_port_remove(\r
-       IN                              ib_pnp_port_rec_t*                      p_pnp_rec )\r
+       IN                              ib_pnp_port_rec_t*              p_pnp_rec )\r
 {\r
        bus_pdo_ext_t   *p_ext;\r
+       port_mgr_t              *gp_port_mgr;\r
+       bus_filter_t    *p_bfi;\r
+       port_pnp_ctx_t  *p_ctx = p_pnp_rec->pnp_rec.context;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
-       /* The PNP record's context is the port extension. */\r
-       p_ext = p_pnp_rec->pnp_rec.context;\r
+       if ( !p_ctx ) {\r
+               BUS_EXIT( BUS_DBG_PNP );\r
+               return;\r
+       }\r
+\r
+       CL_ASSERT( p_ctx->p_bus_filter->magic == BFI_MAGIC );\r
+       p_bfi = p_ctx->p_bus_filter;\r
+       CL_ASSERT( p_bfi );\r
+\r
+       BUS_PRINT(BUS_DBG_PNP,("%s(%s) ca_guid 0x%I64x port_num %d port_mgr %p\n",\r
+                                               __FUNCTION__, p_bfi->whoami, p_bfi->ca_guid,\r
+                                               p_ctx->port_num, p_bfi->p_port_mgr));\r
+\r
+       /* in the process of device remove, port_mgr has been destroyed.\r
+        * cleanup allocated PNP port context; one per port.\r
+        * The issue is the PNP PORT_REMOVE event occurs after\r
+        * fdo_release_resources() completes.\r
+        */\r
+       if ( p_bfi->ca_guid == 0ULL || !p_bfi->p_port_mgr ) {\r
+               cl_free( p_ctx );\r
+               p_pnp_rec->pnp_rec.context = NULL;\r
+               BUS_EXIT( BUS_DBG_PNP );\r
+               return;\r
+       }\r
+\r
+       gp_port_mgr = p_bfi->p_port_mgr;\r
+\r
+       /* Within the PNP record's context is the port extension ptr;\r
+        * see port_was_hibernated().\r
+        */\r
+       p_ext = p_ctx->p_pdo_ext;\r
        CL_ASSERT( p_ext );\r
 \r
+       CL_ASSERT(p_bfi == p_ext->p_parent_ext->bus_filter);\r
+#if DBG // XXX\r
+       if (p_bfi != p_ext->p_parent_ext->bus_filter) {\r
+               BUS_PRINT(BUS_DBG_PNP,\r
+                       ("%s() p_bfi(%p) != p_ext->bus_filter(%p) line %d file %s\n",\r
+                       __FUNCTION__,p_bfi,p_ext->p_parent_ext->bus_filter,\r
+                       __LINE__,__FILE__));\r
+       }\r
+#endif\r
+\r
        /*\r
         * Flag the port PDO as no longer being present.  We have to wait until\r
         * the PnP manager removes it to clean up.  However, we do release the\r
         * reference on the CA object in order to allow the removal of the HCA\r
         * to proceed should it occur before the port's PDO is cleaned up.\r
         */\r
+       if ( !p_ext->h_ca )\r
+       {\r
+               BUS_TRACE( BUS_DBG_PNP, ("%s() %s NULL h_ca? p_ext %p\n",\r
+                                       __FUNCTION__, p_bfi->whoami, p_ext ) );\r
+               return;\r
+       }\r
+\r
        cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
        CL_ASSERT( p_ext->h_ca );\r
 \r
        if( p_ext->b_hibernating )\r
        {\r
-               BUS_TRACE( BUS_DBG_PNP, ("Skip port removing for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d .\n",\r
-                       p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext, p_ext->b_present, \r
-                       p_ext->b_reported_missing, p_ext->b_hibernating ) );\r
+               BUS_TRACE( BUS_DBG_PNP, ("Skip port removing for %s: PDO %p, ext %p, "\r
+                       "present %d, missing %d, hibernating %d .\n",\r
+                       p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do,\r
+                       p_ext, p_ext->b_present, p_ext->b_reported_missing,\r
+                       p_ext->b_hibernating ) );\r
                goto hca_deref;\r
        }\r
 \r
        p_ext->b_present = FALSE;\r
-       BUS_TRACE( BUS_DBG_PNP, ("Mark removing %s: PDO %p, ext %p, present %d, missing %d .\n",\r
-               p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
+       p_ext->b_reported_missing = TRUE;\r
 \r
+       BUS_TRACE( BUS_DBG_PNP,\r
+               ("Mark removing %s: PDO %p, ext %p, present %d, missing %d .\n",\r
+               p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext,\r
+               p_ext->b_present, p_ext->b_reported_missing ) );\r
+\r
+#if 0 // XXX\r
        /* Invalidate removal relations for the bus driver. */\r
-       IoInvalidateDeviceRelations( bus_globals.p_bus_ext->cl_ext.p_pdo,\r
-               RemovalRelations );\r
+       IoInvalidateDeviceRelations( p_bfi->p_bus_ext->cl_ext.p_pdo,\r
+                                                                RemovalRelations );\r
+#endif\r
 \r
        /* Invalidate bus relations for the HCA. */\r
        IoInvalidateDeviceRelations(\r
                p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
 \r
+       /* Free PNP context memory */\r
+       cl_free( p_ctx );\r
+       p_pnp_rec->pnp_rec.context = NULL;\r
+\r
 hca_deref:\r
        deref_al_obj( &p_ext->h_ca->obj );\r
-       p_ext->h_ca = NULL;\r
        cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
 \r
        BUS_EXIT( BUS_DBG_PNP );\r
@@ -850,7 +1152,9 @@ port_start(
        /* Notify the Power Manager that the device is started. */\r
        PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
        *p_action = IrpComplete;\r
+\r
        BUS_EXIT( BUS_DBG_PNP );\r
+\r
        return STATUS_SUCCESS;\r
 }\r
 \r
@@ -869,6 +1173,9 @@ port_query_remove(
 \r
        p_ext = p_dev_obj->DeviceExtension;\r
 \r
+BUS_PRINT( BUS_DBG_PNP, ("%s() %p->n_ifc_ref %d\n",\r
+       __FUNCTION__,p_ext,p_ext->n_ifc_ref ));\r
+\r
        *p_action = IrpComplete;\r
        if( p_ext->n_ifc_ref )\r
        {\r
@@ -895,14 +1202,17 @@ port_release_resources(
 {\r
        bus_port_ext_t  *p_ext;\r
        POWER_STATE             po_state;\r
+       port_mgr_t              *gp_port_mgr;\r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
        p_ext = p_dev_obj->DeviceExtension;\r
+       gp_port_mgr = p_ext->pdo.p_parent_ext->bus_filter->p_port_mgr;\r
 \r
        /* Remove this PDO from its list. */\r
        cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
-       BUS_TRACE( BUS_DBG_PNP, ("Removing port from vector: PDO %p, ext %p\n", p_dev_obj, p_ext) );\r
+       BUS_TRACE( BUS_DBG_PNP, ("Removing port from vector: PDO %p, ext %p\n",\r
+                               p_dev_obj, p_ext) );\r
        cl_qlist_remove_item( &gp_port_mgr->port_list, &p_ext->pdo.list_item );\r
        cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
        po_state.DeviceState = PowerDeviceD3;\r
@@ -932,7 +1242,9 @@ port_remove(
                cl_set_pnp_state( &p_ext->pdo.cl_ext, NotStarted );\r
                /* Don't delete the device.  It may simply be disabled. */\r
                *p_action = IrpComplete;\r
-               BUS_TRACE_EXIT( BUS_DBG_PNP, ("Device still present: PDO %p, ext %p\n", p_dev_obj, p_ext) );\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP,\r
+                               ("Device %s still present: PDO %p, ext %p\n",\r
+                               p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_dev_obj, p_ext) );\r
                return STATUS_SUCCESS;\r
        }\r
 \r
@@ -941,7 +1253,10 @@ port_remove(
                /* Reset the state to RemovePending.  Complib set it to Deleted. */\r
                cl_rollback_pnp_state( &p_ext->pdo.cl_ext );\r
                *p_action = IrpComplete;\r
-               BUS_TRACE_EXIT( BUS_DBG_PNP, ("Device not reported missing yet: PDO %p, ext %p\n", p_dev_obj, p_ext) );\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP,\r
+                                               ("Device %s not reported missing yet: PDO %p, ext %p\n",\r
+                                               p_ext->pdo.cl_ext.vfptr_pnp_po->identity,\r
+                                               p_dev_obj, p_ext) );\r
                return STATUS_SUCCESS;\r
        }\r
 \r
@@ -955,8 +1270,9 @@ port_remove(
        p_irp->IoStatus.Status = STATUS_SUCCESS;\r
        IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
 \r
-       BUS_TRACE( BUS_DBG_PNP, ("Deleted device %s: PDO %p(=%p), ext %p\n",\r
-               p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_ext->pdo.cl_ext.p_self_do, p_dev_obj, p_ext ) );\r
+       BUS_PRINT/*XXX TRACE*/( BUS_DBG_PNP, ("Deleted device %s: PDO %p(=%p), ext %p\n",\r
+               p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_ext->pdo.cl_ext.p_self_do,\r
+               p_dev_obj, p_ext ) );\r
        IoDeleteDevice( p_dev_obj );\r
 \r
        *p_action = IrpDoNothing;\r
@@ -1382,7 +1698,6 @@ port_query_ipoib_ifc(
        ipoib_ifc_data_t                *p_ipoib_data;\r
        bus_port_ext_t                  *p_ext;\r
        const GUID                              *p_guid;\r
-       \r
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
@@ -1455,6 +1770,9 @@ port_query_ipoib_ifc(
        p_ipoib_data->port_guid = p_ext->port_guid;\r
        p_ipoib_data->port_num = (uint8_t)p_ext->n_port;\r
 \r
+       BUS_TRACE_EXIT( BUS_DBG_PNP,\r
+                       ("  %p->n_ifc_ref %d\n",p_ext,p_ext->n_ifc_ref) ); //XXX\r
+\r
        BUS_EXIT( BUS_DBG_PNP );\r
        return STATUS_SUCCESS;\r
 }\r
@@ -1472,9 +1790,7 @@ port_query_interface(
 \r
        BUS_ENTER( BUS_DBG_PNP );\r
 \r
-#pragma warning( push, 3 )\r
        PAGED_CODE();\r
-#pragma warning( pop )\r
 \r
        p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
 \r
index 9bb70f005c215b3e4da547c4cfdf23d00d0251e1..1d0eb7f0e9e749d3d035ccb44ac9b41ff1e80825 100644 (file)
@@ -43,7 +43,6 @@
 typedef struct _port_mgr\r
 {\r
        cl_obj_t                                        obj;\r
-       ib_pnp_handle_t                         h_pnp;  /* Handle for port PnP events */\r
 \r
        /* Mutex protects both pointer vectors. */\r
        cl_mutex_t                                      pdo_mutex;\r
@@ -54,8 +53,11 @@ typedef struct _port_mgr
 }      port_mgr_t;\r
 \r
 \r
+struct _bus_filter_instance;\r
+\r
 ib_api_status_t\r
 create_port_mgr(\r
+       IN                              struct _bus_filter_instance     *p_bfi,\r
                OUT                     port_mgr_t** const                      pp_port_mgr );\r
 \r
 \r
diff --git a/branches/winverbs/core/bus/kernel/etc/ib_iou.inf b/branches/winverbs/core/bus/kernel/etc/ib_iou.inf
new file mode 100644 (file)
index 0000000..7ea47ed
--- /dev/null
@@ -0,0 +1,127 @@
+; OpenIB InfiniBand Bus/IOU Driver.\r
+; Copyright 2005 SilverStorm Technologies all Rights Reserved.\r
+; Copyright 2006 Mellanox Technologies all Rights Reserved.\r
+\r
+[Version]\r
+Signature="$Windows NT$"\r
+Class=System\r
+ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318}\r
+Provider=%OPENIB%\r
+DriverVer=04/29/2008,1.1.0000.1085\r
+\r
+; ================= Device Install section =====================\r
+\r
+; 64-bit platforms also copy 32-bit user-mode binaries.\r
+[DestinationDirs]\r
+DefaultDestDir=%DIRID_DRIVERS%\r
+\r
+[SourceDisksNames.x86]\r
+1=%DiskId%,,,""\r
+\r
+[SourceDisksNames.amd64]\r
+1=%DiskId%,,,""\r
+\r
+[SourceDisksNames.ia64]\r
+1=%DiskId%,,,""\r
+\r
+[SourceDisksFiles.x86]\r
+ibiou.sys=1\r
+\r
+[SourceDisksFiles.amd64]\r
+ibiou.sys=1\r
+\r
+[SourceDisksFiles.ia64]\r
+ibiou.sys=1\r
+\r
+[Manufacturer]\r
+%OPENIB% = GenIOU.DeviceSection,ntx86,ntamd64,ntia64\r
+%SST% = QLogicIOU.DeviceSection,ntx86,ntamd64,ntia64\r
+\r
+[GenIOU.DeviceSection]\r
+; empty since we don't support W9x/Me\r
+\r
+[GenIOU.DeviceSection.ntx86]\r
+%Iou.DeviceDesc% = Iou.DDInstall,IBA\IB_IOU\r
+\r
+[GenIOU.DeviceSection.ntamd64]\r
+%Iou.DeviceDesc% = Iou.DDInstall,IBA\IB_IOU\r
+\r
+[GenIOU.DeviceSection.ntia64]\r
+%Iou.DeviceDesc% = Iou.DDInstall,IBA\IB_IOU\r
+\r
+[QLogicIOU.DeviceSection]\r
+; empty since we don't support W9x/Me\r
+\r
+[QLogicIOU.DeviceSection.ntx86]\r
+%VFx.DeviceDesc% = Iou.DDInstall,IBA\V00066aP0060,IBA\V00066aP0010\r
+%VEx.DeviceDesc% = Iou.DDInstall,IBA\V00066aP0058\r
+%FVIC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00dd\r
+%EVIC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00de\r
+%BC2FC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00e0\r
+%BC2GE.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00e1\r
+\r
+[QLogicIOU.DeviceSection.ntamd64]\r
+%VFx.DeviceDesc% = Iou.DDInstall,IBA\V00066aP0060,IBA\V00066aP0010\r
+%VEx.DeviceDesc% = Iou.DDInstall,IBA\V00066aP0058\r
+%FVIC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00dd\r
+%EVIC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00de\r
+%BC2FC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00e0\r
+%BC2GE.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00e1\r
+\r
+[QLogicIOU.DeviceSection.ntia64]\r
+%VFx.DeviceDesc% = Iou.DDInstall,IBA\V00066aP0060,IBA\V00066aP0010\r
+%VEx.DeviceDesc% = Iou.DDInstall,IBA\V00066aP0058\r
+%FVIC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00dd\r
+%EVIC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00de\r
+%BC2FC.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00e0\r
+%BC2GE.DeviceDesc% = Iou.DDInstall,IBA\V00066aP00e1\r
+\r
+[Iou.DDInstall.nt]\r
+CopyFiles = Iou.CopyFiles\r
+\r
+[Iou.DDInstall.nt.Services]\r
+AddService = ibiou,%SPSVCINST_ASSOCSERVICE%,Iou.ServiceInstall\r
+;AddService = ibiou,,Iou.ServiceInstall\r
+\r
+[Iou.CopyFiles]\r
+ibiou.sys\r
+\r
+;\r
+; ============= Service Install section ==============\r
+;\r
+\r
+[Iou.ServiceInstall]\r
+DisplayName    = %Iou.ServiceDesc%\r
+ServiceType     = %SERVICE_KERNEL_DRIVER%\r
+StartType       = %SERVICE_DEMAND_START%\r
+ErrorControl    = %SERVICE_ERROR_NORMAL%\r
+ServiceBinary   = %12%\ibiou.sys\r
+AddReg          = Iou.ParamsReg\r
+\r
+[Iou.ParamsReg]\r
+HKR,"Parameters","DebugLevel",%REG_DWORD%,2\r
+HKR,"Parameters","DebugFlags",%REG_DWORD%,0x00ffffff\r
+\r
+[Strings]\r
+OPENIB = "OpenFabrics Alliance"\r
+SST = "SilverStorm Technologies"\r
+VFx.DeviceDesc = "SilverStorm VFx"\r
+VEx.DeviceDesc = "SilverStorm VEx"\r
+FVIC.DeviceDesc = "SilverStorm FVIC"\r
+EVIC.DeviceDesc = "SilverStorm EVIC"\r
+BC2FC.DeviceDesc = "QLogic InfiniBand Fibre Channel Bridge Module"\r
+BC2GE.DeviceDesc = "QLogic InfiniBand Ethernet Bridge Module"\r
+\r
+Iou.DeviceDesc = "InfiniBand I/O Unit"\r
+Iou.ServiceDesc = "OpenIB InfiniBand  I/O Unit Driver"\r
+DiskId = "OpenIB InfiniBand Access Layer installation disk"\r
+SPSVCINST_NULL = 0x0\r
+SPSVCINST_ASSOCSERVICE = 0x00000002\r
+SERVICE_KERNEL_DRIVER  = 1\r
+SERVICE_DEMAND_START   = 3\r
+SERVICE_ERROR_NORMAL   = 1\r
+REG_DWORD              = 0x00010001\r
+REG_DWORD_NO_CLOBBER   = 0x00010003\r
+DIRID_SYSTEM           = 11\r
+DIRID_DRIVERS          = 12\r
+DIRID_SYSTEM_X86       = 16425\r
diff --git a/branches/winverbs/core/bus/kernel/etc/mthca.cdf b/branches/winverbs/core/bus/kernel/etc/mthca.cdf
new file mode 100644 (file)
index 0000000..c7003df
--- /dev/null
@@ -0,0 +1,22 @@
+[CatalogHeader]\r
+Name=mthca.cat\r
+PublicVersion=0x0000001\r
+EncodingType=0x00010001\r
+CATATTR1=0x10010001:OSAttr:2:6.0\r
+[CatalogFiles]\r
+<hash>mthca.inf=mthca.inf\r
+<hash>mthca.sys=mthca.sys\r
+<hash>mthcau.dll=mthcau.dll\r
+<hash>mthcaud.dll=mthcaud.dll\r
+<hash>mthca32.dll=mthca32.dll\r
+<hash>mthca32d.dll=mthca32d.dll\r
+<hash>ibal.dll=ibal.dll\r
+<hash>ibald.dll=ibald.dll\r
+<hash>complib.dll=complib.dll\r
+<hash>complibd.dll=complibd.dll\r
+<hash>cl32.dll=cl32.dll\r
+<hash>cl32d.dll=cl32d.dll\r
+<hash>ibal32.dll=ibal32.dll\r
+<hash>ibal32d.dll=ibal32d.dll\r
+<hash>ibbus.sys=ibbus.sys\r
+\r
diff --git a/branches/winverbs/core/bus/kernel/etc/mthca.inx b/branches/winverbs/core/bus/kernel/etc/mthca.inx
new file mode 100644 (file)
index 0000000..c47375f
--- /dev/null
@@ -0,0 +1,318 @@
+; Mellanox Technologies InfiniBand HCAs.\r
+; Copyright 2005 Mellanox Technologies all Rights Reserved.\r
+\r
+[Version]\r
+Signature="$Windows NT$"\r
+Class=InfiniBandController\r
+ClassGUID={58517E00-D3CF-40c9-A679-CEE5752F4491}\r
+Provider=%OFA%\r
+; must be synchronized with MTHCA_DEV.H\r
+DriverVer=05/19/2008,2.0.0000.1177\r
+CatalogFile=mthca.cat\r
+\r
+; ================= Destination directory section =====================\r
+\r
+[DestinationDirs]\r
+DefaultDestDir=%DIRID_DRIVERS%\r
+MTHCA.UMCopyFiles=%DIRID_SYSTEM%\r
+MTHCA.WOW64CopyFiles=%DIRID_SYSTEM_X86%\r
+Ibal.UMCopyFiles=%DIRID_SYSTEM%\r
+Ibal.WOW64CopyFiles=%DIRID_SYSTEM_X86%\r
+\r
+; ================= Class Install section =====================\r
+\r
+[ClassInstall32]\r
+AddReg=ClassAddReg\r
+\r
+[ClassAddReg]\r
+HKR,,,0,"RDMA Channel Adapters"\r
+HKR,,Icon,,-5\r
+HKR,,SilentInstall,,0\r
+HKR,,"UpperFilters",0x00010000,"ibbus" ; enable IBBUS/AL Filter driver loading.\r
+\r
+\r
+; ================= Device Install section =====================\r
+\r
+[SourceDisksNames.x86]\r
+1=%DiskId%,,,""\r
+\r
+[SourceDisksNames.amd64]\r
+1=%DiskId%,,,""\r
+\r
+[SourceDisksNames.ia64]\r
+1=%DiskId%,,,""\r
+\r
+[SourceDisksFiles]\r
+mthca.sys=1,,\r
+mthcau.dll=1,,\r
+mthcaud.dll=1,,\r
+ibal.dll=1,,\r
+complib.dll=1,,\r
+ibald.dll=1,,\r
+complibd.dll=1,,\r
+ibbus.sys=1,,\r
+\r
+[SourceDisksFiles.amd64]\r
+mthca.sys=1,,\r
+mthcau.dll=1,,\r
+mthcaud.dll=1,,\r
+mthca32.dll=1,,\r
+mthca32d.dll=1,,\r
+ibal.dll=1,,\r
+ibald.dll=1,,\r
+complib.dll=1,,\r
+complibd.dll=1,,\r
+cl32.dll=1,,\r
+cl32d.dll=1,,\r
+ibal32.dll=1,,\r
+ibal32d.dll=1,,\r
+ibbus.sys=1,,\r
+\r
+[SourceDisksFiles.ia64]\r
+mthca.sys=1,,\r
+mthcau.dll=1,,\r
+mthcaud.dll=1,,\r
+mthca32.dll=1,,\r
+mthca32d.dll=1,,\r
+ibal.dll=1,,\r
+ibald.dll=1,,\r
+complib.dll=1,,\r
+complibd.dll=1,,\r
+cl32.dll=1,,\r
+cl32d.dll=1,,\r
+ibal32.dll=1,,\r
+ibal32d.dll=1,,\r
+ibbus.sys=1,,\r
+\r
+[Manufacturer]\r
+%MTL% = HCA.DeviceSection,ntx86,ntamd64,ntia64\r
+\r
+[HCA.DeviceSection]\r
+; empty since we don't support W9x/Me\r
+\r
+[HCA.DeviceSection.ntx86]\r
+%MT23108.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5A44\r
+%MT23109.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5A45\r
+%MT25208.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6278\r
+%MT25209.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6279\r
+%MT25218.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6282\r
+%MT24204.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5E8C\r
+%MT24205.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5E8D\r
+%MT25204.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6274\r
+%MT25205.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6275\r
+\r
+[HCA.DeviceSection.ntamd64]\r
+%MT23108.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5A44\r
+%MT23109.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5A45\r
+%MT25208.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6278\r
+%MT25209.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6279\r
+%MT25218.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6282\r
+%MT24204.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5E8C\r
+%MT24205.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5E8D\r
+%MT25204.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6274\r
+%MT25205.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6275\r
+\r
+[HCA.DeviceSection.ntia64]\r
+%MT23108.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5A44\r
+%MT23109.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5A45\r
+%MT25208.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6278\r
+%MT25209.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6279\r
+%MT25218.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6282\r
+%MT24204.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5E8C\r
+%MT24205.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_5E8D\r
+%MT25204.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6274\r
+%MT25205.DeviceDesc%=MTHCA.DDInstall, PCI\VEN_15B3&DEV_6275\r
+\r
+[MTHCA.DDInstall.ntx86]\r
+CopyFiles = MTHCA.CopyFiles\r
+CopyFiles = MTHCA.UMCopyFiles\r
+CopyFiles = Ibal.UMCopyFiles\r
+CopyFiles = Ibbus.CopyFiles\r
+\r
+[MTHCA.DDInstall.ntamd64]\r
+CopyFiles = MTHCA.CopyFiles\r
+CopyFiles = MTHCA.UMCopyFiles\r
+CopyFiles = MTHCA.WOW64CopyFiles\r
+CopyFiles = Ibal.UMCopyFiles\r
+CopyFiles = Ibal.WOW64CopyFiles\r
+CopyFiles = Ibbus.CopyFiles\r
+\r
+[MTHCA.DDInstall.ntia64]\r
+CopyFiles = MTHCA.CopyFiles\r
+CopyFiles = MTHCA.UMCopyFiles\r
+CopyFiles = MTHCA.WOW64CopyFiles\r
+CopyFiles = Ibal.UMCopyFiles\r
+CopyFiles = Ibal.WOW64CopyFiles\r
+CopyFiles = Ibbus.CopyFiles\r
+\r
+\r
+; ============== Services ==============\r
+\r
+[MTHCA.DDInstall.ntx86.Services]\r
+AddService = mthca,%SPSVCINST_ASSOCSERVICE%,MTHCA.ServiceInstall,MTHCA.EventLog\r
+AddService = ibbus,,Ibbus.ServiceInstall\r
+\r
+[MTHCA.DDInstall.ntamd64.Services]\r
+AddService = mthca,%SPSVCINST_ASSOCSERVICE%,MTHCA.ServiceInstall,MTHCA.EventLog\r
+AddService = ibbus,,Ibbus.ServiceInstall\r
+\r
+[MTHCA.DDInstall.ntia64.Services]\r
+AddService = mthca,%SPSVCINST_ASSOCSERVICE%,MTHCA.ServiceInstall,MTHCA.EventLog\r
+AddService = ibbus,,Ibbus.ServiceInstall\r
+\r
+\r
+; ============= File Copy ==============\r
+\r
+[MTHCA.CopyFiles]\r
+mthca.sys\r
+\r
+[MTHCA.UMCopyFiles]\r
+mthcau.dll,,,2\r
+mthcaud.dll,,,2\r
+\r
+[MTHCA.WOW64CopyFiles]\r
+mthcau.dll,mthca32.dll,,2\r
+mthcaud.dll,mthca32d.dll,,2\r
+\r
+[Ibal.UMCopyFiles]\r
+ibal.dll,,,2\r
+ibald.dll,,,2\r
+complib.dll,,,2\r
+complibd.dll,,,2\r
+\r
+[Ibal.WOW64CopyFiles]\r
+ibal.dll,ibal32.dll,,2\r
+ibald.dll,ibal32d.dll,,2\r
+complib.dll,cl32.dll,,2\r
+complibd.dll,cl32d.dll,,2\r
+\r
+[Ibbus.CopyFiles]\r
+ibbus.sys\r
+\r
+\r
+;\r
+; ============= MTHCA Service Install section ==============\r
+;\r
+\r
+[MTHCA.ServiceInstall]\r
+DisplayName     = %MTHCA.ServiceDesc%\r
+ServiceType     = %SERVICE_KERNEL_DRIVER%\r
+StartType       = %SERVICE_DEMAND_START%\r
+ErrorControl    = %SERVICE_ERROR_NORMAL%\r
+ServiceBinary   = %12%\mthca.sys\r
+LoadOrderGroup  = extended base\r
+AddReg          = MTHCA.ParamsReg\r
+\r
+\r
+[MTHCA.EventLog]\r
+AddReg = MTHCA.AddEventLogReg\r
+\r
+[MTHCA.AddEventLogReg]\r
+HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\mthca.sys"\r
+HKR, , TypesSupported,   0x00010001, 7\r
+\r
+[MTHCA.ParamsReg]\r
+HKR,"Parameters","DebugLevel",%REG_DWORD%,0x00000003\r
+HKR,"Parameters","DebugFlags",%REG_DWORD%,0x0000ffff\r
+HKR,"Parameters","SkipTavorReset",%REG_DWORD%,0\r
+HKR,"Parameters","DisableTavorResetOnFailure",%REG_DWORD%,1\r
+HKR,"Parameters","TunePci",%REG_DWORD%,0\r
+HKR,"Parameters","ProcessorAffinity",%REG_DWORD%,0\r
+HKR,"Parameters","MaxDpcTimeUs",%REG_DWORD%,10000\r
+HKR,"Parameters","ProfileQpNum",%REG_DWORD%,0\r
+HKR,"Parameters","ProfileRdOut",%REG_DWORD%,0xffffffff\r
+HKLM,"System\CurrentControlSet\Control\WMI\GlobalLogger\8bf1f640-63fe-4743-b9ef-fa38c695bfde","Flags",%REG_DWORD%,0xffff\r
+HKLM,"System\CurrentControlSet\Control\WMI\GlobalLogger\8bf1f640-63fe-4743-b9ef-fa38c695bfde","Level",%REG_DWORD%,0x3\r
+\r
+\r
+; ============= IBBUS/AL Service Install section ==============\r
+;\r
+\r
+[Ibbus.ServiceInstall]\r
+DisplayName     = %Ibbus.ServiceDesc%\r
+ServiceType     = %SERVICE_KERNEL_DRIVER%\r
+StartType       = %SERVICE_DEMAND_START%\r
+ErrorControl    = %SERVICE_ERROR_NORMAL%\r
+ServiceBinary   = %12%\ibbus.sys\r
+LoadOrderGroup  = PnP Filter\r
+AddReg          = Ibbus.ParamsReg\r
+Dependencies   = mthca\r
+\r
+[Ibbus.ParamsReg]\r
+HKR,"Parameters","IbalDebugLevel",%REG_DWORD%,2\r
+HKR,"Parameters","IbalDebugFlags",%REG_DWORD%,0x00ffffff\r
+HKR,"Parameters","SmiPollInterval",%REG_DWORD_NO_CLOBBER%,20000\r
+HKR,"Parameters","IocQueryTimeout",%REG_DWORD_NO_CLOBBER%,250\r
+HKR,"Parameters","IocQueryRetries",%REG_DWORD_NO_CLOBBER%,4\r
+HKR,"Parameters","IocPollInterval",%REG_DWORD_NO_CLOBBER%,30000\r
+HKR,"Parameters","DebugFlags",%REG_DWORD%,0x80000000\r
+HKR,"Parameters","ReportPortNIC",%REG_DWORD%,1\r
+\r
+\r
+; ============= Uninstall Section =============\r
+\r
+[DefaultUninstall.ntx86]\r
+DelFiles   = MTHCA.CopyFiles\r
+DelFiles   = MTHCA.UMCopyFiles\r
+DelReg     = MTHCA.ParamsReg\r
+DelReg     = MTHCA.AddEventLogReg\r
+DelReg     = ClassAddReg\r
+DelFiles   = Ibal.UMCopyFiles\r
+\r
+\r
+[DefaultUninstall.ntamd64]\r
+DelFiles   = MTHCA.CopyFiles\r
+DelFiles   = MTHCA.UMCopyFiles\r
+DelFiles   = MTHCA.WOW64CopyFiles\r
+DelReg     = MTHCA.ParamsReg\r
+DelReg     = MTHCA.AddEventLogReg\r
+DelReg     = ClassAddReg\r
+DelFiles   = Ibal.UMCopyFiles\r
+DelFiles   = Ibal.WOW64CopyFiles\r
+\r
+\r
+[DefaultUninstall.ntia64]\r
+DelFiles   = MTHCA.CopyFiles\r
+DelFiles   = MTHCA.UMCopyFiles\r
+DelFiles   = MTHCA.WOW64CopyFiles\r
+DelReg     = MTHCA.ParamsReg\r
+DelReg     = MTHCA.AddEventLogReg\r
+DelReg     = ClassAddReg\r
+DelFiles   = Ibal.UMCopyFiles\r
+DelFiles   = Ibal.WOW64CopyFiles\r
+\r
+\r
+[DefaultUninstall.Services]\r
+DelService = Ibbus,%SPSVCINST_STOPSERVICE%\r
+DelService = mthca,%SPSVCINST_STOPSERVICE%\r
+\r
+\r
+[Strings]\r
+IBClassGuid = "{58517E00-D3CF-40c9-A679-CEE5752F4491}"\r
+OFA = "OpenFabrics Alliance"\r
+MTL="Mellanox Technologies Ltd."\r
+MTHCA.ServiceDesc = "Driver for Mellanox InfiniHost Devices"\r
+MT23108.DeviceDesc="InfiniHost (MT23108) - Mellanox InfiniBand HCA"\r
+MT23109.DeviceDesc="InfiniHost (MT23109) - Mellanox InfiniBand HCA (burner device)"\r
+MT25208.DeviceDesc="InfiniHost (MT25208) - Mellanox InfiniBand HCA for PCI Express"\r
+MT25209.DeviceDesc="InfiniHost (MT25209) - Mellanox InfiniBand HCA for PCI Express (burner device)"\r
+MT25218.DeviceDesc="InfiniHost III Ex (MT25218) - Mellanox InfiniBand HCA for PCI Express"\r
+MT24204.DeviceDesc="InfiniHost III Lx (MT24204) - Mellanox InfiniBand HCA for PCI Express"\r
+MT24205.DeviceDesc="InfiniHost III Lx (MT24205) - Mellanox InfiniBand HCA for PCI Express (burner device)"\r
+MT25204.DeviceDesc="InfiniHost III Lx (MT25204) - Mellanox InfiniBand HCA for PCI Express"\r
+MT25205.DeviceDesc="InfiniHost III Lx (MT25205) - Mellanox InfiniBand HCA for PCI Express (burner device)"\r
+DiskId = "Mellanox InfiniBand HCA installation disk"\r
+Ibbus.ServiceDesc = "InfiniBand Bus/Fabric/AL (Filter Driver)"\r
+SPSVCINST_NULL = 0x0\r
+SPSVCINST_ASSOCSERVICE = 0x00000002\r
+SPSVCINST_STOPSERVICE  = 0x00000200\r
+SERVICE_KERNEL_DRIVER  = 1\r
+SERVICE_DEMAND_START   = 3\r
+SERVICE_ERROR_NORMAL   = 1\r
+REG_DWORD              = 0x00010001\r
+REG_DWORD_NO_CLOBBER   = 0x00010003\r
+REG_MULTI_SZ_APPEND    = 0x00010008\r
+DIRID_SYSTEM           = 11\r
+DIRID_DRIVERS          = 12\r
+DIRID_SYSTEM_X86       = 16425\r
+\r