]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
[IBFD] KMDF Bus driver almost ready to start testing.
authorstansmith <stansmith@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Thu, 20 Mar 2008 23:20:41 +0000 (23:20 +0000)
committerstansmith <stansmith@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Thu, 20 Mar 2008 23:20:41 +0000 (23:20 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1@1003 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

19 files changed:
branches/IBFD/core/bus/kmdf/SOURCES
branches/IBFD/core/bus/kmdf/bus_driver.c [new file with mode: 0644]
branches/IBFD/core/bus/kmdf/bus_driver.h [new file with mode: 0644]
branches/IBFD/core/bus/kmdf/bus_iou_mgr.c [new file with mode: 0644]
branches/IBFD/core/bus/kmdf/bus_iou_mgr.h [new file with mode: 0644]
branches/IBFD/core/bus/kmdf/bus_pdo.c [new file with mode: 0644]
branches/IBFD/core/bus/kmdf/bus_pnp.c [new file with mode: 0644]
branches/IBFD/core/bus/kmdf/bus_pnp.h [new file with mode: 0644]
branches/IBFD/core/bus/kmdf/bus_port_mgr.c [new file with mode: 0644]
branches/IBFD/core/bus/kmdf/bus_port_mgr.h [new file with mode: 0644]
branches/IBFD/core/bus/kmdf/busenum.c [deleted file]
branches/IBFD/core/bus/kmdf/buspdo.c [deleted file]
branches/IBFD/core/bus/kmdf/driver.h
branches/IBFD/core/bus/kmdf/ib_bus.cdf
branches/IBFD/core/bus/kmdf/ib_bus.inx
branches/IBFD/core/bus/kmdf/ib_bus.rc
branches/IBFD/core/bus/kmdf/ib_bus_public.h [new file with mode: 0644]
branches/IBFD/core/bus/kmdf/trace.h
branches/IBFD/core/bus/kmdf/wmi.c

index 4ad2c4d72c73abda7de377737b3c94d6e3c348d7..5c3f6a2fed6a1450282bd1be0cb9d5b9f704b42b 100644 (file)
@@ -1,4 +1,4 @@
-TARGETNAME=ib_bus\r
+TARGETNAME=ibbus\r
 TARGETPATH=..\..\..\bin\kernel\obj$(BUILD_ALT_DIR)\r
 TARGETTYPE=DRIVER\r
 \r
@@ -13,13 +13,15 @@ ENABLE_EVENT_TRACING=1
 !endif\r
 \r
 \r
-SOURCES= ib_bus.rc     \\r
-                busenum.c      \\r
-                buspdo.c               \\r
+SOURCES= ib_bus.rc             \\r
+                bus_driver.c   \\r
+                bus_pnp.c              \\r
+                bus_pdo.c              \\r
+                bus_port_mgr.c \\r
+                bus_iou_mgr.c  \\r
                 wmi.c\r
 \r
-INCLUDES= $(INCLUDES);\\r
-               .;..\..\..\inc;..\..\..\inc\kernel;..\..\al;..\..\al\kernel;\r
+INCLUDES=$(INCLUDES);..\..\..\inc;..\..\..\inc\kernel;..\..\al;..\..\al\kernel;\r
 \r
 C_DEFINES=$(C_DEFINES) -DDRIVER -DDEPRECATE_DDK_FUNCTIONS -DNEED_CL_OBJ\r
 \r
diff --git a/branches/IBFD/core/bus/kmdf/bus_driver.c b/branches/IBFD/core/bus/kmdf/bus_driver.c
new file mode 100644 (file)
index 0000000..4174657
--- /dev/null
@@ -0,0 +1,664 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox 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_driver.c 939 2008-02-10 15:25:55Z leonidk $\r
+ */\r
+\r
+\r
+/*\r
+ * Provides the driver entry points for the InfiniBand Bus Driver.\r
+ */\r
+\r
+#include <complib/cl_types.h>\r
+#include "bus_driver.h"\r
+#include "bus_pnp.h"\r
+#include "al_mgr.h"\r
+#include "al_dev.h"\r
+#include "al_debug.h"\r
+#include <complib/cl_init.h>\r
+\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "bus_driver.tmh"\r
+#endif\r
+\r
+#ifdef WINIB\r
+#define DEFAULT_NODE_DESC      "Mellanox Windows® Host"\r
+#else\r
+#define DEFAULT_NODE_DESC      "OpenIB Windows® Host"\r
+#endif\r
+\r
+char   node_desc[IB_NODE_DESCRIPTION_SIZE];\r
+\r
+bus_globals_t  bus_globals = {\r
+       TRACE_LEVEL_VERBOSE,\r
+       DBG_ALL,\r
+       TRUE,\r
+       NULL,\r
+       NULL\r
+};\r
+\r
+// Extern\r
+\r
+EVT_WDF_DRIVER_DEVICE_ADD Bus_EvtDeviceAdd;    // bus_pnp.c\r
+\r
+// Forward references\r
+\r
+DRIVER_INITIALIZE      DriverEntry;\r
+\r
+static VOID\r
+Bus_EvtDriverUnload( IN WDFDRIVER  Driver );\r
+\r
+static void\r
+__read_machine_name( void );\r
+\r
+static NTSTATUS\r
+__read_registry(\r
+       IN                              UNICODE_STRING* const           p_Param_Path );\r
+\r
+static NTSTATUS\r
+bus_drv_open(\r
+       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
+       IN                              IRP                                                     *p_irp );\r
+\r
+static NTSTATUS\r
+bus_drv_cleanup(\r
+       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
+       IN                              IRP                                                     *p_irp );\r
+\r
+static NTSTATUS\r
+bus_drv_close(\r
+       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
+       IN                              IRP                                                     *p_irp );\r
+\r
+static NTSTATUS\r
+bus_drv_ioctl(\r
+       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
+       IN                              IRP                                                     *p_irp );\r
+\r
+/***f* InfiniBand Bus Driver/bus_drv_sysctl\r
+* NAME\r
+*      bus_drv_sysctl\r
+*\r
+* DESCRIPTION\r
+*      Entry point for handling WMI IRPs.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static NTSTATUS\r
+bus_drv_sysctl(\r
+       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
+       IN                              IRP                                                     *p_irp );\r
+/**********/\r
+\r
+static void\r
+bus_drv_unload(\r
+       IN                              DRIVER_OBJECT                           *p_driver_obj );\r
+\r
+\r
+#ifdef ALLOC_PRAGMA\r
+#pragma alloc_text (INIT, DriverEntry)\r
+#pragma alloc_text (INIT, __read_machine_name)\r
+#pragma alloc_text (INIT, __read_registry)\r
+#pragma alloc_text (PAGE, Bus_EvtDriverUnload)\r
+#pragma alloc_text (PAGE, bus_drv_open)\r
+#pragma alloc_text (PAGE, bus_drv_close)\r
+#pragma alloc_text (PAGE, bus_drv_ioctl)\r
+#pragma alloc_text (PAGE_PNP, bus_drv_sysctl)\r
+#endif\r
+\r
+\r
+static void\r
+__read_machine_name( void )\r
+{\r
+       NTSTATUS                                        status;\r
+       /* Remember the terminating entry in the table below. */\r
+       RTL_QUERY_REGISTRY_TABLE        table[2];\r
+       UNICODE_STRING                          hostNamePath;\r
+       UNICODE_STRING                          hostNameW;\r
+       ANSI_STRING                                     hostName;\r
+\r
+       BUS_ENTER( BUS_DBG_DRV );\r
+\r
+       /* Get the host name. */\r
+       RtlInitUnicodeString( &hostNamePath, L"ComputerName\\ComputerName" );\r
+       RtlInitUnicodeString( &hostNameW, NULL );\r
+\r
+       /*\r
+        * Clear the table.  This clears all the query callback pointers,\r
+        * and sets up the terminating table entry.\r
+        */\r
+       cl_memclr( table, sizeof(table) );\r
+       cl_memclr( node_desc, sizeof(node_desc) );\r
+\r
+       /* Setup the table entries. */\r
+       table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;\r
+       table[0].Name = L"ComputerName";\r
+       table[0].EntryContext = &hostNameW;\r
+       table[0].DefaultType = REG_SZ;\r
+       table[0].DefaultData = &hostNameW;\r
+       table[0].DefaultLength = 0;\r
+\r
+       /* Have at it! */\r
+       status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL, \r
+               hostNamePath.Buffer, table, NULL, NULL );\r
+       if( NT_SUCCESS( status ) )\r
+       {\r
+               /* Convert the UNICODE host name to UTF-8 (ASCII). */\r
+               hostName.Length = 0;\r
+               hostName.MaximumLength = sizeof(node_desc);\r
+               hostName.Buffer = node_desc;\r
+               status = RtlUnicodeStringToAnsiString( &hostName, &hostNameW, FALSE );\r
+               RtlFreeUnicodeString( &hostNameW );\r
+       }\r
+       else\r
+       {\r
+               BUS_TRACE(BUS_DBG_ERROR , ("Failed to get host name.\n") );\r
+               /* Use the default name... */\r
+               RtlStringCbCopyNA( node_desc, sizeof(node_desc),\r
+                       DEFAULT_NODE_DESC, sizeof(DEFAULT_NODE_DESC) );\r
+       }\r
+\r
+       BUS_ENTER( BUS_DBG_DRV );\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__read_registry(\r
+       IN                              UNICODE_STRING* const           p_registry_path )\r
+{\r
+       NTSTATUS                                        status;\r
+       /* Remember the terminating entry in the table below. */\r
+       RTL_QUERY_REGISTRY_TABLE        table[9];\r
+       UNICODE_STRING                          param_path;\r
+\r
+       BUS_ENTER( BUS_DBG_DRV );\r
+\r
+       __read_machine_name();\r
+\r
+       RtlInitUnicodeString( &param_path, NULL );\r
+       param_path.MaximumLength = p_registry_path->Length + \r
+               sizeof(L"\\Parameters");\r
+       param_path.Buffer = cl_zalloc( param_path.MaximumLength );\r
+       if( !param_path.Buffer )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("Failed to allocate parameters path buffer.\n") );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       RtlAppendUnicodeStringToString( &param_path, p_registry_path );\r
+       RtlAppendUnicodeToString( &param_path, L"\\Parameters" );\r
+\r
+       /*\r
+        * Clear the table.  This clears all the query callback pointers,\r
+        * and sets up the terminating table entry.\r
+        */\r
+       cl_memclr( table, sizeof(table) );\r
+\r
+       /* Setup the table entries. */\r
+       table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
+       table[0].Name = L"ReportPortNIC";\r
+       table[0].EntryContext = &bus_globals.b_report_port_nic;\r
+       table[0].DefaultType = REG_DWORD;\r
+       table[0].DefaultData = &bus_globals.b_report_port_nic;\r
+       table[0].DefaultLength = sizeof(ULONG);\r
+\r
+       table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
+       table[1].Name = L"DebugFlags";\r
+       table[1].EntryContext = &bus_globals.dbg_lvl;\r
+       table[1].DefaultType = REG_DWORD;\r
+       table[1].DefaultData = &bus_globals.dbg_lvl;\r
+       table[1].DefaultLength = sizeof(ULONG);\r
+\r
+       table[2].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
+       table[2].Name = L"IbalDebugLevel";\r
+       table[2].EntryContext = &g_al_dbg_level;\r
+       table[2].DefaultType = REG_DWORD;\r
+       table[2].DefaultData = &g_al_dbg_level;\r
+       table[2].DefaultLength = sizeof(ULONG);\r
+\r
+       table[3].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
+       table[3].Name = L"IbalDebugFlags";\r
+       table[3].EntryContext = &g_al_dbg_flags;\r
+       table[3].DefaultType = REG_DWORD;\r
+       table[3].DefaultData = &g_al_dbg_flags;\r
+       table[3].DefaultLength = sizeof(ULONG);\r
+       \r
+\r
+       table[4].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
+       table[4].Name = L"SmiPollInterval";\r
+       table[4].EntryContext = &g_smi_poll_interval;\r
+       table[4].DefaultType = REG_DWORD;\r
+       table[4].DefaultData = &g_smi_poll_interval;\r
+       table[4].DefaultLength = sizeof(ULONG);\r
+\r
+       table[5].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
+       table[5].Name = L"IocQueryTimeout";\r
+       table[5].EntryContext = &g_ioc_query_timeout;\r
+       table[5].DefaultType = REG_DWORD;\r
+       table[5].DefaultData = &g_ioc_query_timeout;\r
+       table[5].DefaultLength = sizeof(ULONG);\r
+\r
+       table[6].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
+       table[6].Name = L"IocQueryRetries";\r
+       table[6].EntryContext = &g_ioc_query_retries;\r
+       table[6].DefaultType = REG_DWORD;\r
+       table[6].DefaultData = &g_ioc_query_retries;\r
+       table[6].DefaultLength = sizeof(ULONG);\r
+\r
+       table[7].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
+       table[7].Name = L"IocPollInterval";\r
+       table[7].EntryContext = &g_ioc_poll_interval;\r
+       table[7].DefaultType = REG_DWORD;\r
+       table[7].DefaultData = &g_ioc_poll_interval;\r
+       table[7].DefaultLength = sizeof(ULONG);\r
+\r
+       /* Have at it! */\r
+       status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
+               param_path.Buffer, table, NULL, NULL );\r
+\r
+#if DBG\r
+       if( g_al_dbg_flags & AL_DBG_ERR )\r
+               g_al_dbg_flags |= CL_DBG_ERROR;\r
+#endif\r
+\r
+       BUS_TRACE(BUS_DBG_DRV ,\r
+                       ("debug level %d debug flags 0x%.8x\n",\r
+                       g_al_dbg_level,\r
+                       g_al_dbg_flags));\r
+\r
+       cl_free( param_path.Buffer );\r
+       BUS_EXIT( BUS_DBG_DRV );\r
+       return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+bus_drv_open(\r
+       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
+       IN                              IRP                                                     *p_irp )\r
+{\r
+       BUS_ENTER( BUS_DBG_DRV );\r
+\r
+       UNUSED_PARAM( p_dev_obj );\r
+\r
+       CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );\r
+\r
+       /* We always succeed file handles creation. */\r
+       p_irp->IoStatus.Status = STATUS_SUCCESS;\r
+       p_irp->IoStatus.Information = 0;\r
+       IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+\r
+       BUS_EXIT( BUS_DBG_DRV );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+bus_drv_cleanup(\r
+       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
+       IN                              IRP                                                     *p_irp )\r
+{\r
+       NTSTATUS                        status;\r
+\r
+       BUS_ENTER( BUS_DBG_DRV );\r
+\r
+       UNUSED_PARAM( p_dev_obj );\r
+\r
+       CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );\r
+\r
+       /*\r
+        * Note that we don't acquire the remove and stop lock on close to allow\r
+        * applications to close the device when the locks are already held.\r
+        */\r
+       status = cl_to_ntstatus( al_dev_close( p_irp ) );\r
+\r
+       /* Complete the IRP. */\r
+       p_irp->IoStatus.Status = status;\r
+       p_irp->IoStatus.Information = 0;\r
+       IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+\r
+       BUS_EXIT( BUS_DBG_DRV );\r
+       return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+bus_drv_close( IN      DEVICE_OBJECT   *p_dev_obj,\r
+                          IN   IRP                             *p_irp )\r
+{\r
+       UNUSED_PARAM( p_dev_obj );\r
+\r
+       p_irp->IoStatus.Status = STATUS_SUCCESS;\r
+       p_irp->IoStatus.Information = 0;\r
+       IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+bus_drv_ioctl(\r
+       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
+       IN                              IRP                                                     *p_irp )\r
+{\r
+       NTSTATUS                        status;\r
+       bus_fdo_ext_t           *p_ext;\r
+       PIO_STACK_LOCATION      p_io_stack;\r
+\r
+       BUS_ENTER( BUS_DBG_DRV );\r
+\r
+       /* Get the extension. */\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       /* Get the stack location. */\r
+       p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+\r
+       /* Acquire the stop lock. */\r
+       status = IoAcquireRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               p_irp->IoStatus.Status = status;\r
+               p_irp->IoStatus.Information = 0;\r
+               IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+               BUS_EXIT( BUS_DBG_DRV );\r
+               return status;\r
+       }\r
+\r
+       /* Acquire the remove lock. */\r
+       status = IoAcquireRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               IoReleaseRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );\r
+               p_irp->IoStatus.Status = status;\r
+               p_irp->IoStatus.Information = 0;\r
+               IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+               BUS_EXIT( BUS_DBG_DRV );\r
+               return status;\r
+       }\r
+       \r
+       status = cl_to_ntstatus( al_dev_ioctl( p_irp ) );\r
+       \r
+       /* Only pass down if not handled and not PDO device. */\r
+       if( status == STATUS_INVALID_DEVICE_REQUEST && p_ext->cl_ext.p_next_do )\r
+       {\r
+               IoSkipCurrentIrpStackLocation( p_irp );\r
+               status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
+       }\r
+\r
+       /* Release the remove and stop locks. */\r
+       IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
+       IoReleaseRemoveLock( &p_ext->cl_ext.stop_lock, p_irp );\r
+\r
+       BUS_EXIT( BUS_DBG_DRV );\r
+       return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+bus_drv_sysctl(\r
+       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
+       IN                              IRP                                                     *p_irp )\r
+{\r
+       NTSTATUS                status;\r
+       bus_fdo_ext_t   *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_DRV );\r
+\r
+       CL_ASSERT( p_dev_obj );\r
+       CL_ASSERT( p_irp );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       if( p_ext->cl_ext.p_next_do )\r
+       {\r
+               IoSkipCurrentIrpStackLocation( p_irp );\r
+               status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
+       }\r
+       else\r
+       {\r
+               status = p_irp->IoStatus.Status;\r
+               IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+       }\r
+\r
+       BUS_EXIT( BUS_DBG_DRV );\r
+       return status;\r
+}\r
+\r
+\r
+#ifdef _REPLACED\r
+static void\r
+bus_drv_unload(\r
+       IN                              DRIVER_OBJECT                           *p_driver_obj )\r
+{\r
+       BUS_ENTER( BUS_DBG_DRV );\r
+\r
+       UNUSED_PARAM( p_driver_obj );\r
+\r
+       CL_DEINIT;\r
+\r
+       WPP_CLEANUP(p_driver_obj);\r
+\r
+       BUS_EXIT( BUS_DBG_DRV );\r
+       \r
+}\r
+#endif\r
+\r
+/*++\r
+Routine Description:\r
+\r
+    This routine is called when the IB Bus driver is unloaded.\r
+\r
+Arguments:\r
+\r
+   Driver - pointer to a KMDF Driver object\r
+\r
+\r
+Return Value:\r
+\r
+--*/\r
+static VOID\r
+Bus_EvtDriverUnload( IN WDFDRIVER  Driver )\r
+{\r
+       BUS_ENTER( BUS_DBG_DRV );\r
+\r
+       CL_DEINIT;\r
+\r
+#if defined(EVENT_TRACING)\r
+       WPP_CLEANUP( WdfDriverWdmGetDriverObject(Driver) );\r
+#else\r
+    UNREFERENCED_PARAMETER(Driver);\r
+#endif\r
+\r
+       BUS_EXIT( BUS_DBG_DRV );        \r
+}\r
+\r
+\r
+NTSTATUS\r
+DriverEntry( IN DRIVER_OBJECT  *p_driver_obj,\r
+                        IN UNICODE_STRING      *p_registry_path )\r
+{\r
+       NTSTATUS                        status;\r
+       WDF_DRIVER_CONFIG       config;\r
+       WDFDRIVER                       driver;\r
+\r
+       BUS_ENTER( BUS_DBG_DRV );\r
+\r
+    KdPrint(("WDF InfiniBand Fabric Bus Driver.\n"));\r
+    KdPrint(("Built %s %s\n", __DATE__, __TIME__));\r
+\r
+       WPP_INIT_TRACING(p_driver_obj ,p_registry_path);\r
+\r
+       status = CL_INIT;\r
+       if( !NT_SUCCESS(status) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("cl_init returned %08X.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       /* Store the driver object pointer in the global parameters. */\r
+       bus_globals.p_driver_obj = p_driver_obj;\r
+\r
+       /* Get the registry values. */\r
+       status = __read_registry( p_registry_path );\r
+       if( !NT_SUCCESS(status) )\r
+       {\r
+               CL_DEINIT;\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("__read_registry returned %08x.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       /* Setup the entry points. */\r
+#if 0\r
+       // handled by KMDF callback bus_pnp.c:Bus_EvtDeviceFileCreate\r
+       p_driver_obj->MajorFunction[IRP_MJ_CREATE] = bus_drv_open;\r
+\r
+       p_driver_obj->MajorFunction[IRP_MJ_CLEANUP] = bus_drv_cleanup;\r
+\r
+       // handled by KMDF callback bus_pnp.c:Bus_EvtDeviceFileClose\r
+       p_driver_obj->MajorFunction[IRP_MJ_CLOSE] = bus_drv_close;\r
+\r
+       // handled by the Framework (KMDF), no callbacks\r
+       p_driver_obj->MajorFunction[IRP_MJ_PNP] = cl_pnp;\r
+\r
+       // handled by the Framework (KMDF), no callbacks\r
+       p_driver_obj->MajorFunction[IRP_MJ_POWER] = cl_power;\r
+\r
+       //  handled by callback bus_pnp.c: Bus_EvtIoDeviceControl\r
+       p_driver_obj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = bus_drv_ioctl;\r
+\r
+       //  handled by callback ??\r
+       p_driver_obj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = bus_drv_sysctl;\r
+\r
+       // handled via Framework callbacks\r
+       p_driver_obj->DriverUnload = bus_drv_unload;\r
+       p_driver_obj->DriverExtension->AddDevice = bus_add_device;\r
+#endif\r
+\r
+    // Initiialize driver config to control the attributes that\r
+    // are global to the driver. Note that framework by default\r
+    // provides a driver unload routine. If you create any resources\r
+    // in the DriverEntry and want to be cleaned in driver unload,\r
+    // you can override that by specifing one in the Config structure.\r
+\r
+    WDF_DRIVER_CONFIG_INIT( &config, Bus_EvtDeviceAdd );\r
+\r
+       config.EvtDriverUnload = Bus_EvtDriverUnload;\r
+\r
+    // Create a framework driver object to represent our driver.\r
+    status = WdfDriverCreate(p_driver_obj,\r
+                             p_registry_path,\r
+                             WDF_NO_OBJECT_ATTRIBUTES,\r
+                             &config,\r
+                             &driver);\r
+\r
+    if (!NT_SUCCESS(status)) {\r
+        KdPrint( ("WdfDriverCreate failed with status 0x%x\n", status));\r
+    }\r
+\r
+       BUS_EXIT( BUS_DBG_DRV );\r
+       return status;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Debug print for the sample driver.\r
+\r
+Arguments:\r
+\r
+    TraceEventsLevel - print level between 0 and 3, with 3 the most verbose\r
+\r
+Return Value:\r
+\r
+    None.\r
+\r
+ --*/\r
+\r
+#if !defined(EVENT_TRACING)\r
+\r
+VOID\r
+TraceEvents    (\r
+    IN ULONG   TraceEventsLevel,\r
+    IN ULONG   TraceEventsFlag,\r
+    IN PCCHAR  DebugMessage,\r
+    ...  )\r
+{\r
+#if 1 // always for starters DBG\r
+#define     TEMP_BUFFER_SIZE        512\r
+    va_list    list;\r
+    CHAR       debugMessageBuffer[TEMP_BUFFER_SIZE];\r
+    NTSTATUS   status;\r
+\r
+    va_start(list, DebugMessage);\r
+\r
+    if (DebugMessage) {\r
+\r
+        //\r
+        // Using new safe string functions instead of _vsnprintf.\r
+        // This function takes care of NULL terminating if the message\r
+        // is longer than the buffer.\r
+        //\r
+        status = RtlStringCbVPrintfA( debugMessageBuffer,\r
+                                      sizeof(debugMessageBuffer),\r
+                                      DebugMessage,\r
+                                      list );\r
+        if(!NT_SUCCESS(status)) {\r
+\r
+            DbgPrint(_DRIVER_NAME_": RtlStringCbVPrintfA failed %x\n", status);\r
+            return;\r
+        }\r
+        if (TraceEventsLevel <= TRACE_LEVEL_INFORMATION ||\r
+            (TraceEventsLevel <= bus_globals.dbg_lvl &&\r
+             (TraceEventsFlag & bus_globals.dbg_flags) )) // any bit set\r
+//             ((TraceEventsFlag & bus_globals.dbg_flags) == TraceEventsFlag) ))\r
+               {\r
+            DbgPrint(debugMessageBuffer);\r
+        }\r
+    }\r
+    va_end(list);\r
+\r
+    return;\r
+#else\r
+    UNREFERENCED_PARAMETER(TraceEventsLevel);\r
+    UNREFERENCED_PARAMETER(TraceEventsFlag);\r
+    UNREFERENCED_PARAMETER(DebugMessage);\r
+#endif\r
+}\r
+\r
+#endif /* !defined(EVENT_TRACING) */\r
+\r
diff --git a/branches/IBFD/core/bus/kmdf/bus_driver.h b/branches/IBFD/core/bus/kmdf/bus_driver.h
new file mode 100644 (file)
index 0000000..7e3afff
--- /dev/null
@@ -0,0 +1,408 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation.  All rights reserved.\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
+ * Main header for IB Fabric Bus driver.\r
+ *\r
+ * InfiniBand Fabric (IBF) dynamic bus enumerator - based on MS Toaster\r
+ * Dynamic bus enum example.\r
+ * Whenever you see the term 'bus', think Infiniband Fabric (a.k.a. 'bus'.\r
+ *\r
+ * $Id$\r
+ */\r
+\r
+\r
+#if !defined _IB_BUS_DRIVER_H_\r
+#define _IB_BUS_DRIVER_H_ 1\r
+\r
+#include <ntddk.h>\r
+#include <wdf.h>\r
+#include <ntstrsafe.h>\r
+#include <ntintsafe.h>\r
+\r
+#include "driver.h"\r
+#include "ib_bus_public.h"\r
+\r
+#include "complib/cl_types.h"\r
+#include "complib/cl_atomic.h"\r
+#include "complib/cl_debug.h"\r
+#include "complib/cl_mutex.h"\r
+#include "complib/cl_qlist.h"\r
+#include "complib/cl_ptr_vector.h"\r
+#include "complib/cl_pnp_po.h"\r
+#include "iba/ib_al.h"\r
+#include "bus_port_mgr.h"\r
+#include "bus_iou_mgr.h"\r
+\r
+#include "trace.h"\r
+\r
+#define _DRIVER_NAME_ "IB_BUS"\r
+#define BUS_TAG         'rbaF'\r
+#define BUSRESOURCENAME L"MofResourceName"\r
+#define MOFRESOURCENAME L"IBFabricWMI"\r
+\r
+#define DEF_STATICALLY_ENUMERATED_IB_DEVICES      0\r
+#define MAX_STATICALLY_ENUMERATED_IB_DEVICES      50\r
+#define MAX_INSTANCE_ID_LEN 80\r
+\r
+#ifndef min\r
+#define min(_a, _b)     (((_a) < (_b)) ? (_a) : (_b))\r
+#endif\r
+\r
+#ifndef max\r
+#define max(_a, _b)     (((_a) > (_b)) ? (_a) : (_b))\r
+#endif\r
+\r
+\r
+#define BUS_ENTER( lvl )       \\r
+       TraceEvents(TRACE_LEVEL_INFORMATION, lvl, "--> %s()\n", __FUNCTION__)\r
+\r
+#define BUS_EXIT( lvl )                \\r
+       TraceEvents(TRACE_LEVEL_INFORMATION, lvl, "<-- %s()\n", __FUNCTION__)\r
+\r
+#if 1\r
+#define BUS_TRACE( lvl, msg )          \\r
+       CL_TRACE( lvl, bus_globals.dbg_lvl, msg )\r
+\r
+#define BUS_TRACE_EXIT( lvl, msg )     \\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
+\r
+#else\r
+\r
+#define BUS_TRACE( lvl, msg )  \\r
+       TraceEvents( TRACE_LEVEL_INFORMATION, lvl, (msg) )\r
+\r
+#define BUS_TRACE_EXIT( lvl, msg )     \\r
+       TraceEvents( TRACE_LEVEL_INFORMATION, lvl, msg )\r
+#endif\r
+\r
+//#define BUS_PRINT( lvl, msg )        \\r
+//     if ( ((lvl) & bus_globals.dbl_lvl) ) KbPrint( ( msg ) )\r
+\r
+\r
+/*\r
+ * ALLOC_PRAGMA sections:\r
+ *     PAGE\r
+ *             Default pagable code.  Won't be locked in memory.\r
+ *\r
+ *     PAGE_PNP\r
+ *             Code that needs to be locked in memory when the device is\r
+ *             in the paging, crash dump, or hibernation path.\r
+ *\r
+ *  INIT\r
+ *             Code pages which are called once during driver initialization\r
+ *             (e.g., DriverEntry) that the system may page out.\r
+ */\r
+//\r
+// Structure for reporting data to WMI\r
+//\r
+\r
+typedef struct _IBF_BUS_WMI_STD_DATA {\r
+\r
+    //\r
+    // The error Count\r
+    //\r
+    UINT32   ErrorCount;\r
+\r
+    //\r
+    // Debug Print Level\r
+    //\r
+\r
+    UINT32  DebugPrintLevel;\r
+\r
+} IBF_BUS_WMI_STD_DATA, * PIBF_BUS_WMI_STD_DATA;\r
+\r
+/*\r
+  The goal of the identification and address description abstractions is that\r
+  enough information is stored for a discovered device so that when it appears\r
+  on the bus, the framework (with the help of the driver writer) can determine\r
+  if it is a new or existing device. The identification and address descriptions\r
+  are opaque structures to the framework, they are private to the driver writer.\r
+  The only thing the framework knows about these descriptions is what their\r
+  size is.\r
+  The identification contains the bus specific information required to\r
+  recognize an instance of a device on its the bus. The identification\r
+  information usually contains device IDs along with any serial or slot numbers.\r
+  For some buses (like USB and PCI), the identification of the device is\r
+  sufficient to address the device on the bus; in these instances there is no\r
+  need for a separate address description.  Once reported, the identification\r
+  description remains static for the lifetime of the device.  For example, the\r
+  identification description that the PCI bus driver would use for a child would\r
+  contain the vendor ID, device ID, subsystem ID, revision, and class for the\r
+  device. This sample uses only identification description.\r
+  On other busses (like 1394 and auto LUN SCSI), the device is assigned a\r
+  dynamic address by the hardware (which may reassigned and updated periodically\r
+  in these instances the driver will use the address description to encapsulate\r
+  this dynamic piece of data.\r
+  For example in a 1394 driver, the address description would contain the\r
+  devices current generation count while the identification description would\r
+  contain vendor name, model name, unit spec ID, and unit software version.\r
+*/\r
+\r
+typedef struct _PDO_IDENTIFICATION_DESCRIPTION\r
+{\r
+    WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Header; // should have header\r
+\r
+    // Unique serial number of the device on the bus\r
+    ULONG SerialNo;\r
+\r
+    size_t CchHardwareIds;\r
+\r
+    __field_bcount(CchHardwareIds) PWCHAR HardwareIds;\r
+\r
+} PDO_IDENTIFICATION_DESCRIPTION, *PPDO_IDENTIFICATION_DESCRIPTION;\r
+\r
+\r
+/*\r
+ * Device extension for the device object that serves as entry point for \r
+ * the interface and IOCTL requests.\r
+ * The device extension of the InfiniBand Fabric bus itself.\r
+ * From whence the PDO's are born. \r
+ */\r
+typedef struct _bus_fdo_ext\r
+{\r
+       cl_pnp_po_ext_t                 cl_ext;         // wants to be 1st...\r
+\r
+       WDFDEVICE               WdfDevice;  // for DrvQueuePassiveLevelCallback()\r
+\r
+       WDFWMIINSTANCE                  WmiDeviceArrivalEvent;\r
+\r
+    IB_BUS_INTERFACE_STANDARD BusInterface;\r
+\r
+       IBF_BUS_WMI_STD_DATA    StdBusData;\r
+\r
+    BOOLEAN                                    SupportsPowerMgmt;\r
+       CHAR                                    Identity[8];\r
+\r
+       /* Device power map returned by the bus driver for the device, used \r
+        * when sending IRP_MN_SET_POWER for device state in response to \r
+        * IRP_MN_SET_POWER for system state.\r
+        */\r
+       DEVICE_POWER_STATE              po_state[PowerSystemMaximum];\r
+\r
+   // Current power state of the device(D0 - D3)\r
+    WDF_POWER_DEVICE_STATE  DevPowerState;\r
+    WDF_POWER_DEVICE_STATE  DevPreviousPowerState;\r
+\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
+}      bus_fdo_ext_t, FDO_BUS_DATA, *PFDO_BUS_DATA;\r
+\r
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_BUS_DATA, FdoGetData)\r
+\r
+\r
+// General purpose workitem context used in dispatching work to\r
+// system worker thread to be executed at PASSIVE_LEVEL.\r
+\r
+typedef struct _WORKER_ITEM_CONTEXT {\r
+    PFDO_BUS_DATA              FdoData;\r
+    PVOID                              Argument1;\r
+    PVOID                              Argument2;\r
+} WORKER_ITEM_CONTEXT, *PWORKER_ITEM_CONTEXT;\r
+\r
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WORKER_ITEM_CONTEXT, GetWorkItemContext)\r
+\r
+\r
+/*\r
+ * The PDO device extension.\r
+ */\r
+typedef struct _bus_pdo_ext\r
+{\r
+    // Unique serial number of the device on the bus.\r
+       ULONG                                   SerialNo;\r
+\r
+       cl_pnp_po_ext_t                 cl_ext;\r
+\r
+       cl_list_item_t                  list_item;\r
+\r
+       /* All reported PDOs are children of an HCA. */\r
+       ib_ca_handle_t                  h_ca;\r
+\r
+       /*\r
+        * CA GUID copy - in case we get IRPs after the CA\r
+        * handle has been released.\r
+        */\r
+       net64_t                                 ca_guid;\r
+\r
+       POWER_STATE                             dev_po_state;\r
+\r
+       /*\r
+        * Pointer to the bus root device extension.  Used to manage access to\r
+        * child PDO pointer vector when a child is removed politely.\r
+        */\r
+       bus_fdo_ext_t                   *p_parent_ext;\r
+\r
+       /*\r
+        * The following two flags are exclusively set, but can both be FALSE.\r
+        * Flag that indicates whether the device is present in the system or not.\r
+        * This affects how a IRP_MN_REMOVE_DEVICE IRP is handled for a child PDO.\r
+        * This flag is cleared when:\r
+        *      - an HCA (for IPoIB devices) is removed from the system for all port\r
+        *      devices loaded for that HCA\r
+        *      - an IOU is reported as removed by the CIA.\r
+        */\r
+       boolean_t                               b_present;\r
+\r
+       /*\r
+        * Flag that indicates whether the device has been reported to the PnP\r
+        * manager as having been removed.  That is, the device was reported\r
+        * in a previous BusRelations query and not in a subsequent one.\r
+        * This flag is set when\r
+        *      - the device is in the surprise remove state when the parent bus\r
+        *      device is removed\r
+        *      - the device is found to be not present during a BusRelations query\r
+        *      and thus not reported.\r
+        */\r
+       boolean_t                               b_reported_missing;\r
+\r
+       /* Flag to control the behaviour of the driver during hibernation */\r
+       uint32_t                                b_hibernating;\r
+\r
+       /* work item for handling Power Management request */\r
+       PIO_WORKITEM                    p_po_work_item;\r
+       \r
+}      bus_pdo_ext_t, PDO_DEVICE_DATA, *PPDO_DEVICE_DATA;\r
+\r
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(PDO_DEVICE_DATA, PdoGetData)\r
+\r
+\r
+/*\r
+ * Global Driver parameters.\r
+ */\r
+typedef struct _bus_globals\r
+{\r
+       /* Debug level. */\r
+       uint32_t                                dbg_lvl;\r
+       uint32_t                                dbg_flags;\r
+\r
+       /* Flag to control loading of Ip Over Ib driver for each HCA port. */\r
+       uint32_t                                b_report_port_nic;\r
+\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 (FDO_BUS_DATA*). */\r
+       bus_fdo_ext_t                   *p_bus_ext;\r
+\r
+}      bus_globals_t;\r
+\r
+\r
+extern bus_globals_t   bus_globals;\r
+extern NTSTATUS ib_bus_init(PDRIVER_OBJECT,PUNICODE_STRING);\r
+\r
+//EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL Bus_EvtIoDeviceControl;\r
+\r
+EVT_WDF_CHILD_LIST_CREATE_DEVICE Bus_EvtDeviceListCreatePdo;\r
+EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COMPARE Bus_EvtChildListIdentificationDescriptionCompare;\r
+EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_CLEANUP Bus_EvtChildListIdentificationDescriptionCleanup;\r
+EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_DUPLICATE Bus_EvtChildListIdentificationDescriptionDuplicate;\r
+\r
+NTSTATUS\r
+Bus_PlugInDevice(\r
+    __in WDFDEVICE       Device,\r
+    __in PWCHAR          HardwareIds,\r
+    __in size_t          CchHardwareIds,\r
+    __in ULONG           SerialNo\r
+    );\r
+\r
+NTSTATUS\r
+Bus_UnPlugDevice(\r
+    WDFDEVICE   Device,\r
+    ULONG       SerialNo\r
+    );\r
+\r
+\r
+NTSTATUS\r
+Bus_EjectDevice(\r
+    WDFDEVICE   Device,\r
+    ULONG       SerialNo\r
+    );\r
+\r
+NTSTATUS\r
+Bus_CreatePdo(\r
+    __in WDFDEVICE       Device,\r
+    __in PWDFDEVICE_INIT ChildInit,\r
+    __in PWCHAR          HardwareIds,\r
+    __in ULONG           SerialNo\r
+    );\r
+\r
+NTSTATUS\r
+Bus_DoStaticEnumeration(\r
+    IN WDFDEVICE Device\r
+    );\r
+\r
+\r
+//\r
+// Interface functions\r
+//\r
+\r
+BOOLEAN\r
+Bus_GetCrispinessLevel(\r
+    IN   WDFDEVICE ChildDevice,\r
+    OUT  PUCHAR Level\r
+    );\r
+\r
+BOOLEAN\r
+Bus_SetCrispinessLevel(\r
+    IN   WDFDEVICE ChildDevice,\r
+    OUT  UCHAR Level\r
+    );\r
+\r
+BOOLEAN\r
+Bus_IsSafetyLockEnabled(\r
+    IN PVOID Context\r
+    );\r
+\r
+//\r
+// Defined in wmi.c\r
+//\r
+\r
+NTSTATUS\r
+Bus_WmiRegistration(\r
+    WDFDEVICE      Device\r
+    );\r
+\r
+EVT_WDF_WMI_INSTANCE_SET_ITEM Bus_EvtStdDataSetItem;\r
+EVT_WDF_WMI_INSTANCE_SET_INSTANCE Bus_EvtStdDataSetInstance;\r
+EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE Bus_EvtStdDataQueryInstance;\r
+\r
+\r
+#endif /* !defined _IB_BUS_DRIVER_H_ */\r
diff --git a/branches/IBFD/core/bus/kmdf/bus_iou_mgr.c b/branches/IBFD/core/bus/kmdf/bus_iou_mgr.c
new file mode 100644 (file)
index 0000000..240a0df
--- /dev/null
@@ -0,0 +1,1502 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox 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_iou_mgr.c 931 2008-01-31 09:20:41Z leonidk $\r
+ */\r
+\r
+\r
+#include <iba/ib_types.h>\r
+#include <complib/cl_async_proc.h>\r
+#include <complib/cl_bus_ifc.h>\r
+#include "ib_common.h"\r
+#include "al_ca.h"\r
+#include "al_mgr.h"\r
+#include "bus_pnp.h"\r
+#include "bus_iou_mgr.h"\r
+#include <initguid.h>\r
+#include <wdmguid.h>\r
+#include "iba/iou_ifc.h"\r
+\r
+\r
+/* {5A9649F4-0101-4a7c-8337-796C48082DA2} */\r
+DEFINE_GUID(GUID_BUS_TYPE_IBA, \r
+0x5a9649f4, 0x101, 0x4a7c, 0x83, 0x37, 0x79, 0x6c, 0x48, 0x8, 0x2d, 0xa2);\r
+\r
+\r
+/*\r
+ * Size of device descriptions, in the format:\r
+ *     IBA\VxxxxxxPxxxxxxxxvxxxxxxxx\r
+ */\r
+#define IOU_DEV_ID_SIZE                sizeof(L"IBA\\VxxxxxxPxxxxvxxxxxxxx")\r
+#define IOU_DEV_ID_STRING1     L"IBA\\V%06xP%04hxv%08x"\r
+#define IOU_DEV_ID_STRING2     L"IBA\\V%06xP%04hx"\r
+#define IOU_HW_ID_SIZE         \\r
+       sizeof(L"IBA\\VxxxxxxPxxxxvxxxxxxxx\0IBA\\VxxxxxxPxxxx\0\0")\r
+#define IOU_COMPAT_ID          L"IBA\\IB_IOU\0\0"\r
+#define IOU_LOCATION_SIZE      \\r
+       sizeof(L"Chassis 0xxxxxxxxxxxxxxxxx, Slot xx")\r
+\r
+/*\r
+ * Device extension for IOU PDOs.\r
+ */\r
+typedef struct _bus_iou_ext\r
+{\r
+       bus_pdo_ext_t                   pdo;\r
+\r
+       net64_t                                 chassis_guid;\r
+       uint8_t                                 slot;\r
+       net64_t                                 guid;\r
+       net32_t                                 vend_id;\r
+       net16_t                                 dev_id;\r
+       net32_t                                 revision;\r
+       char                                    desc[IB_NODE_DESCRIPTION_SIZE + 1];\r
+\r
+       /* Number of references on the upper interface. */\r
+       atomic32_t                              n_ifc_ref;\r
+\r
+}      bus_iou_ext_t;\r
+\r
+\r
+iou_mgr_t*                                             gp_iou_mgr = NULL;\r
+\r
+\r
+/*\r
+ * Function prototypes.\r
+ */\r
+void\r
+destroying_iou_mgr(\r
+       IN                              cl_obj_t*                                       p_obj );\r
+\r
+void\r
+free_iou_mgr(\r
+       IN                              cl_obj_t*                                       p_obj );\r
+\r
+ib_api_status_t\r
+bus_reg_iou_pnp( void );\r
+\r
+ib_api_status_t\r
+iou_mgr_pnp_cb(\r
+       IN                              ib_pnp_rec_t*                           p_pnp_rec );\r
+\r
+ib_api_status_t\r
+iou_mgr_iou_add(\r
+       IN                              ib_pnp_iou_rec_t*                       p_pnp_rec );\r
+\r
+void\r
+iou_mgr_iou_remove(\r
+       IN                              ib_pnp_iou_rec_t*                       p_pnp_rec );\r
+\r
+static NTSTATUS\r
+iou_start(\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
+static NTSTATUS\r
+iou_query_remove(\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
+static void\r
+iou_release_resources(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj );\r
+\r
+static NTSTATUS\r
+iou_remove(\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
+static NTSTATUS\r
+iou_surprise_remove(\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
+static NTSTATUS\r
+iou_query_capabilities(\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
+static NTSTATUS\r
+iou_query_target_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
+static NTSTATUS\r
+iou_query_device_id(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+static NTSTATUS\r
+iou_query_hardware_ids(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+static NTSTATUS\r
+iou_query_compatible_ids(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+static NTSTATUS\r
+iou_query_unique_id(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+static NTSTATUS\r
+iou_query_description(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+static NTSTATUS\r
+iou_query_location(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+static NTSTATUS\r
+iou_query_bus_info(\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
+static NTSTATUS\r
+iou_query_interface(\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
+static NTSTATUS\r
+iou_set_power(\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
+\r
+/* All PnP code is called at passive, so it can all be paged out. */\r
+#ifdef ALLOC_PRAGMA\r
+#pragma alloc_text (PAGE, iou_start)\r
+#pragma alloc_text (PAGE, iou_query_remove)\r
+#pragma alloc_text (PAGE, iou_release_resources)\r
+#pragma alloc_text (PAGE, iou_remove)\r
+#pragma alloc_text (PAGE, iou_surprise_remove)\r
+#pragma alloc_text (PAGE, iou_query_capabilities)\r
+#pragma alloc_text (PAGE, iou_query_target_relations)\r
+#pragma alloc_text (PAGE, iou_query_device_id)\r
+#pragma alloc_text (PAGE, iou_query_hardware_ids)\r
+#pragma alloc_text (PAGE, iou_query_compatible_ids)\r
+#pragma alloc_text (PAGE, iou_query_unique_id)\r
+#pragma alloc_text (PAGE, iou_query_description)\r
+#pragma alloc_text (PAGE, iou_query_location)\r
+#pragma alloc_text (PAGE, iou_query_bus_info)\r
+#pragma alloc_text (PAGE, iou_query_interface)\r
+#pragma alloc_text (PAGE_PNP, iou_set_power)\r
+#pragma alloc_text (PAGE, iou_mgr_iou_add)\r
+#pragma alloc_text (PAGE, iou_mgr_iou_remove)\r
+#endif\r
+\r
+\r
+/*\r
+ * Global virtual function pointer tables shared between all \r
+ * instances of Port PDOs.\r
+ */\r
+static const cl_vfptr_pnp_po_t         vfptr_iou_pnp = {\r
+       "IB IOU",\r
+       iou_start,\r
+       cl_irp_succeed,\r
+       cl_irp_succeed,\r
+       cl_irp_succeed,\r
+       iou_query_remove,\r
+       iou_release_resources,\r
+       iou_remove,\r
+       cl_irp_succeed,\r
+       iou_surprise_remove,\r
+       iou_query_capabilities,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       cl_irp_succeed,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       iou_query_target_relations,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       iou_query_bus_info,\r
+       iou_query_interface,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       cl_irp_succeed,                         // QueryPower\r
+       iou_set_power,                          // SetPower\r
+       cl_irp_unsupported,                     // PowerSequence\r
+       cl_irp_unsupported                      // WaitWake\r
+};\r
+\r
+\r
+static const cl_vfptr_query_txt_t              vfptr_iou_query_txt = {\r
+       iou_query_device_id,\r
+       iou_query_hardware_ids,\r
+       iou_query_compatible_ids,\r
+       iou_query_unique_id,\r
+       iou_query_description,\r
+       iou_query_location\r
+};\r
+\r
+\r
+/*\r
+ * Create the AL load service.\r
+ */\r
+ib_api_status_t\r
+create_iou_mgr(\r
+               OUT                     iou_mgr_t** const                       pp_iou_mgr )\r
+{\r
+       ib_api_status_t         status;\r
+       cl_status_t                     cl_status;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       CL_ASSERT( !gp_iou_mgr );\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
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       /* Construct the load service. */\r
+       cl_obj_construct( &gp_iou_mgr->obj, AL_OBJ_TYPE_LOADER );\r
+       cl_mutex_construct( &gp_iou_mgr->pdo_mutex );\r
+       cl_qlist_init( &gp_iou_mgr->iou_list );\r
+\r
+       cl_status = cl_mutex_init( &gp_iou_mgr->pdo_mutex );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               free_iou_mgr( &gp_iou_mgr->obj );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("cl_mutex_init returned %#x.\n", cl_status) );\r
+               return ib_convert_cl_status( cl_status );\r
+       }\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
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               free_iou_mgr( &gp_iou_mgr->obj );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("cl_obj_init returned %#x.\n", cl_status) );\r
+               return ib_convert_cl_status( cl_status );\r
+       }\r
+\r
+       /* Register for port PnP events. */\r
+       status = bus_reg_iou_pnp();\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               cl_obj_destroy( &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
+       }\r
+\r
+       *pp_iou_mgr = gp_iou_mgr;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+/*\r
+ * Pre-destroy the load service.\r
+ */\r
+void\r
+destroying_iou_mgr(\r
+       IN                              cl_obj_t*                                       p_obj )\r
+{\r
+       ib_api_status_t                 status;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       CL_ASSERT( p_obj );\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
+       {\r
+               status = ib_dereg_pnp( gp_iou_mgr->h_pnp,\r
+                       (ib_pfn_destroy_cb_t)cl_obj_deref );\r
+               CL_ASSERT( status == IB_SUCCESS );\r
+       }\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+/*\r
+ * Free the load service.\r
+ */\r
+void\r
+free_iou_mgr(\r
+       IN                              cl_obj_t*                                       p_obj )\r
+{\r
+       bus_pdo_ext_t   *p_ext;\r
+       cl_list_item_t  *p_list_item;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       CL_ASSERT( p_obj );\r
+       CL_ASSERT( gp_iou_mgr == PARENT_STRUCT( p_obj, iou_mgr_t, obj ) );\r
+\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
+        */\r
+       p_list_item = cl_qlist_remove_head( &gp_iou_mgr->iou_list );\r
+       while( p_list_item != cl_qlist_end( &gp_iou_mgr->iou_list ) )\r
+       {\r
+               p_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
+               p_list_item = cl_qlist_remove_head( &gp_iou_mgr->iou_list );\r
+               if( p_ext->cl_ext.pnp_state == SurpriseRemoved )\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
+                       continue;\r
+               }\r
+               if( p_ext->h_ca )\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
+                       /* Release the reference on the CA object. */\r
+                       deref_al_obj( &p_ext->h_ca->obj );\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
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+/*\r
+ * Register the load service for the given PnP class events.\r
+ */\r
+ib_api_status_t\r
+bus_reg_iou_pnp( void )\r
+{\r
+       ib_pnp_req_t                    pnp_req;\r
+       ib_api_status_t                 status;\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
+\r
+       status = ib_reg_pnp( gh_al, &pnp_req, &gp_iou_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_iou_mgr->obj );\r
+       }\r
+\r
+       return status;\r
+}\r
+\r
+\r
+/*\r
+ * Load service PnP event callback.\r
+ */\r
+ib_api_status_t\r
+iou_mgr_pnp_cb(\r
+       IN                              ib_pnp_rec_t*                           p_pnp_rec )\r
+{\r
+       ib_api_status_t         status;\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
+       case IB_PNP_IOU_ADD:\r
+               status = iou_mgr_iou_add( (ib_pnp_iou_rec_t*)p_pnp_rec );\r
+               break;\r
+\r
+       case IB_PNP_IOU_REMOVE:\r
+               iou_mgr_iou_remove( (ib_pnp_iou_rec_t*)p_pnp_rec );\r
+\r
+       default:\r
+               status = IB_SUCCESS;\r
+               break;\r
+       }\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+\r
+/*\r
+ * Called to get child relations for the bus root.\r
+ */\r
+NTSTATUS\r
+iou_mgr_get_bus_relations(\r
+       IN              const   net64_t                                         ca_guid,\r
+       IN                              IRP* const                                      p_irp )\r
+{\r
+       NTSTATUS                        status;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\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
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__iou_was_hibernated(\r
+       IN                              ib_pnp_iou_rec_t*                       p_pnp_rec )\r
+{\r
+       NTSTATUS                status;\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
+       cl_qlist_t*             p_pdo_list = &gp_iou_mgr->iou_list;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+       \r
+       cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
+       \r
+       /* Count the number of child devices. */\r
+       for( p_list_item = cl_qlist_head( p_pdo_list );\r
+               p_list_item != cl_qlist_end( p_pdo_list );\r
+               p_list_item = cl_qlist_next( p_list_item ) )\r
+       {\r
+               p_pdo_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
+               p_iou_ext = (bus_iou_ext_t*)p_pdo_ext;\r
+\r
+               /* TODO: maybe we need more search patterns like vend_id, dev_id ... */\r
+               if( p_pdo_ext->b_present && p_pdo_ext->b_hibernating &&\r
+                       (p_iou_ext->guid == p_pnp_rec->pnp_rec.guid) )\r
+               {\r
+                       n_devs++;\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
+                       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
+       if (n_devs)\r
+       {\r
+               /* Take a reference on the parent HCA. */\r
+               p_pdo_ext->h_ca = acquire_ca( p_pnp_rec->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->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
+                       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
+                               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
+               status = IB_NOT_FOUND;\r
+       }\r
+\r
+       cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+ib_api_status_t\r
+iou_mgr_iou_add(\r
+       IN                              ib_pnp_iou_rec_t*                       p_pnp_rec )\r
+{\r
+       NTSTATUS                status;\r
+       DEVICE_OBJECT   *p_pdo;\r
+       bus_iou_ext_t   *p_iou_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       /* Upon hibernating of 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
+       if( status != IB_NOT_FOUND )\r
+       {\r
+               BUS_EXIT( BUS_DBG_PNP );\r
+               return status;\r
+       }\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
+       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, NULL, p_pdo, bus_globals.dbg_lvl,\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.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
+\r
+       p_iou_ext->guid = p_pnp_rec->guid;\r
+       p_iou_ext->chassis_guid = p_pnp_rec->chassis_guid;\r
+       p_iou_ext->slot = p_pnp_rec->slot;\r
+       p_iou_ext->vend_id = cl_ntoh32( p_pnp_rec->vend_id );\r
+       if( p_iou_ext->vend_id == 0x00066a )\r
+               p_iou_ext->dev_id = (net16_t)(p_pnp_rec->pnp_rec.guid >> 32) & 0x00FF;\r
+       else\r
+               p_iou_ext->dev_id = cl_ntoh16( p_pnp_rec->dev_id );\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
+\r
+       /* Cache the CA GUID. */\r
+       p_iou_ext->pdo.ca_guid = p_pnp_rec->ca_guid;\r
+\r
+       /* Take a reference on the parent HCA. */\r
+       p_iou_ext->pdo.h_ca = acquire_ca( p_pnp_rec->ca_guid );\r
+       if( !p_iou_ext->pdo.h_ca )\r
+       {\r
+               IoDeleteDevice( p_pdo );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("acquire_ca failed to find CA.\n") );\r
+               return IB_INVALID_GUID;\r
+       }\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_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
+\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
+\r
+       /* Invalidate removal relations for the bus driver. */\r
+       IoInvalidateDeviceRelations(\r
+               bus_globals.p_bus_ext->cl_ext.p_pdo, RemovalRelations );\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+iou_mgr_iou_remove(\r
+       IN                              ib_pnp_iou_rec_t*                       p_pnp_rec )\r
+{\r
+       bus_pdo_ext_t   *p_ext;\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
+       CL_ASSERT( p_ext );\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
+       cl_mutex_acquire( &gp_iou_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
+               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
+\r
+       /* Invalidate removal relations for the bus driver. */\r
+       IoInvalidateDeviceRelations( bus_globals.p_bus_ext->cl_ext.p_pdo,\r
+               RemovalRelations );\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
+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
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_start(\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
+       bus_pdo_ext_t   *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( p_irp );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       /* Notify the Power Manager that the device is started. */\r
+       PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
+\r
+       *p_action = IrpComplete;\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_query_remove(\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
+       bus_iou_ext_t   *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( p_irp );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       *p_action = IrpComplete;\r
+       if( p_ext->n_ifc_ref )\r
+       {\r
+               /*\r
+                * Our interface is still being held by someone.\r
+                * Rollback the PnP state that was changed in the complib handler.\r
+                */\r
+               cl_rollback_pnp_state( &p_ext->pdo.cl_ext );\r
+\r
+               /* Fail the query. */\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP, ("Failing IRP_MN_QUERY_REMOVE_DEVICE:\n"\r
+                       "\tInterface has %d reference\n", p_ext->n_ifc_ref ) );\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+iou_release_resources(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
+{\r
+       bus_iou_ext_t   *p_ext;\r
+       POWER_STATE             po_state;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       /* Remove this PDO from its list. */\r
+       cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
+       BUS_TRACE( BUS_DBG_PNP, ("Removing IOU from list.\n") );\r
+       cl_qlist_remove_item( &gp_iou_mgr->iou_list, &p_ext->pdo.list_item );\r
+       cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
+       po_state.DeviceState = PowerDeviceD3;\r
+       PoSetPowerState( p_ext->pdo.cl_ext.p_pdo, DevicePowerState, po_state );\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_remove(\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
+       bus_iou_ext_t   *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       if( p_ext->pdo.b_present )\r
+       {\r
+               CL_ASSERT( p_ext->pdo.cl_ext.pnp_state != NotStarted );\r
+               CL_ASSERT( !p_ext->pdo.b_reported_missing );\r
+               /* Reset the state to NotStarted.  CompLib set it to Deleted. */\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.\n") );\r
+               return STATUS_SUCCESS;\r
+       }\r
+\r
+       if( !p_ext->pdo.b_reported_missing )\r
+       {\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.\n") );\r
+               return STATUS_SUCCESS;\r
+       }\r
+\r
+       /* Wait for all I/O operations to complete. */\r
+       IoReleaseRemoveLockAndWait( &p_ext->pdo.cl_ext.remove_lock, p_irp );\r
+\r
+       /* Release resources if it was not done yet. */\r
+       if( p_ext->pdo.cl_ext.last_pnp_state != SurpriseRemoved )\r
+               p_ext->pdo.cl_ext.vfptr_pnp_po->pfn_release_resources( p_dev_obj );\r
+\r
+       p_irp->IoStatus.Status = STATUS_SUCCESS;\r
+       IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+\r
+       IoDeleteDevice( p_dev_obj );\r
+\r
+       *p_action = IrpDoNothing;\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_surprise_remove(\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
+       bus_iou_ext_t   *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( p_irp );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+       p_ext->pdo.b_present = FALSE;\r
+       p_ext->pdo.b_reported_missing = TRUE;\r
+       BUS_TRACE( BUS_DBG_PNP, ("%s: ext %p, present %d, missing %d .\n",\r
+               p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_ext, p_ext->pdo.b_present, p_ext->pdo.b_reported_missing ) );\r
+\r
+       *p_action = IrpComplete;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_query_capabilities(\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
+       DEVICE_CAPABILITIES             *p_caps;\r
+       IO_STACK_LOCATION               *p_io_stack;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( p_dev_obj );\r
+\r
+       p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+       p_caps = p_io_stack->Parameters.DeviceCapabilities.Capabilities;\r
+\r
+       p_caps->DeviceD1 = FALSE;\r
+       p_caps->DeviceD2 = FALSE;\r
+       p_caps->LockSupported = FALSE;\r
+       p_caps->EjectSupported = FALSE;\r
+       p_caps->Removable = TRUE;\r
+       p_caps->DockDevice = FALSE;\r
+       p_caps->UniqueID = TRUE;\r
+       p_caps->SilentInstall = TRUE;\r
+       p_caps->RawDeviceOK = FALSE;\r
+       p_caps->SurpriseRemovalOK = FALSE;\r
+       p_caps->WakeFromD0 = FALSE;\r
+       p_caps->WakeFromD1 = FALSE;\r
+       p_caps->WakeFromD2 = FALSE;\r
+       p_caps->WakeFromD3 = FALSE;\r
+       p_caps->HardwareDisabled = FALSE;\r
+       p_caps->DeviceState[PowerSystemWorking] = PowerDeviceD0;\r
+       p_caps->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;\r
+       p_caps->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;\r
+       p_caps->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;\r
+       p_caps->DeviceState[PowerSystemHibernate] = PowerDeviceD3;\r
+       p_caps->DeviceState[PowerSystemShutdown] = PowerDeviceD3;\r
+       p_caps->SystemWake = PowerSystemUnspecified;\r
+       p_caps->DeviceWake = PowerDeviceUnspecified;\r
+       p_caps->D1Latency = 0;\r
+       p_caps->D2Latency = 0;\r
+       p_caps->D3Latency = 0;\r
+\r
+       *p_action = IrpComplete;\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_query_target_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
+       DEVICE_RELATIONS        *p_rel;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       *p_action = IrpComplete;\r
+\r
+       status = cl_alloc_relations( p_irp, 1 );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("cl_alloc_relations returned 0x%08x.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
+       p_rel->Count = 1;\r
+       p_rel->Objects[0] = p_dev_obj;\r
+\r
+       ObReferenceObject( p_dev_obj );\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_query_device_id(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
+               OUT                             IRP* const                              p_irp )\r
+{\r
+       NTSTATUS                        status;\r
+       bus_iou_ext_t           *p_ext;\r
+       WCHAR                           *p_string;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = (bus_iou_ext_t*)p_dev_obj->DeviceExtension;\r
+       if( !p_ext->pdo.b_present )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+\r
+       /* Device ID is "IBA\SID_<sid> where <sid> is the IPoIB Service ID. */\r
+       p_string = ExAllocatePoolWithTag( PagedPool, IOU_DEV_ID_SIZE, 'didq' );\r
+       if( !p_string )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("Failed to allocate device ID buffer (%d bytes).\n",\r
+                       IOU_DEV_ID_SIZE) );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       status =\r
+               RtlStringCbPrintfW( p_string, IOU_DEV_ID_SIZE, IOU_DEV_ID_STRING1,\r
+                       p_ext->vend_id, p_ext->dev_id, p_ext->revision );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               ExFreePool( p_string );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to format device ID string.\n") );\r
+               return status;\r
+       }\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_query_hardware_ids(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
+               OUT                             IRP* const                              p_irp )\r
+{\r
+       NTSTATUS                        status;\r
+       bus_iou_ext_t           *p_ext;\r
+       WCHAR                           *p_string, *p_start;\r
+       size_t                          size;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = (bus_iou_ext_t*)p_dev_obj->DeviceExtension;\r
+       if( !p_ext->pdo.b_present )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+\r
+       p_string = ExAllocatePoolWithTag( PagedPool, IOU_HW_ID_SIZE, 'dihq' );\r
+       if( !p_string )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("Failed to allocate hardware ID buffer (%d bytes).\n",\r
+                       IOU_HW_ID_SIZE) );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       p_start = p_string;\r
+       size = IOU_HW_ID_SIZE;\r
+       /* Fill in the first HW ID. */\r
+       status = RtlStringCbPrintfExW( p_start, size, &p_start, &size,\r
+               STRSAFE_FILL_BEHIND_NULL | STRSAFE_NO_TRUNCATION, IOU_DEV_ID_STRING1,\r
+               p_ext->vend_id, p_ext->dev_id, p_ext->revision );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               ExFreePool( p_string );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to format device ID string.\n") );\r
+               return status;\r
+       }\r
+       /* Fill in the second HW ID. */\r
+       CL_ASSERT( *p_start == L'\0' );\r
+       p_start++;\r
+       size -= sizeof(WCHAR);\r
+       status = RtlStringCbPrintfExW( p_start, size, NULL, NULL,\r
+               STRSAFE_FILL_BEHIND_NULL | STRSAFE_NO_TRUNCATION, IOU_DEV_ID_STRING2,\r
+               p_ext->vend_id, p_ext->dev_id );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               ExFreePool( p_string );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to format device ID string.\n") );\r
+               return status;\r
+       }\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_query_compatible_ids(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
+               OUT                             IRP* const                              p_irp )\r
+{\r
+       WCHAR                           *p_string;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( p_dev_obj );\r
+\r
+       p_string = ExAllocatePoolWithTag( PagedPool, sizeof(IOU_COMPAT_ID), 'dicq' );\r
+       if( !p_string )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("Failed to allocate compatible ID buffer (%d bytes).\n",\r
+                       IOU_HW_ID_SIZE) );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       cl_memcpy( p_string, IOU_COMPAT_ID, sizeof(IOU_COMPAT_ID) );\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_query_unique_id(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
+               OUT                             IRP* const                              p_irp )\r
+{\r
+       NTSTATUS                        status;\r
+       WCHAR                           *p_string;\r
+       bus_iou_ext_t           *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+       \r
+       p_ext = p_dev_obj->DeviceExtension;\r
+       if( !p_ext->pdo.b_present )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+\r
+       /* The instance ID is the port GUID. */\r
+       p_string = ExAllocatePoolWithTag( PagedPool, sizeof(WCHAR) * 33, 'diuq' );\r
+       if( !p_string )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("Failed to allocate instance ID buffer (%d bytes).\n",\r
+                       sizeof(WCHAR) * 17) );\r
+               return STATUS_NO_MEMORY;\r
+       }\r
+\r
+       status = RtlStringCchPrintfW( p_string, 33, L"%016I64x%016I64x",\r
+               p_ext->guid, p_ext->pdo.ca_guid );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               CL_ASSERT( NT_SUCCESS( status ) );\r
+               ExFreePool( p_string );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("RtlStringCchPrintfW returned %08x.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_query_description(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
+               OUT                             IRP* const                              p_irp )\r
+{\r
+       NTSTATUS                        status;\r
+       WCHAR                           *p_string;\r
+       bus_iou_ext_t           *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+       \r
+       p_ext = p_dev_obj->DeviceExtension;\r
+       if( !p_ext->pdo.b_present )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+\r
+       /* The instance ID is the port GUID. */\r
+       p_string = ExAllocatePoolWithTag( PagedPool,\r
+                                                                         sizeof(WCHAR) * sizeof(p_ext->desc),\r
+                                                                         'sedq' );\r
+       if( !p_string )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("Failed to allocate device description buffer (%d bytes).\n",\r
+                       sizeof(WCHAR) * sizeof(p_ext->desc)) );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       status = RtlStringCchPrintfW( p_string, sizeof(p_ext->desc),\r
+               L"%S", p_ext->desc );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               CL_ASSERT( NT_SUCCESS( status ) );\r
+               ExFreePool( p_string );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("RtlStringCchPrintfW returned %08x.\n", status) );\r
+               return status;\r
+       }\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_query_location(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
+               OUT                             IRP* const                              p_irp )\r
+{\r
+       NTSTATUS                        status;\r
+       bus_iou_ext_t           *p_ext;\r
+       WCHAR                           *p_string;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = (bus_iou_ext_t*)p_dev_obj->DeviceExtension;\r
+       if( !p_ext->pdo.b_present )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+\r
+       p_string = ExAllocatePoolWithTag( PagedPool, IOU_LOCATION_SIZE, 'colq' );\r
+       if( !p_string )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("Failed to allocate location buffer (%d bytes).\n",\r
+                       IOU_LOCATION_SIZE) );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       status = RtlStringCbPrintfW( p_string, IOU_LOCATION_SIZE,\r
+               L"Chassis 0x%016I64x, Slot %d", p_ext->chassis_guid, p_ext->slot );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               ExFreePool( p_string );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to format device ID string.\n") );\r
+               return status;\r
+       }\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_query_bus_info(\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
+       PNP_BUS_INFORMATION     *p_bus_info;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( p_dev_obj );\r
+\r
+       *p_action = IrpComplete;\r
+\r
+       p_bus_info = ExAllocatePoolWithTag( PagedPool, sizeof(PNP_BUS_INFORMATION), 'subq' );\r
+       if( !p_bus_info )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to allocate PNP_BUS_INFORMATION (%d bytes).\n",\r
+                       sizeof(PNP_BUS_INFORMATION)) );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       p_bus_info->BusTypeGuid = GUID_BUS_TYPE_IBA;\r
+       //TODO: Memory from Intel - storage miniport would not stay loaded unless\r
+       //TODO: bus type was PCI.  Look here if SRP is having problems staying\r
+       //TODO: loaded.\r
+       p_bus_info->LegacyBusType = PNPBus;\r
+       p_bus_info->BusNumber = 0;\r
+\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_bus_info;\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_query_iou_ifc(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IO_STACK_LOCATION* const        p_io_stack )\r
+{\r
+       NTSTATUS                                status;\r
+       ib_al_ifc_t                             *p_ifc;\r
+       ib_al_ifc_data_t                *p_ifc_data;\r
+       iou_ifc_data_t                  *p_iou_data;\r
+       bus_iou_ext_t                   *p_ext;\r
+       const GUID                              *p_guid;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       /* Get the interface. */\r
+       status = cl_fwd_query_ifc(\r
+               p_ext->pdo.p_parent_ext->cl_ext.p_self_do, p_io_stack );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to forward interface query: %08X\n", status) );\r
+               return status;\r
+       }\r
+\r
+       if( !p_io_stack->Parameters.QueryInterface.InterfaceSpecificData )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("No interface specific data!\n") );\r
+               return status;\r
+       }\r
+\r
+       p_ifc = (ib_al_ifc_t*)p_io_stack->Parameters.QueryInterface.Interface;\r
+\r
+       p_ifc_data = (ib_al_ifc_data_t*)\r
+               p_io_stack->Parameters.QueryInterface.InterfaceSpecificData;\r
+       p_guid = p_ifc_data->type;\r
+       if( !IsEqualGUID( p_guid, &GUID_IOU_INTERFACE_DATA ) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP, ("Unsupported interface data: \n\t"\r
+                       "0x%08x, 0x%04x, 0x%04x, 0x%02x, 0x%02x, 0x%02x,"\r
+                       "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n",\r
+                       p_guid->Data1, p_guid->Data2, p_guid->Data3,\r
+                       p_guid->Data4[0], p_guid->Data4[1], p_guid->Data4[2],\r
+                       p_guid->Data4[3], p_guid->Data4[4], p_guid->Data4[5],\r
+                       p_guid->Data4[6], p_guid->Data4[7]) );\r
+               return status;\r
+       }\r
+\r
+       if( p_ifc_data->version != IOU_INTERFACE_DATA_VERSION )\r
+       {\r
+               p_ifc->wdm.InterfaceDereference( p_ifc->wdm.Context );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Unsupported version %d, expected %d\n",\r
+                       p_ifc_data->version, IOU_INTERFACE_DATA_VERSION) );\r
+               return STATUS_NOT_SUPPORTED;\r
+       }\r
+\r
+       ASSERT( p_ifc_data->p_data );\r
+\r
+       if( p_ifc_data->size != sizeof(iou_ifc_data_t) )\r
+       {\r
+               p_ifc->wdm.InterfaceDereference( p_ifc->wdm.Context );\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP,\r
+                       ("Buffer too small (%d given, %d required).\n",\r
+                       p_ifc_data->size,\r
+                       sizeof(iou_ifc_data_t)) );\r
+               return STATUS_BUFFER_TOO_SMALL;\r
+       }\r
+\r
+       /* Set the interface data. */\r
+       p_iou_data = (iou_ifc_data_t*)p_ifc_data->p_data;\r
+\r
+       p_iou_data->ca_guid = p_ext->pdo.ca_guid;\r
+       p_iou_data->chassis_guid = p_ext->chassis_guid;\r
+       p_iou_data->slot = p_ext->slot;\r
+       p_iou_data->guid = p_ext->guid;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+iou_query_interface(\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
+       bus_pdo_ext_t           *p_ext;\r
+       NTSTATUS                        status;\r
+       IO_STACK_LOCATION       *p_io_stack;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
+\r
+       p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+       \r
+       /* Bottom of the stack - IRP must be completed. */\r
+       *p_action = IrpComplete;\r
+\r
+       /* Compare requested GUID with our supported interface GUIDs. */\r
+       if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
+               &GUID_IB_AL_INTERFACE ) )\r
+       {\r
+               status = iou_query_iou_ifc( p_dev_obj, p_io_stack );\r
+       }\r
+       else if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
+               &GUID_BUS_INTERFACE_STANDARD ) )\r
+       {\r
+               p_ext = p_dev_obj->DeviceExtension;\r
+               if( !p_ext->h_ca ||\r
+                       !p_ext->b_present ||\r
+                       p_ext->b_reported_missing )\r
+               {\r
+                       return STATUS_NO_SUCH_DEVICE;\r
+               }\r
+\r
+\r
+               status = cl_fwd_query_ifc(\r
+                       p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, p_io_stack );\r
+       }\r
+       else\r
+       {\r
+               status = p_irp->IoStatus.Status;\r
+       }\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+\r
+\r
+/* Work item callback to handle DevicePowerD3 IRPs at passive level. */\r
+static void\r
+__HibernateUpWorkItem(\r
+       IN                              DEVICE_OBJECT*                          p_dev_obj,\r
+       IN                              void*                                           context )\r
+{\r
+       IO_STACK_LOCATION       *p_io_stack;\r
+       bus_pdo_ext_t           *p_ext;\r
+       IRP                                     *p_irp;\r
+       POWER_STATE powerState;\r
+\r
+       BUS_ENTER( BUS_DBG_POWER );\r
+\r
+       p_ext = (bus_pdo_ext_t*)p_dev_obj->DeviceExtension;\r
+       p_irp = (IRP*)context;\r
+       p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+\r
+       IoFreeWorkItem( p_ext->p_po_work_item );\r
+       p_ext->p_po_work_item = NULL;\r
+\r
+       while (!p_ext->h_ca) {\r
+               BUS_TRACE( BUS_DBG_PNP, ("Waiting for the end of HCA registration ... \n"));\r
+               cl_thread_suspend( 200 );       /* suspend for 200 ms */\r
+       }\r
+\r
+       p_ext->dev_po_state = p_io_stack->Parameters.Power.State;\r
+       powerState = PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
+\r
+       BUS_TRACE( BUS_DBG_POWER, \r
+               ("PoSetPowerState: old state %d, new state to %d\n", \r
+               powerState.DeviceState, p_ext->dev_po_state ));\r
+\r
+       p_irp->IoStatus.Status = STATUS_SUCCESS;\r
+       PoStartNextPowerIrp( p_irp );\r
+       IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+       IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
+\r
+       BUS_EXIT( BUS_DBG_POWER );\r
+}\r
+\r
+/*\r
+ * The PDOs created by the IB Bus driver are software devices.  As such,\r
+ * all power states are supported.  It is left to the HCA power policy \r
+ * owner to handle which states can be supported by the HCA.\r
+ */\r
+static NTSTATUS\r
+iou_set_power(\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 = STATUS_SUCCESS;\r
+       IO_STACK_LOCATION       *p_io_stack;\r
+       bus_pdo_ext_t           *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_POWER );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+       p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+\r
+       BUS_TRACE( BUS_DBG_POWER, \r
+               ("SET_POWER for PDO %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.State.DeviceState, \r
+               p_io_stack->Parameters.Power.ShutdownType ));\r
+\r
+       if ((p_io_stack->Parameters.Power.Type == SystemPowerState) &&\r
+               (p_io_stack->Parameters.Power.State.SystemState ==PowerSystemHibernate ||\r
+               p_io_stack->Parameters.Power.State.SystemState ==PowerSystemSleeping1 ))\r
+       {\r
+               BUS_TRACE( BUS_DBG_POWER, ("Setting b_hibernating flag for PDO %p \n", p_dev_obj));\r
+               p_ext->b_hibernating = TRUE;\r
+       }\r
+\r
+       if( p_io_stack->Parameters.Power.Type == DevicePowerState )\r
+       {\r
+               /* after hibernation PDO is not ready for work. we need to wait for finishing of the HCA registration */\r
+               if( p_io_stack->Parameters.Power.State.DeviceState == PowerDeviceD0 && p_ext->b_hibernating)\r
+               {\r
+                       /* Process in a work item - deregister_ca and HcaDeinit block. */\r
+                       ASSERT( !p_ext->p_po_work_item );\r
+                       p_ext->p_po_work_item = IoAllocateWorkItem( p_dev_obj );\r
+                       if( !p_ext->p_po_work_item )\r
+                               status = STATUS_INSUFFICIENT_RESOURCES;\r
+                       else {\r
+                               /* Process in work item callback. */\r
+                               IoMarkIrpPending( p_irp );\r
+                               IoQueueWorkItem(\r
+                                       p_ext->p_po_work_item, __HibernateUpWorkItem, DelayedWorkQueue, p_irp );\r
+                               *p_action = IrpDoNothing;\r
+                               BUS_EXIT( BUS_DBG_POWER );\r
+                               return STATUS_PENDING;\r
+                       }\r
+               }\r
+\r
+               /* Notify the power manager. */\r
+               p_ext->dev_po_state = p_io_stack->Parameters.Power.State;\r
+               PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
+       }\r
+\r
+       *p_action = IrpComplete;\r
+       BUS_EXIT( BUS_DBG_POWER );\r
+       return STATUS_SUCCESS;\r
+}\r
diff --git a/branches/IBFD/core/bus/kmdf/bus_iou_mgr.h b/branches/IBFD/core/bus/kmdf/bus_iou_mgr.h
new file mode 100644 (file)
index 0000000..b181ba0
--- /dev/null
@@ -0,0 +1,66 @@
+/*\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_iou_mgr.h 9 2005-05-23 22:38:08Z ftillier $\r
+ */\r
+\r
+\r
+#if !defined( __BUS_IOU_MGR_H__ )\r
+#define __BUS_IOU_MGR_H__\r
+\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_mutex.h>\r
+#include <complib/cl_obj.h>\r
+\r
+\r
+/* Global load service */\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
+\r
+       /* Pointer vector of child IOU PDOs. */\r
+       cl_qlist_t                                      iou_list;\r
+\r
+}      iou_mgr_t;\r
+\r
+\r
+ib_api_status_t\r
+create_iou_mgr(\r
+               OUT                     iou_mgr_t** const                       pp_iou_mgr );\r
+\r
+\r
+NTSTATUS\r
+iou_mgr_get_bus_relations(\r
+       IN              const   net64_t                                         ca_guid,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+#endif\r
diff --git a/branches/IBFD/core/bus/kmdf/bus_pdo.c b/branches/IBFD/core/bus/kmdf/bus_pdo.c
new file mode 100644 (file)
index 0000000..dfd20c5
--- /dev/null
@@ -0,0 +1,560 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation All Rights Reserved\r
+ * Copyright (c) 2008 Microsoft Corporation 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$\r
+ */\r
+\r
+/*++\r
+Module Name:\r
+\r
+    BusPdo.c\r
+\r
+Abstract:\r
+\r
+    This module handles plug & play calls for the child device (PDO).\r
+\r
+Environment:\r
+\r
+    kernel mode only\r
+\r
+--*/\r
+\r
+#include "bus_driver.h"\r
+#include <initguid.h>\r
+#include "driver.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#include "buspdo.tmh\r
+#endif\r
+\r
+// short-hand notation...\r
+#define PWDF_CHILD_ID_DESC_HDR PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER \r
+\r
+NTSTATUS\r
+Bus_DeviceListCreatePdo( WDFCHILDLIST                          DeviceList,\r
+                                                PWDF_CHILD_ID_DESC_HDR         IdentificationDescription,\r
+                                                PWDFDEVICE_INIT                        ChildInit );\r
+\r
+NTSTATUS\r
+Bus_CreatePdo(\r
+       __in WDFDEVICE       Device,\r
+       __in PWDFDEVICE_INIT DeviceInit,\r
+       __in PWCHAR          HardwareIds,\r
+       __in ULONG           SerialNo );\r
+\r
+#ifdef ALLOC_PRAGMA\r
+#pragma alloc_text(PAGE, Bus_CreatePdo)\r
+#pragma alloc_text(PAGE, Bus_DeviceListCreatePdo)\r
+#endif\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    It is called when the framework needs to make a copy of a description.\r
+    This happens when a request is made to create a new child device by\r
+    calling WdfChildListAddOrUpdateChildDescriptionAsPresent.\r
+    If this function is left unspecified, RtlCopyMemory will be used to copy the\r
+    source description to destination. Memory for the description is managed by\r
+       the framework.\r
+\r
+    NOTE:   Callback is invoked with an internal lock held.  So do not call out\r
+    to any WDF function which will require this lock\r
+    (basically any other WDFCHILDLIST api)\r
+\r
+Arguments:\r
+\r
+    DeviceList - Handle to the default WDFCHILDLIST created by the framework.\r
+    SourceIdentificationDescription - Description of the child being created\r
+                                                                       - memory in the calling thread stack.\r
+    DestinationIdentificationDescription - Created by the framework in nonpaged\r
+                                                                                - pool.\r
+\r
+Return Value:\r
+\r
+    NT Status code.\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+Bus_ChildListIdentificationDescriptionDuplicate(\r
+                   WDFCHILDLIST                        DeviceList,\r
+                   PWDF_CHILD_ID_DESC_HDR      SourceIdentificationDescription,\r
+                   PWDF_CHILD_ID_DESC_HDR      DestinationIdentificationDescription )\r
+{\r
+    PPDO_IDENTIFICATION_DESCRIPTION src, dst;\r
+    size_t safeMultResult;\r
+    NTSTATUS status;\r
+\r
+    UNREFERENCED_PARAMETER(DeviceList);\r
+\r
+    src = CONTAINING_RECORD(SourceIdentificationDescription,\r
+                            PDO_IDENTIFICATION_DESCRIPTION,\r
+                            Header);\r
+    dst = CONTAINING_RECORD(DestinationIdentificationDescription,\r
+                            PDO_IDENTIFICATION_DESCRIPTION,\r
+                            Header);\r
+\r
+    dst->SerialNo = src->SerialNo;\r
+    dst->CchHardwareIds = src->CchHardwareIds;\r
+    status = RtlSizeTMult(dst->CchHardwareIds,\r
+                                  sizeof(WCHAR),\r
+                                  &safeMultResult\r
+                                  );\r
+    if(!NT_SUCCESS(status)){\r
+        return status;\r
+    }\r
+\r
+    dst->HardwareIds = (PWCHAR) ExAllocatePoolWithTag(\r
+        NonPagedPool,\r
+        safeMultResult,\r
+        BUS_TAG);\r
+\r
+    if (dst->HardwareIds == NULL) {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    RtlCopyMemory(dst->HardwareIds,\r
+                  src->HardwareIds,\r
+                  dst->CchHardwareIds * sizeof(WCHAR));\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    This is called when the framework needs to compare one description with\r
+       another.  Typically this happens whenever a request is made to add a new\r
+       child device.  If this function is left unspecified, RtlCompareMemory will\r
+       be used to compare the descriptions.\r
+\r
+    NOTE:   Callback is invoked with an internal lock held.  So do not call out\r
+    to any WDF function which will require this lock\r
+    (basically any other WDFCHILDLIST api)\r
+\r
+Arguments:\r
+\r
+    DeviceList - Handle to the default WDFCHILDLIST created by the framework.\r
+\r
+Return Value:\r
+\r
+   TRUE or FALSE.\r
+\r
+--*/\r
+\r
+BOOLEAN\r
+Bus_ChildListIdentificationDescriptionCompare(\r
+                   WDFCHILDLIST                        DeviceList,\r
+                   PWDF_CHILD_ID_DESC_HDR      FirstIdentificationDescription,\r
+                   PWDF_CHILD_ID_DESC_HDR      SecondIdentificationDescription )\r
+{\r
+    PPDO_IDENTIFICATION_DESCRIPTION lhs, rhs;\r
+\r
+    UNREFERENCED_PARAMETER(DeviceList);\r
+\r
+    lhs = CONTAINING_RECORD(FirstIdentificationDescription,\r
+                            PDO_IDENTIFICATION_DESCRIPTION,\r
+                            Header);\r
+    rhs = CONTAINING_RECORD(SecondIdentificationDescription,\r
+                            PDO_IDENTIFICATION_DESCRIPTION,\r
+                            Header);\r
+\r
+    return (lhs->SerialNo == rhs->SerialNo) ? TRUE : FALSE;\r
+}\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    It is called to free up any memory resources allocated as part of the\r
+       description.  This happens when a child device is unplugged or ejected from\r
+       the bus.  Memory for the description itself will be freed by the framework.\r
+\r
+Arguments:\r
+\r
+    DeviceList - Handle to the default WDFCHILDLIST created by the framework.\r
+\r
+    IdentificationDescription - Description of the child being deleted\r
+\r
+Return Value:\r
+\r
+--*/\r
+\r
+VOID\r
+Bus_ChildListIdentificationDescriptionCleanup(\r
+                   WDFCHILDLIST                        DeviceList,\r
+                   PWDF_CHILD_ID_DESC_HDR      IdentificationDescription )\r
+{\r
+    PPDO_IDENTIFICATION_DESCRIPTION pDesc;\r
+\r
+\r
+    UNREFERENCED_PARAMETER(DeviceList);\r
+\r
+    pDesc = CONTAINING_RECORD(IdentificationDescription,\r
+                              PDO_IDENTIFICATION_DESCRIPTION,\r
+                              Header);\r
+\r
+    if (pDesc->HardwareIds != NULL) {\r
+        ExFreePool(pDesc->HardwareIds);\r
+        pDesc->HardwareIds = NULL;\r
+    }\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Called by the framework in response to Query-Device relation when\r
+    a new PDO for a child device needs to be created.\r
+\r
+Arguments:\r
+\r
+    DeviceList - Handle to the default WDFCHILDLIST created by the framework\r
+                                as part of FDO.\r
+\r
+    IdentificationDescription - Decription of the new child device.\r
+\r
+    ChildInit - It's a opaque structure used in collecting device settings\r
+                and passed in as a parameter to CreateDevice.\r
+\r
+Return Value:\r
+\r
+    NT Status code.\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+Bus_DeviceListCreatePdo( WDFCHILDLIST                          DeviceList,\r
+                                                PWDF_CHILD_ID_DESC_HDR         IdentificationDescription,\r
+                                                PWDFDEVICE_INIT                        ChildInit )\r
+{\r
+    PPDO_IDENTIFICATION_DESCRIPTION pDesc;\r
+\r
+    PAGED_CODE();\r
+\r
+    pDesc = CONTAINING_RECORD(IdentificationDescription,\r
+                              PDO_IDENTIFICATION_DESCRIPTION,\r
+                              Header);\r
+\r
+    return Bus_CreatePdo(WdfChildListGetDevice(DeviceList),\r
+                         ChildInit,\r
+                         pDesc->HardwareIds,\r
+                         pDesc->SerialNo);\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    This routine creates and initialize a PDO.\r
+\r
+Arguments:\r
+\r
+Return Value:\r
+\r
+    NT Status code.\r
+\r
+--*/\r
+NTSTATUS\r
+Bus_CreatePdo(\r
+       __in WDFDEVICE       Device,\r
+       __in PWDFDEVICE_INIT DeviceInit,\r
+       __in PWCHAR          HardwareIds,\r
+       __in ULONG           SerialNo )\r
+{\r
+    NTSTATUS                    status;\r
+    PPDO_DEVICE_DATA            pdoData = NULL;\r
+    WDFDEVICE                   hChild = NULL;\r
+    WDF_QUERY_INTERFACE_CONFIG  qiConfig;\r
+    WDF_OBJECT_ATTRIBUTES       pdoAttributes;\r
+    WDF_DEVICE_PNP_CAPABILITIES pnpCaps;\r
+    WDF_DEVICE_POWER_CAPABILITIES powerCaps;\r
+    IB_BUS_INTERFACE_STANDARD  FabricInterface;\r
+    DECLARE_CONST_UNICODE_STRING(compatId, BUSENUM_COMPATIBLE_IDS);\r
+    DECLARE_CONST_UNICODE_STRING(deviceLocation, L"InfiniBand Fabric 0");\r
+    DECLARE_UNICODE_STRING_SIZE(buffer, MAX_INSTANCE_ID_LEN);\r
+    DECLARE_UNICODE_STRING_SIZE(deviceId, MAX_INSTANCE_ID_LEN);\r
+\r
+    PAGED_CODE();\r
+\r
+    UNREFERENCED_PARAMETER(Device);\r
+\r
+    KdPrint(("Entered Bus_CreatePdo\n"));\r
+\r
+    //\r
+    // Set DeviceType\r
+    //\r
+    WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);\r
+\r
+    //\r
+    // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId\r
+    //\r
+    RtlInitUnicodeString(&deviceId, HardwareIds);\r
+\r
+    status = WdfPdoInitAssignDeviceID(DeviceInit, &deviceId);\r
+    if (!NT_SUCCESS(status)) {\r
+        return status;\r
+    }\r
+\r
+    //\r
+    // NOTE: same string  is used to initialize hardware id too\r
+    //\r
+    status = WdfPdoInitAddHardwareID(DeviceInit, &deviceId);\r
+    if (!NT_SUCCESS(status)) {\r
+        return status;\r
+    }\r
+\r
+    status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId );\r
+    if (!NT_SUCCESS(status)) {\r
+        return status;\r
+    }\r
+\r
+    status =  RtlUnicodeStringPrintf(&buffer, L"%02d", SerialNo);\r
+    if (!NT_SUCCESS(status)) {\r
+        return status;\r
+    }\r
+\r
+    status = WdfPdoInitAssignInstanceID(DeviceInit, &buffer);\r
+    if (!NT_SUCCESS(status)) {\r
+        return status;\r
+    }\r
+\r
+    //\r
+    // Provide a description about the device. This text is usually read from\r
+    // the device. In the case of USB device, this text comes from the string\r
+    // descriptor. This text is displayed momentarily by the PnP manager while\r
+    // it's looking for a matching INF. If it finds one, it uses the Device\r
+    // Description from the INF file or the friendly name created by\r
+    // coinstallers to display in the device manager. FriendlyName takes\r
+    // precedence over the DeviceDesc from the INF file.\r
+    //\r
+    status = RtlUnicodeStringPrintf( &buffer,\r
+                                     L"InfiniBand_HCA%02d",\r
+                                     SerialNo ); // XXX?\r
+    if (!NT_SUCCESS(status)) {\r
+        return status;\r
+    }\r
+\r
+    //\r
+    // You can call WdfPdoInitAddDeviceText multiple times, adding device\r
+    // text for multiple locales. When the system displays the text, it\r
+    // chooses the text that matches the current locale, if available.\r
+    // Otherwise it will use the string for the default locale.\r
+    // The driver can specify the driver's default locale by calling\r
+    // WdfPdoInitSetDefaultLocale.\r
+    //\r
+    status = WdfPdoInitAddDeviceText(DeviceInit,\r
+                                    &buffer,\r
+                                    &deviceLocation,\r
+                                     0x409 );\r
+    if (!NT_SUCCESS(status)) {\r
+        return status;\r
+    }\r
+\r
+    WdfPdoInitSetDefaultLocale(DeviceInit, 0x409);\r
+\r
+    //\r
+    // Initialize the attributes to specify the size of PDO device extension.\r
+    // All the state information private to the PDO will be tracked here.\r
+    //\r
+    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, PDO_DEVICE_DATA);\r
+\r
+    status = WdfDeviceCreate(&DeviceInit, &pdoAttributes, &hChild);\r
+    if (!NT_SUCCESS(status)) {\r
+        return status;\r
+    }\r
+\r
+    //\r
+    // Get the device context.\r
+    //\r
+    pdoData = PdoGetData(hChild);\r
+\r
+    pdoData->SerialNo = SerialNo;\r
+\r
+    //\r
+    // Set some properties for the child device.\r
+    //\r
+    WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);\r
+    pnpCaps.Removable         = WdfTrue;\r
+    pnpCaps.EjectSupported    = WdfTrue;\r
+    pnpCaps.SurpriseRemovalOK = WdfTrue;\r
+\r
+    pnpCaps.Address  = SerialNo;\r
+    pnpCaps.UINumber = SerialNo;\r
+\r
+    WdfDeviceSetPnpCapabilities(hChild, &pnpCaps);\r
+\r
+    WDF_DEVICE_POWER_CAPABILITIES_INIT(&powerCaps);\r
+\r
+    powerCaps.DeviceD1 = WdfTrue;\r
+    powerCaps.WakeFromD1 = WdfTrue;\r
+    powerCaps.DeviceWake = PowerDeviceD1;\r
+\r
+    powerCaps.DeviceState[PowerSystemWorking]   = PowerDeviceD1;\r
+    powerCaps.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;\r
+    powerCaps.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;\r
+    powerCaps.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;\r
+    powerCaps.DeviceState[PowerSystemHibernate] = PowerDeviceD3;\r
+    powerCaps.DeviceState[PowerSystemShutdown]  = PowerDeviceD3;\r
+\r
+    WdfDeviceSetPowerCapabilities(hChild, &powerCaps);\r
+\r
+    //\r
+    // Create a custom interface so that other drivers can\r
+    // query (IRP_MN_QUERY_INTERFACE) and use our callbacks directly.\r
+    //\r
+    RtlZeroMemory(&FabricInterface, sizeof(FabricInterface));\r
+\r
+    FabricInterface.InterfaceHeader.Size = sizeof(FabricInterface);\r
+    FabricInterface.InterfaceHeader.Version = 1;\r
+    FabricInterface.InterfaceHeader.Context = (PVOID) hChild;\r
+\r
+    //\r
+    // Let the framework handle reference counting.\r
+    //\r
+    FabricInterface.InterfaceHeader.InterfaceReference\r
+                                                                       = WdfDeviceInterfaceReferenceNoOp;\r
+    FabricInterface.InterfaceHeader.InterfaceDereference\r
+                                                                       = WdfDeviceInterfaceDereferenceNoOp;\r
+\r
+    FabricInterface.GetCrispinessLevel  = Bus_GetCrispinessLevel;\r
+    FabricInterface.SetCrispinessLevel  = Bus_SetCrispinessLevel;\r
+    FabricInterface.IsSafetyLockEnabled = Bus_IsSafetyLockEnabled;\r
+\r
+    WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig,\r
+                                    (PINTERFACE) &FabricInterface,\r
+                                    &GUID_IBF_INTERFACE_STANDARD,\r
+                                    NULL);\r
+    //\r
+    // If you have multiple interfaces, you can call WdfDeviceAddQueryInterface\r
+    // multiple times to add additional interfaces.\r
+    //\r
+    status = WdfDeviceAddQueryInterface(hChild, &qiConfig);\r
+\r
+    if (!NT_SUCCESS(status)) {\r
+               KdPrint(("WdfDeviceAddQueryInterface() rc 0x%x\n",status));\r
+    }\r
+    return status;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    This routine gets the current crispiness level of the toaster.\r
+\r
+Arguments:\r
+\r
+    Context        pointer to  PDO device extension\r
+    Level          crispiness level of the device\r
+\r
+Return Value:\r
+\r
+    TRUE or FALSE\r
+\r
+--*/\r
+\r
+BOOLEAN\r
+Bus_GetCrispinessLevel( IN   WDFDEVICE ChildDevice,\r
+                                           OUT  PUCHAR         Level )\r
+{\r
+    UNREFERENCED_PARAMETER(ChildDevice);\r
+\r
+    //\r
+    // Validate the context to see if it's really a pointer\r
+    // to PDO's device extension. You can store some kind\r
+    // of signature in the PDO for this purpose\r
+    //\r
+\r
+    KdPrint(("GetCrispnessLevel\n"));\r
+\r
+    *Level = 10;\r
+    return TRUE;\r
+}\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    This routine sets the current crispiness level of the toaster.\r
+\r
+Arguments:\r
+\r
+    Context        pointer to  PDO device extension\r
+    Level          crispiness level of the device\r
+\r
+Return Value:\r
+\r
+    TRUE or FALSE\r
+\r
+--*/\r
+\r
+BOOLEAN\r
+Bus_SetCrispinessLevel( IN   WDFDEVICE ChildDevice,\r
+                                           IN   UCHAR          Level )\r
+{\r
+    UNREFERENCED_PARAMETER(ChildDevice);\r
+    UNREFERENCED_PARAMETER(Level);\r
+\r
+    KdPrint(("SetCrispnessLevel\n"));\r
+\r
+    return TRUE;\r
+}\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Routine to check whether safety lock is enabled\r
+\r
+Arguments:\r
+\r
+    Context - pointer to  PDO device extension\r
+\r
+Return Value:\r
+\r
+    TRUE or FALSE\r
+\r
+--*/\r
+BOOLEAN\r
+Bus_IsSafetyLockEnabled( IN WDFDEVICE ChildDevice )\r
+{\r
+    UNREFERENCED_PARAMETER(ChildDevice);\r
+\r
+    KdPrint(("IsSafetyLockEnabled\n"));\r
+\r
+    return TRUE;\r
+}\r
+\r
+\r
diff --git a/branches/IBFD/core/bus/kmdf/bus_pnp.c b/branches/IBFD/core/bus/kmdf/bus_pnp.c
new file mode 100644 (file)
index 0000000..bd703f4
--- /dev/null
@@ -0,0 +1,2921 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox 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.c 744 2007-07-31 19:04:15Z leonidk $\r
+ */\r
+\r
+\r
+\r
+/*\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
+#include "al_dev.h"\r
+#include "bus_port_mgr.h"\r
+#include "bus_iou_mgr.h"\r
+#include "complib/cl_memory.h"\r
+#include <initguid.h>\r
+#include "iba/ib_ci_ifc.h"\r
+\r
+#include "ib_bus_public.h"\r
+\r
+EVT_WDF_DRIVER_DEVICE_ADD Bus_EvtDeviceAdd;\r
+\r
+EVT_WDF_CHILD_LIST_CREATE_DEVICE Bus_DeviceListCreatePdo;\r
+\r
+EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COMPARE\r
+                                       Bus_ChildListIdentificationDescriptionCompare;\r
+\r
+EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_CLEANUP\r
+                                       Bus_ChildListIdentificationDescriptionCleanup;\r
+\r
+EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_DUPLICATE\r
+                                       Bus_ChildListIdentificationDescriptionDuplicate;\r
+\r
+EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT    Bus_EvtDeviceSelfManagedIoInit;\r
+EVT_WDF_DEVICE_SELF_MANAGED_IO_CLEANUP Bus_EvtDeviceSelfManagedIoCleanup;\r
+EVT_WDF_DEVICE_SELF_MANAGED_IO_SUSPEND Bus_EvtDeviceSelfManagedIoSuspend;\r
+EVT_WDF_DEVICE_SELF_MANAGED_IO_RESTART Bus_EvtDeviceSelfManagedIoRestart; \r
+\r
+EVT_WDF_DEVICE_SURPRISE_REMOVAL                        Bus_EvtDeviceSurpriseRemoval;\r
+EVT_WDF_DEVICE_QUERY_REMOVE                            Bus_EvtDeviceQueryRemove;\r
+EVT_WDF_DEVICE_QUERY_STOP                              Bus_EvtDeviceQueryStop;\r
+\r
+EVT_WDF_DEVICE_USAGE_NOTIFICATION              Bus_EvtDeviceUsageNotify;\r
+EVT_WDF_DEVICE_RELATIONS_QUERY                 Bus_EvtDeviceRelationsQuery;\r
+\r
+static VOID\r
+Bus_EvtDriverObjCleanup( IN WDFOBJECT  Driver );\r
+\r
+static VOID\r
+Bus_EvtIoDeviceControl(\r
+    IN WDFQUEUE     Queue,\r
+    IN WDFREQUEST   Request,\r
+    IN size_t       OutputBufferLength,\r
+    IN size_t       InputBufferLength,\r
+    IN ULONG        IoControlCode );\r
+\r
+static VOID\r
+Bus_EvtDeviceFileCreate ( IN WDFDEVICE         Device,\r
+                                                IN WDFREQUEST          Request,\r
+                                                IN WDFFILEOBJECT       FileObject );\r
+static VOID\r
+Bus_EvtFileClose ( IN WDFFILEOBJECT    FileObject );\r
+\r
+static NTSTATUS\r
+Bus_EvtDeviceD0Entry(\r
+    IN  WDFDEVICE Device,\r
+    IN  WDF_POWER_DEVICE_STATE PreviousState );\r
+\r
+static NTSTATUS\r
+Bus_EvtDeviceD0Exit(\r
+    IN  WDFDEVICE Device,\r
+    IN  WDF_POWER_DEVICE_STATE TargetState );\r
+\r
+static NTSTATUS\r
+Bus_EvtDevicePrepareHardware (\r
+    WDFDEVICE      Device,\r
+    WDFCMRESLIST   ResourcesRaw,\r
+    WDFCMRESLIST   ResourcesTranslated );\r
+\r
+static NTSTATUS\r
+Bus_EvtDeviceReleaseHardware(\r
+    IN  WDFDEVICE    Device,\r
+    IN  WDFCMRESLIST ResourcesTranslated );\r
+\r
+static NTSTATUS\r
+fdo_start(\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
+static void\r
+fdo_release_resources(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj );\r
+\r
+static NTSTATUS\r
+fdo_query_remove(\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
+static NTSTATUS\r
+fdo_query_capabilities(\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
+static NTSTATUS\r
+fdo_query_remove_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
+static NTSTATUS\r
+__query_al_ifc(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IO_STACK_LOCATION* const        p_io_stack );\r
+\r
+static NTSTATUS\r
+__get_relations(\r
+       IN              const   net64_t                                         ca_guid,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+static NTSTATUS\r
+__query_ci_ifc(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IO_STACK_LOCATION* const        p_io_stack );\r
+\r
+static NTSTATUS\r
+fdo_query_interface(\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
+static NTSTATUS\r
+__fdo_query_power(\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
+static NTSTATUS\r
+__fdo_set_power(\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
+\r
+/* All PnP code is called at passive, so it can all be paged out. */\r
+#ifdef ALLOC_PRAGMA\r
+#pragma alloc_text (PAGE, Bus_EvtDeviceAdd)\r
+#pragma alloc_text (PAGE, Bus_EvtIoDeviceControl)\r
+#pragma alloc_text (PAGE, Bus_EvtDriverObjCleanup)\r
+#pragma alloc_text (PAGE, Bus_EvtDevicePrepareHardware)\r
+#pragma alloc_text (PAGE, Bus_EvtDeviceReleaseHardware)\r
+\r
+#pragma alloc_text (PAGE, fdo_start)\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, __query_al_ifc)\r
+#pragma alloc_text (PAGE, __query_ci_ifc)\r
+#pragma alloc_text (PAGE, __get_relations)\r
+#pragma alloc_text (PAGE, fdo_query_interface)\r
+#pragma alloc_text (PAGE_PNP, __fdo_query_power)\r
+#pragma alloc_text (PAGE_PNP, __fdo_set_power)\r
+#endif\r
+\r
+\r
+/* Global virtual function pointer tables shared between all instances of FDO. */\r
+static const cl_vfptr_pnp_po_t         vfptr_fdo_pnp = {\r
+       "IB Bus",\r
+       fdo_start,                                      // D0Entry\r
+       cl_irp_skip,\r
+       cl_irp_skip,\r
+       cl_do_sync_pnp,\r
+       fdo_query_remove,                       // DeviceQueryRemoval\r
+       fdo_release_resources,          // D0 Exit\r
+       cl_do_remove,\r
+       cl_do_sync_pnp,\r
+       cl_irp_skip,\r
+       fdo_query_capabilities,         // ?\r
+       cl_irp_skip,\r
+       cl_irp_skip,\r
+       cl_do_sync_pnp,\r
+       cl_irp_ignore,\r
+       cl_irp_ignore,\r
+       fdo_query_remove_relations,\r
+       cl_irp_ignore,\r
+       cl_irp_ignore,\r
+       cl_irp_ignore,\r
+       cl_irp_ignore,\r
+       cl_irp_ignore,\r
+       fdo_query_interface,    /* QueryInterface */\r
+       cl_irp_ignore,\r
+       cl_irp_ignore,\r
+       cl_irp_ignore,\r
+       cl_irp_ignore,\r
+       __fdo_query_power,              /* QueryPower */\r
+       __fdo_set_power,                /* SetPower */\r
+       cl_irp_ignore,                  /* PowerSequence */\r
+       cl_irp_ignore                   /* WaitWake */\r
+};\r
+\r
+\r
+#ifdef _REPLACED\r
+\r
+NTSTATUS\r
+bus_add_device(\r
+       IN                              DRIVER_OBJECT                           *p_driver_obj,\r
+       IN                              DEVICE_OBJECT                           *p_pdo )\r
+{\r
+       NTSTATUS                status;\r
+       DEVICE_OBJECT   *p_dev_obj, *p_next_do;\r
+       bus_fdo_ext_t   *p_ext;\r
+       UNICODE_STRING  dev_name, dos_name;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       if( bus_globals.p_bus_ext )\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
+       }\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
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("Failed to create bus root FDO device.\n") );\r
+               return status;\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
+       }\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\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
+       }\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
+\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
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               IoDetachDevice( p_ext->cl_ext.p_next_do );\r
+               IoDeleteDevice( p_dev_obj );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("IoRegisterDeviceInterface for upper interface returned %08x\n",\r
+                       status) );\r
+               return STATUS_NO_SUCH_DEVICE;\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
+       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
+       }\r
+\r
+       bus_globals.p_bus_ext = p_ext;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+#endif\r
+\r
+static NTSTATUS\r
+GetDeviceUnicodeName( WDFDEVICE Device, const GUID *guid, PUNICODE_STRING dst )\r
+{\r
+       NTSTATUS        status;\r
+       WDFSTRING       string;\r
+\r
+       status = WdfStringCreate( WDF_NO_OBJECT_ATTRIBUTES, NULL, &string );\r
+\r
+       if (!NT_SUCCESS(status))\r
+        return status ;\r
+\r
+    status = WdfDeviceRetrieveDeviceInterfaceString( Device,\r
+                                                                                                        guid,\r
+                                                                                                        NULL,\r
+                                                                                                        string );\r
+    if (!NT_SUCCESS(status))\r
+        return status;\r
+\r
+       WdfStringGetUnicodeString( string, dst );\r
+\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+/*++\r
+Routine Description:\r
+\r
+    Bus_EvtDeviceAdd is called by the framework in response to AddDevice\r
+    call from the PnP manager. We create and initialize a device object to\r
+    represent a new instance of InfiniBand Fabric device (I/O Unit, e.g., vnic\r
+       or SRP iou, etc.).\r
+\r
+Arguments:\r
+\r
+    Driver - Handle to a framework driver object created in DriverEntry\r
+\r
+    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.\r
+\r
+Return Value:\r
+\r
+    NTSTATUS\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+Bus_EvtDeviceAdd( IN  WDFDRIVER                        Driver,\r
+                                 IN  PWDFDEVICE_INIT   DeviceInit )\r
+{\r
+    NTSTATUS                                   status;\r
+    WDFDEVICE                                  device;\r
+    WDF_CHILD_LIST_CONFIG              config;\r
+       WDF_FILEOBJECT_CONFIG           FileObjConfig;\r
+    WDF_OBJECT_ATTRIBUTES              Attributes;\r
+    WDF_IO_QUEUE_CONFIG                        queueConfig;\r
+    PNP_BUS_INFORMATION                        busInfo;\r
+    WDFQUEUE                                   queue;\r
+       FDO_BUS_DATA                            *p_ext;\r
+       UNICODE_STRING                          dev_name, dos_name;\r
+\r
+    WDF_PNPPOWER_EVENT_CALLBACKS     pnpPowerCallbacks;\r
+    WDF_POWER_POLICY_EVENT_CALLBACKS powerPolicyCallbacks;\r
+\r
+    PAGED_CODE ();\r
+\r
+    KdPrint(("--> %s(): 0x%p\n", __FUNCTION__, Driver));\r
+\r
+       if( bus_globals.p_bus_ext )\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
+       }\r
+\r
+       RtlInitUnicodeString( &dev_name, AL_DEVICE_NAME );\r
+       RtlInitUnicodeString( &dos_name, L"\\DosDevices\\Global\\ibal" );\r
+\r
+    // Initialize all the properties specific to the device.\r
+    // Framework has default values for the one that are not\r
+    // set explicitly here. So please read the doc and make sure\r
+    // you are okay with the defaults.\r
+\r
+    WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);\r
+    WdfDeviceInitSetExclusive(DeviceInit, TRUE);\r
+\r
+    // This is an InifiniBand bus enumerator, we need to register for those\r
+    // PNP/Power callbacks of interest.  Framework will take the default action\r
+       // for all the PNP and Power IRPs which are not registered here.\r
+\r
+// XXX consider surprise_remove, etc.\r
+\r
+    // Initialize the PnpPowerCallbacks structure.\r
+    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);\r
+\r
+    // Set Callbacks for any of the functions we are interested in.\r
+    // If no callback is set, Framework will take the default action\r
+    // by itself.  This sample provides many of the possible callbacks,\r
+    // mostly because it's a fairly complex sample that drives full-featured\r
+    // hardware.  Drivers derived from this sample will often be able to\r
+    // provide only some of these.\r
+\r
+    // This next group of five callbacks allow a driver to become involved in\r
+    // starting and stopping operations within a driver as the driver moves\r
+    // through various PnP/Power states.  These functions are not necessary\r
+    // if the Framework is managing all the device's queues and there is no\r
+    // activity going on that isn't queue-based.\r
+\r
+    pnpPowerCallbacks.EvtDeviceSelfManagedIoInit =\r
+                                                                                       Bus_EvtDeviceSelfManagedIoInit;\r
+    pnpPowerCallbacks.EvtDeviceSelfManagedIoCleanup =\r
+                                                                                       Bus_EvtDeviceSelfManagedIoCleanup;\r
+    pnpPowerCallbacks.EvtDeviceSelfManagedIoSuspend =\r
+                                                                                       Bus_EvtDeviceSelfManagedIoSuspend;\r
+    pnpPowerCallbacks.EvtDeviceSelfManagedIoRestart =\r
+                                                                                       Bus_EvtDeviceSelfManagedIoRestart;\r
+\r
+    // These two callbacks set up and tear down hardware state,\r
+    // specifically that which only has to be done once.\r
+\r
+    pnpPowerCallbacks.EvtDevicePrepareHardware = Bus_EvtDevicePrepareHardware;\r
+    pnpPowerCallbacks.EvtDeviceReleaseHardware = Bus_EvtDeviceReleaseHardware;\r
+\r
+    // These two callbacks set up and tear down hardware state that must be\r
+    // done every time the device moves in and out of the D0-working state.\r
+       // (aka, start & stop the device).\r
+\r
+    pnpPowerCallbacks.EvtDeviceD0Entry = Bus_EvtDeviceD0Entry;\r
+    pnpPowerCallbacks.EvtDeviceD0Exit  = Bus_EvtDeviceD0Exit;\r
+\r
+    pnpPowerCallbacks.EvtDeviceQueryStop = Bus_EvtDeviceQueryStop;\r
+    pnpPowerCallbacks.EvtDeviceQueryRemove = Bus_EvtDeviceQueryRemove;\r
+    pnpPowerCallbacks.EvtDeviceSurpriseRemoval = Bus_EvtDeviceSurpriseRemoval;\r
+\r
+//    pnpPowerCallbacks.EvtDeviceUsageNotification = Bus_EvtDeviceUsageNotify;\r
+//    pnpPowerCallbacks.EvtDeviceRelationsQuery = Bus_EvtDeviceRelationsQuery;\r
+\r
+    // Register the PnP and power callbacks.\r
+    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);\r
+\r
+    // Init the power policy callbacks\r
+    WDF_POWER_POLICY_EVENT_CALLBACKS_INIT(&powerPolicyCallbacks);\r
+\r
+       // no power issues at this level - device specific driver handles power \r
+\r
+    // WDF_ DEVICE_LIST_CONFIG describes how the framework should handle\r
+    // dynamic child enumeration on behalf of the driver writer.\r
+    // Since we are a bus driver, we need to specify identification description\r
+    // for our child devices. This description will serve as the identity of our\r
+    // child device. Since the description is opaque to the framework, we\r
+    // have to provide a set of callbacks to compare, copy, or free any\r
+       // additional resources associated with the description.\r
+\r
+    WDF_CHILD_LIST_CONFIG_INIT( &config,\r
+                                sizeof(PDO_IDENTIFICATION_DESCRIPTION),\r
+                                Bus_DeviceListCreatePdo );\r
+                                                                // callback to create a child device.\r
+\r
+    // This function pointer will be called when the framework needs to copy a\r
+    // identification description from one location to another.\r
+       // An implementation of this function is only necessary if the description\r
+       // contains description relative pointer values (like  LIST_ENTRY for\r
+       // instance).\r
+    // If set to NULL, the framework will use RtlCopyMemory to copy an\r
+       // identification description. In this sample, it's not required to provide\r
+       // these callbacks they are added just for illustration.\r
+    //\r
+    config.EvtChildListIdentificationDescriptionDuplicate =\r
+                                                       Bus_ChildListIdentificationDescriptionDuplicate;\r
+\r
+    //\r
+    // This function pointer will be called when the framework needs to compare\r
+    // two identificaiton descriptions.  If left NULL a call to RtlCompareMemory\r
+    // will be used to compare two identificaiton descriptions.\r
+    //\r
+    config.EvtChildListIdentificationDescriptionCompare =\r
+                            Bus_ChildListIdentificationDescriptionCompare;\r
+    //\r
+    // This function pointer will be called when the framework needs to free a\r
+    // identification description.  An implementation of this function is only\r
+    // necessary if the description contains dynamically allocated memory\r
+    // (by the driver writer) that needs to be freed. The actual identification\r
+    // description pointer itself will be freed by the framework.\r
+    //\r
+    config.EvtChildListIdentificationDescriptionCleanup =\r
+                            Bus_ChildListIdentificationDescriptionCleanup;\r
+\r
+    //\r
+    // Tell the framework to use the built-in childlist to track the state\r
+    // of the device based on the configuration we just created.\r
+    //\r
+    WdfFdoInitSetDefaultChildListConfig(DeviceInit,\r
+                                         &config,\r
+                                         WDF_NO_OBJECT_ATTRIBUTES);\r
+\r
+\r
+       // setup callbacks to hande IRP_MJ_CREATE & IRP_MJ_CLOSE\r
+\r
+       WDF_FILEOBJECT_CONFIG_INIT(\r
+                           &FileObjConfig,\r
+                           Bus_EvtDeviceFileCreate,\r
+                           Bus_EvtFileClose,\r
+                           WDF_NO_EVENT_CALLBACK // No cleanup callback function\r
+                           );\r
+\r
+       WDF_OBJECT_ATTRIBUTES_INIT(&Attributes);\r
+\r
+       Attributes.SynchronizationScope = WdfSynchronizationScopeNone;\r
+       Attributes.ExecutionLevel = WdfExecutionLevelPassive;\r
+\r
+       WdfDeviceInitSetFileObjectConfig( DeviceInit,\r
+                                                                         &FileObjConfig,\r
+                                                                         &Attributes );\r
+\r
+    // Initialize attributes structure to specify size and accessor function\r
+    // for storing device context.\r
+\r
+    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attributes, FDO_BUS_DATA);\r
+\r
+    // Register a cleanup callback on the device to free up some resources at\r
+       // the time the device is deleted.\r
+    Attributes.EvtCleanupCallback = Bus_EvtDriverObjCleanup;\r
+\r
+    // By opting for SynchronizationScopeDevice, we tell the framework to\r
+    // synchronize callbacks events of all the objects directly associated\r
+    // with the device. In this driver, we will associate queues.\r
+    // By doing that we don't have to worrry about synchronizing\r
+    // access to device-context by various io Events.\r
+    // Framework will serialize them by using an internal device-lock.\r
+    Attributes.SynchronizationScope = WdfSynchronizationScopeDevice;\r
+\r
+    // Create a framework device object. In response to this call, framework\r
+    // creates a WDM deviceobject and attaches to the PDO.\r
+\r
+    status = WdfDeviceCreate(&DeviceInit, &Attributes, &device);\r
+\r
+    if (!NT_SUCCESS(status)) {\r
+        KdPrint(("Error creating WdfDeviceCreate 0x%x, line#%d\n",\r
+                                       status,__LINE__));\r
+        return status;\r
+    }\r
+\r
+       IoDeleteSymbolicLink( &dos_name );\r
+       status = IoCreateSymbolicLink( &dos_name, &dev_name );\r
+       if( !NT_SUCCESS(status) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to create symlink for dos name.\n") );\r
+               return status;\r
+       }\r
+       KdPrint(("%s() Created symlink for dos name\n",__FUNCTION__));\r
+\r
+    // Configure a default queue so that requests that are not\r
+    // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto\r
+    // other queues get dispatched here.\r
+\r
+    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &queueConfig,\r
+                                                                                       WdfIoQueueDispatchParallel );\r
+\r
+       // handle IRP_MJ_DEVICE_CONTROL with this callback\r
+    queueConfig.EvtIoDeviceControl = Bus_EvtIoDeviceControl;\r
+\r
+    status = WdfIoQueueCreate( device,\r
+                               &queueConfig,\r
+                               WDF_NO_OBJECT_ATTRIBUTES,\r
+                               &queue );\r
+\r
+    if (!NT_SUCCESS(status)) {\r
+        KdPrint(("WdfIoQueueCreate failed status 0x%x\n", status));\r
+        return status;\r
+    }\r
+\r
+    // Get the device object 'dev extention data' ptr & initialize the FDO\r
+       // extension data.\r
+\r
+    p_ext = FdoGetData(device);\r
+\r
+       RtlZeroMemory( (VOID*)p_ext, sizeof(*p_ext) );\r
+\r
+       RtlStringCbCopyA( p_ext->Identity, sizeof("IB Bus"), "IB Bus" );\r
+\r
+       p_ext->WdfDevice = device;      // record framework device object ptr.\r
+\r
+       p_ext->SupportsPowerMgmt = TRUE;\r
+       p_ext->DevPowerState = WdfPowerDeviceInvalid;\r
+       p_ext->DevPreviousPowerState = WdfPowerDeviceInvalid;\r
+\r
+       /* replicate what was previously done in \r
+               cl_init_pnp_po_ext( p_dev_obj, p_next_do, p_pdo, bus_globals.dbg_lvl,\r
+                                                               &vfptr_fdo_pnp, NULL );\r
+               to prevent any oops. FLW.\r
+        */\r
+       p_ext->cl_ext.dbg_lvl = bus_globals.dbg_lvl;\r
+\r
+       /* Store the pointer to our own device. */\r
+       p_ext->cl_ext.p_self_do = WdfDeviceWdmGetDeviceObject(device);\r
+       IoInitializeRemoveLock( &p_ext->cl_ext.remove_lock, 'bilc', 15, 1000 );\r
+\r
+       /* Initialize the PnP states. */\r
+       p_ext->cl_ext.pnp_state = NotStarted;\r
+       p_ext->cl_ext.last_pnp_state = NotStarted;\r
+\r
+       /* Store the pointer to the next device in the stack. */\r
+       p_ext->cl_ext.p_next_do = NULL;\r
+\r
+       /* Store the pointer to the underlying PDO. */\r
+       p_ext->cl_ext.p_pdo = WdfDeviceWdmGetPhysicalDevice(device);\r
+\r
+       /* Store the PnP virtual function pointer table. */\r
+       p_ext->cl_ext.vfptr_pnp_po = &vfptr_fdo_pnp;\r
+\r
+       /* Store the Power Management virtual function pointer table. */\r
+       p_ext->cl_ext.vfptr_query_txt = NULL;\r
+       // end cl_init_pnp_po_ext()\r
+\r
+    //\r
+    // Create device interface for this device. The interface will be\r
+    // enabled by the framework when we return from StartDevice successfully.\r
+    // Clients of this driver will open this interface and send ioctls.\r
+    //\r
+       /* Register the upper interface (the one used by clients). */\r
+    status = WdfDeviceCreateDeviceInterface( device,\r
+                                                                                        &GUID_IB_AL_INTERFACE,\r
+                                                                                        NULL );\r
+    if (!NT_SUCCESS(status)) {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("WdfDeviceCreateDeviceInterface for upper interface AL "\r
+                        "returned 0x%08x\n", status) );\r
+        return status  /*STATUS_NO_SUCH_DEVICE*/;\r
+    }\r
+       status = GetDeviceUnicodeName( device,\r
+                                                                  (const GUID*)&GUID_IB_AL_INTERFACE,\r
+                                                                  &p_ext->al_ifc_name );\r
+    if (!NT_SUCCESS(status)) {\r
+               BUS_TRACE_EXIT(BUS_DBG_ERROR,\r
+                                               ("GetDeviceUnicodeName() ret %x\n", status));\r
+        return status;\r
+    }\r
+\r
+       /* Register the lower interface (the one used by HCA VPDs). */\r
+    status = WdfDeviceCreateDeviceInterface( device,\r
+                                                                                        &GUID_IB_CI_INTERFACE,\r
+                                                                                        NULL );\r
+\r
+    if (!NT_SUCCESS(status)) {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                               ("WdfDeviceCreateDeviceInterface for lower interface CI "\r
+                                       "ret 0x%08x\n", status) );\r
+        return status  /*STATUS_NO_SUCH_DEVICE*/;\r
+    }\r
+\r
+       status = GetDeviceUnicodeName( device,\r
+                                                                  (const GUID*)&GUID_IB_CI_INTERFACE,\r
+                                                                  &p_ext->ci_ifc_name );\r
+    if (!NT_SUCCESS(status)) {\r
+               BUS_TRACE_EXIT(BUS_DBG_ERROR,\r
+                                               ("GetDeviceUnicodeName() ret %x\n", status));\r
+        return status;\r
+    }\r
+\r
+       bus_globals.p_bus_ext = p_ext;  // save our FDO data extension ptr.\r
+\r
+    //\r
+    // This value is used in responding to the IRP_MN_QUERY_BUS_INFORMATION\r
+    // for the child devices. This is an optional information provided to\r
+    // uniquely idenitfy the bus the device is connected.\r
+    //\r
+    busInfo.BusTypeGuid = GUID_DEVCLASS_IB_FABRIC;\r
+    busInfo.LegacyBusType = PNPBus;\r
+    busInfo.BusNumber = 0; // only 1 IB fabric bus instance.\r
+\r
+    WdfDeviceSetBusInformationForChildren(device, &busInfo);\r
+\r
+    status = Bus_WmiRegistration(device);\r
+    if (!NT_SUCCESS(status)) {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("Bus_WmiRegistration() failed returned 0x%08x\n", status) );\r
+        return status;\r
+    }\r
+\r
+    KdPrint(("<-- %s(): 0x%p status 0x%x\n", __FUNCTION__, Driver, status));\r
+\r
+    return status;\r
+}\r
+\r
+\r
+\r
+static NTSTATUS\r
+fdo_start(\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
+       ib_api_status_t ib_status;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       /* Handled on the way up. */\r
+       status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("Lower drivers failed IRP_MN_START_DEVICE.\n") );\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
+       }\r
+\r
+       /* Initialize the port manager. */\r
+       ib_status = create_port_mgr( &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
+                       ib_get_err_str(ib_status)) );\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       /* Initialize the IOU manager. */\r
+       ib_status = create_iou_mgr( &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
+                       ib_get_err_str(ib_status)) );\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       status = IoSetDeviceInterfaceState( &p_ext->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
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+fdo_query_remove(\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
+       bus_fdo_ext_t   *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       if( p_ext->n_ci_ifc_ref )\r
+       {\r
+               /*\r
+                * Our interface is still being held by someone.\r
+                * Rollback the PnP state that was changed in the cl_ext handler.\r
+                */\r
+               cl_rollback_pnp_state( &p_ext->cl_ext );\r
+\r
+               /* Fail the query. */\r
+               *p_action = IrpComplete;\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP, \r
+                       ("Failing IRP_MN_QUERY_REMOVE_DEVICE:\n"\r
+                       "\tLowerInterface has %d references\n", \r
+                       p_ext->n_ci_ifc_ref ) );\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       *p_action = IrpSkip;\r
+       /* The FDO driver must set the status even when passing down. */\r
+       p_irp->IoStatus.Status = STATUS_SUCCESS;\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+/*\r
+ * This function gets called after releasing the remove lock and waiting\r
+ * for all other threads to release the lock.  No more modifications will\r
+ * occur to the PDO pointer vectors.\r
+ */\r
+static void\r
+fdo_release_resources(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
+{\r
+       bus_fdo_ext_t   *p_ext;\r
+       NTSTATUS                status;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       //TODO: Fail outstanding I/O operations.\r
+\r
+       /* Disable any exported interfaces. */\r
+       status = IoSetDeviceInterfaceState( &p_ext->al_ifc_name, FALSE );\r
+       ASSERT( NT_SUCCESS( status ) );\r
+       status = IoSetDeviceInterfaceState( &p_ext->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
+\r
+       al_cleanup();\r
+\r
+       bus_globals.p_bus_ext = NULL;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+static NTSTATUS\r
+fdo_query_capabilities(\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
+       IO_STACK_LOCATION       *p_io_stack;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       /* Process on the way up. */\r
+       status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
+\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("cl_do_sync_pnp returned %08x.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+\r
+       /*\r
+        * Store the device power maping into our extension since we're\r
+        * the power policy owner.  The mapping is used when handling\r
+        * IRP_MN_SET_POWER IRPs.\r
+        */\r
+       cl_memcpy( p_ext->po_state, \r
+               p_io_stack->Parameters.DeviceCapabilities.Capabilities->DeviceState,\r
+               sizeof( p_ext->po_state ) );\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+fdo_query_remove_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
+\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
+       {\r
+               status = iou_mgr_get_bus_relations( 0, p_irp );\r
+       }\r
+       if( status == STATUS_NO_SUCH_DEVICE )\r
+               status = STATUS_SUCCESS;\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
+al_ref_ifc(\r
+       IN                              DEVICE_OBJECT*                          p_dev_obj )\r
+{\r
+       bus_fdo_ext_t   *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       cl_atomic_inc( &p_ext->n_al_ifc_ref );\r
+       ObReferenceObject( p_dev_obj );\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+void\r
+al_deref_ifc(\r
+       IN                              DEVICE_OBJECT*                          p_dev_obj )\r
+{\r
+       bus_fdo_ext_t   *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       cl_atomic_dec( &p_ext->n_al_ifc_ref );\r
+       ObDereferenceObject( p_dev_obj );\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+void\r
+al_ref_ci_ifc(\r
+       IN                              DEVICE_OBJECT*                          p_dev_obj )\r
+{\r
+       bus_fdo_ext_t   *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       cl_atomic_inc( &p_ext->n_ci_ifc_ref );\r
+       ObReferenceObject( p_dev_obj );\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+void\r
+al_deref_ci_ifc(\r
+       IN                              DEVICE_OBJECT*                          p_dev_obj )\r
+{\r
+       bus_fdo_ext_t   *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       cl_atomic_dec( &p_ext->n_ci_ifc_ref );\r
+       ObDereferenceObject( p_dev_obj );\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__query_al_ifc(\r
+       IN                                      DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                                      IO_STACK_LOCATION* const        p_io_stack )\r
+{\r
+       ib_al_ifc_t             *p_ifc;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       if( p_io_stack->Parameters.QueryInterface.Version != \r
+               AL_INTERFACE_VERSION )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP, ("Incorrect interface version (%d)\n",\r
+                       p_io_stack->Parameters.QueryInterface.Version ) );\r
+               return STATUS_NOT_SUPPORTED;\r
+       }\r
+\r
+       if( p_io_stack->Parameters.QueryInterface.Size < sizeof(ib_al_ifc_t) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP, \r
+                       ("Buffer too small (%d given, %d required).\n",\r
+                       p_io_stack->Parameters.QueryInterface.Size, sizeof(ib_al_ifc_t)) );\r
+               return STATUS_BUFFER_TOO_SMALL;\r
+       }\r
+\r
+       // Copy the interface.\r
+       p_ifc = (ib_al_ifc_t*)p_io_stack->Parameters.QueryInterface.Interface;\r
+\r
+       p_ifc->wdm.Size = sizeof(ib_al_ifc_t);\r
+       p_ifc->wdm.Version = AL_INTERFACE_VERSION;\r
+       p_ifc->wdm.Context = p_dev_obj;\r
+       p_ifc->wdm.InterfaceReference = al_ref_ifc;\r
+       p_ifc->wdm.InterfaceDereference = al_deref_ifc;\r
+\r
+       al_set_ifc( p_ifc );\r
+\r
+       // take the reference before returning.\r
+       al_ref_ifc( p_dev_obj );\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+al_set_ifc(\r
+               OUT                     ib_al_ifc_t* const                      p_ifc )\r
+{\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ifc->wdm.Size = sizeof(ib_al_ifc_t);\r
+       p_ifc->wdm.InterfaceReference = al_ref_ifc;\r
+       p_ifc->wdm.InterfaceDereference = al_deref_ifc;\r
+\r
+       p_ifc->sync_destroy = ib_sync_destroy;\r
+       p_ifc->open_ca = ib_open_ca;\r
+       p_ifc->query_ca = ib_query_ca;\r
+       p_ifc->get_dev = get_ca_dev;\r
+       p_ifc->close_ca = ib_close_ca;\r
+       p_ifc->alloc_pd = ib_alloc_pd;\r
+       p_ifc->dealloc_pd = ib_dealloc_pd;\r
+       p_ifc->create_av = ib_create_av;\r
+       p_ifc->query_av = ib_query_av;\r
+       p_ifc->modify_av = ib_modify_av;\r
+       p_ifc->destroy_av = ib_destroy_av;\r
+       p_ifc->create_qp = ib_create_qp;\r
+       p_ifc->get_spl_qp = ib_get_spl_qp;\r
+       p_ifc->query_qp = ib_query_qp;\r
+       p_ifc->modify_qp = ib_modify_qp;\r
+       p_ifc->destroy_qp = ib_destroy_qp;\r
+       p_ifc->create_cq = ib_create_cq;\r
+       p_ifc->modify_cq = ib_modify_cq;\r
+       p_ifc->query_cq = ib_query_cq;\r
+       p_ifc->destroy_cq = ib_destroy_cq;\r
+       p_ifc->reg_mem = ib_reg_mem;\r
+       p_ifc->reg_phys = ib_reg_phys;\r
+       p_ifc->query_mr = ib_query_mr;\r
+       p_ifc->rereg_mem = ib_rereg_mem;\r
+       p_ifc->reg_shmid = ib_reg_shmid;\r
+       p_ifc->dereg_mr = ib_dereg_mr;\r
+       p_ifc->create_mw = ib_create_mw;\r
+       p_ifc->query_mw = ib_query_mw;\r
+       p_ifc->bind_mw = ib_bind_mw;\r
+       p_ifc->destroy_mw = ib_destroy_mw;\r
+       p_ifc->post_send = ib_post_send;\r
+       p_ifc->post_recv = ib_post_recv;\r
+       p_ifc->send_mad = ib_send_mad;\r
+       p_ifc->cancel_mad = ib_cancel_mad;\r
+       p_ifc->poll_cq = ib_poll_cq;\r
+       p_ifc->rearm_cq = ib_rearm_cq;\r
+       p_ifc->join_mcast = ib_join_mcast;\r
+       p_ifc->leave_mcast = ib_leave_mcast;\r
+       p_ifc->local_mad = ib_local_mad;\r
+       p_ifc->cm_listen = ib_cm_listen;\r
+       p_ifc->cm_cancel = ib_cm_cancel;\r
+       p_ifc->cm_req = ib_cm_req;\r
+       p_ifc->cm_rep = ib_cm_rep;\r
+       p_ifc->cm_rtu = ib_cm_rtu;\r
+       p_ifc->cm_rej = ib_cm_rej;\r
+       p_ifc->cm_mra = ib_cm_mra;\r
+       p_ifc->cm_lap = ib_cm_lap;\r
+       p_ifc->cm_apr = ib_cm_apr;\r
+       p_ifc->force_apm = ib_force_apm;\r
+       p_ifc->cm_dreq = ib_cm_dreq;\r
+       p_ifc->cm_drep = ib_cm_drep;\r
+       p_ifc->cm_handoff = ib_cm_handoff;\r
+       p_ifc->create_ioc = ib_create_ioc;\r
+       p_ifc->destroy_ioc = ib_destroy_ioc;\r
+       p_ifc->reg_ioc = ib_reg_ioc;\r
+       p_ifc->add_svc_entry = ib_add_svc_entry;\r
+       p_ifc->remove_svc_entry = ib_remove_svc_entry;\r
+       p_ifc->get_ca_guids = ib_get_ca_guids;\r
+       p_ifc->get_ca_by_gid = ib_get_ca_by_gid;\r
+       p_ifc->get_port_by_gid = ib_get_port_by_gid;\r
+       p_ifc->create_mad_pool = ib_create_mad_pool;\r
+       p_ifc->destroy_mad_pool = ib_destroy_mad_pool;\r
+       p_ifc->reg_mad_pool = ib_reg_mad_pool;\r
+       p_ifc->dereg_mad_pool = ib_dereg_mad_pool;\r
+       p_ifc->get_mad = ib_get_mad;\r
+       p_ifc->put_mad = ib_put_mad;\r
+       p_ifc->init_dgrm_svc = ib_init_dgrm_svc;\r
+       p_ifc->reg_mad_svc = ib_reg_mad_svc;\r
+       p_ifc->reg_svc = ib_reg_svc;\r
+       p_ifc->dereg_svc = ib_dereg_svc;\r
+       p_ifc->query = ib_query;\r
+       p_ifc->cancel_query = ib_cancel_query;\r
+       p_ifc->reg_pnp = ib_reg_pnp;\r
+       p_ifc->dereg_pnp = ib_dereg_pnp;\r
+       p_ifc->subscribe = ib_subscribe;\r
+       p_ifc->unsubscribe = ib_unsubscribe;\r
+       p_ifc->reject_ioc = ib_reject_ioc;\r
+       p_ifc->ci_call = ib_ci_call;\r
+       p_ifc->open_al = ib_open_al;\r
+       p_ifc->close_al = ib_close_al;\r
+       p_ifc->get_err_str = ib_get_err_str;\r
+       p_ifc->get_wc_status_str = ib_get_wc_status_str;\r
+       p_ifc->create_mlnx_fmr = mlnx_create_fmr;\r
+       p_ifc->map_phys_mlnx_fmr = mlnx_map_phys_fmr;\r
+       p_ifc->unmap_mlnx_fmr = mlnx_unmap_fmr;\r
+       p_ifc->destroy_mlnx_fmr = mlnx_destroy_fmr;\r
+       p_ifc->create_mlnx_fmr_pool = mlnx_create_fmr_pool;\r
+       p_ifc->destroy_mlnx_fmr_pool = mlnx_destroy_fmr_pool;\r
+       p_ifc->map_phys_mlnx_fmr_pool = mlnx_map_phys_fmr_pool;\r
+       p_ifc->unmap_mlnx_fmr_pool = mlnx_unmap_fmr_pool;\r
+       p_ifc->flush_mlnx_fmr_pool = mlnx_flush_fmr_pool;\r
+       p_ifc->create_srq = ib_create_srq;\r
+       p_ifc->modify_srq = ib_modify_srq;\r
+       p_ifc->query_srq = ib_query_srq;\r
+       p_ifc->destroy_srq = ib_destroy_srq;\r
+       p_ifc->post_srq_recv = ib_post_srq_recv;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__get_relations(\r
+       IN              const   net64_t                                         ca_guid,\r
+       IN                              IRP* const                                      p_irp )\r
+{\r
+       NTSTATUS                        status;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       /* TODO: For IOUs, filter relations based on multi-HCA support. */\r
+       status = port_mgr_get_bus_relations( ca_guid, p_irp );\r
+       if( status == STATUS_SUCCESS || \r
+               status == STATUS_NO_SUCH_DEVICE )\r
+       {\r
+               status = iou_mgr_get_bus_relations( ca_guid, p_irp );\r
+       }\r
+       if( status == STATUS_NO_SUCH_DEVICE )\r
+               status = STATUS_SUCCESS;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__query_ci_ifc(\r
+       IN                                      DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                                      IO_STACK_LOCATION* const        p_io_stack )\r
+{\r
+       ib_ci_ifc_t             *p_ifc;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       if( p_io_stack->Parameters.QueryInterface.Version != \r
+               IB_CI_INTERFACE_VERSION )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP, ("Incorrect interface version (%d)\n",\r
+                       p_io_stack->Parameters.QueryInterface.Version ) );\r
+               return STATUS_NOT_SUPPORTED;\r
+       }\r
+\r
+       if( p_io_stack->Parameters.QueryInterface.Size < sizeof(ib_ci_ifc_t) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP, \r
+                       ("Buffer too small (%d given, %d required).\n",\r
+                       p_io_stack->Parameters.QueryInterface.Size, sizeof(ib_ci_ifc_t)) );\r
+               return STATUS_BUFFER_TOO_SMALL;\r
+       }\r
+\r
+       /* Copy the interface. */\r
+       p_ifc = (ib_ci_ifc_t*)p_io_stack->Parameters.QueryInterface.Interface;\r
+\r
+       p_ifc->wdm.Size = sizeof(ib_ci_ifc_t);\r
+       p_ifc->wdm.Version = IB_CI_INTERFACE_VERSION;\r
+       p_ifc->wdm.Context = p_dev_obj;\r
+       p_ifc->wdm.InterfaceReference = al_ref_ci_ifc;\r
+       p_ifc->wdm.InterfaceDereference = al_deref_ci_ifc;\r
+\r
+       /* Set the entry points. */\r
+       p_ifc->register_ca = ib_register_ca;\r
+       p_ifc->deregister_ca = ib_deregister_ca;\r
+       p_ifc->get_relations = __get_relations;\r
+       p_ifc->get_err_str = ib_get_err_str;\r
+\r
+       /* take the reference before returning. */\r
+       al_ref_ci_ifc( p_dev_obj );\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+fdo_query_interface(\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
+       IO_STACK_LOCATION       *p_io_stack;\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
+       /* Compare requested GUID with our supported interface GUIDs. */\r
+       if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
+               &GUID_IB_AL_INTERFACE ) )\r
+       {\r
+               status = __query_al_ifc( p_dev_obj, p_io_stack );\r
+       }\r
+       else if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
+               &GUID_IB_CI_INTERFACE ) )\r
+       {\r
+               status = __query_ci_ifc( p_dev_obj, p_io_stack );\r
+       }\r
+       else\r
+       {\r
+               status = p_irp->IoStatus.Status;\r
+       }\r
+\r
+       if( NT_SUCCESS( status ) )\r
+               *p_action = IrpSkip;\r
+       else if( status == STATUS_BUFFER_TOO_SMALL )\r
+               *p_action = IrpComplete;\r
+       else\r
+               *p_action = IrpIgnore;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__fdo_query_power(\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 = STATUS_SUCCESS;\r
+       IO_STACK_LOCATION       *p_io_stack;\r
+\r
+       BUS_ENTER( BUS_DBG_POWER );\r
+\r
+       UNUSED_PARAM( p_dev_obj );\r
+\r
+       p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+\r
+       switch( p_io_stack->Parameters.Power.Type )\r
+       {\r
+       case SystemPowerState:\r
+               /* Fail any requests to hibernate or sleep the system. */\r
+               switch( p_io_stack->Parameters.Power.State.SystemState )\r
+               {\r
+                       case PowerSystemHibernate:\r
+                       case PowerSystemSleeping1:      // STANDBY support\r
+                       case PowerSystemWorking:\r
+                       case PowerSystemShutdown:\r
+                               break;\r
+\r
+                       default:\r
+                               status = STATUS_NOT_SUPPORTED;\r
+               }\r
+               break;\r
+\r
+       case DevicePowerState:\r
+               /* Fail any query for low power states. */\r
+               switch( p_io_stack->Parameters.Power.State.DeviceState )\r
+               {\r
+               case PowerDeviceD0:\r
+               case PowerDeviceD3:\r
+                       /* We only support fully powered or off power states. */\r
+                       break;\r
+\r
+               default:\r
+                       status = STATUS_NOT_SUPPORTED;\r
+               }\r
+               break;\r
+       }\r
+\r
+       if( status == STATUS_NOT_SUPPORTED )\r
+               *p_action = IrpComplete;\r
+       else\r
+               *p_action = IrpSkip;\r
+\r
+       BUS_EXIT( BUS_DBG_POWER );\r
+       return status;\r
+}\r
+\r
+\r
+static void\r
+__request_power_completion(\r
+       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
+       IN                              UCHAR                                           minor_function,\r
+       IN                              POWER_STATE                                     power_state,\r
+       IN                              void                                            *context,\r
+       IN                              IO_STATUS_BLOCK                         *p_io_status )\r
+{\r
+       IRP                                     *p_irp;\r
+       cl_pnp_po_ext_t         *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( minor_function );\r
+       UNUSED_PARAM( power_state );\r
+\r
+       p_irp = (IRP*)context;\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       /* Propagate the device IRP status to the system IRP status. */\r
+       p_irp->IoStatus.Status = p_io_status->Status;\r
+\r
+       /* Continue Power IRP processing. */\r
+       PoStartNextPowerIrp( p_irp );\r
+       IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+       IoReleaseRemoveLock( &p_ext->remove_lock, p_irp );\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+/*NOTE: Completion routines must NEVER be pageable. */\r
+static NTSTATUS\r
+__set_power_completion(\r
+       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
+       IN                              IRP                                                     *p_irp,\r
+       IN                              void                                            *context )\r
+{\r
+       NTSTATUS                        status;\r
+       POWER_STATE                     state;\r
+       bus_fdo_ext_t           *p_ext;\r
+       IO_STACK_LOCATION       *p_io_stack;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( context );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+       p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+\r
+       if( !NT_SUCCESS( p_irp->IoStatus.Status ) )\r
+       {\r
+               PoStartNextPowerIrp( p_irp );\r
+               IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
+                       ("IRP_MN_SET_POWER for system failed by lower driver with %08x.\n",\r
+                       p_irp->IoStatus.Status) );\r
+               return STATUS_SUCCESS;\r
+       }\r
+\r
+       state.DeviceState = \r
+               p_ext->po_state[p_io_stack->Parameters.Power.State.SystemState];\r
+\r
+       /*\r
+        * Send a device power IRP to our devnode.  Using our device object will\r
+        * only work on win2k and other NT based systems.\r
+        */\r
+       status = PoRequestPowerIrp( p_dev_obj, IRP_MN_SET_POWER, state,\r
+               __request_power_completion, p_irp, NULL );\r
+\r
+       if( status != STATUS_PENDING )\r
+       {\r
+               PoStartNextPowerIrp( p_irp );\r
+               /* Propagate the failure. */\r
+               p_irp->IoStatus.Status = status;\r
+               IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+               IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
+               BUS_TRACE( BUS_DBG_ERROR,\r
+                       ("PoRequestPowerIrp returned %08x.\n", status) );\r
+       }\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_MORE_PROCESSING_REQUIRED;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__fdo_set_power(\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
+       IO_STACK_LOCATION       *p_io_stack;\r
+       bus_fdo_ext_t           *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_POWER );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+       p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+\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.State.DeviceState, \r
+               p_io_stack->Parameters.Power.ShutdownType ));\r
+\r
+       switch( p_io_stack->Parameters.Power.Type )\r
+       {\r
+       case SystemPowerState:\r
+               /*\r
+                * Process on the way up the stack.  We cannot block since the \r
+                * power dispatch function can be called at elevated IRQL if the\r
+                * device is in a paging/hibernation/crash dump path.\r
+                */\r
+               IoMarkIrpPending( p_irp );\r
+               IoCopyCurrentIrpStackLocationToNext( p_irp );\r
+#pragma warning( push, 3 )\r
+               IoSetCompletionRoutine( p_irp, __set_power_completion, NULL, \r
+                       TRUE, TRUE, TRUE );\r
+#pragma warning( pop )\r
+               PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
+\r
+               *p_action = IrpDoNothing;\r
+               status = STATUS_PENDING;\r
+               break;\r
+\r
+       case DevicePowerState:\r
+       default:\r
+               /* Pass down and let the PDO driver handle it. */\r
+               *p_action = IrpIgnore;\r
+               status = STATUS_SUCCESS;\r
+               break;\r
+       }\r
+\r
+       BUS_EXIT( BUS_DBG_POWER );\r
+       return status;\r
+}\r
+\r
+\r
+/*\r
+ * A CA GUID of zero means that all devices should be reported.\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                        status;\r
+       DEVICE_RELATIONS        *p_rel;\r
+       cl_list_item_t          *p_list_item;\r
+       bus_pdo_ext_t           *p_pdo_ext;\r
+       size_t                          n_devs = 0;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       /* Count the number of child devices. */\r
+       for( p_list_item = cl_qlist_head( p_pdo_list );\r
+               p_list_item != cl_qlist_end( p_pdo_list );\r
+               p_list_item = cl_qlist_next( p_list_item ) )\r
+       {\r
+               p_pdo_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
+\r
+               if( !p_pdo_ext->b_present )\r
+                       continue;\r
+               \r
+               if( ca_guid && p_pdo_ext->ca_guid != ca_guid )\r
+                       continue;\r
+\r
+               n_devs++;\r
+       }\r
+\r
+       if( !n_devs )\r
+       {\r
+               BUS_EXIT( BUS_DBG_PNP );\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+\r
+       BUS_TRACE( BUS_DBG_PNP, ("Found %d PDOs .\n", n_devs ));\r
+\r
+       /* Add space for our child IOUs. */\r
+       status = cl_alloc_relations( p_irp, n_devs );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("cl_alloc_relations returned %08x.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
+\r
+       for( p_list_item = cl_qlist_head( p_pdo_list );\r
+               p_list_item != cl_qlist_end( p_pdo_list );\r
+               p_list_item = cl_qlist_next( p_list_item ) )\r
+       {\r
+               p_pdo_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
+\r
+               if( !p_pdo_ext->b_present )\r
+               {\r
+                       /*\r
+                        * We don't report a PDO that is no longer present.  This is how\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
+                       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
+                       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
+               ObReferenceObject( p_rel->Objects[p_rel->Count++] );\r
+       }\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/*++\r
+Routine Description:\r
+\r
+  Handle user mode PlugIn, UnPlug and device Eject requests.\r
+\r
+Arguments:\r
+\r
+    Queue - Handle to the framework queue object that is associated\r
+            with the I/O request.\r
+\r
+    Request - Handle to a framework request object. This one represents\r
+              the IRP_MJ_DEVICE_CONTROL IRP received by the framework.\r
+\r
+    OutputBufferLength - Length, in bytes, of the request's output buffer,\r
+                        if an output buffer is available.\r
+\r
+    InputBufferLength - Length, in bytes, of the request's input buffer,\r
+                        if an input buffer is available.\r
+    IoControlCode - Driver-defined or system-defined I/O control code (IOCTL)\r
+                    that is associated with the request.\r
+\r
+Return Value:\r
+\r
+   VOID\r
+\r
+--*/\r
+\r
+static VOID\r
+Bus_EvtIoDeviceControl (\r
+    IN WDFQUEUE     Queue,\r
+    IN WDFREQUEST   Request,\r
+    IN size_t       OutputBufferLength,\r
+    IN size_t       InputBufferLength,\r
+    IN ULONG        IoControlCode )\r
+{\r
+    NTSTATUS                 status = STATUS_INVALID_PARAMETER;\r
+    WDFDEVICE                hDevice;\r
+//    size_t                   length = 0;\r
+\r
+       BOOLEAN                                 xferStatus;\r
+       PIRP                                    irp;\r
+    PIO_STACK_LOCATION         NextStack;\r
+       WDFIOTARGET                             hTarget;\r
+\r
+    UNREFERENCED_PARAMETER(OutputBufferLength);\r
+    UNREFERENCED_PARAMETER(InputBufferLength);\r
+\r
+    PAGED_CODE ();\r
+\r
+    hDevice = WdfIoQueueGetDevice(Queue);\r
+\r
+    KdPrint(("%s() 0x%p IOCTL 0x%x\n", __FUNCTION__, hDevice,IoControlCode));\r
+\r
+    irp = WdfRequestWdmGetIrp(Request);\r
+\r
+    //CurStack = IoGetCurrentIrpStackLocation(irp);\r
+\r
+       status = cl_to_ntstatus( al_dev_ioctl( irp ) ); \r
+       switch( status )\r
+       {\r
+               case STATUS_SUCCESS:\r
+                       // already completed.\r
+                       break;\r
+\r
+               case STATUS_INVALID_DEVICE_REQUEST:\r
+                       // pass down the stack?\r
+                       hTarget = WdfDeviceGetIoTarget(hDevice);\r
+                       if ( hTarget )\r
+                       {\r
+                       NextStack = IoGetNextIrpStackLocation(irp);\r
+                               WdfRequestWdmFormatUsingStackLocation( Request, NextStack );\r
+                               xferStatus = WdfRequestSend( Request, hTarget, NULL );\r
+                               if ( xferStatus == FALSE )\r
+                                       WdfRequestComplete(Request, status);\r
+                       }\r
+                       else\r
+                               WdfRequestComplete(Request, status);\r
+                       break;\r
+\r
+               case STATUS_PENDING:\r
+                       // callback already set?\r
+                       break;\r
+\r
+               default:\r
+                       WdfRequestComplete(Request, status);\r
+                       break;\r
+       }\r
+\r
+#if 0\r
+    PBUSENUM_PLUGIN_HARDWARE plugIn = NULL;\r
+    PBUSENUM_UNPLUG_HARDWARE unPlug = NULL;\r
+    PBUSENUM_EJECT_HARDWARE  eject  = NULL;\r
+\r
+    switch (IoControlCode)\r
+       {\r
+    case IOCTL_BUSENUM_PLUGIN_HARDWARE:\r
+\r
+        status = WdfRequestRetrieveInputBuffer (Request,\r
+                                    sizeof (BUSENUM_PLUGIN_HARDWARE) +\r
+                                    (sizeof(UNICODE_NULL) * 2),\r
+                                                                        // 2 for double NULL termination (MULTI_SZ)\r
+                                    &plugIn, &length);\r
+        if( !NT_SUCCESS(status) ) {\r
+            KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status));\r
+            break;\r
+        }\r
+\r
+        ASSERT(length == InputBufferLength);\r
+\r
+        if (sizeof (BUSENUM_PLUGIN_HARDWARE) == plugIn->Size)\r
+        {\r
+\r
+            length = (InputBufferLength - sizeof (BUSENUM_PLUGIN_HARDWARE))\r
+                                               / sizeof(WCHAR);\r
+            //\r
+            // Make sure the IDs is two NULL terminated.\r
+            //\r
+            if ((UNICODE_NULL != plugIn->HardwareIDs[length - 1]) ||\r
+                (UNICODE_NULL != plugIn->HardwareIDs[length - 2])) {\r
+\r
+                status = STATUS_INVALID_PARAMETER;\r
+                break;\r
+            }\r
+\r
+            status = Bus_PlugInDevice( hDevice,\r
+                                       plugIn->HardwareIDs,\r
+                                       length,\r
+                                       plugIn->SerialNo );\r
+        }\r
+\r
+        break;\r
+\r
+    case IOCTL_BUSENUM_UNPLUG_HARDWARE:\r
+\r
+        status = WdfRequestRetrieveInputBuffer( Request,\r
+                                                sizeof(BUSENUM_UNPLUG_HARDWARE),\r
+                                                &unPlug,\r
+                                                &length );\r
+        if( !NT_SUCCESS(status) ) {\r
+            KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status));\r
+            break;\r
+        }\r
+\r
+        if (unPlug->Size == InputBufferLength)\r
+        {\r
+\r
+            status= Bus_UnPlugDevice(hDevice, unPlug->SerialNo );\r
+\r
+        }\r
+\r
+        break;\r
+\r
+    case IOCTL_BUSENUM_EJECT_HARDWARE:\r
+\r
+        status = WdfRequestRetrieveInputBuffer (Request,\r
+                                                sizeof (BUSENUM_EJECT_HARDWARE),\r
+                                                &eject, &length);\r
+        if( !NT_SUCCESS(status) ) {\r
+            KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status));\r
+            break;\r
+        }\r
+\r
+        if (eject->Size == InputBufferLength)\r
+        {\r
+            status= Bus_EjectDevice(hDevice, eject->SerialNo);\r
+\r
+        }\r
+\r
+        break;\r
+\r
+    default:\r
+        break; // default status is STATUS_INVALID_PARAMETER\r
+    }\r
+    WdfRequestCompleteWithInformation(Request, status, length);\r
+#endif\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    The user application has told us that a new device on the bus has arrived.\r
+    We therefore create a description structure in stack, fill in information\r
+       about the child device and call\r
+               WdfChildListAddOrUpdateChildDescriptionAsPresent()\r
+    to add the device.\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+Bus_PlugInDevice(\r
+    __in WDFDEVICE       Device,\r
+    __in PWCHAR          HardwareIds,\r
+    __in size_t          CchHardwareIds,\r
+    __in ULONG           SerialNo )\r
+{\r
+    PDO_IDENTIFICATION_DESCRIPTION description;\r
+    NTSTATUS         status;\r
+\r
+    PAGED_CODE ();\r
+\r
+    //\r
+    // Initialize the description with the information about the newly\r
+    // plugged in device.\r
+    //\r
+    WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(\r
+        &description.Header,\r
+        sizeof(description) );\r
+\r
+    description.SerialNo = SerialNo;\r
+    description.CchHardwareIds = CchHardwareIds;\r
+    description.HardwareIds = HardwareIds;\r
+\r
+    //\r
+    // Call the framework to add this child to the childlist. This call\r
+    // will internally call our DescriptionCompare callback to check\r
+    // whether this device is a new device or existing device. If\r
+    // it's a new device, the framework will call DescriptionDuplicate to create\r
+    // a copy of this description in nonpaged pool.\r
+    // The actual creation of the child device will happen when the framework\r
+    // receives QUERY_DEVICE_RELATION request from the PNP manager in\r
+    // response to InvalidateDeviceRelations call made as part of adding\r
+    // a new child.\r
+    //\r
+    status = WdfChildListAddOrUpdateChildDescriptionAsPresent(\r
+                    WdfFdoGetDefaultChildList(Device),\r
+                                       &description.Header,\r
+                    NULL); // AddressDescription\r
+\r
+    if (status == STATUS_OBJECT_NAME_EXISTS) {\r
+        //\r
+        // The description is already present in the list, the serial number is\r
+        // not unique, return error.\r
+        //\r
+        status = STATUS_INVALID_PARAMETER;\r
+    }\r
+\r
+    return status;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    The application has told us a device has departed from the bus.\r
+\r
+    We therefore need to flag the PDO as no longer present.\r
+\r
+Arguments:\r
+\r
+\r
+Returns:\r
+\r
+    STATUS_SUCCESS upon successful removal from the list\r
+    STATUS_INVALID_PARAMETER if the removal was unsuccessful\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+Bus_UnPlugDevice(\r
+    WDFDEVICE   Device,\r
+    ULONG       SerialNo )\r
+{\r
+    NTSTATUS       status;\r
+    WDFCHILDLIST   list;\r
+\r
+    PAGED_CODE ();\r
+\r
+    list = WdfFdoGetDefaultChildList(Device);\r
+\r
+    if (0 == SerialNo) {\r
+        //\r
+        // Unplug everybody: do this by starting a scan and then not reporting\r
+        // any children upon its completion\r
+        //\r
+        status = STATUS_SUCCESS;\r
+\r
+        WdfChildListBeginScan(list);\r
+\r
+        // A call to WdfChildListBeginScan indicates to the framework that the\r
+        // driver is about to scan for dynamic children. After this call has\r
+        // returned, all previously reported children associated with this will\r
+               // be marked as potentially missing.  A call to either\r
+        // WdfChildListUpdateChildDescriptionAsPresent  or\r
+        // WdfChildListMarkAllChildDescriptionsPresent will mark all previuosly\r
+        // reported missing children as present.  If any children currently\r
+        // present are not reported present by calling\r
+        // WdfChildListUpdateChildDescriptionAsPresent at the time of\r
+        // WdfChildListEndScan, they will be reported as missing to the PnP\r
+               // subsystem After WdfChildListEndScan call has returned, the framework\r
+               // will invalidate the device relations for the FDO associated with the\r
+               // list and report the changes\r
+        //\r
+        WdfChildListEndScan(list);\r
+    }\r
+    else {\r
+        PDO_IDENTIFICATION_DESCRIPTION description;\r
+\r
+        WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(\r
+            &description.Header,\r
+            sizeof(description)\r
+            );\r
+\r
+        description.SerialNo = SerialNo;\r
+\r
+        // WdfFdoUpdateChildDescriptionAsMissing indicates to the framework\r
+               // that a child device that was previuosly detected is no longer present\r
+               // on the bus.\r
+        // This API can be called by itself or after a call to\r
+               //   WdfChildListBeginScan().\r
+        // After this call has returned, the framework will invalidate the\r
+               // device relations for the FDO associated with the list and report the\r
+               // changes.\r
+\r
+        status = WdfChildListUpdateChildDescriptionAsMissing(\r
+                                                                               list,\r
+                                        &description.Header );\r
+        if (status == STATUS_NO_SUCH_DEVICE) {\r
+            // serial number didn't exist. Remap it to a status that user\r
+            // application can understand when it gets translated to win32\r
+            // error code.\r
+            status = STATUS_INVALID_PARAMETER;\r
+        }\r
+    }\r
+    return status;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    The user application has told us to eject the device from the bus.\r
+    In a real situation the driver gets notified by an interrupt when the\r
+    user presses the Eject button on the device.\r
+\r
+Arguments:\r
+\r
+\r
+Returns:\r
+\r
+    STATUS_SUCCESS upon successful removal from the list\r
+    STATUS_INVALID_PARAMETER if the ejection was unsuccessful\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+Bus_EjectDevice( WDFDEVICE Device, ULONG SerialNo )\r
+{\r
+    WDFDEVICE        hChild;\r
+    NTSTATUS         status = STATUS_INVALID_PARAMETER;\r
+    WDFCHILDLIST     list;\r
+\r
+    PAGED_CODE ();\r
+\r
+    list = WdfFdoGetDefaultChildList(Device);\r
+\r
+    //\r
+    // A zero serial number means eject all children\r
+    //\r
+    if (0 == SerialNo) {\r
+        WDF_CHILD_LIST_ITERATOR     iterator;\r
+\r
+        WDF_CHILD_LIST_ITERATOR_INIT( &iterator,\r
+                                      WdfRetrievePresentChildren );\r
+\r
+        WdfChildListBeginIteration(list, &iterator);\r
+\r
+        for ( ; ; ) {\r
+            WDF_CHILD_RETRIEVE_INFO         childInfo;\r
+            PDO_IDENTIFICATION_DESCRIPTION  description;\r
+            BOOLEAN                         ret;\r
+\r
+            //\r
+            // Init the structures.\r
+            //\r
+            WDF_CHILD_RETRIEVE_INFO_INIT(&childInfo, &description.Header);\r
+\r
+            WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(\r
+                                    &description.Header,\r
+                                    sizeof(description)\r
+                                    );\r
+            //\r
+            // Get the device identification description\r
+            //\r
+            status = WdfChildListRetrieveNextDevice(list,\r
+                                                &iterator,\r
+                                                &hChild,\r
+                                                &childInfo);\r
+\r
+            if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES) {\r
+                break;\r
+            }\r
+\r
+            ASSERT(childInfo.Status == WdfChildListRetrieveDeviceSuccess);\r
+\r
+            //\r
+            // Use that description to request an eject.\r
+            //\r
+            ret = WdfChildListRequestChildEject(list, &description.Header);\r
+            if(!ret) {\r
+                WDFVERIFY(ret);\r
+            }\r
+\r
+        }\r
+\r
+        WdfChildListEndIteration(list, &iterator);\r
+\r
+        if (status == STATUS_NO_MORE_ENTRIES) {\r
+            status = STATUS_SUCCESS;\r
+        }\r
+\r
+    }\r
+    else {\r
+\r
+        PDO_IDENTIFICATION_DESCRIPTION description;\r
+\r
+        WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(\r
+            &description.Header,\r
+            sizeof(description)\r
+            );\r
+\r
+        description.SerialNo = SerialNo;\r
+\r
+        if (WdfChildListRequestChildEject(list, &description.Header)) {\r
+            status = STATUS_SUCCESS;\r
+        }\r
+    }\r
+    return status;\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+\r
+    This routine is used to queue workitems so that the callback\r
+    functions can be executed at PASSIVE_LEVEL in the conext of\r
+    a system thread.\r
+\r
+Arguments:\r
+\r
+   FdoData - pointer to a device extenion.\r
+\r
+   CallbackFunction - Function to invoke when at PASSIVE_LEVEL.\r
+\r
+   Context1 & 2 - Meaning of the context values depends on the\r
+                  callback function.\r
+\r
+Return Value:\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+DrvQueuePassiveLevelCallback(\r
+    IN PFDO_BUS_DATA    FdoData,\r
+    IN PFN_WDF_WORKITEM CallbackFunction,\r
+    IN PVOID            Context1,\r
+    IN PVOID            Context2 )\r
+{\r
+    NTSTATUS                status = STATUS_SUCCESS;\r
+    PWORKER_ITEM_CONTEXT    context;\r
+    WDF_OBJECT_ATTRIBUTES   attributes;\r
+    WDF_WORKITEM_CONFIG     workitemConfig;\r
+    WDFWORKITEM             hWorkItem;\r
+\r
+    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, WORKER_ITEM_CONTEXT);\r
+\r
+    attributes.ParentObject = FdoData->WdfDevice;\r
+\r
+    WDF_WORKITEM_CONFIG_INIT(&workitemConfig, CallbackFunction);\r
+\r
+    status = WdfWorkItemCreate( &workitemConfig,\r
+                                &attributes,\r
+                                &hWorkItem);\r
+\r
+    if (!NT_SUCCESS(status)) {\r
+        return status;\r
+    }\r
+\r
+    context = GetWorkItemContext(hWorkItem);\r
+\r
+    context->FdoData = FdoData;\r
+    context->Argument1 = Context1;\r
+    context->Argument2 = Context2;\r
+\r
+    //\r
+    // Execute this work item.\r
+    //\r
+    WdfWorkItemEnqueue(hWorkItem);\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    EvtDevicePrepareHardware event callback performs operations that are\r
+    necessary to make the driver's device operational. The framework calls the\r
+    driver's EvtDevicePrepareHardware callback when the PnP manager sends an\r
+    IRP_MN_START_DEVICE request to the driver stack.\r
+\r
+    Specifically, most drivers will use this callback to map resources.  USB\r
+    drivers may use it to get device descriptors, config descriptors and to\r
+    select configs.\r
+\r
+    Common things to do here:\r
+        Maps physical memory addresses to virtual addresses so the driver can access\r
+        memory that is assigned to the device. \r
+        Determine the device's revision number. \r
+        Configure USB devices. \r
+        Obtain driver-defined interfaces from other drivers. \r
+\r
+Arguments:\r
+\r
+    Device - Handle to a framework device object.\r
+\r
+    ResourcesRaw - Handle to a collection of framework resource objects.\r
+                   This collection identifies the raw (bus-relative) hardware\r
+                   resources that have been assigned to the device.\r
+\r
+    ResourcesTranslated - Handle to a collection of framework resource objects.\r
+                This collection identifies the translated (system-physical)\r
+                hardware resources that have been assigned to the device.\r
+                The resources appear from the CPU's point of view.\r
+                Use this list of resources to map I/O space and\r
+                device-accessible memory into virtual address space\r
+Return Value:\r
+\r
+    WDF status code\r
+\r
+--*/\r
+\r
+static NTSTATUS\r
+Bus_EvtDevicePrepareHardware (\r
+    WDFDEVICE      Device,\r
+    WDFCMRESLIST   ResourcesRaw,\r
+    WDFCMRESLIST   ResourcesTranslated )\r
+{\r
+    NTSTATUS           status = STATUS_SUCCESS;\r
+    PFDO_BUS_DATA      fdoData = NULL;\r
+       DEVICE_OBJECT*  p_dev_obj;\r
+\r
+    UNREFERENCED_PARAMETER(ResourcesRaw);\r
+    UNREFERENCED_PARAMETER(ResourcesTranslated);\r
+\r
+    PAGED_CODE();\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s()\n", __FUNCTION__);\r
+\r
+    fdoData = FdoGetData(Device);\r
+       p_dev_obj = WdfDeviceWdmGetAttachedDevice(Device),\r
+\r
+       // Map hardware, etc. do not start device.\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+                "<-- %s() ret %x\n", __FUNCTION__, status);\r
+    return status;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    EvtDeviceReleaseHardware is called by the framework whenever the PnP manager\r
+    is revoking ownership of our resources.  This may be in response to either\r
+    IRP_MN_STOP_DEVICE or IRP_MN_REMOVE_DEVICE.  The callback is made before\r
+    passing down the IRP to the lower driver.\r
+\r
+    In this callback, do anything necessary to free those resources.\r
+\r
+Arguments:\r
+\r
+    Device - Handle to a framework device object.\r
+\r
+    ResourcesTranslated - Handle to a collection of framework resource objects.\r
+                This collection identifies the translated (system-physical)\r
+                hardware resources that have been assigned to the device.\r
+                The resources appear from the CPU's point of view.\r
+                Use this list of resources to map I/O space and\r
+                device-accessible memory into virtual address space\r
+\r
+Return Value:\r
+\r
+    NTSTATUS - Failures will be logged, but not acted on.\r
+\r
+--*/\r
+\r
+static NTSTATUS\r
+Bus_EvtDeviceReleaseHardware(\r
+    IN  WDFDEVICE    Device,\r
+    IN  WDFCMRESLIST ResourcesTranslated )\r
+{\r
+    PFDO_BUS_DATA              fdoData;\r
+       PDEVICE_OBJECT          p_dev_obj;\r
+\r
+    UNREFERENCED_PARAMETER(ResourcesTranslated);\r
+\r
+    PAGED_CODE();\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s()\n", __FUNCTION__);\r
+\r
+    fdoData = FdoGetData(Device);\r
+       p_dev_obj = WdfDeviceWdmGetAttachedDevice(Device),\r
+\r
+       // Basically undo what PrepareHardware did.\r
+    // Unmap any I/O ports. Disconnecting from the interrupt will be done\r
+    // automatically by the framework.\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s()\n", __FUNCTION__);\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static PCHAR\r
+DbgDevicePowerString( IN WDF_POWER_DEVICE_STATE Type )\r
+{\r
+    switch (Type)\r
+    {\r
+    case WdfPowerDeviceInvalid:\r
+        return "WdfPowerDeviceInvalid";\r
+    case WdfPowerDeviceD0:\r
+        return "WdfPowerDeviceD0";\r
+    case PowerDeviceD1:\r
+        return "WdfPowerDeviceD1";\r
+    case WdfPowerDeviceD2:\r
+        return "WdfPowerDeviceD2";\r
+    case WdfPowerDeviceD3:\r
+        return "WdfPowerDeviceD3";\r
+    case WdfPowerDeviceD3Final:\r
+        return "WdfPowerDeviceD3Final";\r
+    case WdfPowerDevicePrepareForHibernation:\r
+        return "WdfPowerDevicePrepareForHibernation";\r
+    case WdfPowerDeviceMaximum:\r
+        return "PowerDeviceMaximum";\r
+    default:\r
+        return "UnKnown Device Power State";\r
+    }\r
+}\r
+\r
+\r
+void\r
+SetPowerLow( FDO_BUS_DATA *fdoData, WDF_POWER_DEVICE_STATE TargetState )\r
+{\r
+       UNREFERENCED_PARAMETER(fdoData);\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER,\r
+                               "--> %s() target state %s\n", __FUNCTION__,\r
+                               DbgDevicePowerString(TargetState));\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<-- %s()\n", __FUNCTION__);\r
+}\r
+\r
+void\r
+SetPowerD0( FDO_BUS_DATA       *fdoData )\r
+{\r
+       UNREFERENCED_PARAMETER(fdoData);\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "--> %s()\n", __FUNCTION__);\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<-- %s()\n", __FUNCTION__);\r
+}\r
+\r
+void\r
+SetPowerShutdown( FDO_BUS_DATA *fdoData )\r
+{\r
+       UNREFERENCED_PARAMETER(fdoData);\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER,\r
+                               "--> %s() D3 Final\n", __FUNCTION__);\r
+        // Reset and put the device into a known initial state we're shutting\r
+        // down for the last time.\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<-- %s()\n", __FUNCTION__);\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    EvtDeviceD0Entry event callback must perform any operations that are\r
+    necessary before the specified device is used.  It will be called every\r
+    time the hardware needs to be (re-)initialized.  This includes after\r
+    IRP_MN_START_DEVICE, IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE,\r
+    IRP_MN_SET_POWER-D0.\r
+\r
+    This function is not marked pageable because this function is in the\r
+    device power up path. When a function is marked pagable and the code\r
+    section is paged out, it will generate a page fault which could impact\r
+    the fast resume behavior because the client driver will have to wait\r
+    until the system drivers can service this page fault.\r
+\r
+    This function runs at PASSIVE_LEVEL, even though it is not paged.  A\r
+    driver can optionally make this function pageable if DO_POWER_PAGABLE\r
+    is set.  Even if DO_POWER_PAGABLE isn't set, this function still runs\r
+    at PASSIVE_LEVEL.  In this case, though, the function absolutely must\r
+    not do anything that will cause a page fault.\r
+\r
+Arguments:\r
+\r
+    Device - Handle to a framework device object.\r
+\r
+    PreviousState - Device power state which the device was in most recently.\r
+        If the device is being newly started, this will be\r
+        PowerDeviceUnspecified.\r
+\r
+Return Value:\r
+\r
+    NTSTATUS\r
+\r
+--*/\r
+\r
+static NTSTATUS\r
+Bus_EvtDeviceD0Entry (\r
+               IN  WDFDEVICE Device,\r
+               IN  WDF_POWER_DEVICE_STATE PreviousState )\r
+{\r
+       NTSTATUS                        status;\r
+    PFDO_BUS_DATA              fdo;\r
+       ib_api_status_t         ib_status;\r
+\r
+    fdo = FdoGetData(Device);\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER,\r
+                "--> %s() transition from %s to %s \n", __FUNCTION__,\r
+                DbgDevicePowerString(fdo->DevPowerState),\r
+                DbgDevicePowerString(PreviousState));\r
+\r
+\r
+    ASSERT(PowerDeviceD0 != PreviousState);\r
+\r
+    fdo->DevPreviousPowerState = PreviousState;\r
+    fdo->DevPowerState = PowerDeviceD0;\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
+       }\r
+\r
+       /* Initialize the port manager. */\r
+       ib_status = create_port_mgr( &fdo->p_port_mgr );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("create_port_mgr returned %s.\n",\r
+                       ib_get_err_str(ib_status)) );\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       /* Initialize the IOU manager. */\r
+       ib_status = create_iou_mgr( &fdo->p_iou_mgr );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("create_iou_mgr returned %s.\n",\r
+                       ib_get_err_str(ib_status)) );\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       status = IoSetDeviceInterfaceState( &fdo->al_ifc_name, TRUE );\r
+       ASSERT( NT_SUCCESS( status ) );\r
+\r
+       status = IoSetDeviceInterfaceState( &fdo->ci_ifc_name, TRUE );\r
+       ASSERT( NT_SUCCESS( status ) );\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<-- %s()\n", __FUNCTION__);\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    This routine undoes anything done in EvtDeviceD0Entry.  It is called\r
+    whenever the device leaves the D0 state, which happens when the device is\r
+    stopped, when it is removed, and when it is powered off.\r
+\r
+    The device is still in D0 when this callback is invoked, which means that\r
+    the driver can still touch hardware in this routine.\r
+\r
+    Note that interrupts have already been disabled by the time that this\r
+    callback is invoked.\r
+\r
+   EvtDeviceD0Exit event callback must perform any operations that are\r
+   necessary before the specified device is moved out of the D0 state.  If the\r
+   driver needs to save hardware state before the device is powered down, then\r
+   that should be done here.\r
+\r
+   This function runs at PASSIVE_LEVEL, though it is generally not paged.  A\r
+   driver can optionally make this function pageable if DO_POWER_PAGABLE is set.\r
+\r
+   Even if DO_POWER_PAGABLE isn't set, this function still runs at\r
+   PASSIVE_LEVEL.  In this case, though, the function absolutely must not do\r
+   anything that will cause a page fault.\r
+\r
+Arguments:\r
+\r
+    Device - Handle to a framework device object.\r
+\r
+    TargetState - Device power state which the device will be put in once this\r
+        callback is complete.\r
+\r
+Return Value:\r
+\r
+    NTSTATUS    - A failure here will indicate a fatal error in the driver.\r
+                  The Framework will attempt to tear down the stack.\r
+\r
+--*/\r
+\r
+static NTSTATUS\r
+Bus_EvtDeviceD0Exit (\r
+    IN  WDFDEVICE Device,\r
+    IN  WDF_POWER_DEVICE_STATE TargetState )\r
+{\r
+       NTSTATUS                status;\r
+    PFDO_BUS_DATA      fdo;\r
+\r
+    fdo = FdoGetData(Device);\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER,\r
+                "--> %s() current %s - moving to %s\n",\r
+                DbgDevicePowerString(fdo->DevPowerState),\r
+                DbgDevicePowerString(TargetState));\r
+\r
+    fdo->DevPreviousPowerState = fdo->DevPowerState;\r
+    fdo->DevPowerState = TargetState;\r
+\r
+    switch (TargetState)\r
+       {\r
+    case WdfPowerDeviceD1:\r
+    case WdfPowerDeviceD2:\r
+    case WdfPowerDeviceD3:\r
+\r
+            TraceEvents(TRACE_LEVEL_VERBOSE, DBG_POWER,\r
+                        "%s() Entering a deeper sleep state\n", __FUNCTION__);\r
+        break;\r
+\r
+    case WdfPowerDevicePrepareForHibernation:\r
+\r
+        //\r
+        // Fill in any code to save hardware state here.  Do not put in any\r
+        // code to shut the device off.  If this device cannot support being\r
+        // in the paging path (or being a parent or grandparent of a paging\r
+        // path device) then this whole case can be deleted.\r
+        //\r
+               TraceEvents(TRACE_LEVEL_ERROR, DBG_POWER,\r
+                                       "%s() Hibernation? not supported.\n", __FUNCTION__);\r
+        break;\r
+\r
+    case WdfPowerDeviceD3Final:\r
+        //\r
+        // Reset and put the device into a known initial state we're shutting\r
+        // down for the last time.\r
+        //\r
+               TraceEvents(TRACE_LEVEL_VERBOSE, DBG_POWER,\r
+                                       "%s() Shutdown - D3Final.\n", __FUNCTION__);\r
+        break;\r
+\r
+    default:\r
+               TraceEvents(TRACE_LEVEL_ERROR, DBG_POWER,\r
+                                       "%s() Unsupported Power state %s\n", __FUNCTION__,\r
+                                       DbgDevicePowerString(TargetState));\r
+        break;\r
+    }\r
+\r
+       /* Disable any exported interfaces. */\r
+       status = IoSetDeviceInterfaceState( &fdo->al_ifc_name, FALSE );\r
+       //ASSERT( NT_SUCCESS( status ) );\r
+\r
+       status = IoSetDeviceInterfaceState( &fdo->ci_ifc_name, FALSE );\r
+       //ASSERT( NT_SUCCESS( status ) );\r
+\r
+       cl_obj_destroy( &fdo->p_port_mgr->obj );\r
+       cl_obj_destroy( &fdo->p_iou_mgr->obj );\r
+\r
+       al_cleanup();\r
+\r
+       bus_globals.p_bus_ext = NULL;\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<-- %s()\n", __FUNCTION__);\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    The framework calls a driver's EvtDeviceFileCreate callback\r
+    when the framework receives an IRP_MJ_CREATE request.\r
+    The system sends this request when a user application opens the\r
+    device to perform an I/O operation, such as reading or writing to a device.\r
+    This callback is called in the context of the thread\r
+    that created the IRP_MJ_CREATE request.\r
+\r
+Arguments:\r
+\r
+    Device - Handle to a framework device object.\r
+    FileObject - Pointer to fileobject that represents the open handle.\r
+    CreateParams - Parameters for create\r
+\r
+Return Value:\r
+\r
+   NT status code\r
+\r
+--*/\r
+\r
+static VOID\r
+Bus_EvtDeviceFileCreate ( IN WDFDEVICE         Device,\r
+                                                 IN WDFREQUEST         Request,\r
+                                                 IN WDFFILEOBJECT      FileObject )\r
+{\r
+    PFDO_BUS_DATA   fdoData;\r
+\r
+    UNREFERENCED_PARAMETER(FileObject);\r
+\r
+    KdPrint(("%s() --> Dev %p\n", Device));\r
+\r
+    PAGED_CODE ();\r
+\r
+       CL_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );\r
+\r
+    //\r
+    // Get the device context given the device handle.\r
+    //\r
+    fdoData = FdoGetData(Device);\r
+\r
+    WdfRequestComplete(Request, STATUS_SUCCESS);\r
+\r
+    KdPrint(("%s() <--\n",__FUNCTION__));\r
+    return;\r
+}\r
+\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+       EvtFileClose is the dispatch routine for IRP_MJ_CLOSE. It is called when all\r
+       the handles represented by the FileObject are closed and all the references\r
+       to FileObject are removed.\r
+\r
+       This callback may get called in an arbitrary thread context instead of the\r
+       thread that called CloseHandle. If you want to delete any per FileObject\r
+       context that must be done in the context of the user thread that made the\r
+       Create call, you should do that in the EvtDeviceCleanup callback.\r
+\r
+Arguments:\r
+\r
+    FileObject - Pointer to fileobject that represents the open handle.\r
+\r
+Return Value:\r
+\r
+\r
+--*/\r
+\r
+static VOID\r
+Bus_EvtFileClose ( IN WDFFILEOBJECT    FileObject )\r
+{\r
+    PFDO_BUS_DATA    fdoData;\r
+\r
+    PAGED_CODE ();\r
+    KdPrint(("%s()--->\n",__FUNCTION__));\r
+\r
+    fdoData = FdoGetData(WdfFileObjectGetDevice(FileObject));\r
+\r
+    KdPrint(("%s()<---\n",__FUNCTION__));\r
+\r
+    return;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+       EvtDeviceCleanup is the dispatch routine for IRP_MJ_CLENAUP.\r
+\r
+\r
+Arguments:\r
+\r
+\r
+Return Value:\r
+\r
+\r
+--*/\r
+\r
+static VOID\r
+Bus_EvtDriverObjCleanup( IN WDFOBJECT  Driver )\r
+{\r
+    PFDO_BUS_DATA    fdoData;\r
+\r
+    PAGED_CODE ();\r
+    KdPrint(("--> %s()\n",__FUNCTION__));\r
+\r
+    fdoData = FdoGetData(Driver);\r
+\r
+    KdPrint(("<-- %s()\n",__FUNCTION__));\r
+\r
+    return;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    EvtDeviceSelfManagedIoInit is called by the Framework when the device\r
+    enters the D0 state.  Its job is to start any I/O-related actions that the\r
+    Framework isn't managing.  This might include releasing queues that are not\r
+    power-managed, that is, the Framework is not automatically holding and\r
+       releasing them across PnP/Power transitions. (The default behavior for\r
+       WDFQUEUE is auto-managed, so most queues don't need to be dealt with here.)\r
+        This might also include setting up non-queue-based actions.\r
+\r
+    If you allow the Framework to manage most or all of your queues, then when\r
+    you build a driver from this sample, you can probably delete this function.\r
+\r
+    In this driver, the SelfManagedIo callbacks are used to implement a\r
+       watchdog timer.\r
+\r
+    This function is not marked pagable because this function is in the\r
+    device power up path. When a function is marked pagable and the code\r
+    section is paged out, it will generate a page fault which could impact\r
+    the fast resume behavior because the client driver will have to wait\r
+    until the system drivers can service this page fault.\r
+\r
+Arguments:\r
+\r
+    Device - Handle to a framework device object.\r
+\r
+Return Value:\r
+\r
+    NTSTATUS - Failures will result in the device stack being torn down.\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+Bus_EvtDeviceSelfManagedIoInit( IN  WDFDEVICE Device )\r
+{\r
+    NTSTATUS           status=STATUS_SUCCESS;\r
+    PFDO_BUS_DATA      fdoData;\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s()\n", __FUNCTION__);\r
+\r
+    fdoData = FdoGetData(Device);\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+                "<-- %s() ret %x\n", __FUNCTION__, status);\r
+\r
+    return status;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    EvtDeviceSelfManagedIoSuspend is called by the Framework before the device\r
+    leaves the D0 state.  Its job is to stop any I/O-related actions that the\r
+    Framework isn't managing, and which cannot be handled when the device\r
+    hardware isn't available.  In general, this means reversing anything that\r
+    was done in EvtDeviceSelfManagedIoStart.\r
+\r
+    If you allow the Framework to manage most or all of your queues, then when\r
+    you build a driver from this sample, you can probably delete this function.\r
+\r
+Arguments:\r
+\r
+    Device - Handle to a framework device object.\r
+\r
+Return Value:\r
+\r
+    NTSTATUS - Failures will result in the device stack being torn down.\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+Bus_EvtDeviceSelfManagedIoSuspend( IN  WDFDEVICE Device )\r
+{\r
+    PFDO_BUS_DATA   fdoData;\r
+\r
+    PAGED_CODE();\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s()\n", __FUNCTION__);\r
+\r
+    fdoData = FdoGetData(Device);\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s()\n", __FUNCTION__);\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    EvtDeviceSelfManagedIoRestart is called by the Framework before the device\r
+    is restarted for one of the following reasons:\r
+    a) the PnP resources were rebalanced (framework received\r
+        query-stop and stop IRPS )\r
+    b) the device resumed from a low power state to D0.\r
+\r
+    This function is not marked pagable because this function is in the\r
+    device power up path. When a function is marked pagable and the code\r
+    section is paged out, it will generate a page fault which could impact\r
+    the fast resume behavior because the client driver will have to wait\r
+    until the system drivers can service this page fault.\r
+\r
+Arguments:\r
+\r
+    Device - Handle to a framework device object.\r
+\r
+Return Value:\r
+\r
+    NTSTATUS - Failure will cause the device stack to be torn down.\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+Bus_EvtDeviceSelfManagedIoRestart( IN  WDFDEVICE Device )\r
+{\r
+    PFDO_BUS_DATA   fdoData;\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s()\n", __FUNCTION__);\r
+\r
+    fdoData = FdoGetData(Device);\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s()\n", __FUNCTION__);\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    EvtDeviceSelfManagedIoCleanup is called by the Framework when the device is\r
+    being torn down, either in response to the WDM IRP_MN_REMOVE_DEVICE\r
+    It will be called only once.  Its job is to stop all outstanding I/O in the driver\r
+    that the Framework is not managing.\r
+\r
+Arguments:\r
+\r
+    Device - Handle to a framework device object.\r
+\r
+Return Value:\r
+\r
+    None\r
+\r
+--*/\r
+\r
+VOID\r
+Bus_EvtDeviceSelfManagedIoCleanup( IN  WDFDEVICE Device )\r
+{\r
+    PFDO_BUS_DATA      fdoData;\r
+\r
+    PAGED_CODE();\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s()\n",__FUNCTION__);\r
+\r
+    fdoData = FdoGetData(Device);\r
+\r
+    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s()\n",__FUNCTION__);\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+       EvtDeviceQueryStop event callback function determines whether a specified\r
+       device can be stopped so that the PnP manager can redistribute system\r
+       hardware resources.\r
+\r
+Arguments:\r
+\r
+    Device - Handle to a framework device object.\r
+\r
+Return Value:\r
+\r
+    SUCCESS - OK to stop the device, otherwise NOT advisable to stop device.\r
+\r
+--*/\r
+\r
+NTSTATUS\r
+Bus_EvtDeviceQueryStop ( IN WDFDEVICE  Device )\r
+{\r
+    PFDO_BUS_DATA   fdoData;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+    fdoData = FdoGetData(Device);\r
+       // always OK to STOP the device.\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+       EvtDeviceQueryRemove event callback function determines whether a specified\r
+       device can be stopped and removed.\r
+\r
+Arguments:\r
+\r
+    Device - Handle to a framework device object.\r
+\r
+Return Value:\r
+\r
+    SUCCESS - OK to stop the device, otherwise NOT advisable to stop device.\r
+\r
+--*/\r
+\r
+\r
+NTSTATUS\r
+Bus_EvtDeviceQueryRemove ( IN WDFDEVICE  Device )\r
+{\r
+       NTSTATUS                status = STATUS_SUCCESS;\r
+    PFDO_BUS_DATA   p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+    p_ext = FdoGetData(Device);\r
+\r
+       if ( p_ext->n_ci_ifc_ref )\r
+       {\r
+               /*\r
+                * Our interface is still being held by someone.\r
+                * Fail the query.\r
+                */\r
+\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP, \r
+                       ("Failing IRP_MN_QUERY_REMOVE_DEVICE:\n"\r
+                       "\tLowerInterface has %d references\n", \r
+                       p_ext->n_ci_ifc_ref ) );\r
+               status = STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+\r
+    return status;\r
+}\r
+\r
+\r
+VOID\r
+Bus_EvtDeviceSurpriseRemoval ( IN WDFDEVICE  Device )\r
+{\r
+    PFDO_BUS_DATA   fdoData;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+    fdoData = FdoGetData(Device);\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+VOID\r
+Bus_EvtDeviceUsageNotify (\r
+               IN  WDFDEVICE                           Device,\r
+               IN  WDF_SPECIAL_FILE_TYPE       NotificationType,\r
+               IN  BOOLEAN                                     IsInNotificationPath )\r
+{\r
+    PFDO_BUS_DATA   fdoData;\r
+       UNREFERENCED_PARAMETER( NotificationType );\r
+       UNREFERENCED_PARAMETER( IsInNotificationPath );\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+    fdoData = FdoGetData(Device);\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+       Handle IRP_MN_DEVICE_QUERY_RELATIONS.\r
+       EvtDeviceRelationsQuery event callback reports changes in the relationships\r
+       among devices that are supported by the driver.\r
+\r
+Arguments:\r
+\r
+    Device - Handle to a framework device object.\r
+       RelationType - A DEVICE_RELATION_TYPE-typed enumerator value\r
+\r
+Return Value:\r
+\r
+    SUCCESS - \r
+\r
+--*/\r
+\r
+/*\r
+  Documentation clains most driver do NOT use this callback.\r
+ */\r
+VOID\r
+Bus_EvtDeviceRelationsQuery (\r
+               IN WDFDEVICE                            Device,\r
+               IN DEVICE_RELATION_TYPE         RelationType )\r
+{\r
+    PFDO_BUS_DATA   p_ext;\r
+       PCHAR                   WhoAmI;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+    p_ext = FdoGetData(Device);\r
+       WhoAmI = p_ext->Identity;\r
+\r
+       switch( RelationType )\r
+       {\r
+         case BusRelations:\r
+               TraceEvents( TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+                                       ("BusRelations for %s\n", WhoAmI) );\r
+               // IRP ignore\r
+               break;\r
+\r
+         case EjectionRelations:\r
+               TraceEvents( TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+                                       ("EjectionRelations for %s\n", WhoAmI) );\r
+               // IRP ignore\r
+               break;\r
+\r
+       case RemovalRelations:\r
+               TraceEvents( TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+                                       ("RemovalRelations for %s\n", WhoAmI) );\r
+#if 0 // want to call this... how to get irp?\r
+fdo_query_remove_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
+#endif\r
+               break;\r
+\r
+       case TargetDeviceRelation:\r
+               TraceEvents( TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+                                       ("TargetDeviceRelation for %s\n", WhoAmI) );\r
+               // IRP ignore\r
+               break;\r
+\r
+       default:\r
+               TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,\r
+                                       ("Unknown Relation 0x%x on %s\n", RelationType, WhoAmI) );\r
+               break;\r
+       }\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
diff --git a/branches/IBFD/core/bus/kmdf/bus_pnp.h b/branches/IBFD/core/bus/kmdf/bus_pnp.h
new file mode 100644 (file)
index 0000000..8f78d27
--- /dev/null
@@ -0,0 +1,89 @@
+/*\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 10 2005-05-24 00:33:03Z ftillier $\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
+#endif // !defined _BUS_DRV_PNP_H_\r
diff --git a/branches/IBFD/core/bus/kmdf/bus_port_mgr.c b/branches/IBFD/core/bus/kmdf/bus_port_mgr.c
new file mode 100644 (file)
index 0000000..ef1a8f4
--- /dev/null
@@ -0,0 +1,1494 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox 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_port_mgr.c 931 2008-01-31 09:20:41Z leonidk $\r
+ */\r
+\r
+\r
+#include <iba/ib_types.h>\r
+#include <complib/cl_async_proc.h>\r
+#include <complib/cl_bus_ifc.h>\r
+#include "ib_common.h"\r
+#include "bus_pnp.h"\r
+#include "bus_port_mgr.h"\r
+#include "al_ca.h"\r
+#include "al_mgr.h"\r
+#include <initguid.h>\r
+#include <wdmguid.h>\r
+#include "iba/ipoib_ifc.h"\r
+\r
+\r
+#define IPOIB_DEVICE_ID                        L"IBA\\IPoIB"\r
+#define IPOIB_COMPAT_ID                        L"IBA\\SID_1000066a00020000\0\0"\r
+/* Hardware ID is a MULTI_SZ, so is terminated with a double NULL. */\r
+#define IPOIB_HARDWARE_ID              IPOIB_DEVICE_ID L"\0"\r
+#define IPOIB_DESCRIPTION              L"OpenIB IPoIB Adapter"\r
+\r
+/* {5A9649F4-0101-4a7c-8337-796C48082DA2} */\r
+DEFINE_GUID(GUID_BUS_TYPE_IBA,\r
+0x5a9649f4, 0x101, 0x4a7c, 0x83, 0x37, 0x79, 0x6c, 0x48, 0x8, 0x2d, 0xa2);\r
+\r
+\r
+/*\r
+ * Device extension for IPoIB port PDOs.\r
+ */\r
+typedef struct _bus_port_ext\r
+{\r
+       bus_pdo_ext_t                   pdo;\r
+\r
+       net64_t                                 port_guid;\r
+       uint32_t                                n_port;\r
+\r
+       /* Number of references on the upper interface. */\r
+       atomic32_t                              n_ifc_ref;\r
+\r
+}      bus_port_ext_t;\r
+\r
+\r
+port_mgr_t*                                            gp_port_mgr = NULL;\r
+\r
+\r
+/*\r
+ * Function prototypes.\r
+ */\r
+void\r
+destroying_port_mgr(\r
+       IN                              cl_obj_t*                                       p_obj );\r
+\r
+void\r
+free_port_mgr(\r
+       IN                              cl_obj_t*                                       p_obj );\r
+\r
+ib_api_status_t\r
+bus_reg_port_pnp( void );\r
+\r
+ib_api_status_t\r
+port_mgr_pnp_cb(\r
+       IN                              ib_pnp_rec_t*                           p_pnp_rec );\r
+\r
+ib_api_status_t\r
+port_mgr_port_add(\r
+       IN                              ib_pnp_port_rec_t*                      p_pnp_rec );\r
+\r
+void\r
+port_mgr_port_remove(\r
+       IN                              ib_pnp_port_rec_t*                      p_pnp_rec );\r
+\r
+static NTSTATUS\r
+port_start(\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
+static NTSTATUS\r
+port_query_remove(\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
+static void\r
+port_release_resources(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj );\r
+\r
+static NTSTATUS\r
+port_remove(\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
+static NTSTATUS\r
+port_surprise_remove(\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
+static NTSTATUS\r
+port_query_capabilities(\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
+static NTSTATUS\r
+port_query_target_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
+static NTSTATUS\r
+port_query_device_id(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+static NTSTATUS\r
+port_query_hardware_ids(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+static NTSTATUS\r
+port_query_compatible_ids(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+static NTSTATUS\r
+port_query_unique_id(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+static NTSTATUS\r
+port_query_description(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+static NTSTATUS\r
+port_query_location(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+static NTSTATUS\r
+port_query_bus_info(\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
+static NTSTATUS\r
+port_query_ipoib_ifc(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IO_STACK_LOCATION* const        p_io_stack );\r
+\r
+static NTSTATUS\r
+port_query_interface(\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
+static NTSTATUS\r
+port_set_power(\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
+\r
+/* All PnP code is called at passive, so it can all be paged out. */\r
+#ifdef ALLOC_PRAGMA\r
+#pragma alloc_text (PAGE, port_start)\r
+#pragma alloc_text (PAGE, port_query_remove)\r
+#pragma alloc_text (PAGE, port_release_resources)\r
+#pragma alloc_text (PAGE, port_remove)\r
+#pragma alloc_text (PAGE, port_surprise_remove)\r
+#pragma alloc_text (PAGE, port_query_capabilities)\r
+#pragma alloc_text (PAGE, port_query_target_relations)\r
+#pragma alloc_text (PAGE, port_query_device_id)\r
+#pragma alloc_text (PAGE, port_query_hardware_ids)\r
+#pragma alloc_text (PAGE, port_query_compatible_ids)\r
+#pragma alloc_text (PAGE, port_query_unique_id)\r
+#pragma alloc_text (PAGE, port_query_description)\r
+#pragma alloc_text (PAGE, port_query_location)\r
+#pragma alloc_text (PAGE, port_query_bus_info)\r
+#pragma alloc_text (PAGE, port_query_ipoib_ifc)\r
+#pragma alloc_text (PAGE, port_query_interface)\r
+#pragma alloc_text (PAGE_PNP, port_set_power)\r
+#pragma alloc_text (PAGE, port_mgr_port_add)\r
+#pragma alloc_text (PAGE, port_mgr_port_remove)\r
+#endif\r
+\r
+\r
+/*\r
+ * Global virtual function pointer tables shared between all\r
+ * instances of Port PDOs.\r
+ */\r
+static const cl_vfptr_pnp_po_t         vfptr_port_pnp = {\r
+       "IPoIB",\r
+       port_start,\r
+       cl_irp_succeed,\r
+       cl_irp_succeed,\r
+       cl_irp_succeed,\r
+       port_query_remove,\r
+       port_release_resources,\r
+       port_remove,\r
+       cl_irp_succeed,\r
+       port_surprise_remove,\r
+       port_query_capabilities,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       cl_irp_succeed,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       port_query_target_relations,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       port_query_bus_info,\r
+       port_query_interface,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       cl_irp_complete,\r
+       cl_irp_succeed,                         // QueryPower\r
+       port_set_power,                         // SetPower\r
+       cl_irp_unsupported,                     // PowerSequence\r
+       cl_irp_unsupported                      // WaitWake\r
+};\r
+\r
+\r
+static const cl_vfptr_query_txt_t              vfptr_port_query_txt = {\r
+       port_query_device_id,\r
+       port_query_hardware_ids,\r
+       port_query_compatible_ids,\r
+       port_query_unique_id,\r
+       port_query_description,\r
+       port_query_location\r
+};\r
+\r
+\r
+/*\r
+ * Create the AL load service.\r
+ */\r
+ib_api_status_t\r
+create_port_mgr(\r
+               OUT                     port_mgr_t** const                      pp_port_mgr )\r
+{\r
+       ib_api_status_t         status;\r
+       cl_status_t                     cl_status;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       CL_ASSERT( !gp_port_mgr );\r
+\r
+       gp_port_mgr = cl_zalloc( sizeof( port_mgr_t ) );\r
+       if( !gp_port_mgr )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to allocate port manager.\n") );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       /* Construct the load service. */\r
+       cl_obj_construct( &gp_port_mgr->obj, AL_OBJ_TYPE_LOADER );\r
+       cl_mutex_construct( &gp_port_mgr->pdo_mutex );\r
+       cl_qlist_init( &gp_port_mgr->port_list );\r
+\r
+       cl_status = cl_mutex_init( &gp_port_mgr->pdo_mutex );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               free_port_mgr( &gp_port_mgr->obj );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("cl_mutex_init returned %#x.\n", cl_status) );\r
+               return ib_convert_cl_status( cl_status );\r
+       }\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
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               free_port_mgr( &gp_port_mgr->obj );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("cl_obj_init returned %#x.\n", cl_status) );\r
+               return ib_convert_cl_status( cl_status );\r
+       }\r
+\r
+       /* Register for port PnP events. */\r
+       status = bus_reg_port_pnp();\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
+               return status;\r
+       }\r
+\r
+       *pp_port_mgr = gp_port_mgr;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+/*\r
+ * Pre-destroy the load service.\r
+ */\r
+void\r
+destroying_port_mgr(\r
+       IN                              cl_obj_t*                                       p_obj )\r
+{\r
+       ib_api_status_t                 status;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       CL_ASSERT( p_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
+               CL_ASSERT( status == IB_SUCCESS );\r
+       }\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+/*\r
+ * Free the load service.\r
+ */\r
+void\r
+free_port_mgr(\r
+       IN                              cl_obj_t*                                       p_obj )\r
+{\r
+       bus_pdo_ext_t   *p_ext;\r
+       cl_list_item_t  *p_list_item;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       CL_ASSERT( p_obj );\r
+       CL_ASSERT( gp_port_mgr == PARENT_STRUCT( p_obj, port_mgr_t, obj ) );\r
+\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
+        */\r
+       p_list_item = cl_qlist_remove_head( &gp_port_mgr->port_list );\r
+       while( p_list_item != cl_qlist_end( &gp_port_mgr->port_list ) )\r
+       {\r
+               p_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
+               p_list_item = cl_qlist_remove_head( &gp_port_mgr->port_list );\r
+               if( p_ext->cl_ext.pnp_state == SurpriseRemoved )\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
+                       continue;\r
+               }\r
+               if( p_ext->h_ca )\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
+                       /* 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
+               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
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+/*\r
+ * Register the load service for the given PnP class events.\r
+ */\r
+ib_api_status_t\r
+bus_reg_port_pnp( void )\r
+{\r
+       ib_pnp_req_t                    pnp_req;\r
+       ib_api_status_t                 status;\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
+       }\r
+\r
+       return status;\r
+}\r
+\r
+\r
+/*\r
+ * Load service PnP event callback.\r
+ */\r
+ib_api_status_t\r
+port_mgr_pnp_cb(\r
+       IN                              ib_pnp_rec_t*                           p_pnp_rec )\r
+{\r
+       ib_api_status_t         status;\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
+       case IB_PNP_PORT_ADD:\r
+               status = port_mgr_port_add( (ib_pnp_port_rec_t*)p_pnp_rec );\r
+               break;\r
+\r
+       case IB_PNP_PORT_REMOVE:\r
+               port_mgr_port_remove( (ib_pnp_port_rec_t*)p_pnp_rec );\r
+\r
+       default:\r
+               status = IB_SUCCESS;\r
+               break;\r
+       }\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+\r
+/*\r
+ * Called to get bus relations for an HCA.\r
+ */\r
+NTSTATUS\r
+port_mgr_get_bus_relations(\r
+       IN              const   net64_t                                         ca_guid,\r
+       IN                              IRP* const                                      p_irp )\r
+{\r
+       NTSTATUS                        status;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\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
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+static ib_api_status_t\r
+__port_was_hibernated(\r
+       IN                              ib_pnp_port_rec_t*                      p_pnp_rec )\r
+{\r
+       NTSTATUS                status;\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
+       cl_qlist_t*             p_pdo_list = &gp_port_mgr->port_list;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+       \r
+       cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
+       \r
+       /* Count the number of child devices. */\r
+       for( p_list_item = cl_qlist_head( p_pdo_list );\r
+               p_list_item != cl_qlist_end( p_pdo_list );\r
+               p_list_item = cl_qlist_next( p_list_item ) )\r
+       {\r
+               p_pdo_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
+               p_port_ext = (bus_port_ext_t*)p_pdo_ext;\r
+       \r
+               if( p_pdo_ext->b_present && p_pdo_ext->b_hibernating &&\r
+                       (p_port_ext->port_guid == p_pnp_rec->p_port_attr->port_guid) )\r
+               {\r
+                       n_devs++;\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
+                       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 ) );\r
+       }\r
+\r
+       if (n_devs)\r
+       {\r
+               /* Take a reference on the parent HCA. */\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
+                       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
+                       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
+                               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 ) );\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
+               status = IB_NOT_FOUND;\r
+       }\r
+\r
+       cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+ib_api_status_t\r
+port_mgr_port_add(\r
+       IN                              ib_pnp_port_rec_t*                      p_pnp_rec )\r
+{\r
+       NTSTATUS                status;\r
+       DEVICE_OBJECT   *p_pdo;\r
+       bus_port_ext_t  *p_port_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\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
+          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
+       if( status != IB_NOT_FOUND )\r
+       {\r
+               BUS_EXIT( BUS_DBG_PNP );\r
+               return status;\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 );\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, NULL, p_pdo, bus_globals.dbg_lvl,\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->Flags |= DO_BUS_ENUMERATED_DEVICE;\r
+\r
+       p_port_ext = p_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, p_port_ext, p_port_ext->pdo.b_present, \r
+               p_port_ext->pdo.b_reported_missing ) );\r
+\r
+       /* Cache the CA GUID. */\r
+       p_port_ext->pdo.ca_guid = p_pnp_rec->p_ca_attr->ca_guid;\r
+\r
+       /* Take a reference on the parent HCA. */\r
+       p_port_ext->pdo.h_ca = acquire_ca( p_pnp_rec->p_ca_attr->ca_guid );\r
+       if( !p_port_ext->pdo.h_ca )\r
+       {\r
+               BUS_TRACE( BUS_DBG_PNP, ("Deleted device: PDO %p\n", p_pdo ));\r
+               IoDeleteDevice( p_pdo );\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 = p_pnp_rec->p_port_attr->port_guid;\r
+       p_port_ext->n_port = p_pnp_rec->p_port_attr->port_num;\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
+       p_pnp_rec->pnp_rec.context = p_port_ext;\r
+\r
+       /* Tell the PnP Manager to rescan for the HCA's bus relations. */\r
+       IoInvalidateDeviceRelations(\r
+               p_port_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
+\r
+       /* Invalidate removal relations for the bus driver. */\r
+       IoInvalidateDeviceRelations(\r
+               bus_globals.p_bus_ext->cl_ext.p_pdo, RemovalRelations );\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+port_mgr_port_remove(\r
+       IN                              ib_pnp_port_rec_t*                      p_pnp_rec )\r
+{\r
+       bus_pdo_ext_t   *p_ext;\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
+       CL_ASSERT( p_ext );\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
+       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
+               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
+\r
+       /* Invalidate removal relations for the bus driver. */\r
+       IoInvalidateDeviceRelations( bus_globals.p_bus_ext->cl_ext.p_pdo,\r
+               RemovalRelations );\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
+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
+}\r
+\r
+\r
+static NTSTATUS\r
+port_start(\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
+       bus_pdo_ext_t   *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( p_irp );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\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
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_query_remove(\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
+       bus_port_ext_t  *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( p_irp );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       *p_action = IrpComplete;\r
+       if( p_ext->n_ifc_ref )\r
+       {\r
+               /*\r
+                * Our interface is still being held by someone.\r
+                * Rollback the PnP state that was changed in the complib handler.\r
+                */\r
+               cl_rollback_pnp_state( &p_ext->pdo.cl_ext );\r
+\r
+               /* Fail the query. */\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP, ("Failing IRP_MN_QUERY_REMOVE_DEVICE:\n"\r
+                       "\tInterface has %d reference\n", p_ext->n_ifc_ref ) );\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+port_release_resources(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
+{\r
+       bus_port_ext_t  *p_ext;\r
+       POWER_STATE             po_state;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\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
+       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
+       PoSetPowerState( p_ext->pdo.cl_ext.p_pdo, DevicePowerState, po_state );\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_remove(\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
+       bus_port_ext_t  *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       if( p_ext->pdo.b_present )\r
+       {\r
+               CL_ASSERT( p_ext->pdo.cl_ext.pnp_state != NotStarted );\r
+               CL_ASSERT( !p_ext->pdo.b_reported_missing );\r
+               /* Reset the state to NotStarted.  CompLib set it to Deleted. */\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
+               return STATUS_SUCCESS;\r
+       }\r
+\r
+       if( !p_ext->pdo.b_reported_missing )\r
+       {\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
+               return STATUS_SUCCESS;\r
+       }\r
+\r
+       /* Wait for all I/O operations to complete. */\r
+       IoReleaseRemoveLockAndWait( &p_ext->pdo.cl_ext.remove_lock, p_irp );\r
+\r
+       /* Release resources if it was not done yet. */\r
+       if( p_ext->pdo.cl_ext.last_pnp_state != SurpriseRemoved )\r
+               p_ext->pdo.cl_ext.vfptr_pnp_po->pfn_release_resources( p_dev_obj );\r
+\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
+       IoDeleteDevice( p_dev_obj );\r
+\r
+       *p_action = IrpDoNothing;\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_surprise_remove(\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
+       bus_port_ext_t  *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( p_irp );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+       p_ext->pdo.b_present = FALSE;\r
+       p_ext->pdo.b_reported_missing = TRUE;\r
+       BUS_TRACE( BUS_DBG_PNP, ("%s: PDO %p, ext %p, present %d, missing %d .\n",\r
+               p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_ext->pdo.cl_ext.p_self_do, \r
+               p_ext, p_ext->pdo.b_present, p_ext->pdo.b_reported_missing ) );\r
+\r
+       *p_action = IrpComplete;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_query_capabilities(\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
+       DEVICE_CAPABILITIES             *p_caps;\r
+       IO_STACK_LOCATION               *p_io_stack;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( p_dev_obj );\r
+\r
+       p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+       p_caps = p_io_stack->Parameters.DeviceCapabilities.Capabilities;\r
+\r
+       p_caps->DeviceD1 = FALSE;\r
+       p_caps->DeviceD2 = FALSE;\r
+       p_caps->LockSupported = FALSE;\r
+       p_caps->EjectSupported = FALSE;\r
+       p_caps->Removable = FALSE;\r
+       p_caps->DockDevice = FALSE;\r
+       p_caps->UniqueID = TRUE;\r
+       p_caps->SilentInstall = TRUE;\r
+       p_caps->RawDeviceOK = FALSE;\r
+       p_caps->SurpriseRemovalOK = FALSE;\r
+       p_caps->WakeFromD0 = FALSE;\r
+       p_caps->WakeFromD1 = FALSE;\r
+       p_caps->WakeFromD2 = FALSE;\r
+       p_caps->WakeFromD3 = FALSE;\r
+       p_caps->HardwareDisabled = FALSE;\r
+       p_caps->DeviceState[PowerSystemWorking] = PowerDeviceD0;\r
+       p_caps->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;\r
+       p_caps->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;\r
+       p_caps->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;\r
+       p_caps->DeviceState[PowerSystemHibernate] = PowerDeviceD3;\r
+       p_caps->DeviceState[PowerSystemShutdown] = PowerDeviceD3;\r
+       p_caps->SystemWake = PowerSystemUnspecified;\r
+       p_caps->DeviceWake = PowerDeviceUnspecified;\r
+       p_caps->D1Latency = 0;\r
+       p_caps->D2Latency = 0;\r
+       p_caps->D3Latency = 0;\r
+\r
+       *p_action = IrpComplete;\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_query_target_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
+       DEVICE_RELATIONS        *p_rel;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       *p_action = IrpComplete;\r
+\r
+       status = cl_alloc_relations( p_irp, 1 );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("cl_alloc_relations returned 0x%08x.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
+       p_rel->Count = 1;\r
+       p_rel->Objects[0] = p_dev_obj;\r
+\r
+       ObReferenceObject( p_dev_obj );\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_query_device_id(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
+               OUT                             IRP* const                              p_irp )\r
+{\r
+       WCHAR                           *p_string;\r
+       bus_port_ext_t          *p_ext;\r
+       \r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       \r
+       p_ext = (bus_port_ext_t*)p_dev_obj->DeviceExtension;\r
+       if( !p_ext->pdo.b_present )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+\r
+       /* Device ID is "IBA\SID_<sid> where <sid> is the IPoIB Service ID. */\r
+       p_string = ExAllocatePoolWithTag( PagedPool, sizeof(IPOIB_DEVICE_ID), 'vedq' );\r
+       if( !p_string )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to allocate device ID buffer (%d bytes).\n",\r
+                       sizeof(IPOIB_DEVICE_ID)) );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+       cl_memcpy( p_string, IPOIB_DEVICE_ID, sizeof(IPOIB_DEVICE_ID) );\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_query_hardware_ids(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
+               OUT                             IRP* const                              p_irp )\r
+{\r
+       WCHAR                           *p_string;\r
+       bus_port_ext_t          *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+\r
+       p_ext = (bus_port_ext_t*)p_dev_obj->DeviceExtension;\r
+       if( !p_ext->pdo.b_present )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+\r
+       p_string = ExAllocatePoolWithTag( PagedPool, sizeof(IPOIB_HARDWARE_ID), 'ihqp' );\r
+       if( !p_string )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to allocate hardware ID buffer (%d bytes).\n",\r
+                       sizeof(IPOIB_HARDWARE_ID)) );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+       cl_memcpy( p_string, IPOIB_HARDWARE_ID, sizeof(IPOIB_HARDWARE_ID) );\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_query_compatible_ids(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
+               OUT                             IRP* const                              p_irp )\r
+{\r
+       WCHAR                           *p_string;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( p_dev_obj );\r
+\r
+       p_string = ExAllocatePoolWithTag( PagedPool, sizeof(IPOIB_COMPAT_ID), 'icqp' );\r
+       if( !p_string )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to allocate compatible ID buffer (%d bytes).\n",\r
+                       sizeof(IPOIB_COMPAT_ID)) );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+       cl_memcpy( p_string, IPOIB_COMPAT_ID, sizeof(IPOIB_COMPAT_ID) );\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_query_unique_id(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
+               OUT                             IRP* const                              p_irp )\r
+{\r
+       NTSTATUS                        status;\r
+       WCHAR                           *p_string;\r
+       bus_port_ext_t          *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       if( !p_ext->pdo.b_present )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+\r
+       /* The instance ID is the port GUID. */\r
+       p_string = ExAllocatePoolWithTag( PagedPool, sizeof(WCHAR) * 17, 'iuqp' );\r
+       if( !p_string )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to allocate instance ID buffer (%d bytes).\n",\r
+                       sizeof(WCHAR) * 17) );\r
+               return STATUS_NO_MEMORY;\r
+       }\r
+\r
+       status = RtlStringCchPrintfW( p_string, 17, L"%016I64x", p_ext->port_guid );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               CL_ASSERT( NT_SUCCESS( status ) );\r
+               ExFreePool( p_string );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("RtlStringCchPrintfW returned %08x.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_query_description(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
+               OUT                             IRP* const                              p_irp )\r
+{\r
+       WCHAR                           *p_string;\r
+       bus_port_ext_t          *p_ext;\r
+       \r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+       if( !p_ext->pdo.b_present )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+\r
+\r
+       /* The instance ID is the port GUID. */\r
+       p_string = ExAllocatePoolWithTag( PagedPool, sizeof(IPOIB_DESCRIPTION), 'edqp' );\r
+       if( !p_string )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to allocate device description buffer (%d bytes).\n",\r
+                       sizeof(IPOIB_DESCRIPTION)) );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+       cl_memcpy( p_string, IPOIB_DESCRIPTION, sizeof(IPOIB_DESCRIPTION) );\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_query_location(\r
+       IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
+               OUT                             IRP* const                              p_irp )\r
+{\r
+       WCHAR                           *p_string;\r
+       bus_port_ext_t          *p_ext;\r
+       size_t                          size;\r
+       ULONG                           len;\r
+       NTSTATUS                        status;\r
+       DEVICE_OBJECT           *p_hca_dev;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+       if( !p_ext->pdo.b_present )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
+               return STATUS_NO_SUCH_DEVICE;\r
+       }\r
+\r
+       p_hca_dev = p_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev;\r
+\r
+       /* Get the length of the HCA's location. */\r
+       status = IoGetDeviceProperty( p_hca_dev,\r
+               DevicePropertyLocationInformation, 0, NULL, &len );\r
+       if( status != STATUS_BUFFER_TOO_SMALL )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("IoGetDeviceProperty for device location size returned %08x.\n",\r
+                       status) );\r
+               return status;\r
+       }\r
+\r
+       /*\r
+        * Allocate the string buffer to hold the HCA's location along with the\r
+        * port number.  The port number is 32-bits, so in decimal it can be at\r
+        * most 10 characters.\r
+        */\r
+       size = len + sizeof(L", port ") + (sizeof(WCHAR) * 10);\r
+       if( size > (USHORT)-1 )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Length beyond limits.\n") );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       p_string = ExAllocatePoolWithTag( PagedPool, size, 'olqp' );\r
+       if( !p_string )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to allocate device location buffer (%d bytes).\n", len) );\r
+               return STATUS_NO_MEMORY;\r
+       }\r
+\r
+       /* Get the HCA's location information. */\r
+       status = IoGetDeviceProperty( p_hca_dev,\r
+               DevicePropertyLocationInformation, len, p_string, &len );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               ExFreePool( p_string );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("IoGetDeviceProperty for device location returned %08x.\n",\r
+                       status) );\r
+               return status;\r
+       }\r
+\r
+       /* Append the port number to the HCA's location. */\r
+       status = RtlStringCbPrintfW( p_string + (len/2) - 1, size - len + 1,\r
+               L", port %d", p_ext->n_port );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               CL_ASSERT( NT_SUCCESS( status ) );\r
+               ExFreePool( p_string );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("RtlStringCbPrintfW returned %08x.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
+\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_query_bus_info(\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
+       PNP_BUS_INFORMATION     *p_bus_info;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       UNUSED_PARAM( p_dev_obj );\r
+\r
+       *p_action = IrpComplete;\r
+\r
+       p_bus_info = ExAllocatePoolWithTag( PagedPool, sizeof(PNP_BUS_INFORMATION), 'ibqp' );\r
+       if( !p_bus_info )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to allocate PNP_BUS_INFORMATION (%d bytes).\n",\r
+                       sizeof(PNP_BUS_INFORMATION)) );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       p_bus_info->BusTypeGuid = GUID_BUS_TYPE_IBA;\r
+       //TODO: Memory from Intel - storage miniport would not stay loaded unless\r
+       //TODO: bus type was PCI.  Look here if SRP is having problems staying\r
+       //TODO: loaded.\r
+       p_bus_info->LegacyBusType = PNPBus;\r
+       p_bus_info->BusNumber = 0;\r
+\r
+       p_irp->IoStatus.Information = (ULONG_PTR)p_bus_info;\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_query_ipoib_ifc(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IO_STACK_LOCATION* const        p_io_stack )\r
+{\r
+       NTSTATUS                                status;\r
+       ib_al_ifc_t                             *p_ifc;\r
+       ib_al_ifc_data_t                *p_ifc_data;\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
+       CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+\r
+       BUS_TRACE( BUS_DBG_PNP, ("Query i/f for %s: PDO %p (=%p),ext %p, present %d, missing %d .\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, p_ext->pdo.b_present, p_ext->pdo.b_reported_missing ) );\r
+\r
+       /* Get the interface. */\r
+       status = cl_fwd_query_ifc(\r
+               p_ext->pdo.p_parent_ext->cl_ext.p_self_do, p_io_stack );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Failed to forward interface query: %08X\n", status) );\r
+               return status;\r
+       }\r
+\r
+       if( !p_io_stack->Parameters.QueryInterface.InterfaceSpecificData )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR, ("No interface specific data!\n") );\r
+               return status;\r
+       }\r
+\r
+       p_ifc = (ib_al_ifc_t*)p_io_stack->Parameters.QueryInterface.Interface;\r
+\r
+       p_ifc_data = (ib_al_ifc_data_t*)\r
+               p_io_stack->Parameters.QueryInterface.InterfaceSpecificData;\r
+       p_guid = p_ifc_data->type;\r
+       if( !IsEqualGUID( p_guid, &GUID_IPOIB_INTERFACE_DATA ) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP, ("Unsupported interface data: \n\t"\r
+                       "0x%08x, 0x%04x, 0x%04x, 0x%02x, 0x%02x, 0x%02x,"\r
+                       "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n",\r
+                       p_guid->Data1, p_guid->Data2, p_guid->Data3,\r
+                       p_guid->Data4[0], p_guid->Data4[1], p_guid->Data4[2],\r
+                       p_guid->Data4[3], p_guid->Data4[4], p_guid->Data4[5],\r
+                       p_guid->Data4[6], p_guid->Data4[7]) );\r
+               return status;\r
+       }\r
+\r
+       if( p_ifc_data->version != IPOIB_INTERFACE_DATA_VERSION )\r
+       {\r
+               p_ifc->wdm.InterfaceDereference( p_ifc->wdm.Context );\r
+               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
+                       ("Unsupported version %d, expected %d\n",\r
+                       p_ifc_data->version, IPOIB_INTERFACE_DATA_VERSION) );\r
+               return STATUS_NOT_SUPPORTED;\r
+       }\r
+\r
+       ASSERT( p_ifc_data->p_data );\r
+\r
+       if( p_ifc_data->size != sizeof(ipoib_ifc_data_t) )\r
+       {\r
+               p_ifc->wdm.InterfaceDereference( p_ifc->wdm.Context );\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP,\r
+                       ("Buffer too small (%d given, %d required).\n",\r
+                       p_ifc_data->size,\r
+                       sizeof(ipoib_ifc_data_t)) );\r
+               return STATUS_BUFFER_TOO_SMALL;\r
+       }\r
+\r
+       /* Set the interface data. */\r
+       p_ipoib_data = (ipoib_ifc_data_t*)p_ifc_data->p_data;\r
+\r
+       p_ipoib_data->ca_guid = p_ext->pdo.h_ca->obj.p_ci_ca->verbs.guid;\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_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+port_query_interface(\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
+       bus_pdo_ext_t           *p_ext;\r
+       NTSTATUS                        status;\r
+       IO_STACK_LOCATION       *p_io_stack;\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
+       /* Bottom of the stack - IRP must be completed. */\r
+       *p_action = IrpComplete;\r
+\r
+       /* Compare requested GUID with our supported interface GUIDs. */\r
+       if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
+               &GUID_IB_AL_INTERFACE ) )\r
+       {\r
+               status = port_query_ipoib_ifc( p_dev_obj, p_io_stack );\r
+       }\r
+       else if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
+               &GUID_BUS_INTERFACE_STANDARD ) )\r
+       {\r
+               p_ext = p_dev_obj->DeviceExtension;\r
+               if( !p_ext->h_ca ||\r
+                       !p_ext->b_present ||\r
+                       p_ext->b_reported_missing )\r
+               {\r
+                       return STATUS_NO_SUCH_DEVICE;\r
+               }\r
+\r
+               status = cl_fwd_query_ifc(\r
+                       p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, p_io_stack );\r
+       }\r
+       else\r
+       {\r
+               status = p_irp->IoStatus.Status;\r
+       }\r
+       \r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+\r
+/* Work item callback to handle DevicePowerD3 IRPs at passive level. */\r
+static void\r
+__HibernateUpWorkItem(\r
+       IN                              DEVICE_OBJECT*                          p_dev_obj,\r
+       IN                              void*                                           context )\r
+{\r
+       IO_STACK_LOCATION       *p_io_stack;\r
+       bus_pdo_ext_t           *p_ext;\r
+       IRP                                     *p_irp;\r
+       POWER_STATE powerState;\r
+\r
+       BUS_ENTER( BUS_DBG_POWER );\r
+\r
+       p_ext = (bus_pdo_ext_t*)p_dev_obj->DeviceExtension;\r
+       p_irp = (IRP*)context;\r
+       p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+\r
+       IoFreeWorkItem( p_ext->p_po_work_item );\r
+       p_ext->p_po_work_item = NULL;\r
+\r
+       while (!p_ext->h_ca) {\r
+               BUS_TRACE( BUS_DBG_PNP, ("Waiting for the end of HCA registration ... \n"));\r
+               cl_thread_suspend( 200 );       /* suspend for 200 ms */\r
+       }\r
+\r
+       p_ext->dev_po_state = p_io_stack->Parameters.Power.State;\r
+       powerState = PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
+\r
+       BUS_TRACE( BUS_DBG_POWER, \r
+               ("PoSetPowerState: old state %d, new state to %d\n", \r
+               powerState.DeviceState, p_ext->dev_po_state ));\r
+\r
+       p_irp->IoStatus.Status = STATUS_SUCCESS;\r
+       PoStartNextPowerIrp( p_irp );\r
+       IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+       IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
+\r
+       BUS_EXIT( BUS_DBG_POWER );\r
+}\r
+\r
+\r
+/*\r
+ * The PDOs created by the IB Bus driver are software devices.  As such,\r
+ * all power states are supported.  It is left to the HCA power policy\r
+ * owner to handle which states can be supported by the HCA.\r
+ */\r
+static NTSTATUS\r
+port_set_power(\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 = STATUS_SUCCESS;\r
+       IO_STACK_LOCATION       *p_io_stack;\r
+       bus_pdo_ext_t           *p_ext;\r
+\r
+       BUS_ENTER( BUS_DBG_POWER );\r
+\r
+       p_ext = p_dev_obj->DeviceExtension;\r
+       p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+\r
+       BUS_TRACE( BUS_DBG_POWER, \r
+               ("SET_POWER for PDO %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.State.DeviceState, \r
+               p_io_stack->Parameters.Power.ShutdownType ));\r
+\r
+       if ((p_io_stack->Parameters.Power.Type == SystemPowerState) &&\r
+               (p_io_stack->Parameters.Power.State.SystemState ==PowerSystemHibernate ||\r
+               p_io_stack->Parameters.Power.State.SystemState ==PowerSystemSleeping1 ))\r
+       {\r
+               BUS_TRACE( BUS_DBG_POWER, ("Setting b_hibernating flag for PDO %p \n", p_dev_obj));\r
+               p_ext->b_hibernating = TRUE;\r
+       }\r
+\r
+       if( p_io_stack->Parameters.Power.Type == DevicePowerState )\r
+       {\r
+               /* after hibernation PDO is not ready for work. we need to wait for finishing of the HCA registration */\r
+               if( p_io_stack->Parameters.Power.State.DeviceState == PowerDeviceD0 && p_ext->b_hibernating)\r
+               {\r
+                       /* Process in a work item - deregister_ca and HcaDeinit block. */\r
+                       ASSERT( !p_ext->p_po_work_item );\r
+                       p_ext->p_po_work_item = IoAllocateWorkItem( p_dev_obj );\r
+                       if( !p_ext->p_po_work_item )\r
+                               status = STATUS_INSUFFICIENT_RESOURCES;\r
+                       else {\r
+                               /* Process in work item callback. */\r
+                               IoMarkIrpPending( p_irp );\r
+                               IoQueueWorkItem(\r
+                                       p_ext->p_po_work_item, __HibernateUpWorkItem, DelayedWorkQueue, p_irp );\r
+                               *p_action = IrpDoNothing;\r
+                               BUS_EXIT( BUS_DBG_POWER );\r
+                               return STATUS_PENDING;\r
+                       }\r
+               }\r
+\r
+               /* Notify the power manager. */\r
+               p_ext->dev_po_state = p_io_stack->Parameters.Power.State;\r
+               PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
+       }\r
+\r
+       *p_action = IrpComplete;\r
+       BUS_EXIT( BUS_DBG_POWER );\r
+       return status;\r
+}\r
diff --git a/branches/IBFD/core/bus/kmdf/bus_port_mgr.h b/branches/IBFD/core/bus/kmdf/bus_port_mgr.h
new file mode 100644 (file)
index 0000000..122733b
--- /dev/null
@@ -0,0 +1,66 @@
+/*\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_port_mgr.h 9 2005-05-23 22:38:08Z ftillier $\r
+ */\r
+\r
+\r
+#if !defined( __BUS_PORT_MGR_H__ )\r
+#define __BUS_PORT_MGR_H__\r
+\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_mutex.h>\r
+#include <complib/cl_obj.h>\r
+\r
+\r
+/* Global load service */\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
+\r
+       /* Pointer vector of child IPoIB port PDOs. */\r
+       cl_qlist_t                                      port_list;\r
+\r
+}      port_mgr_t;\r
+\r
+\r
+ib_api_status_t\r
+create_port_mgr(\r
+               OUT                     port_mgr_t** const                      pp_port_mgr );\r
+\r
+\r
+NTSTATUS\r
+port_mgr_get_bus_relations(\r
+       IN              const   net64_t                                         ca_guid,\r
+       IN                              IRP* const                                      p_irp );\r
+\r
+#endif\r
diff --git a/branches/IBFD/core/bus/kmdf/busenum.c b/branches/IBFD/core/bus/kmdf/busenum.c
deleted file mode 100644 (file)
index 77c35ac..0000000
+++ /dev/null
@@ -1,1158 +0,0 @@
-/*\r
- * Copyright (c) 2008 Intel Corporation All Rights Reserved\r
- * Copyright (c) 2008 Microsoft Corporation 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$\r
- */\r
-\r
-/*++\r
-Module Name:\r
-\r
-    BUSENUM.C\r
-\r
-Abstract:\r
-\r
-    Provide the driver entry points for the InfiniBand Bus Driver.\r
-    This module contains routies to handle the function driver\r
-    aspect of the bus driver. This sample is functionally\r
-    equivalent to the WDM toaster bus driver.\r
-       Whever you read the word 'bus', think InfiniBand Fabric (aka, 'bus').\r
-\r
-Environment:\r
-\r
-    kernel mode only\r
-\r
---*/\r
-\r
-#include "ib_fabric.h"\r
-#include <complib/cl_init.h>\r
-\r
-#ifdef WINIB\r
-#define DEFAULT_NODE_DESC      "Mellanox Windows® Host"\r
-#else\r
-#define DEFAULT_NODE_DESC      "OpenIB Windows® Host"\r
-#endif\r
-\r
-#if defined(EVENT_TRACING)\r
-/*\r
- * The .c file specific trace message header (.tmh) file must be included in a\r
- * source file before any WPP macro calls and after defining a WPP_CONTROL_GUIDS\r
- * macro (defined in toaster.h). During the compilation, WPP scans the source\r
- * files for DoTraceMessage() calls and builds a .tmh file which stores a unique\r
- * data GUID for each message, the text resource string for each message,\r
- * and the data types of the variables passed in for each message.  This file\r
- * is automatically generated and used during post-processing.\r
- */\r
-\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "busenum.tmh"\r
-\r
-ULONG DebugLevel = TRACE_LEVEL_INFORMATION;\r
-ULONG DebugFlag = 0x2f;//0x46;//0x4FF; //0x00000006;\r
-\r
-#else\r
-\r
-ULONG DebugLevel = ~0UL; // Initial DEBUG level for bringup.\r
-ULONG DebugFlag = ~0UL;\r
-\r
-#endif /* EVENT_TRACING */\r
-\r
-char   node_desc[IB_NODE_DESCRIPTION_SIZE];\r
-\r
-bus_globals_t  bus_globals = {\r
-       ~0U/*BUS_DBG_ERROR*/,\r
-       TRUE,\r
-       NULL,\r
-       NULL\r
-};\r
-\r
-int g_smi_poll_interval;\r
-int g_ioc_poll_interval;\r
-int g_ioc_query_retries;\r
-int g_ioc_query_timeout;\r
-\r
-DRIVER_INITIALIZE      DriverEntry;\r
-\r
-static VOID Bus_EvtDriverUnload( IN WDFDRIVER  Driver );\r
-\r
-static void\r
-__read_machine_name( void );\r
-\r
-static NTSTATUS\r
-__read_registry(\r
-       IN                              UNICODE_STRING* const           p_Param_Path );\r
-\r
-static NTSTATUS\r
-bus_drv_open(\r
-       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
-       IN                              IRP                                                     *p_irp );\r
-\r
-static NTSTATUS\r
-bus_drv_cleanup(\r
-       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
-       IN                              IRP                                                     *p_irp );\r
-\r
-static NTSTATUS\r
-bus_drv_close(\r
-       IN                              DEVICE_OBJECT                           *p_dev_obj,\r
-       IN                              IRP                                                     *p_irp );\r
-\r
-\r
-#ifdef ALLOC_PRAGMA\r
-#pragma alloc_text (INIT, DriverEntry)\r
-#pragma alloc_text (INIT, __read_machine_name)\r
-#pragma alloc_text (INIT, __read_registry)\r
-#pragma alloc_text (PAGE, Bus_EvtDeviceAdd)\r
-#pragma alloc_text (PAGE, Bus_EvtIoDeviceControl)\r
-#pragma alloc_text (PAGE, Bus_PlugInDevice)\r
-#pragma alloc_text (PAGE, Bus_UnPlugDevice)\r
-#pragma alloc_text (PAGE, Bus_EjectDevice)\r
-#pragma alloc_text (PAGE, Bus_EvtDriverUnload)\r
-#endif\r
-\r
-/*++\r
-Routine Description:\r
-\r
-    Initialize the call backs structure of Driver Framework.\r
-\r
-Arguments:\r
-\r
-    DriverObject - pointer to the driver object\r
-\r
-    RegistryPath - pointer to a unicode string representing the path,\r
-                   to driver-specific key in the registry.\r
-\r
-Return Value:\r
-\r
-  NT Status Code\r
-\r
---*/\r
-NTSTATUS\r
-DriverEntry(\r
-    IN PDRIVER_OBJECT DriverObject,\r
-    IN PUNICODE_STRING RegistryPath )\r
-{\r
-    WDF_DRIVER_CONFIG   config;\r
-    NTSTATUS            status;\r
-    WDFDRIVER                  driver;\r
-\r
-    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "--> %s()\n", __FUNCTION__);\r
-\r
-    KdPrint(("WDF InfiniBand Fabric Dynamic Bus Enumerator.\n"));\r
-    KdPrint(("Built %s %s\n", __DATE__, __TIME__));\r
-\r
-#if defined(EVENT_TRACING)\r
-       WPP_INIT_TRACING(DriverObject ,RegistryPath);\r
-#endif\r
-\r
-       status = CL_INIT;\r
-       if( !NT_SUCCESS(status) )\r
-       {\r
-               BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
-                       ("cl_init returned %08X.\n", status) );\r
-               return status;\r
-       }\r
-\r
-       /* Store the driver object pointer in the global parameters. */\r
-       bus_globals.p_driver_obj = DriverObject;\r
-\r
-       /* Get the registry values. */\r
-       status = __read_registry( RegistryPath );\r
-       if( !NT_SUCCESS(status) )\r
-       {\r
-               CL_DEINIT;\r
-               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
-                       ("__read_registry returned %08x.\n", status) );\r
-               return status;\r
-       }\r
-    //\r
-    // Initiialize driver config to control the attributes that\r
-    // are global to the driver. Note that framework by default\r
-    // provides a driver unload routine. If you create any resources\r
-    // in the DriverEntry and want to be cleaned in driver unload,\r
-    // you can override that by specifing one in the Config structure.\r
-    //\r
-    WDF_DRIVER_CONFIG_INIT( &config, Bus_EvtDeviceAdd );\r
-\r
-       config.EvtDriverUnload = Bus_EvtDriverUnload;\r
-\r
-    // Create a framework driver object to represent our driver.\r
-    status = WdfDriverCreate(DriverObject,\r
-                             RegistryPath,\r
-                             WDF_NO_OBJECT_ATTRIBUTES,\r
-                             &config,\r
-                             &driver);\r
-\r
-    if (!NT_SUCCESS(status)) {\r
-        KdPrint( ("WdfDriverCreate failed with status 0x%x\n", status));\r
-    }\r
-\r
-    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,\r
-                               "<-- %s() ret %x\n", __FUNCTION__, status);\r
-    return status;\r
-}\r
-\r
-\r
-static void\r
-__read_machine_name( void )\r
-{\r
-       NTSTATUS                                        status;\r
-       /* Remember the terminating entry in the table below. */\r
-       RTL_QUERY_REGISTRY_TABLE        table[2];\r
-       UNICODE_STRING                          hostNamePath;\r
-       UNICODE_STRING                          hostNameW;\r
-       ANSI_STRING                                     hostName;\r
-\r
-       BUS_ENTER( BUS_DBG_DRV );\r
-\r
-       /* Get the host name. */\r
-       RtlInitUnicodeString( &hostNamePath, L"ComputerName\\ComputerName" );\r
-       RtlInitUnicodeString( &hostNameW, NULL );\r
-\r
-       /*\r
-        * Clear the table.  This clears all the query callback pointers,\r
-        * and sets up the terminating table entry.\r
-        */\r
-       cl_memclr( table, sizeof(table) );\r
-       cl_memclr( node_desc, sizeof(node_desc) );\r
-\r
-       /* Setup the table entries. */\r
-       table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;\r
-       table[0].Name = L"ComputerName";\r
-       table[0].EntryContext = &hostNameW;\r
-       table[0].DefaultType = REG_SZ;\r
-       table[0].DefaultData = &hostNameW;\r
-       table[0].DefaultLength = 0;\r
-\r
-       /* Have at it! */\r
-       status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL, \r
-               hostNamePath.Buffer, table, NULL, NULL );\r
-       if( NT_SUCCESS( status ) )\r
-       {\r
-               /* Convert the UNICODE host name to UTF-8 (ASCII). */\r
-               hostName.Length = 0;\r
-               hostName.MaximumLength = sizeof(node_desc);\r
-               hostName.Buffer = node_desc;\r
-               status = RtlUnicodeStringToAnsiString( &hostName, &hostNameW, FALSE );\r
-               RtlFreeUnicodeString( &hostNameW );\r
-       }\r
-       else\r
-       {\r
-               BUS_TRACE(BUS_DBG_ERROR , ("Failed to get host name.\n") );\r
-               /* Use the default name... */\r
-               RtlStringCbCopyNA( node_desc, sizeof(node_desc),\r
-                       DEFAULT_NODE_DESC, sizeof(DEFAULT_NODE_DESC) );\r
-       }\r
-\r
-       BUS_ENTER( BUS_DBG_DRV );\r
-}\r
-\r
-\r
-static NTSTATUS\r
-__read_registry(\r
-       IN                              UNICODE_STRING* const           p_registry_path )\r
-{\r
-       NTSTATUS                                        status;\r
-       /* Remember the terminating entry in the table below. */\r
-       RTL_QUERY_REGISTRY_TABLE        table[9];\r
-       UNICODE_STRING                          param_path;\r
-\r
-       BUS_ENTER( BUS_DBG_DRV );\r
-\r
-       __read_machine_name();\r
-\r
-       RtlInitUnicodeString( &param_path, NULL );\r
-       param_path.MaximumLength = p_registry_path->Length + \r
-               sizeof(L"\\Parameters");\r
-       param_path.Buffer = cl_zalloc( param_path.MaximumLength );\r
-       if( !param_path.Buffer )\r
-       {\r
-               BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
-                       ("Failed to allocate parameters path buffer.\n") );\r
-               return STATUS_INSUFFICIENT_RESOURCES;\r
-       }\r
-\r
-       RtlAppendUnicodeStringToString( &param_path, p_registry_path );\r
-       RtlAppendUnicodeToString( &param_path, L"\\Parameters" );\r
-\r
-       /*\r
-        * Clear the table.  This clears all the query callback pointers,\r
-        * and sets up the terminating table entry.\r
-        */\r
-       cl_memclr( table, sizeof(table) );\r
-\r
-       /* Setup the table entries. */\r
-       table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
-       table[0].Name = L"ReportPortNIC";\r
-       table[0].EntryContext = &bus_globals.b_report_port_nic;\r
-       table[0].DefaultType = REG_DWORD;\r
-       table[0].DefaultData = &bus_globals.b_report_port_nic;\r
-       table[0].DefaultLength = sizeof(ULONG);\r
-\r
-       table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
-       table[1].Name = L"DebugFlags";\r
-       table[1].EntryContext = &bus_globals.dbg_lvl;\r
-       table[1].DefaultType = REG_DWORD;\r
-       table[1].DefaultData = &bus_globals.dbg_lvl;\r
-       table[1].DefaultLength = sizeof(ULONG);\r
-\r
-       table[2].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
-       table[2].Name = L"IbalDebugLevel";\r
-       table[2].EntryContext = &g_al_dbg_level;\r
-       table[2].DefaultType = REG_DWORD;\r
-       table[2].DefaultData = &g_al_dbg_level;\r
-       table[2].DefaultLength = sizeof(ULONG);\r
-\r
-       table[3].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
-       table[3].Name = L"IbalDebugFlags";\r
-       table[3].EntryContext = &g_al_dbg_flags;\r
-       table[3].DefaultType = REG_DWORD;\r
-       table[3].DefaultData = &g_al_dbg_flags;\r
-       table[3].DefaultLength = sizeof(ULONG);\r
-       \r
-\r
-       table[4].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
-       table[4].Name = L"SmiPollInterval";\r
-       table[4].EntryContext = &g_smi_poll_interval;\r
-       table[4].DefaultType = REG_DWORD;\r
-       table[4].DefaultData = &g_smi_poll_interval;\r
-       table[4].DefaultLength = sizeof(ULONG);\r
-\r
-       table[5].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
-       table[5].Name = L"IocQueryTimeout";\r
-       table[5].EntryContext = &g_ioc_query_timeout;\r
-       table[5].DefaultType = REG_DWORD;\r
-       table[5].DefaultData = &g_ioc_query_timeout;\r
-       table[5].DefaultLength = sizeof(ULONG);\r
-\r
-       table[6].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
-       table[6].Name = L"IocQueryRetries";\r
-       table[6].EntryContext = &g_ioc_query_retries;\r
-       table[6].DefaultType = REG_DWORD;\r
-       table[6].DefaultData = &g_ioc_query_retries;\r
-       table[6].DefaultLength = sizeof(ULONG);\r
-\r
-       table[7].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
-       table[7].Name = L"IocPollInterval";\r
-       table[7].EntryContext = &g_ioc_poll_interval;\r
-       table[7].DefaultType = REG_DWORD;\r
-       table[7].DefaultData = &g_ioc_poll_interval;\r
-       table[7].DefaultLength = sizeof(ULONG);\r
-\r
-       /* Have at it! */\r
-       status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
-               param_path.Buffer, table, NULL, NULL );\r
-\r
-#if DBG\r
-       if( g_al_dbg_flags & AL_DBG_ERR )\r
-               g_al_dbg_flags |= CL_DBG_ERROR;\r
-#endif\r
-\r
-       BUS_TRACE(BUS_DBG_DRV ,\r
-                       ("debug level %d debug flags 0x%.8x\n",\r
-                       g_al_dbg_level,\r
-                       g_al_dbg_flags));\r
-\r
-       cl_free( param_path.Buffer );\r
-       BUS_EXIT( BUS_DBG_DRV );\r
-       return status;\r
-}\r
-\r
-\r
-/*++\r
-Routine Description:\r
-\r
-    Bus_EvtDeviceAdd is called by the framework in response to AddDevice\r
-    call from the PnP manager. We create and initialize a device object to\r
-    represent a new instance of InfiniBand Fabric device (I/O Unit, e.g., vnic\r
-       or SRP iou, etc.).\r
-\r
-Arguments:\r
-\r
-    Driver - Handle to a framework driver object created in DriverEntry\r
-\r
-    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.\r
-\r
-Return Value:\r
-\r
-    NTSTATUS\r
-\r
---*/\r
-\r
-NTSTATUS\r
-Bus_EvtDeviceAdd( IN  WDFDRIVER                        Driver,\r
-                                 IN  PWDFDEVICE_INIT   DeviceInit )\r
-{\r
-    WDF_CHILD_LIST_CONFIG      config;\r
-    WDF_OBJECT_ATTRIBUTES      fdoAttributes;\r
-    NTSTATUS                   status;\r
-    WDFDEVICE                  device;\r
-    WDF_IO_QUEUE_CONFIG        queueConfig;\r
-    PNP_BUS_INFORMATION        busInfo;\r
-    PFDO_DEVICE_DATA           deviceData;\r
-    WDFQUEUE                   queue;\r
-\r
-    WDF_PNPPOWER_EVENT_CALLBACKS     pnpPowerCallbacks;\r
-    WDF_POWER_POLICY_EVENT_CALLBACKS powerPolicyCallbacks;\r
-\r
-    UNREFERENCED_PARAMETER(Driver);\r
-\r
-    PAGED_CODE ();\r
-\r
-    KdPrint(("Bus_EvtDeviceAdd: 0x%p\n", Driver));\r
-\r
-    // Initialize all the properties specific to the device.\r
-    // Framework has default values for the one that are not\r
-    // set explicitly here. So please read the doc and make sure\r
-    // you are okay with the defaults.\r
-\r
-    WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);\r
-    WdfDeviceInitSetExclusive(DeviceInit, TRUE);\r
-\r
-    // This is an InifiniBand bus enumerator, we need to register for those\r
-    // PNP/Power callbacks of interest.  Framework will take the default action\r
-       // for all the PNP and Power IRPs which are not registered here.\r
-\r
-// XXX consider surprise_remove, etc.\r
-\r
-    // Initialize the PnpPowerCallbacks structure.\r
-    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);\r
-\r
-    // Set Callbacks for any of the functions we are interested in.\r
-    // If no callback is set, Framework will take the default action\r
-    // by itself.  This sample provides many of the possible callbacks,\r
-    // mostly because it's a fairly complex sample that drives full-featured\r
-    // hardware.  Drivers derived from this sample will often be able to\r
-    // provide only some of these.\r
-\r
-    // This next group of five callbacks allow a driver to become involved in\r
-    // starting and stopping operations within a driver as the driver moves\r
-    // through various PnP/Power states.  These functions are not necessary\r
-    // if the Framework is managing all the device's queues and there is no\r
-    // activity going on that isn't queue-based.\r
-#if 0\r
-    pnpPowerCallbacks.EvtDeviceSelfManagedIoInit =\r
-                                                                                       PciDrvEvtDeviceSelfManagedIoInit;\r
-    pnpPowerCallbacks.EvtDeviceSelfManagedIoCleanup =\r
-                                                                                       PciDrvEvtDeviceSelfManagedIoCleanup;\r
-    pnpPowerCallbacks.EvtDeviceSelfManagedIoSuspend =\r
-                                                                                       PciDrvEvtDeviceSelfManagedIoSuspend;\r
-    pnpPowerCallbacks.EvtDeviceSelfManagedIoRestart =\r
-                                                                                       PciDrvEvtDeviceSelfManagedIoRestart;\r
-\r
-    // Register the PnP and power callbacks. Power policy related callbacks will\r
-       // be registered later.\r
-\r
-    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);\r
-#endif\r
-\r
-    // Init the power policy callbacks\r
-\r
-    WDF_POWER_POLICY_EVENT_CALLBACKS_INIT(&powerPolicyCallbacks);\r
-\r
-       // no power issues at this level - device specific driver handles power \r
-\r
-    // WDF_ DEVICE_LIST_CONFIG describes how the framework should handle\r
-    // dynamic child enumeration on behalf of the driver writer.\r
-    // Since we are a bus driver, we need to specify identification description\r
-    // for our child devices. This description will serve as the identity of our\r
-    // child device. Since the description is opaque to the framework, we\r
-    // have to provide bunch of callbacks to compare, copy, or free\r
-    // any other resources associated with the description.\r
-\r
-    WDF_CHILD_LIST_CONFIG_INIT( &config,\r
-                                sizeof(PDO_IDENTIFICATION_DESCRIPTION),\r
-                                Bus_EvtDeviceListCreatePdo );\r
-                                                                // callback to create a child device.\r
-\r
-    // This function pointer will be called when the framework needs to copy a\r
-    // identification description from one location to another.\r
-       // An implementation of this function is only necessary if the description\r
-       // contains description relative pointer values (like  LIST_ENTRY for\r
-       // instance).\r
-    // If set to NULL, the framework will use RtlCopyMemory to copy an\r
-       // identification description. In this sample, it's not required to provide\r
-       // these callbacks they are added just for illustration.\r
-    //\r
-    config.EvtChildListIdentificationDescriptionDuplicate =\r
-                                                       Bus_EvtChildListIdentificationDescriptionDuplicate;\r
-\r
-    //\r
-    // This function pointer will be called when the framework needs to compare\r
-    // two identificaiton descriptions.  If left NULL a call to RtlCompareMemory\r
-    // will be used to compare two identificaiton descriptions.\r
-    //\r
-    config.EvtChildListIdentificationDescriptionCompare =\r
-                            Bus_EvtChildListIdentificationDescriptionCompare;\r
-    //\r
-    // This function pointer will be called when the framework needs to free a\r
-    // identification description.  An implementation of this function is only\r
-    // necessary if the description contains dynamically allocated memory\r
-    // (by the driver writer) that needs to be freed. The actual identification\r
-    // description pointer itself will be freed by the framework.\r
-    //\r
-    config.EvtChildListIdentificationDescriptionCleanup =\r
-                            Bus_EvtChildListIdentificationDescriptionCleanup;\r
-\r
-    //\r
-    // Tell the framework to use the built-in childlist to track the state\r
-    // of the device based on the configuration we just created.\r
-    //\r
-    WdfFdoInitSetDefaultChildListConfig(DeviceInit,\r
-                                         &config,\r
-                                         WDF_NO_OBJECT_ATTRIBUTES);\r
-\r
-    // Initialize attributes structure to specify size and accessor function\r
-    // for storing device context.\r
-\r
-    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DEVICE_DATA);\r
-\r
-    // Create a framework device object. In response to this call, framework\r
-    // creates a WDM deviceobject and attaches to the PDO.\r
-\r
-    status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device);\r
-\r
-    if (!NT_SUCCESS(status)) {\r
-        KdPrint(("Error creating WdfDeviceCreate 0x%x, line#%d\n",\r
-                                       status,__LINE__));\r
-        return status;\r
-    }\r
-\r
-    // Configure a default queue so that requests that are not\r
-    // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto\r
-    // other queues get dispatched here.\r
-\r
-    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &queueConfig,\r
-                                                                                       WdfIoQueueDispatchParallel );\r
-\r
-    queueConfig.EvtIoDeviceControl = Bus_EvtIoDeviceControl;\r
-\r
-    status = WdfIoQueueCreate( device,\r
-                               &queueConfig,\r
-                               WDF_NO_OBJECT_ATTRIBUTES,\r
-                               &queue );\r
-\r
-    if (!NT_SUCCESS(status)) {\r
-        KdPrint(("WdfIoQueueCreate failed status 0x%x\n", status));\r
-        return status;\r
-    }\r
-\r
-    // Get the device context.\r
-\r
-    deviceData = FdoGetData(device);\r
-       deviceData->WdfDevice = device; // record framework device object ptr.\r
-\r
-    //\r
-    // Create device interface for this device. The interface will be\r
-    // enabled by the framework when we return from StartDevice successfully.\r
-    // Clients of this driver will open this interface and send ioctls.\r
-    //\r
-    status = WdfDeviceCreateDeviceInterface( device,\r
-                                                                                        &GUID_DEVINTERFACE_BUSENUM_IBF,\r
-                                                                                        NULL );\r
-               // NULL == No Reference String. If you provide one it will appended to\r
-               // the symbolic link. Some drivers register multiple interfaces for the\r
-               // same device and use the reference string to distinguish between them\r
-\r
-    if (!NT_SUCCESS(status)) {\r
-        return status;\r
-    }\r
-\r
-    //\r
-    // This value is used in responding to the IRP_MN_QUERY_BUS_INFORMATION\r
-    // for the child devices. This is an optional information provided to\r
-    // uniquely idenitfy the bus the device is connected.\r
-    //\r
-    busInfo.BusTypeGuid = GUID_DEVCLASS_IB_FABRIC;\r
-    busInfo.LegacyBusType = PNPBus;\r
-    busInfo.BusNumber = 0; // XXX correct?\r
-\r
-    WdfDeviceSetBusInformationForChildren(device, &busInfo);\r
-\r
-    status = Bus_WmiRegistration(device);\r
-    if (!NT_SUCCESS(status)) {\r
-        return status;\r
-    }\r
-\r
-    return status;\r
-}\r
-\r
-\r
-/*++\r
-Routine Description:\r
-\r
-  Handle user mode PlugIn, UnPlug and device Eject requests.\r
-\r
-Arguments:\r
-\r
-    Queue - Handle to the framework queue object that is associated\r
-            with the I/O request.\r
-\r
-    Request - Handle to a framework request object. This one represents\r
-              the IRP_MJ_DEVICE_CONTROL IRP received by the framework.\r
-\r
-    OutputBufferLength - Length, in bytes, of the request's output buffer,\r
-                        if an output buffer is available.\r
-\r
-    InputBufferLength - Length, in bytes, of the request's input buffer,\r
-                        if an input buffer is available.\r
-    IoControlCode - Driver-defined or system-defined I/O control code (IOCTL)\r
-                    that is associated with the request.\r
-\r
-Return Value:\r
-\r
-   VOID\r
-\r
---*/\r
-\r
-VOID\r
-Bus_EvtIoDeviceControl(\r
-    IN WDFQUEUE     Queue,\r
-    IN WDFREQUEST   Request,\r
-    IN size_t       OutputBufferLength,\r
-    IN size_t       InputBufferLength,\r
-    IN ULONG        IoControlCode\r
-    )\r
-{\r
-    NTSTATUS                 status = STATUS_INVALID_PARAMETER;\r
-    WDFDEVICE                hDevice;\r
-    size_t                   length = 0;\r
-    PBUSENUM_PLUGIN_HARDWARE plugIn = NULL;\r
-    PBUSENUM_UNPLUG_HARDWARE unPlug = NULL;\r
-    PBUSENUM_EJECT_HARDWARE  eject  = NULL;\r
-\r
-\r
-    UNREFERENCED_PARAMETER(OutputBufferLength);\r
-\r
-    PAGED_CODE ();\r
-\r
-    hDevice = WdfIoQueueGetDevice(Queue);\r
-\r
-    KdPrint(("Bus_EvtIoDeviceControl: 0x%p\n", hDevice));\r
-\r
-    switch (IoControlCode) {\r
-    case IOCTL_BUSENUM_PLUGIN_HARDWARE:\r
-\r
-        status = WdfRequestRetrieveInputBuffer (Request,\r
-                                    sizeof (BUSENUM_PLUGIN_HARDWARE) +\r
-                                    (sizeof(UNICODE_NULL) * 2),\r
-                                                                        // 2 for double NULL termination (MULTI_SZ)\r
-                                    &plugIn, &length);\r
-        if( !NT_SUCCESS(status) ) {\r
-            KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status));\r
-            break;\r
-        }\r
-\r
-        ASSERT(length == InputBufferLength);\r
-\r
-        if (sizeof (BUSENUM_PLUGIN_HARDWARE) == plugIn->Size)\r
-        {\r
-\r
-            length = (InputBufferLength - sizeof (BUSENUM_PLUGIN_HARDWARE))\r
-                                               / sizeof(WCHAR);\r
-            //\r
-            // Make sure the IDs is two NULL terminated.\r
-            //\r
-            if ((UNICODE_NULL != plugIn->HardwareIDs[length - 1]) ||\r
-                (UNICODE_NULL != plugIn->HardwareIDs[length - 2])) {\r
-\r
-                status = STATUS_INVALID_PARAMETER;\r
-                break;\r
-            }\r
-\r
-            status = Bus_PlugInDevice( hDevice,\r
-                                       plugIn->HardwareIDs,\r
-                                       length,\r
-                                       plugIn->SerialNo );\r
-        }\r
-\r
-        break;\r
-\r
-    case IOCTL_BUSENUM_UNPLUG_HARDWARE:\r
-\r
-        status = WdfRequestRetrieveInputBuffer( Request,\r
-                                                sizeof(BUSENUM_UNPLUG_HARDWARE),\r
-                                                &unPlug,\r
-                                                &length );\r
-        if( !NT_SUCCESS(status) ) {\r
-            KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status));\r
-            break;\r
-        }\r
-\r
-        if (unPlug->Size == InputBufferLength)\r
-        {\r
-\r
-            status= Bus_UnPlugDevice(hDevice, unPlug->SerialNo );\r
-\r
-        }\r
-\r
-        break;\r
-\r
-    case IOCTL_BUSENUM_EJECT_HARDWARE:\r
-\r
-        status = WdfRequestRetrieveInputBuffer (Request,\r
-                                                sizeof (BUSENUM_EJECT_HARDWARE),\r
-                                                &eject, &length);\r
-        if( !NT_SUCCESS(status) ) {\r
-            KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status));\r
-            break;\r
-        }\r
-\r
-        if (eject->Size == InputBufferLength)\r
-        {\r
-            status= Bus_EjectDevice(hDevice, eject->SerialNo);\r
-\r
-        }\r
-\r
-        break;\r
-\r
-    default:\r
-        break; // default status is STATUS_INVALID_PARAMETER\r
-    }\r
-\r
-    WdfRequestCompleteWithInformation(Request, status, length);\r
-}\r
-\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
-    The user application has told us that a new device on the bus has arrived.\r
-    We therefore create a description structure in stack, fill in information\r
-       about the child device and call\r
-               WdfChildListAddOrUpdateChildDescriptionAsPresent()\r
-    to add the device.\r
-\r
---*/\r
-\r
-NTSTATUS\r
-Bus_PlugInDevice(\r
-    __in WDFDEVICE       Device,\r
-    __in PWCHAR          HardwareIds,\r
-    __in size_t          CchHardwareIds,\r
-    __in ULONG           SerialNo )\r
-{\r
-    PDO_IDENTIFICATION_DESCRIPTION description;\r
-    NTSTATUS         status;\r
-\r
-    PAGED_CODE ();\r
-\r
-    //\r
-    // Initialize the description with the information about the newly\r
-    // plugged in device.\r
-    //\r
-    WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(\r
-        &description.Header,\r
-        sizeof(description)\r
-        );\r
-\r
-    description.SerialNo = SerialNo;\r
-    description.CchHardwareIds = CchHardwareIds;\r
-    description.HardwareIds = HardwareIds;\r
-\r
-    //\r
-    // Call the framework to add this child to the childlist. This call\r
-    // will internaly call our DescriptionCompare callback to check\r
-    // whether this device is a new device or existing device. If\r
-    // it's a new device, the framework will call DescriptionDuplicate to create\r
-    // a copy of this description in nonpaged pool.\r
-    // The actual creation of the child device will happen when the framework\r
-    // receives QUERY_DEVICE_RELATION request from the PNP manager in\r
-    // response to InvalidateDeviceRelations call made as part of adding\r
-    // a new child.\r
-    //\r
-    status = WdfChildListAddOrUpdateChildDescriptionAsPresent(\r
-                    WdfFdoGetDefaultChildList(Device), &description.Header,\r
-                    NULL); // AddressDescription\r
-\r
-    if (status == STATUS_OBJECT_NAME_EXISTS) {\r
-        //\r
-        // The description is already present in the list, the serial number is\r
-        // not unique, return error.\r
-        //\r
-        status = STATUS_INVALID_PARAMETER;\r
-    }\r
-\r
-    return status;\r
-}\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
-    The application has told us a device has departed from the bus.\r
-\r
-    We therefore need to flag the PDO as no longer present.\r
-\r
-Arguments:\r
-\r
-\r
-Returns:\r
-\r
-    STATUS_SUCCESS upon successful removal from the list\r
-    STATUS_INVALID_PARAMETER if the removal was unsuccessful\r
-\r
---*/\r
-\r
-NTSTATUS\r
-Bus_UnPlugDevice(\r
-    WDFDEVICE   Device,\r
-    ULONG       SerialNo )\r
-{\r
-    NTSTATUS       status;\r
-    WDFCHILDLIST   list;\r
-\r
-    PAGED_CODE ();\r
-\r
-    list = WdfFdoGetDefaultChildList(Device);\r
-\r
-    if (0 == SerialNo) {\r
-        //\r
-        // Unplug everybody: do this by starting a scan and then not reporting\r
-        // any children upon its completion\r
-        //\r
-        status = STATUS_SUCCESS;\r
-\r
-        WdfChildListBeginScan(list);\r
-\r
-        // A call to WdfChildListBeginScan indicates to the framework that the\r
-        // driver is about to scan for dynamic children. After this call has\r
-        // returned, all previously reported children associated with this will\r
-               // be marked as potentially missing.  A call to either\r
-        // WdfChildListUpdateChildDescriptionAsPresent  or\r
-        // WdfChildListMarkAllChildDescriptionsPresent will mark all previuosly\r
-        // reported missing children as present.  If any children currently\r
-        // present are not reported present by calling\r
-        // WdfChildListUpdateChildDescriptionAsPresent at the time of\r
-        // WdfChildListEndScan, they will be reported as missing to the PnP\r
-               // subsystem After WdfChildListEndScan call has returned, the framework\r
-               // will invalidate the device relations for the FDO associated with the\r
-               // list and report the changes\r
-        //\r
-        WdfChildListEndScan(list);\r
-    }\r
-    else {\r
-        PDO_IDENTIFICATION_DESCRIPTION description;\r
-\r
-        WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(\r
-            &description.Header,\r
-            sizeof(description)\r
-            );\r
-\r
-        description.SerialNo = SerialNo;\r
-\r
-        // WdfFdoUpdateChildDescriptionAsMissing indicates to the framework\r
-               // that a child device that was previuosly detected is no longer present\r
-               // on the bus.\r
-        // This API can be called by itself or after a call to\r
-               //   WdfChildListBeginScan().\r
-        // After this call has returned, the framework will invalidate the\r
-               // device relations for the FDO associated with the list and report the\r
-               // changes.\r
-\r
-        status = WdfChildListUpdateChildDescriptionAsMissing(\r
-                                                                               list,\r
-                                        &description.Header );\r
-        if (status == STATUS_NO_SUCH_DEVICE) {\r
-            // serial number didn't exist. Remap it to a status that user\r
-            // application can understand when it gets translated to win32\r
-            // error code.\r
-            status = STATUS_INVALID_PARAMETER;\r
-        }\r
-    }\r
-    return status;\r
-}\r
-\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
-    The user application has told us to eject the device from the bus.\r
-    In a real situation the driver gets notified by an interrupt when the\r
-    user presses the Eject button on the device.\r
-\r
-Arguments:\r
-\r
-\r
-Returns:\r
-\r
-    STATUS_SUCCESS upon successful removal from the list\r
-    STATUS_INVALID_PARAMETER if the ejection was unsuccessful\r
-\r
---*/\r
-\r
-NTSTATUS\r
-Bus_EjectDevice( WDFDEVICE Device, ULONG SerialNo )\r
-{\r
-    WDFDEVICE        hChild;\r
-    NTSTATUS         status = STATUS_INVALID_PARAMETER;\r
-    WDFCHILDLIST     list;\r
-\r
-    PAGED_CODE ();\r
-\r
-    list = WdfFdoGetDefaultChildList(Device);\r
-\r
-    //\r
-    // A zero serial number means eject all children\r
-    //\r
-    if (0 == SerialNo) {\r
-        WDF_CHILD_LIST_ITERATOR     iterator;\r
-\r
-        WDF_CHILD_LIST_ITERATOR_INIT( &iterator,\r
-                                      WdfRetrievePresentChildren );\r
-\r
-        WdfChildListBeginIteration(list, &iterator);\r
-\r
-        for ( ; ; ) {\r
-            WDF_CHILD_RETRIEVE_INFO         childInfo;\r
-            PDO_IDENTIFICATION_DESCRIPTION  description;\r
-            BOOLEAN                         ret;\r
-\r
-            //\r
-            // Init the structures.\r
-            //\r
-            WDF_CHILD_RETRIEVE_INFO_INIT(&childInfo, &description.Header);\r
-\r
-            WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(\r
-                                    &description.Header,\r
-                                    sizeof(description)\r
-                                    );\r
-            //\r
-            // Get the device identification description\r
-            //\r
-            status = WdfChildListRetrieveNextDevice(list,\r
-                                                &iterator,\r
-                                                &hChild,\r
-                                                &childInfo);\r
-\r
-            if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES) {\r
-                break;\r
-            }\r
-\r
-            ASSERT(childInfo.Status == WdfChildListRetrieveDeviceSuccess);\r
-\r
-            //\r
-            // Use that description to request an eject.\r
-            //\r
-            ret = WdfChildListRequestChildEject(list, &description.Header);\r
-            if(!ret) {\r
-                WDFVERIFY(ret);\r
-            }\r
-\r
-        }\r
-\r
-        WdfChildListEndIteration(list, &iterator);\r
-\r
-        if (status == STATUS_NO_MORE_ENTRIES) {\r
-            status = STATUS_SUCCESS;\r
-        }\r
-\r
-    }\r
-    else {\r
-\r
-        PDO_IDENTIFICATION_DESCRIPTION description;\r
-\r
-        WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(\r
-            &description.Header,\r
-            sizeof(description)\r
-            );\r
-\r
-        description.SerialNo = SerialNo;\r
-\r
-        if (WdfChildListRequestChildEject(list, &description.Header)) {\r
-            status = STATUS_SUCCESS;\r
-        }\r
-    }\r
-    return status;\r
-}\r
-\r
-\r
-/*++\r
-Routine Description:\r
-\r
-    This routine is used to queue workitems so that the callback\r
-    functions can be executed at PASSIVE_LEVEL in the conext of\r
-    a system thread.\r
-\r
-Arguments:\r
-\r
-   FdoData - pointer to a device extenion.\r
-\r
-   CallbackFunction - Function to invoke when at PASSIVE_LEVEL.\r
-\r
-   Context1 & 2 - Meaning of the context values depends on the\r
-                  callback function.\r
-\r
-Return Value:\r
-\r
---*/\r
-\r
-NTSTATUS\r
-DrvQueuePassiveLevelCallback(\r
-    IN PFDO_DEVICE_DATA FdoData,\r
-    IN PFN_WDF_WORKITEM CallbackFunction,\r
-    IN PVOID            Context1,\r
-    IN PVOID            Context2 )\r
-{\r
-    NTSTATUS                status = STATUS_SUCCESS;\r
-    PWORKER_ITEM_CONTEXT    context;\r
-    WDF_OBJECT_ATTRIBUTES   attributes;\r
-    WDF_WORKITEM_CONFIG     workitemConfig;\r
-    WDFWORKITEM             hWorkItem;\r
-\r
-    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, WORKER_ITEM_CONTEXT);\r
-\r
-    attributes.ParentObject = FdoData->WdfDevice;\r
-\r
-    WDF_WORKITEM_CONFIG_INIT(&workitemConfig, CallbackFunction);\r
-\r
-    status = WdfWorkItemCreate( &workitemConfig,\r
-                                &attributes,\r
-                                &hWorkItem);\r
-\r
-    if (!NT_SUCCESS(status)) {\r
-        return status;\r
-    }\r
-\r
-    context = GetWorkItemContext(hWorkItem);\r
-\r
-    context->FdoData = FdoData;\r
-    context->Argument1 = Context1;\r
-    context->Argument2 = Context2;\r
-\r
-    //\r
-    // Execute this work item.\r
-    //\r
-    WdfWorkItemEnqueue(hWorkItem);\r
-\r
-    return STATUS_SUCCESS;\r
-}\r
-\r
-/*++\r
-Routine Description:\r
-\r
-    This routine is called when the IB Bus driver is unloaded.\r
-\r
-Arguments:\r
-\r
-   Driver - pointer to a KMDF Driver object\r
-\r
-\r
-Return Value:\r
-\r
---*/\r
-static VOID\r
-Bus_EvtDriverUnload( IN WDFDRIVER  Driver )\r
-{\r
-       BUS_ENTER( BUS_DBG_DRV );\r
-\r
-       CL_DEINIT;\r
-\r
-#if defined(EVENT_TRACING)\r
-       WPP_CLEANUP( WdfDriverWdmGetDriverObject(Driver) );\r
-#else\r
-    UNREFERENCED_PARAMETER(Driver);\r
-#endif\r
-\r
-       BUS_EXIT( BUS_DBG_DRV );        \r
-       return;\r
-}\r
-\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
-    Debug print for the sample driver.\r
-\r
-Arguments:\r
-\r
-    TraceEventsLevel - print level between 0 and 3, with 3 the most verbose\r
-\r
-Return Value:\r
-\r
-    None.\r
-\r
- --*/\r
-\r
-#if !defined(EVENT_TRACING)\r
-\r
-VOID\r
-TraceEvents    (\r
-    IN ULONG   TraceEventsLevel,\r
-    IN ULONG   TraceEventsFlag,\r
-    IN PCCHAR  DebugMessage,\r
-    ...  )\r
- {\r
-#if 1 // always for starters DBG\r
-#define     TEMP_BUFFER_SIZE        512\r
-    va_list    list;\r
-    CHAR       debugMessageBuffer[TEMP_BUFFER_SIZE];\r
-    NTSTATUS   status;\r
-\r
-    va_start(list, DebugMessage);\r
-\r
-    if (DebugMessage) {\r
-\r
-        //\r
-        // Using new safe string functions instead of _vsnprintf.\r
-        // This function takes care of NULL terminating if the message\r
-        // is longer than the buffer.\r
-        //\r
-        status = RtlStringCbVPrintfA( debugMessageBuffer,\r
-                                      sizeof(debugMessageBuffer),\r
-                                      DebugMessage,\r
-                                      list );\r
-        if(!NT_SUCCESS(status)) {\r
-\r
-            DbgPrint (_DRIVER_NAME_": RtlStringCbVPrintfA failed %x\n",\r
-                      status);\r
-            return;\r
-        }\r
-        if (TraceEventsLevel <= TRACE_LEVEL_INFORMATION ||\r
-            (TraceEventsLevel <= DebugLevel &&\r
-             ((TraceEventsFlag & DebugFlag) == TraceEventsFlag))) {\r
-            DbgPrint(debugMessageBuffer);\r
-        }\r
-    }\r
-    va_end(list);\r
-\r
-    return;\r
-#else\r
-    UNREFERENCED_PARAMETER(TraceEventsLevel);\r
-    UNREFERENCED_PARAMETER(TraceEventsFlag);\r
-    UNREFERENCED_PARAMETER(DebugMessage);\r
-#endif\r
-}\r
-\r
-#endif /* !defined(EVENT_TRACING) */\r
-\r
diff --git a/branches/IBFD/core/bus/kmdf/buspdo.c b/branches/IBFD/core/bus/kmdf/buspdo.c
deleted file mode 100644 (file)
index 4a54d6c..0000000
+++ /dev/null
@@ -1,546 +0,0 @@
-/*\r
- * Copyright (c) 2008 Intel Corporation All Rights Reserved\r
- * Copyright (c) 2008 Microsoft Corporation 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$\r
- */\r
-\r
-/*++\r
-Module Name:\r
-\r
-    BusPdo.c\r
-\r
-Abstract:\r
-\r
-    This module handles plug & play calls for the child device (PDO).\r
-\r
-Environment:\r
-\r
-    kernel mode only\r
-\r
---*/\r
-\r
-#include "ib_fabric.h"\r
-\r
-#if defined(EVENT_TRACING)\r
-#include "buspdo.tmh\r
-#endif\r
-\r
-// short-hand notation...\r
-#define PWDF_CHILD_ID_DESC_HDR PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER \r
-\r
-#ifdef ALLOC_PRAGMA\r
-#pragma alloc_text(PAGE, Bus_CreatePdo)\r
-#pragma alloc_text(PAGE, Bus_EvtDeviceListCreatePdo)\r
-#endif\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
-    It is called when the framework needs to make a copy of a description.\r
-    This happens when a request is made to create a new child device by\r
-    calling WdfChildListAddOrUpdateChildDescriptionAsPresent.\r
-    If this function is left unspecified, RtlCopyMemory will be used to copy the\r
-    source description to destination. Memory for the description is managed by\r
-       the framework.\r
-\r
-    NOTE:   Callback is invoked with an internal lock held.  So do not call out\r
-    to any WDF function which will require this lock\r
-    (basically any other WDFCHILDLIST api)\r
-\r
-Arguments:\r
-\r
-    DeviceList - Handle to the default WDFCHILDLIST created by the framework.\r
-    SourceIdentificationDescription - Description of the child being created\r
-                                                                       - memory in the calling thread stack.\r
-    DestinationIdentificationDescription - Created by the framework in nonpaged\r
-                                                                                - pool.\r
-\r
-Return Value:\r
-\r
-    NT Status code.\r
-\r
---*/\r
-\r
-NTSTATUS\r
-Bus_EvtChildListIdentificationDescriptionDuplicate(\r
-                   WDFCHILDLIST                        DeviceList,\r
-                   PWDF_CHILD_ID_DESC_HDR      SourceIdentificationDescription,\r
-                   PWDF_CHILD_ID_DESC_HDR      DestinationIdentificationDescription )\r
-{\r
-    PPDO_IDENTIFICATION_DESCRIPTION src, dst;\r
-    size_t safeMultResult;\r
-    NTSTATUS status;\r
-\r
-    UNREFERENCED_PARAMETER(DeviceList);\r
-\r
-    src = CONTAINING_RECORD(SourceIdentificationDescription,\r
-                            PDO_IDENTIFICATION_DESCRIPTION,\r
-                            Header);\r
-    dst = CONTAINING_RECORD(DestinationIdentificationDescription,\r
-                            PDO_IDENTIFICATION_DESCRIPTION,\r
-                            Header);\r
-\r
-    dst->SerialNo = src->SerialNo;\r
-    dst->CchHardwareIds = src->CchHardwareIds;\r
-    status = RtlSizeTMult(dst->CchHardwareIds,\r
-                                  sizeof(WCHAR),\r
-                                  &safeMultResult\r
-                                  );\r
-    if(!NT_SUCCESS(status)){\r
-        return status;\r
-    }\r
-\r
-    dst->HardwareIds = (PWCHAR) ExAllocatePoolWithTag(\r
-        NonPagedPool,\r
-        safeMultResult,\r
-        BUS_TAG);\r
-\r
-    if (dst->HardwareIds == NULL) {\r
-        return STATUS_INSUFFICIENT_RESOURCES;\r
-    }\r
-\r
-    RtlCopyMemory(dst->HardwareIds,\r
-                  src->HardwareIds,\r
-                  dst->CchHardwareIds * sizeof(WCHAR));\r
-\r
-    return STATUS_SUCCESS;\r
-}\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
-    This is called when the framework needs to compare one description with\r
-       another.  Typically this happens whenever a request is made to add a new\r
-       child device.  If this function is left unspecified, RtlCompareMemory will\r
-       be used to compare the descriptions.\r
-\r
-    NOTE:   Callback is invoked with an internal lock held.  So do not call out\r
-    to any WDF function which will require this lock\r
-    (basically any other WDFCHILDLIST api)\r
-\r
-Arguments:\r
-\r
-    DeviceList - Handle to the default WDFCHILDLIST created by the framework.\r
-\r
-Return Value:\r
-\r
-   TRUE or FALSE.\r
-\r
---*/\r
-\r
-BOOLEAN\r
-Bus_EvtChildListIdentificationDescriptionCompare(\r
-                   WDFCHILDLIST                        DeviceList,\r
-                   PWDF_CHILD_ID_DESC_HDR      FirstIdentificationDescription,\r
-                   PWDF_CHILD_ID_DESC_HDR      SecondIdentificationDescription )\r
-{\r
-    PPDO_IDENTIFICATION_DESCRIPTION lhs, rhs;\r
-\r
-    UNREFERENCED_PARAMETER(DeviceList);\r
-\r
-    lhs = CONTAINING_RECORD(FirstIdentificationDescription,\r
-                            PDO_IDENTIFICATION_DESCRIPTION,\r
-                            Header);\r
-    rhs = CONTAINING_RECORD(SecondIdentificationDescription,\r
-                            PDO_IDENTIFICATION_DESCRIPTION,\r
-                            Header);\r
-\r
-    return (lhs->SerialNo == rhs->SerialNo) ? TRUE : FALSE;\r
-}\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
-    It is called to free up any memory resources allocated as part of the\r
-       description.  This happens when a child device is unplugged or ejected from\r
-       the bus.  Memory for the description itself will be freed by the framework.\r
-\r
-Arguments:\r
-\r
-    DeviceList - Handle to the default WDFCHILDLIST created by the framework.\r
-\r
-    IdentificationDescription - Description of the child being deleted\r
-\r
-Return Value:\r
-\r
---*/\r
-\r
-VOID\r
-Bus_EvtChildListIdentificationDescriptionCleanup(\r
-                   WDFCHILDLIST                        DeviceList,\r
-                   PWDF_CHILD_ID_DESC_HDR      IdentificationDescription )\r
-{\r
-    PPDO_IDENTIFICATION_DESCRIPTION pDesc;\r
-\r
-\r
-    UNREFERENCED_PARAMETER(DeviceList);\r
-\r
-    pDesc = CONTAINING_RECORD(IdentificationDescription,\r
-                              PDO_IDENTIFICATION_DESCRIPTION,\r
-                              Header);\r
-\r
-    if (pDesc->HardwareIds != NULL) {\r
-        ExFreePool(pDesc->HardwareIds);\r
-        pDesc->HardwareIds = NULL;\r
-    }\r
-}\r
-\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
-    Called by the framework in response to Query-Device relation when\r
-    a new PDO for a child device needs to be created.\r
-\r
-Arguments:\r
-\r
-    DeviceList - Handle to the default WDFCHILDLIST created by the framework\r
-                                as part of FDO.\r
-\r
-    IdentificationDescription - Decription of the new child device.\r
-\r
-    ChildInit - It's a opaque structure used in collecting device settings\r
-                and passed in as a parameter to CreateDevice.\r
-\r
-Return Value:\r
-\r
-    NT Status code.\r
-\r
---*/\r
-\r
-NTSTATUS\r
-Bus_EvtDeviceListCreatePdo( WDFCHILDLIST                       DeviceList,\r
-                                                       PWDF_CHILD_ID_DESC_HDR  IdentificationDescription,\r
-                                                       PWDFDEVICE_INIT                 ChildInit )\r
-{\r
-    PPDO_IDENTIFICATION_DESCRIPTION pDesc;\r
-\r
-    PAGED_CODE();\r
-\r
-    pDesc = CONTAINING_RECORD(IdentificationDescription,\r
-                              PDO_IDENTIFICATION_DESCRIPTION,\r
-                              Header);\r
-\r
-    return Bus_CreatePdo(WdfChildListGetDevice(DeviceList),\r
-                         ChildInit,\r
-                         pDesc->HardwareIds,\r
-                         pDesc->SerialNo);\r
-}\r
-\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
-    This routine creates and initialize a PDO.\r
-\r
-Arguments:\r
-\r
-Return Value:\r
-\r
-    NT Status code.\r
-\r
---*/\r
-NTSTATUS\r
-Bus_CreatePdo(\r
-    __in WDFDEVICE       Device,\r
-    __in PWDFDEVICE_INIT DeviceInit,\r
-    __in PWCHAR          HardwareIds,\r
-    __in ULONG           SerialNo )\r
-{\r
-    NTSTATUS                    status;\r
-    PPDO_DEVICE_DATA            pdoData = NULL;\r
-    WDFDEVICE                   hChild = NULL;\r
-    WDF_QUERY_INTERFACE_CONFIG  qiConfig;\r
-    WDF_OBJECT_ATTRIBUTES       pdoAttributes;\r
-    WDF_DEVICE_PNP_CAPABILITIES pnpCaps;\r
-    WDF_DEVICE_POWER_CAPABILITIES powerCaps;\r
-    IBF_INTERFACE_STANDARD             FabricInterface;\r
-    DECLARE_CONST_UNICODE_STRING(compatId, BUSENUM_COMPATIBLE_IDS);\r
-    DECLARE_CONST_UNICODE_STRING(deviceLocation, L"InfiniBand Fabric 0");\r
-    DECLARE_UNICODE_STRING_SIZE(buffer, MAX_INSTANCE_ID_LEN);\r
-    DECLARE_UNICODE_STRING_SIZE(deviceId, MAX_INSTANCE_ID_LEN);\r
-\r
-    PAGED_CODE();\r
-\r
-    UNREFERENCED_PARAMETER(Device);\r
-\r
-    KdPrint(("Entered Bus_CreatePdo\n"));\r
-\r
-    //\r
-    // Set DeviceType\r
-    //\r
-    WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);\r
-\r
-    //\r
-    // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId\r
-    //\r
-    RtlInitUnicodeString(&deviceId, HardwareIds);\r
-\r
-    status = WdfPdoInitAssignDeviceID(DeviceInit, &deviceId);\r
-    if (!NT_SUCCESS(status)) {\r
-        return status;\r
-    }\r
-\r
-    //\r
-    // NOTE: same string  is used to initialize hardware id too\r
-    //\r
-    status = WdfPdoInitAddHardwareID(DeviceInit, &deviceId);\r
-    if (!NT_SUCCESS(status)) {\r
-        return status;\r
-    }\r
-\r
-    status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId );\r
-    if (!NT_SUCCESS(status)) {\r
-        return status;\r
-    }\r
-\r
-    status =  RtlUnicodeStringPrintf(&buffer, L"%02d", SerialNo);\r
-    if (!NT_SUCCESS(status)) {\r
-        return status;\r
-    }\r
-\r
-    status = WdfPdoInitAssignInstanceID(DeviceInit, &buffer);\r
-    if (!NT_SUCCESS(status)) {\r
-        return status;\r
-    }\r
-\r
-    //\r
-    // Provide a description about the device. This text is usually read from\r
-    // the device. In the case of USB device, this text comes from the string\r
-    // descriptor. This text is displayed momentarily by the PnP manager while\r
-    // it's looking for a matching INF. If it finds one, it uses the Device\r
-    // Description from the INF file or the friendly name created by\r
-    // coinstallers to display in the device manager. FriendlyName takes\r
-    // precedence over the DeviceDesc from the INF file.\r
-    //\r
-    status = RtlUnicodeStringPrintf( &buffer,\r
-                                     L"InfiniBand_HCA%02d",\r
-                                     SerialNo ); // XXX?\r
-    if (!NT_SUCCESS(status)) {\r
-        return status;\r
-    }\r
-\r
-    //\r
-    // You can call WdfPdoInitAddDeviceText multiple times, adding device\r
-    // text for multiple locales. When the system displays the text, it\r
-    // chooses the text that matches the current locale, if available.\r
-    // Otherwise it will use the string for the default locale.\r
-    // The driver can specify the driver's default locale by calling\r
-    // WdfPdoInitSetDefaultLocale.\r
-    //\r
-    status = WdfPdoInitAddDeviceText(DeviceInit,\r
-                                    &buffer,\r
-                                    &deviceLocation,\r
-                                     0x409 );\r
-    if (!NT_SUCCESS(status)) {\r
-        return status;\r
-    }\r
-\r
-    WdfPdoInitSetDefaultLocale(DeviceInit, 0x409);\r
-\r
-    //\r
-    // Initialize the attributes to specify the size of PDO device extension.\r
-    // All the state information private to the PDO will be tracked here.\r
-    //\r
-    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, PDO_DEVICE_DATA);\r
-\r
-    status = WdfDeviceCreate(&DeviceInit, &pdoAttributes, &hChild);\r
-    if (!NT_SUCCESS(status)) {\r
-        return status;\r
-    }\r
-\r
-    //\r
-    // Get the device context.\r
-    //\r
-    pdoData = PdoGetData(hChild);\r
-\r
-    pdoData->SerialNo = SerialNo;\r
-\r
-    //\r
-    // Set some properties for the child device.\r
-    //\r
-    WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);\r
-    pnpCaps.Removable         = WdfTrue;\r
-    pnpCaps.EjectSupported    = WdfTrue;\r
-    pnpCaps.SurpriseRemovalOK = WdfTrue;\r
-\r
-    pnpCaps.Address  = SerialNo;\r
-    pnpCaps.UINumber = SerialNo;\r
-\r
-    WdfDeviceSetPnpCapabilities(hChild, &pnpCaps);\r
-\r
-    WDF_DEVICE_POWER_CAPABILITIES_INIT(&powerCaps);\r
-\r
-    powerCaps.DeviceD1 = WdfTrue;\r
-    powerCaps.WakeFromD1 = WdfTrue;\r
-    powerCaps.DeviceWake = PowerDeviceD1;\r
-\r
-    powerCaps.DeviceState[PowerSystemWorking]   = PowerDeviceD1;\r
-    powerCaps.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;\r
-    powerCaps.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;\r
-    powerCaps.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;\r
-    powerCaps.DeviceState[PowerSystemHibernate] = PowerDeviceD3;\r
-    powerCaps.DeviceState[PowerSystemShutdown]  = PowerDeviceD3;\r
-\r
-    WdfDeviceSetPowerCapabilities(hChild, &powerCaps);\r
-\r
-    //\r
-    // Create a custom interface so that other drivers can\r
-    // query (IRP_MN_QUERY_INTERFACE) and use our callbacks directly.\r
-    //\r
-    RtlZeroMemory(&FabricInterface, sizeof(FabricInterface));\r
-\r
-    FabricInterface.InterfaceHeader.Size = sizeof(FabricInterface);\r
-    FabricInterface.InterfaceHeader.Version = 1;\r
-    FabricInterface.InterfaceHeader.Context = (PVOID) hChild;\r
-\r
-    //\r
-    // Let the framework handle reference counting.\r
-    //\r
-    FabricInterface.InterfaceHeader.InterfaceReference\r
-                                                                       = WdfDeviceInterfaceReferenceNoOp;\r
-    FabricInterface.InterfaceHeader.InterfaceDereference\r
-                                                                       = WdfDeviceInterfaceDereferenceNoOp;\r
-\r
-    FabricInterface.GetCrispinessLevel  = Bus_GetCrispinessLevel;\r
-    FabricInterface.SetCrispinessLevel  = Bus_SetCrispinessLevel;\r
-    FabricInterface.IsSafetyLockEnabled = Bus_IsSafetyLockEnabled;\r
-\r
-    WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig,\r
-                                    (PINTERFACE) &FabricInterface,\r
-                                    &GUID_IBF_INTERFACE_STANDARD,\r
-                                    NULL);\r
-    //\r
-    // If you have multiple interfaces, you can call WdfDeviceAddQueryInterface\r
-    // multiple times to add additional interfaces.\r
-    //\r
-    status = WdfDeviceAddQueryInterface(hChild, &qiConfig);\r
-\r
-    if (!NT_SUCCESS(status)) {\r
-               KdPrint(("WdfDeviceAddQueryInterface() rc 0x%x\n",status));\r
-    }\r
-    return status;\r
-}\r
-\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
-    This routine gets the current crispiness level of the toaster.\r
-\r
-Arguments:\r
-\r
-    Context        pointer to  PDO device extension\r
-    Level          crispiness level of the device\r
-\r
-Return Value:\r
-\r
-    TRUE or FALSE\r
-\r
---*/\r
-\r
-BOOLEAN\r
-Bus_GetCrispinessLevel( IN   WDFDEVICE ChildDevice,\r
-                                           OUT  PUCHAR         Level )\r
-{\r
-    UNREFERENCED_PARAMETER(ChildDevice);\r
-\r
-    //\r
-    // Validate the context to see if it's really a pointer\r
-    // to PDO's device extension. You can store some kind\r
-    // of signature in the PDO for this purpose\r
-    //\r
-\r
-    KdPrint(("GetCrispnessLevel\n"));\r
-\r
-    *Level = 10;\r
-    return TRUE;\r
-}\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
-    This routine sets the current crispiness level of the toaster.\r
-\r
-Arguments:\r
-\r
-    Context        pointer to  PDO device extension\r
-    Level          crispiness level of the device\r
-\r
-Return Value:\r
-\r
-    TRUE or FALSE\r
-\r
---*/\r
-\r
-BOOLEAN\r
-Bus_SetCrispinessLevel( IN   WDFDEVICE ChildDevice,\r
-                                           IN   UCHAR          Level )\r
-{\r
-    UNREFERENCED_PARAMETER(ChildDevice);\r
-    UNREFERENCED_PARAMETER(Level);\r
-\r
-    KdPrint(("SetCrispnessLevel\n"));\r
-\r
-    return TRUE;\r
-}\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
-    Routine to check whether safety lock is enabled\r
-\r
-Arguments:\r
-\r
-    Context - pointer to  PDO device extension\r
-\r
-Return Value:\r
-\r
-    TRUE or FALSE\r
-\r
---*/\r
-BOOLEAN\r
-Bus_IsSafetyLockEnabled( IN WDFDEVICE ChildDevice )\r
-{\r
-    UNREFERENCED_PARAMETER(ChildDevice);\r
-\r
-    KdPrint(("IsSafetyLockEnabled\n"));\r
-\r
-    return TRUE;\r
-}\r
-\r
-\r
index cb80ceae9b2f8adbfd55f5e4a86cea53963b8573..b587fb3be14f7c7a819c10831903a2c3510f7fe7 100644 (file)
@@ -65,14 +65,14 @@ BOOLEAN
                              );\r
 \r
 //\r
