]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
[IBBUS] added patch file for review & Leonid's mlx4_hca2.inf
authorstansmith <stansmith@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sat, 2 Aug 2008 01:49:51 +0000 (01:49 +0000)
committerstansmith <stansmith@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sat, 2 Aug 2008 01:49:51 +0000 (01:49 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1@1456 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

branches/winverbs/core/bus/kernel/etc/mlx4_hca2.inf [new file with mode: 0644]
branches/winverbs/core/bus/kernel/ibbus.patch [new file with mode: 0644]

diff --git a/branches/winverbs/core/bus/kernel/etc/mlx4_hca2.inf b/branches/winverbs/core/bus/kernel/etc/mlx4_hca2.inf
new file mode 100644 (file)
index 0000000..7c42b7a
--- /dev/null
@@ -0,0 +1,346 @@
+; Mellanox Technologies InfiniBand HCAs.\r
+; Copyright 2008 Mellanox Technologies all Rights Reserved.\r
+\r
+[Version]\r
+Signature="$WINDOWS NT$"\r
+Class=InfinibandMlx4Controller\r
+ClassGUID={31B0B28A-26FF-4dca-A6FA-E767C7DFBA20}\r
+Provider=%MTL%\r
+; must be synchronized with hca\drv.c\r
+DriverVer=02/01/2008,1.0.0.0\r
+CatalogFile=mlx4_hca.cat\r
+\r
+\r
+;*****************************************\r
+; Destination directory section\r
+;*****************************************\r
+\r
+[DestinationDirs]\r
+DefaultDestDir = %DIRID_DRIVERS%\r
+MLX4HCA.UMCopyFiles = %DIRID_SYSTEM%\r
+MLX4HCA.WOW64CopyFiles = %DIRID_SYSTEM_X86%\r
+;Wdf_CoInstaller_CopyFiles = %DIRID_SYSTEM%\r
+Ibal.UMCopyFiles=%DIRID_SYSTEM%\r
+Ibal.WOW64CopyFiles=%DIRID_SYSTEM_X86%\r
+\r
+\r
+;*****************************************\r
+; Class Install section\r
+;*****************************************\r
+\r
+[ClassInstall32]\r
+AddReg=ClassAddReg\r
+\r
+[ClassAddReg]\r
+HKR,,,,"Mellanox ConnectX Virtual InfiniBand Adapters"\r
+HKR,,Icon,,-5\r
+HKR,,SilentInstall,,0\r
+HKR,,"UpperFilters",0x00010000,"ibbus" ; enable IBBUS/AL Filter driver loading.\r
+\r
+\r
+;*****************************************\r
+; Device Install section\r
+;*****************************************\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
+IbInstaller.dll = 1,,\r
+mlx4_hca.sys = 1,,\r
+mlx4u.dll = 1,,\r
+mlx4ud.dll = 1,,\r
+;wdfcoinstaller01005.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
+IbInstaller.dll = 1,,\r
+mlx4_hca.sys = 1,,\r
+mlx4u.dll = 1,,\r
+mlx4ud.dll = 1,,\r
+mlx4u32.dll = 1,,\r
+mlx4u32d.dll = 1,,\r
+;wdfcoinstaller01005.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
+IbInstaller.dll = 1,,\r
+mlx4_hca.sys = 1,,\r
+mlx4u.dll = 1,,\r
+mlx4ud.dll = 1,,\r
+mlx4u32.dll = 1,,\r
+mlx4u32d.dll = 1,,\r
+;wdfcoinstaller01005.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
+\r
+;*****************************************\r
+; Mlx4Bus  Install Section\r
+;*****************************************\r
+\r
+[Manufacturer]\r
+%MTL% = MLX4HCA.DeviceSection,ntx86,ntamd64,ntia64\r
+\r
+[MLX4HCA.DeviceSection]\r
+; empty since we don't support W9x/Me\r
+\r
+[MLX4HCA.DeviceSection.ntx86]\r
+%Mlx4_Hca.DeviceDesc%=MLX4HCA.DDInstall, MLX4\ConnectX_Hca\r
+\r
+[MLX4HCA.DeviceSection.ntamd64]\r
+%Mlx4_Hca.DeviceDesc%=MLX4HCA.DDInstall, MLX4\ConnectX_Hca\r
+\r
+[MLX4HCA.DeviceSection.ntia64]\r
+%Mlx4_Hca.DeviceDesc%=MLX4HCA.DDInstall, MLX4\ConnectX_Hca\r
+\r
+[MLX4HCA.DDInstall.ntx86]\r
+CopyFiles = MLX4HCA.CopyFiles\r
+CopyFiles = MLX4HCA.UMCopyFiles\r
+CopyFiles = Ibal.UMCopyFiles\r
+CopyFiles = Ibbus.CopyFiles\r
+\r
+[MLX4HCA.DDInstall.ntamd64]\r
+CopyFiles = MLX4HCA.CopyFiles\r
+CopyFiles = MLX4HCA.UMCopyFiles\r
+CopyFiles = MLX4HCA.WOW64CopyFiles\r
+CopyFiles = Ibal.UMCopyFiles\r
+CopyFiles = Ibal.WOW64CopyFiles\r
+CopyFiles = Ibbus.CopyFiles\r
+\r
+[MLX4HCA.DDInstall.ntia64]\r
+CopyFiles = MLX4HCA.CopyFiles\r
+CopyFiles = MLX4HCA.UMCopyFiles\r
+CopyFiles = MLX4HCA.WOW64CopyFiles\r
+CopyFiles = Ibal.UMCopyFiles\r
+CopyFiles = Ibal.WOW64CopyFiles\r
+CopyFiles = Ibbus.CopyFiles\r
+\r
+[MLX4HCA.DDInstall.ntx86.Services]\r
+AddService = mlx4_hca,%SPSVCINST_ASSOCSERVICE%,MLX4HCA.ServiceInstall,MLX4HCA.EventLog\r
+AddService = ibbus,,Ibbus.ServiceInstall\r
+\r
+[MLX4HCA.DDInstall.ntamd64.Services]\r
+AddService = mlx4_hca,%SPSVCINST_ASSOCSERVICE%,MLX4HCA.ServiceInstall,MLX4HCA.EventLog\r
+AddService = ibbus,,Ibbus.ServiceInstall\r
+\r
+[MLX4HCA.DDInstall.ntia64.Services]\r
+AddService = mlx4_hca,%SPSVCINST_ASSOCSERVICE%,MLX4HCA.ServiceInstall,MLX4HCA.EventLog\r
+AddService = ibbus,,Ibbus.ServiceInstall\r
+\r
+\r
+;*****************************************\r
+; File Copy\r
+;*****************************************\r
+\r
+[MLX4HCA.CopyFiles]\r
+mlx4_hca.sys\r
+\r
+[MLX4HCA.UMCopyFiles]\r
+mlx4u.dll,,,2\r
+mlx4ud.dll,,,2\r
+\r
+[MLX4HCA.WOW64CopyFiles]\r
+mlx4u.dll,mlx4u32.dll,,2\r
+mlx4ud.dll,mlx4u32d.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
+; MLX4 Service Install section\r
+;*****************************************\r
+\r
+[MLX4HCA.ServiceInstall]\r
+DisplayName     = %MLX4HCA.ServiceDesc%\r
+ServiceType     = %SERVICE_KERNEL_DRIVER%\r
+StartType       = %SERVICE_DEMAND_START%\r
+ErrorControl    = %SERVICE_ERROR_NORMAL%\r
+ServiceBinary   = %12%\mlx4_hca.sys\r
+LoadOrderGroup  = extended base\r
+AddReg          = MLX4HCA.ParamsReg\r
+\r
+[MLX4HCA.EventLog]\r
+AddReg = MLX4HCA.AddEventLogReg\r
+\r
+[MLX4HCA.AddEventLogReg]\r
+HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\mlx4_hca.sys"\r
+HKR, , TypesSupported,   0x00010001, 7\r
+\r
+[MLX4HCA.ParamsReg]\r
+HKR,,DeviceCharacteristics,0x10001,0x0100         ; Use same security checks on relative opens\r
+HKR,,Security,,"D:P(A;;GA;;;BA)(A;;GA;;;SY)"      ; Allow generic-all access to Built-in administrators and Local system \r
+HKR,"Parameters","DebugLevel",%REG_DWORD%,0x00000003\r
+HKR,"Parameters","DebugFlags",%REG_DWORD%,0x0000ffff\r
+HKLM,"System\CurrentControlSet\Control\WMI\GlobalLogger\F8C96A49-AE22-41e9-8025-D7E416884D89","Flags",%REG_DWORD%,0xffff\r
+HKLM,"System\CurrentControlSet\Control\WMI\GlobalLogger\F8C96A49-AE22-41e9-8025-D7E416884D89","Level",%REG_DWORD%,0x3\r
+\r
+\r
+;*****************************************\r
+; IBBUS 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
+;*****************************************\r
+; Uninstall section (not used now)\r
+;*****************************************\r
+\r
+[DefaultUninstall.ntx86]\r
+DelFiles   = MLX4HCA.CopyFiles\r
+DelFiles   = MLX4HCA.UMCopyFiles\r
+DelReg     = MLX4HCA.ParamsReg\r
+DelReg     = MLX4HCA.AddEventLogReg\r
+DelReg     = ClassAddReg\r
+DelFiles   = Ibal.UMCopyFiles\r
+\r
+\r
+[DefaultUninstall.ntamd64]\r
+DelFiles   = MLX4HCA.CopyFiles\r
+DelFiles   = MLX4HCA.UMCopyFiles\r
+DelFiles   = MLX4HCA.WOW64CopyFiles\r
+DelReg     = MLX4HCA.ParamsReg\r
+DelReg     = MLX4HCA.AddEventLogReg\r
+DelReg     = ClassAddReg\r
+DelFiles   = Ibal.UMCopyFiles\r
+DelFiles   = Ibal.WOW64CopyFiles\r
+DelFiles   = Ibbus.CopyFiles\r
+DelReg     = Ibbus.ParamsReg\r
+\r
+[DefaultUninstall.ntia64]\r
+DelFiles   = MLX4HCA.CopyFiles\r
+DelFiles   = MLX4HCA.UMCopyFiles\r
+DelFiles   = MLX4HCA.WOW64CopyFiles\r
+DelReg     = MLX4HCA.ParamsReg\r
+DelReg     = MLX4HCA.AddEventLogReg\r
+DelReg     = ClassAddReg\r
+DelFiles   = Ibal.UMCopyFiles\r
+DelFiles   = Ibal.WOW64CopyFiles\r
+DelFiles   = Ibbus.CopyFiles\r
+DelReg     = Ibbus.ParamsReg\r
+\r
+[DefaultUninstall.Services]\r
+DelService = Ibbus,%SPSVCINST_STOPSERVICE%\r
+DelService = mthca,%SPSVCINST_STOPSERVICE%\r
+\r
+\r
+;\r
+; The below section is temporarily disabled.\r
+; It should be uncommented after returning MLX4_HCA to WDF model.\r
+;\r
+\r
+;*****************************************\r
+; WDF Coinstaller installation section\r
+;*****************************************\r
+\r
+;[MLX4HCA.DDInstall.ntx86.CoInstallers]\r
+;AddReg=Wdf_CoInstaller_AddReg\r
+;CopyFiles=Wdf_CoInstaller_CopyFiles\r
+\r
+;[MLX4HCA.DDInstall.ntamd64.CoInstallers]\r
+;AddReg=Wdf_CoInstaller_AddReg\r
+;CopyFiles=Wdf_CoInstaller_CopyFiles\r
+\r
+;[MLX4HCA.DDInstall.ntia64.CoInstallers]\r
+;AddReg=Wdf_CoInstaller_AddReg\r
+;CopyFiles=Wdf_CoInstaller_CopyFiles\r
+\r
+;[Wdf_CoInstaller_AddReg]\r
+;HKR,,CoInstallers32,0x00010000, "wdfcoinstaller01005.dll,WdfCoInstaller"\r
+\r
+;[Wdf_CoInstaller_CopyFiles]\r
+;wdfcoinstaller01005.dll\r
+\r
+;[MLX4HCA.DDInstall.ntx86.Wdf]\r
+;KmdfService = mlx4_hca, mlx4_hca_wdfsect\r
+\r
+;[MLX4HCA.DDInstall.ntamd64.Wdf]\r
+;KmdfService = mlx4_hca, mlx4_hca_wdfsect\r
+\r
+;[MLX4HCA.DDInstall.ntia64.Wdf]\r
+;KmdfService = mlx4_hca, mlx4_hca_wdfsect\r
+\r
+;[mlx4_hca_wdfsect]\r
+;KmdfLibraryVersion = 1.5\r
+\r
+\r
+;*****************************************\r
+; Strings\r
+;*****************************************\r
+\r
+[Strings]\r
+Mlx4HcaClassGuid = "{31B0B28A-26FF-4dca-A6FA-E767C7DFBA20}"\r
+MTL="Mellanox Technologies Ltd."\r
+MLX4HCA.ServiceDesc = "Mellanox ConnectX Virtual Infiband Driver"\r
+Ibbus.ServiceDesc = "InfiniBand Bus/Fabric/AL (Filter Driver)"\r
+Mlx4_Hca.DeviceDesc="Mellanox ConnectX Virtual Channel Adapter"\r
+DiskId = "Mellanox Mlx4 Bus installation disk"\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
diff --git a/branches/winverbs/core/bus/kernel/ibbus.patch b/branches/winverbs/core/bus/kernel/ibbus.patch
new file mode 100644 (file)
index 0000000..6b69a69
--- /dev/null
@@ -0,0 +1,3279 @@
+diff -Naur --exclude-from=OMIT kernel/bus_driver.c FilterDriver/bus_driver.c\r
+--- kernel/bus_driver.c        2008-07-08 11:28:35.970718400 -0700\r
++++ FilterDriver/bus_driver.c  2008-08-01 12:33:32.531009800 -0700\r
+@@ -27,7 +27,7 @@\r
+  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+  * SOFTWARE.\r
+  *\r
+- * $Id: bus_driver.c 1336 2008-07-07 17:29:40Z shefty $\r
++ * $Id: bus_driver.c 1294 2008-06-21 00:27:03Z stansmith $\r
+  */\r
\r
\r
+@@ -191,7 +191,8 @@\r
+ * 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 @@\r
+       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 @@\r
+ #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 @@\r
+       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 @@\r
+       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
+diff -Naur --exclude-from=OMIT kernel/bus_driver.h FilterDriver/bus_driver.h\r
+--- kernel/bus_driver.h        2008-08-01 14:47:13.196356800 -0700\r
++++ FilterDriver/bus_driver.h  2008-08-01 14:43:07.886051500 -0700\r
+@@ -27,7 +27,7 @@\r
+  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+  * SOFTWARE.\r
+  *\r
+- * $Id: bus_driver.h 1336 2008-07-07 17:29:40Z shefty $\r
++ * $Id: bus_driver.h 1307 2008-06-29 16:45:16Z leonidk $\r
+  */\r
\r
\r
+@@ -74,7 +74,12 @@\r
+       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 @@\r
+  *            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 @@\r
+       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 @@\r
+       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 @@\r
+       /* 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
+diff -Naur --exclude-from=OMIT kernel/bus_iou_mgr.c FilterDriver/bus_iou_mgr.c\r
+--- kernel/bus_iou_mgr.c       2008-04-04 15:31:40.247102400 -0700\r
++++ FilterDriver/bus_iou_mgr.c 2008-08-01 14:40:07.673696300 -0700\r
+@@ -83,7 +83,12 @@\r
+ }     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 @@\r
+       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 @@\r
+  */\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 @@\r
\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 @@\r
+               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 @@\r
+ }\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 @@\r
+       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 @@\r
+ {\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 @@\r
+               {\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 @@\r
+                       /* 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 @@\r
+  * 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 @@\r
+ 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 @@\r
\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 @@\r
+       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 @@\r
\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 @@\r
+                       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 @@\r
+               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 @@\r
+       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 @@\r
\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 @@\r
\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 @@\r
+       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 @@\r
\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 @@\r
+       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 @@\r
+        * 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 @@\r
+ {\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
+diff -Naur --exclude-from=OMIT kernel/bus_iou_mgr.h FilterDriver/bus_iou_mgr.h\r
+--- kernel/bus_iou_mgr.h       2008-07-08 11:28:35.940675200 -0700\r
++++ FilterDriver/bus_iou_mgr.h 2008-07-24 11:03:33.255011800 -0700\r
+@@ -27,7 +27,7 @@\r
+  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+  * SOFTWARE.\r
+  *\r
+- * $Id: bus_iou_mgr.h 1336 2008-07-07 17:29:40Z shefty $\r
++ * $Id: bus_iou_mgr.h 1307 2008-06-29 16:45:16Z leonidk $\r
+  */\r
\r
\r
+@@ -43,7 +43,6 @@\r
+ 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 @@\r
+ }     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
+diff -Naur --exclude-from=OMIT kernel/bus_pnp.c FilterDriver/bus_pnp.c\r
+--- kernel/bus_pnp.c   2008-04-04 15:31:40.187016000 -0700\r
++++ FilterDriver/bus_pnp.c     2008-08-01 14:43:58.929578700 -0700\r
+@@ -36,7 +36,6 @@\r
+  * 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
+@@ -48,6 +47,17 @@\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 @@\r
+               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 @@\r
+ #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 @@\r
+       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 @@\r
+ {\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 @@\r
+               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 @@\r
+       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 @@\r
+               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 @@\r
+       }\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 @@\r
+               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 @@\r
\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 @@\r
+ {\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 @@\r
+ }\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 @@\r
+       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 @@\r
+       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 @@\r
+       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 @@\r
+       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 @@\r
+       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 @@\r
\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 @@\r
+       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 @@\r
+                        * 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 @@\r
+       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
+diff -Naur --exclude-from=OMIT kernel/bus_pnp.h.bak FilterDriver/bus_pnp.h.bak\r
+--- kernel/bus_pnp.h.bak       1969-12-31 16:00:00.000000000 -0800\r
++++ FilterDriver/bus_pnp.h.bak 2008-07-08 12:01:36.000000000 -0700\r
+@@ -0,0 +1,90 @@\r
++/*\r
++ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
++ *\r
++ * This software is available to you under the OpenIB.org BSD license\r
++ * below:\r
++ *\r
++ *     Redistribution and use in source and binary forms, with or\r
++ *     without modification, are permitted provided that the following\r
++ *     conditions are met:\r
++ *\r
++ *      - Redistributions of source code must retain the above\r
++ *        copyright notice, this list of conditions and the following\r
++ *        disclaimer.\r
++ *\r
++ *      - Redistributions in binary form must reproduce the above\r
++ *        copyright notice, this list of conditions and the following\r
++ *        disclaimer in the documentation and/or other materials\r
++ *        provided with the distribution.\r
++ *\r
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
++ * SOFTWARE.\r
++ *\r
++ * $Id: bus_pnp.h 1160 2008-05-12 13:01:47Z tzachid $\r
++ */\r
++\r
++\r
++\r
++#if !defined _BUS_DRV_PNP_H_\r
++#define _BUS_DRV_PNP_H_\r
++\r
++\r
++#include "bus_driver.h"\r
++#include "iba/ib_al_ifc.h"\r
++\r
++\r
++/****f* InfiniBand Bus Driver: Plug and Play/bus_add_device\r
++* NAME\r
++*     bus_add_device\r
++*\r
++* DESCRIPTION\r
++*     Main AddDevice entrypoint for the IB Bus driver.\r
++*     Adds the bus root functional device object to the device node.  The\r
++*     bus root FDO performs all PnP operations for fabric attached devices.\r
++*\r
++* SYNOPSIS\r
++*/\r
++NTSTATUS\r
++bus_add_device(\r
++      IN                              PDRIVER_OBJECT                          p_driver_obj,\r
++      IN                              PDEVICE_OBJECT                          p_pdo );\r
++/*\r
++* PARAMETERS\r
++*     p_driver_obj\r
++*             Driver object for the BUS driver.\r
++*\r
++*     p_pdo\r
++*             Pointer to the device object representing the PDO for the device on\r
++*             which we are loading.\r
++*\r
++* RETURN VBUSUES\r
++*     STATUS_SUCCESS if the device was successfully added.\r
++*\r
++*     Other NTSTATUS error values if errors are encountered.\r
++*\r
++* SEE ALSO\r
++*********/\r
++\r
++\r
++void\r
++al_set_ifc(\r
++              OUT                     ib_al_ifc_t* const                      p_ifc );\r
++\r
++void\r
++al_ref_ifc(\r
++      IN                              DEVICE_OBJECT*                          p_dev_obj );\r
++\r
++NTSTATUS\r
++bus_get_relations(\r
++      IN                              cl_qlist_t*     const                   p_pdo_list,\r
++      IN              const   net64_t                                         ca_guid,\r
++      IN                              IRP* const                                      p_irp );\r
++\r
++NTSTATUS port_mgr_pkey_add();\r
++#endif        // !defined _BUS_DRV_PNP_H_\r
+diff -Naur --exclude-from=OMIT kernel/bus_port_mgr.c FilterDriver/bus_port_mgr.c\r
+--- kernel/bus_port_mgr.c      2008-06-25 09:57:32.091601600 -0700\r
++++ FilterDriver/bus_port_mgr.c        2008-08-01 14:42:28.511399100 -0700\r
+@@ -27,7 +27,7 @@\r
+  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+  * SOFTWARE.\r
+  *\r
+- * $Id: bus_port_mgr.c 1236 2008-06-03 22:41:24Z shefty $\r
++ * $Id: bus_port_mgr.c 1160 2008-05-12 13:01:47Z tzachid $\r
+  */\r
\r
\r
+@@ -71,7 +71,14 @@\r
+ }     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 @@\r
+       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 @@\r
+  */\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 @@\r
+                       ("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 @@\r
\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 @@\r
+               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 @@\r
+       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 @@\r
+ {\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 @@\r
+               {\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 @@\r
+                       /* 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 @@\r
+  * 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
+-\r
+-      status = ib_reg_pnp( gh_al, &pnp_req, &gp_port_mgr->h_pnp );\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
++      /* 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, &bus_globals.h_pnp_port );\r
++      }\r
++      ExReleaseFastMutexUnsafe(&ControlMutex);\r
++\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 @@\r
+ 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 @@\r
\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 @@\r
+       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 @@\r
\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 @@\r
+                       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 @@\r
+               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 @@\r
+       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 @@\r
+     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 @@\r
\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
++              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
++              /* 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
++              /* 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 @@\r
+       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 @@\r
+       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 @@\r
+       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 @@\r
+       \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 @@\r
+       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 @@\r
\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 @@\r
+       /* 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 @@\r
\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 @@\r
+ {\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 @@\r
+               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 @@\r
+               /* 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 @@\r
+       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 @@\r
+       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 @@\r
+       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 @@\r
\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
+diff -Naur --exclude-from=OMIT kernel/bus_port_mgr.h FilterDriver/bus_port_mgr.h\r
+--- kernel/bus_port_mgr.h      2008-07-08 11:28:36.000761600 -0700\r
++++ FilterDriver/bus_port_mgr.h        2008-07-24 11:03:45.579090800 -0700\r
+@@ -27,7 +27,7 @@\r
+  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+  * SOFTWARE.\r
+  *\r
+- * $Id: bus_port_mgr.h 1336 2008-07-07 17:29:40Z shefty $\r
++ * $Id: bus_port_mgr.h 1307 2008-06-29 16:45:16Z leonidk $\r
+  */\r
\r
\r
+@@ -43,7 +43,6 @@\r
+ 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 @@\r
+ }     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 -Naur --exclude-from=OMIT kernel/etc/ib_iou.inf FilterDriver/etc/ib_iou.inf\r
+--- kernel/etc/ib_iou.inf      1969-12-31 16:00:00.000000000 -0800\r
++++ FilterDriver/etc/ib_iou.inf        2008-06-10 14:53:48.602241900 -0700\r
+@@ -0,0 +1,127 @@\r
++; 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 -Naur --exclude-from=OMIT kernel/etc/mthca.cdf FilterDriver/etc/mthca.cdf\r
+--- kernel/etc/mthca.cdf       1969-12-31 16:00:00.000000000 -0800\r
++++ FilterDriver/etc/mthca.cdf 2008-06-03 13:06:32.000000000 -0700\r
+@@ -0,0 +1,22 @@\r
++[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 -Naur --exclude-from=OMIT kernel/etc/mthca.inx FilterDriver/etc/mthca.inx\r
+--- kernel/etc/mthca.inx       1969-12-31 16:00:00.000000000 -0800\r
++++ FilterDriver/etc/mthca.inx 2008-06-26 11:05:20.962763400 -0700\r
+@@ -0,0 +1,318 @@\r
++; 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