-// InfiniBand Fabric Interface for getting and setting power level etc.,\r
+// InfiniBand Fabric Bus Interface\r
 //\r
-typedef struct _IBF_INTERFACE_STANDARD {\r
+typedef struct _IB_BUS_INTERFACE_STANDARD {\r
     INTERFACE                                          InterfaceHeader;\r
     PIBF_GET_CRISPINESS_LEVEL          GetCrispinessLevel;\r
     PIBF_SET_CRISPINESS_LEVEL          SetCrispinessLevel;\r
     PIBF_IS_CHILD_PROTECTED                    IsSafetyLockEnabled;\r
-} IBF_INTERFACE_STANDARD, *PIBF_INTERFACE_STANDARD;\r
+} IB_BUS_INTERFACE_STANDARD, *PIB_BUS_INTERFACE_STANDARD;\r
 \r
 \r
 #endif\r
index c16b253131803719c101ffc147fe76fe079ef9bb..ac428f1df52bd879d8223a4fcf581ddbd1acfdc2 100644 (file)
@@ -1,11 +1,11 @@
 [CatalogHeader]\r
-Name=ib_fabric.cat\r
+Name=ib_bus.cat\r
 PublicVersion=0x0000001\r
 EncodingType=0x00010001\r
 CATATTR1=0x10010001:OSAttr:2:6.0\r
 [CatalogFiles]\r
-<hash>ib_fabric.inf=ib_fabric.inf\r
-<hash>ibfabric.sys=ibfabric.sys\r
+<hash>ib_bus.inf=ib_bus.inf\r
+<hash>ibbus.sys=ibbus.sys\r
 <hash>ibiou.sys=ibiou.sys\r
 <hash>ibal.dll=ibal.dll\r
 <hash>complib.dll=complib.dll\r
index c5809ae82e95d11afe65baef6d7d785578d28b39..d2575607f1e4bfaff2c678f0097ff1a2d6c702ef 100644 (file)
@@ -1,30 +1,21 @@
-;/*++\r
-;\r
-;Copyright (c) 2008 Intel Corporation All rights Reserved\r
-;Copyright (c) 1990-1999 Microsoft Corporation All rights Reserved\r
-;\r
-;Module Name:\r
-;\r
-;    ib_fabric.INF\r
-;\r
-;Abstract:\r
-;    INF file for installing the Infinband Fabric bus enumerator driver\r
-;\r
-;Installation Notes:\r
-;    Using Devcon: Type "devcon install ib_fabric.inf root\ib_fabric" to install\r
-;\r
-;--*/\r
+; OpenIB InfiniBand Fabric Bus Driver.\r
+; Copyright 2008 SilverStorm Technologies all Rights Reserved.\r
+; Copyright 2005 SilverStorm Technologies all Rights Reserved.\r
+; Copyright 2006 Mellanox Technologies all Rights Reserved.\r
+\r
 [Version]\r
-Signature="$WINDOWS NT$"\r
+Signature="$Windows NT$"\r
 Class=System\r
 ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318}\r
 Provider=%OPENIB%\r
-DriverVer=04/15/2008, 1.0.0000.999\r
+DriverVer=03/08/2006,1.0.0000.614\r
 CatalogFile=ib_bus.cat\r
 \r
+; ================= Device Install section =====================\r
 \r
+; 64-bit platforms also copy 32-bit user-mode binaries.\r
 [DestinationDirs]\r
-DefaultDestDir = %DIRID_DRIVERS%\r
+DefaultDestDir=%DIRID_DRIVERS%\r
 Ibbus.UMCopyFiles=%DIRID_SYSTEM%\r
 Ibbus.WOW64CopyFiles=%DIRID_SYSTEM_X86%\r
 \r
@@ -69,63 +60,158 @@ cl32.dll=1
 ibal32d.dll=1\r
 ibal32.dll=1\r
 \r
-;*****************************************\r
-; IbFabricDynamicBus  Install Section\r
-;*****************************************\r
-\r
 [Manufacturer]\r
-%StdMfg%=Standard,NT$ARCH$\r
+%OPENIB% = Ibbus.DeviceSection,ntx86,ntamd64,ntia64\r
+%SST% = SST.DeviceSection,ntx86,ntamd64,ntia64\r
+\r
+[Ibbus.DeviceSection]\r
+; empty since we don't support W9x/Me\r
+\r
+[Ibbus.DeviceSection.ntx86]\r
+%Ibbus.DeviceDesc% = Ibbus.DDInstall,{94f41ced-78eb-407c-b5df-958040af0fd8}\r
+%Iou.DeviceDesc% = Iou.DDInstall,IBA\IB_IOU\r
+\r
+[Ibbus.DeviceSection.ntamd64]\r
+%Ibbus.DeviceDesc% = Ibbus.DDInstall,{94f41ced-78eb-407c-b5df-958040af0fd8}\r
+%Iou.DeviceDesc% = Iou.DDInstall,IBA\IB_IOU\r
+\r
+[Ibbus.DeviceSection.ntia64]\r
+%Ibbus.DeviceDesc% = Ibbus.DDInstall,{94f41ced-78eb-407c-b5df-958040af0fd8}\r
+%Iou.DeviceDesc% = Iou.DDInstall,IBA\IB_IOU\r
+\r
+[SST.DeviceSection]\r
+; empty since we don't support W9x/Me\r
+\r
+[SST.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
+[SST.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
+[SST.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
+[Ibbus.DDInstall.ntx86]\r
+CopyFiles = Ibbus.CopyFiles\r
+CopyFiles = Ibbus.UMCopyFiles\r
+\r
+[Ibbus.DDInstall.ntamd64]\r
+CopyFiles = Ibbus.CopyFiles\r
+CopyFiles = Ibbus.UMCopyFiles\r
+CopyFiles = Ibbus.WOW64CopyFiles\r
+\r
+[Ibbus.DDInstall.ntia64]\r
+CopyFiles = Ibbus.CopyFiles\r
+CopyFiles = Ibbus.UMCopyFiles\r
+CopyFiles = Ibbus.WOW64CopyFiles\r
+\r
+[Ibbus.DDInstall.ntx86.Services]\r
+AddService = ibbus,%SPSVCINST_ASSOCSERVICE%,Ibbus.ServiceInstall\r
+\r
+[Ibbus.DDInstall.ntamd64.Services]\r
+AddService = ibbus,%SPSVCINST_ASSOCSERVICE%,Ibbus.ServiceInstall\r
+\r
+[Ibbus.DDInstall.ntia64.Services]\r
+AddService = ibbus,%SPSVCINST_ASSOCSERVICE%,Ibbus.ServiceInstall\r
+\r
+[Iou.DDInstall.nt]\r
+CopyFiles = Iou.CopyFiles\r
+\r
+[Iou.DDInstall.nt.Services]\r
+AddService = ibiou,%SPSVCINST_ASSOCSERVICE%,Iou.ServiceInstall\r
+\r
+[Ibbus.CopyFiles]\r
+ibbus.sys\r
+\r
+[Ibbus.UMCopyFiles]\r
+complib.dll,,,2\r
+ibal.dll,,,2\r
+complibd.dll,,,2\r
+ibald.dll,,,2\r
+\r
+[Ibbus.WOW64CopyFiles]\r
+complib.dll,cl32.dll,,2\r
+ibal.dll,ibal32.dll,,2\r
+complibd.dll,cl32d.dll,,2\r
+ibald.dll,ibal32d.dll,,2\r
+\r
+[Iou.CopyFiles]\r
+ibiou.sys\r
 \r
-; For Win2K because it cannot parse decorated sections\r
-[Standard]\r
 ;\r
-; These are the toaster bus pnp ids\r
+; ============= Service Install section ==============\r
 ;\r
-%IbFabricDynamicBus.DeviceDesc%=IbFabricDynamicBus_Device, root\ib_bus\r
-\r
-; For XP and later\r
-[Standard.NT$ARCH$]\r
-%IbFabricDynamicBus.DeviceDesc%=IbFabricDynamicBus_Device, root\ib_bus\r
-\r
-[IbFabricDynamicBus_Device.NT]\r
-CopyFiles=Drivers_Dir\r
-\r
-[IbFabricDynamicBus_Device.NT.HW]\r
-AddReg=IbFabricDynamicBus_Device.NT.AddReg\r
-\r
-[IbFabricDynamicBus_Device.NT.AddReg]                            \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
-\r
-[Drivers_Dir]\r
-ib_bus.sys\r
-\r
-\r
-;-------------- Service installation\r
-[IbFabricDynamicBus_Device.NT.Services]\r
-AddService = ib_bus,%SPSVCINST_ASSOCSERVICE%, ib_bus_Service_Inst\r
-\r
-; -------------- IB bus driver install sections\r
-[dynambus_Service_Inst]\r
-DisplayName    = %ib_bus.SVCDESC%\r
-ServiceType    = 1               ; SERVICE_KERNEL_DRIVER\r
-StartType      = 3               ; SERVICE_DEMAND_START \r
-ErrorControl   = 1               ; SERVICE_ERROR_NORMAL\r
-ServiceBinary  = %12%\ib_bus.sys\r
-LoadOrderGroup = Extended Base\r
-\r
-\r
-[IB_Bus_Device.NT.Wdf]\r
-KmdfService = ib_bus, ib_bus_wdfsect\r
-[ib_bus_wdfsect]\r
-KmdfLibraryVersion = $KMDFVERSION$\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  = extended base\r
+AddReg          = Ibbus.ParamsReg\r
+Dependencies   = mthca\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
+[Ibbus.ParamsReg]\r
+HKR,"Parameters","DebugFlags",%REG_DWORD%,0x80000000\r
+HKR,"Parameters","ReportPortNIC",%REG_DWORD%,1\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
+\r
+[Iou.ParamsReg]\r
+HKR,"Parameters","DebugLevel",%REG_DWORD%,2\r
+HKR,"Parameters","DebugFlags",%REG_DWORD%,0x00ffffff\r
 \r
 [Strings]\r
-SPSVCINST_ASSOCSERVICE= 0x00000002\r
-MSFT = "Microsoft"\r
-StdMfg = "(Standard system devices)"\r
-DiskId1 = "InfiniBand Fabric Dynamic Bus Installation Disk #1"\r
-IB_Bus.DeviceDesc = "InfiniBand Fabric Dynamic Bus Enumerator"\r
-ib_bus.SVCDESC = "InfiniBand Fabric Dynamic Bus Enumerator"\r
-\r
+OPENIB = "OpenIB Alliance"\r
+SST = "SilverStorm Technologies"\r
+IbFabric.DeviceDesc = "InfiniBand Fabric"\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
+IbFabric.ServiceDesc = "OpenIB InfiniBand Bus Driver"\r
+Ibal.ServiceDesc = "OpenIB InfiniBand Access Layer"\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
index 967be5c15026c50cea83a3a90ee559bd20320fdc..e6f549c754318813b042b99b01c0d282076aff7d 100644 (file)
@@ -41,8 +41,8 @@
 #define VER_FILEDESCRIPTION_STR                "InfiniBand Fabric Dynamic Bus Enumerator"\r
 #endif\r
 \r
-#define VER_INTERNALNAME_STR           "ib_bus.sys"\r
-#define VER_ORIGINALFILENAME_STR       "ib_bus.sys"\r
+#define VER_INTERNALNAME_STR           "ibbus.sys"\r
+#define VER_ORIGINALFILENAME_STR       "ibbus.sys"\r
 \r
 #include <common.ver>\r
 \r
diff --git a/branches/IBFD/core/bus/kmdf/ib_bus_public.h b/branches/IBFD/core/bus/kmdf/ib_bus_public.h
new file mode 100644 (file)
index 0000000..0f60674
--- /dev/null
@@ -0,0 +1,166 @@
+/*++\r
+Copyright (c) 1990-2000    Microsoft Corporation All Rights Reserved\r
+\r
+Module Name:\r
+\r
+    public.h\r
+\r
+Abstract:\r
+\r
+    This module contains the common declarations shared by driver\r
+    and user applications.\r
+\r
+Environment:\r
+\r
+    user and kernel\r
+\r
+--*/\r
+\r
+//\r
+// Define an Interface Guid for bus enumerator class.\r
+// This GUID is used to register (IoRegisterDeviceInterface)\r
+// an instance of an interface so that enumerator application\r
+// can send an ioctl to the bus driver.\r
+//\r
+\r
+DEFINE_GUID (GUID_DEVINTERFACE_BUSENUM_IBF,\r
+        0xD35F7840, 0x6A0C, 0x11d2, 0xB8, 0x41, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71);\r
+//  {D35F7840-6A0C-11d2-B841-00C04FAD5171}\r
+\r
+//\r
+// Define an Interface Guid for toaster device class.\r
+// This GUID is used to register (IoRegisterDeviceInterface)\r
+// an instance of an interface so that user application\r
+// can control the toaster device.\r
+//\r
+\r
+DEFINE_GUID (GUID_DEVINTERFACE_IB_HCA,\r
+        0x781EF630, 0x72B2, 0x11d2, 0xB8, 0x52, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71);\r
+//{781EF630-72B2-11d2-B852-00C04FAD5171}\r
+\r
+//\r
+// Define a Setup Class GUID for Toaster Class. This is same\r
+// as the TOASTSER CLASS guid in the INF files.\r
+//\r
+\r
+DEFINE_GUID (GUID_DEVCLASS_IB_FABRIC,\r
+        0xB85B7C50, 0x6A01, 0x11d2, 0xB8, 0x41, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71);\r
+//{B85B7C50-6A01-11d2-B841-00C04FAD5171}\r
+\r
+//\r
+// Define a WMI GUID to get busenum info.\r
+//\r
+\r
+DEFINE_GUID (IBF_BUS_WMI_STD_DATA_GUID,\r
+        0x0006A660, 0x8F12, 0x11d2, 0xB8, 0x54, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71);\r
+//{0006A660-8F12-11d2-B854-00C04FAD5171}\r
+\r
+//\r
+// Define a WMI GUID to get IB Fabric device info.\r
+\r
+DEFINE_GUID (IBF_WMI_STD_DATA_GUID,\r
+        0xBBA21300L, 0x6DD3, 0x11d2, 0xB8, 0x44, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71);\r
+\r
+//\r
+// Define a WMI GUID to represent device arrival notification WMIEvent class.\r
+//\r
+\r
+DEFINE_GUID (IBF_NOTIFY_DEVICE_ARRIVAL_EVENT,\r
+        0x1cdaff1, 0xc901, 0x45b4, 0xb3, 0x59, 0xb5, 0x54, 0x27, 0x25, 0xe2, 0x9c);\r
+// {01CDAFF1-C901-45b4-B359-B5542725E29C}\r
+\r
+\r
+//\r
+// GUID definition is required to be outside of header inclusion pragma to avoid\r
+// error during precompiled headers.\r
+//\r
+\r
+#ifndef __IB_PUBLIC_H\r
+#define __IB_PUBLIC_H\r
+\r
+#define BUS_HARDWARE_IDS L"{B85B7C50-6A01-11d2-B841-00C04FAD5171}\\MsToaster\0"\r
+#define BUS_HARDWARE_IDS_LENGTH sizeof (BUS_HARDWARE_IDS)\r
+\r
+#define BUSENUM_COMPATIBLE_IDS L"{B85B7C50-6A01-11d2-B841-00C04FAD5171}\\MsCompatibleToaster\0"\r
+#define BUSENUM_COMPATIBLE_IDS_LENGTH sizeof(BUSENUM_COMPATIBLE_IDS)\r
+\r
+\r
+#define FILE_DEVICE_BUSENUM         FILE_DEVICE_BUS_EXTENDER\r
+\r
+#define BUSENUM_IOCTL(_index_) \\r
+    CTL_CODE (FILE_DEVICE_BUSENUM, _index_, METHOD_BUFFERED, FILE_READ_DATA)\r
+\r
+#define IOCTL_BUSENUM_PLUGIN_HARDWARE               BUSENUM_IOCTL (0x0)\r
+#define IOCTL_BUSENUM_UNPLUG_HARDWARE               BUSENUM_IOCTL (0x1)\r
+#define IOCTL_BUSENUM_EJECT_HARDWARE                BUSENUM_IOCTL (0x2)\r
+#define IOCTL_IBF_DONT_DISPLAY_IN_UI_DEVICE         BUSENUM_IOCTL (0x3)\r
+\r
+//\r
+//  Data structure used in PlugIn and UnPlug ioctls\r
+//\r
+\r
+typedef struct _BUSENUM_PLUGIN_HARDWARE\r
+{\r
+    //\r
+    // sizeof (struct _BUSENUM_HARDWARE)\r
+    //\r
+    IN ULONG Size;\r
+\r
+    //\r
+    // Unique serial number of the device to be enumerated.\r
+    // Enumeration will be failed if another device on the\r
+    // bus has the same serail number.\r
+    //\r
+\r
+    IN ULONG SerialNo;\r
+\r
+    //\r
+    // An array of (zero terminated wide character strings). The array itself\r
+    //  also null terminated (ie, MULTI_SZ)\r
+    //\r
+    #pragma warning(disable:4200)  // nonstandard extension used\r
+\r
+    IN  WCHAR   HardwareIDs[];\r
+\r
+    #pragma warning(default:4200)\r
+\r
+} BUSENUM_PLUGIN_HARDWARE, *PBUSENUM_PLUGIN_HARDWARE;\r
+\r
+typedef struct _BUSENUM_UNPLUG_HARDWARE\r
+{\r
+    //\r
+    // sizeof (struct _REMOVE_HARDWARE)\r
+    //\r
+\r
+    IN ULONG Size;\r
+\r
+    //\r
+    // Serial number of the device to be plugged out\r
+    //\r
+\r
+    ULONG   SerialNo;\r
+\r
+    ULONG Reserved[2];\r
+\r
+} BUSENUM_UNPLUG_HARDWARE, *PBUSENUM_UNPLUG_HARDWARE;\r
+\r
+typedef struct _BUSENUM_EJECT_HARDWARE\r
+{\r
+    //\r
+    // sizeof (struct _EJECT_HARDWARE)\r
+    //\r
+\r
+    IN ULONG Size;\r
+\r
+    //\r
+    // Serial number of the device to be ejected\r
+    //\r
+\r
+    ULONG   SerialNo;\r
+\r
+    ULONG Reserved[2];\r
+\r
+} BUSENUM_EJECT_HARDWARE, *PBUSENUM_EJECT_HARDWARE;\r
+\r
+#endif\r
+\r
index 27d8ed8b80d242bde471b85c3e23139cfcc020cd..2bbddde94fe53981709c27dcf55a5b4bae8454f3 100644 (file)
@@ -31,8 +31,8 @@ Environment:
 // TODO: These defines are missing in evntrace.h\r
 // in some DDK build environments (XP).\r
 //\r
-#if !defined(TRACE_LEVEL_NONE)\r
   #define TRACE_LEVEL_NONE        0\r
+  #define TRACE_LEVEL_ALWAYS      0\r
   #define TRACE_LEVEL_CRITICAL    1\r
   #define TRACE_LEVEL_FATAL       1\r
   #define TRACE_LEVEL_ERROR       2\r
@@ -43,8 +43,6 @@ Environment:
   #define TRACE_LEVEL_RESERVED7   7\r
   #define TRACE_LEVEL_RESERVED8   8\r
   #define TRACE_LEVEL_RESERVED9   9\r
-#endif\r
-\r
 \r
 //\r
 // Define Debug Flags\r
@@ -62,6 +60,18 @@ Environment:
 #define DBG_LOCKS               0x00000400\r
 #define DBG_QUEUEING            0x00000800\r
 #define DBG_HW_ACCESS           0x00001000\r
+#define DBG_PORT                0x00002000\r
+#define DBG_IOU                 0x00004000\r
+#define DBG_TRACE               0x00008000\r
+#define DBG_ALL                 0xFFFFFFFF\r
+\r
+#define BUS_DBG_DRIVER                 DBG_INIT\r
+#define BUS_DBG_DRV                            BUS_DBG_DRIVER\r
+#define BUS_DBG_PNP                            DBG_PNP\r
+#define BUS_DBG_POWER                  DBG_POWER\r
+\r
+#define BUS_DBG_ERROR                  0x80000000      \r
+\r
 \r
 VOID\r
 TraceEvents    (\r
index f2883a4e684eb8db90b977ee135c8b6c61e09ae5..c578e5e0407bc1def032056e6bdef5aeceade872 100644 (file)
@@ -22,7 +22,7 @@ Environment:
 \r
 --*/\r
 \r
-#include "ib_fabric.h"\r
+#include "bus_driver.h"\r
 #include "ib_busMof.h"\r
 \r
 #if defined(EVENT_TRACING)\r
@@ -48,9 +48,9 @@ NTSTATUS
 Bus_WmiRegistration( WDFDEVICE      Device )\r
 {\r
     WDF_WMI_PROVIDER_CONFIG providerConfig;\r
-    WDF_WMI_INSTANCE_CONFIG instanceConfig;\r
-    PFDO_DEVICE_DATA deviceData;\r
-    NTSTATUS status;\r
+    WDF_WMI_INSTANCE_CONFIG    instanceConfig;\r
+    PFDO_BUS_DATA                      deviceData;\r
+    NTSTATUS                           status;\r
     DECLARE_CONST_UNICODE_STRING(busRsrcName, BUSRESOURCENAME);\r
 \r
     PAGED_CODE();\r
@@ -135,7 +135,7 @@ Bus_EvtStdDataSetItem(
     IN  ULONG InBufferSize,\r
     IN  PVOID InBuffer )\r
 {\r
-    PFDO_DEVICE_DATA    fdoData;\r
+    PFDO_BUS_DATA    fdoData;\r
 \r
     PAGED_CODE();\r
 \r
@@ -151,7 +151,7 @@ Bus_EvtStdDataSetItem(
             return STATUS_BUFFER_TOO_SMALL;\r
         }\r
 \r
-        DebugLevel = fdoData->StdBusData.DebugPrintLevel = *((PULONG)InBuffer);\r
+        bus_globals.dbg_lvl = fdoData->StdBusData.DebugPrintLevel = *((PULONG)InBuffer);\r
 \r
         return STATUS_SUCCESS;\r
     }\r
@@ -189,7 +189,7 @@ Bus_EvtStdDataSetInstance(
     IN  ULONG InBufferSize,\r
     IN  PVOID InBuffer )\r
 {\r
-    PFDO_DEVICE_DATA   fdoData;\r
+    PFDO_BUS_DATA   fdoData;\r
 \r
     UNREFERENCED_PARAMETER(InBufferSize);\r
 \r
@@ -200,7 +200,7 @@ Bus_EvtStdDataSetInstance(
     //\r
     // We will update only writable elements.\r
     //\r
-    DebugLevel = fdoData->StdBusData.DebugPrintLevel =\r
+    bus_globals.dbg_lvl = fdoData->StdBusData.DebugPrintLevel =\r
         ((PIBF_BUS_WMI_STD_DATA)InBuffer)->DebugPrintLevel;\r
 \r
     return STATUS_SUCCESS;\r
@@ -238,7 +238,7 @@ Bus_EvtStdDataQueryInstance(
     IN  PVOID OutBuffer,\r
     OUT PULONG BufferUsed )\r
 {\r
-    PFDO_DEVICE_DATA fdoData;\r
+    PFDO_BUS_DATA fdoData;\r
 \r
     UNREFERENCED_PARAMETER(OutBufferSize);\r
 \r