]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
[eth6] Add first version of ipoib NDIS 6.0 driver.
authortzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 23 Jun 2009 15:58:00 +0000 (15:58 +0000)
committertzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Tue, 23 Jun 2009 15:58:00 +0000 (15:58 +0000)
Signed off by: xalex@mellanox.co.il

git-svn-id: svn://openib.tc.cornell.edu/gen1@2263 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

49 files changed:
trunk/ulp/ipoib/kernel6/SOURCES [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib.cdf [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib.rc [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib32-xp.cdf [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib32.cdf [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_adapter.c [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_adapter.h [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_cm.c [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_debug.h [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_driver.c [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_driver.h [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_endpoint.c [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_endpoint.h [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_ibat.c [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_ibat.h [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_log.mc [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_port.c [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_port.h [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_xfr_mgr.c [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/ipoib_xfr_mgr.h [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/makefile [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/makefile.inc [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/netipoib-xp32.inf [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/netipoib.inx [new file with mode: 0644]
trunk/ulp/ipoib/kernel6/offload.h [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/dirs [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/ip_stats.h [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/SOURCES [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib.cdf [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib.rc [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib32.cdf [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.c [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.h [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_debug.h [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.c [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.h [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_endpoint.c [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_endpoint.h [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_ibat.c [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_ibat.h [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_log.mc [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.c [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.h [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_xfr_mgr.c [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_xfr_mgr.h [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/makefile [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/makefile.inc [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/netipoib.inx [new file with mode: 0644]
trunk/ulp/ipoib_NDIS6_CM/kernel/offload.h [new file with mode: 0644]

diff --git a/trunk/ulp/ipoib/kernel6/SOURCES b/trunk/ulp/ipoib/kernel6/SOURCES
new file mode 100644 (file)
index 0000000..a528904
--- /dev/null
@@ -0,0 +1,59 @@
+TARGETNAME=ipoib\r
+TARGETPATH=..\..\..\bin\kernel\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE=DRIVER\r
+\r
+!if $(_NT_TOOLS_VERSION) != 0x700\r
+# WDK build only - transform .inx --> .inf adding date & version stamp.\r
+# see .\makefile.inc\r
+INF_NAME=netipoib\r
+INF_TARGET=..\..\..\bin\kernel\$(O)\$(INF_NAME).inf\r
+NTTARGETFILES=$(INF_TARGET)\r
+!endif\r
+\r
+!if $(FREEBUILD)\r
+ENABLE_EVENT_TRACING=1\r
+!else\r
+#ENABLE_EVENT_TRACING=1\r
+!endif\r
+\r
+\r
+SOURCES=       ipoib_log.mc \\r
+               ipoib.rc \\r
+               ipoib_driver.c \\r
+               ipoib_adapter.c \\r
+               ipoib_endpoint.c \\r
+               ipoib_port.c \\r
+               ipoib_ibat.c \\r
+#              ipoib_cm.c      \\r
+               ipoib_xfr_mgr.c\r
+\r
+INCLUDES=..;..\..\..\inc;..\..\..\inc\kernel;\r
+\r
+C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER -DNDIS_WDM=1 \\r
+       -DDEPRECATE_DDK_FUNCTIONS -DNDIS60_MINIPORT=1 -DNEED_CL_OBJ -DBINARY_COMPATIBLE=0 -DVER_FILEREV=42\r
+\r
+TARGETLIBS= \\r
+       $(TARGETPATH)\*\complib.lib \\r
+       $(DDK_LIB_PATH)\ndis.lib \\r
+       $(DDK_LIB_PATH)\ntstrsafe.lib \\r
+       $(DDK_LIB_PATH)\strsafe.lib\r
+\r
+!if !defined(DDK_TARGET_OS) || "$(DDK_TARGET_OS)"=="Win2K"\r
+#\r
+# The driver is built in the Win2K build environment\r
+# - use the library version of safe strings \r
+#\r
+#TARGETLIBS= $(TARGETLIBS) $(DDK_LIB_PATH)\ntstrsafe.lib\r
+!endif\r
+\r
+!IFDEF ENABLE_EVENT_TRACING\r
+\r
+C_DEFINES = $(C_DEFINES) -DEVENT_TRACING\r
+\r
+RUN_WPP = $(SOURCES) -km -ext: .c .h .C .H \\r
+       -scan:ipoib_debug.h \\r
+       -func:IPOIB_PRINT(LEVEL,FLAGS,(MSG,...)) \\r
+       -func:IPOIB_PRINT_EXIT(LEVEL,FLAGS,(MSG,...))\r
+!ENDIF\r
+\r
+MSC_WARNING_LEVEL= /W4\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib.cdf b/trunk/ulp/ipoib/kernel6/ipoib.cdf
new file mode 100644 (file)
index 0000000..eb21da9
--- /dev/null
@@ -0,0 +1,13 @@
+[CatalogHeader]\r
+Name=ipoib.cat\r
+PublicVersion=0x0000001\r
+EncodingType=0x00010001\r
+CATATTR1=0x10010001:OSAttr:2:6.0\r
+[CatalogFiles]\r
+<hash>netipoib.inf=netipoib.inf\r
+<hash>ipoib.sys=ipoib.sys\r
+<hash>ibwsd.dll=ibwsd.dll\r
+<hash>ibwsd32.dll=ibwsd32.dll\r
+<hash>ibndprov.dll=ibndprov.dll\r
+<hash>ibndprov32.dll=ibndprov32.dll\r
+<hash>ndinstall.exe=ndinstall.exe\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib.rc b/trunk/ulp/ipoib/kernel6/ipoib.rc
new file mode 100644 (file)
index 0000000..330f19e
--- /dev/null
@@ -0,0 +1,48 @@
+/*\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: ipoib.rc 1611 2006-08-20 14:48:55Z sleybo $\r
+ */\r
+\r
+\r
+#include <oib_ver.h>\r
+\r
+#define VER_FILETYPE                           VFT_DRV\r
+#define VER_FILESUBTYPE                                VFT2_UNKNOWN\r
+\r
+#ifdef _DEBUG_\r
+#define VER_FILEDESCRIPTION_STR                "IP over InfiniBand NDIS Miniport (Debug)"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR                "IP over InfiniBand NDIS Miniport"\r
+#endif\r
+\r
+#define VER_INTERNALNAME_STR           "ipoib.sys"\r
+#define VER_ORIGINALFILENAME_STR       "ipoib.sys"\r
+\r
+#include <common.ver>\r
+#include "ipoib_log.rc"\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib32-xp.cdf b/trunk/ulp/ipoib/kernel6/ipoib32-xp.cdf
new file mode 100644 (file)
index 0000000..faf8ea6
--- /dev/null
@@ -0,0 +1,10 @@
+[CatalogHeader]\r
+Name=ipoib.cat\r
+PublicVersion=0x0000001\r
+EncodingType=0x00010001\r
+CATATTR1=0x10010001:OSAttr:2:6.0\r
+[CatalogFiles]\r
+<hash>netipoib.inf=netipoib.inf\r
+<hash>ipoib.sys=ipoib.sys\r
+<hash>ibndprov.dll=ibndprov.dll\r
+<hash>ndinstall.exe=ndinstall.exe\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib32.cdf b/trunk/ulp/ipoib/kernel6/ipoib32.cdf
new file mode 100644 (file)
index 0000000..50225ba
--- /dev/null
@@ -0,0 +1,11 @@
+[CatalogHeader]\r
+Name=ipoib.cat\r
+PublicVersion=0x0000001\r
+EncodingType=0x00010001\r
+CATATTR1=0x10010001:OSAttr:2:6.0\r
+[CatalogFiles]\r
+<hash>netipoib.inf=netipoib.inf\r
+<hash>ipoib.sys=ipoib.sys\r
+<hash>ibwsd.dll=ibwsd.dll\r
+<hash>ibndprov.dll=ibndprov.dll\r
+<hash>ndinstall.exe=ndinstall.exe\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_adapter.c b/trunk/ulp/ipoib/kernel6/ipoib_adapter.c
new file mode 100644 (file)
index 0000000..78eff26
--- /dev/null
@@ -0,0 +1,1632 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_adapter.c 4226 2009-04-06 06:01:03Z xalex $\r
+ */\r
+\r
+\r
+\r
+#include "ipoib_adapter.h"\r
+#include "ipoib_port.h"\r
+#include "ipoib_driver.h"\r
+#include "ipoib_debug.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_adapter.tmh"\r
+#endif\r
+\r
+\r
+#define ITEM_POOL_START                16\r
+#define ITEM_POOL_GROW         16\r
+\r
+\r
+/* IB Link speeds in 100bps */\r
+#define ONE_X_IN_100BPS                25000000\r
+#define FOUR_X_IN_100BPS       100000000\r
+#define TWELVE_X_IN_100BPS     300000000\r
+\r
+\r
+/* Declarations */\r
+static void\r
+adapter_construct(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+\r
+static ib_api_status_t\r
+adapter_init(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+\r
+static void\r
+__adapter_destroying(\r
+       IN                              cl_obj_t* const                         p_obj );\r
+\r
+\r
+static void\r
+__adapter_free(\r
+       IN                              cl_obj_t* const                         p_obj );\r
+\r
+\r
+static ib_api_status_t\r
+__ipoib_pnp_reg(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              ib_pnp_class_t                          flags );\r
+\r
+\r
+static void\r
+__ipoib_pnp_dereg(\r
+       IN                              void*                                           context );\r
+\r
+\r
+static void\r
+__ipoib_adapter_reset(\r
+       IN                              void*   context);\r
+\r
+\r
+static ib_api_status_t\r
+__ipoib_pnp_cb(\r
+       IN                              ib_pnp_rec_t                            *p_pnp_rec );\r
+\r
+\r
+void\r
+ipoib_join_mcast(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+\r
+/* Leaves all mcast groups when port goes down. */\r
+static void\r
+ipoib_clear_mcast(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+NDIS_STATUS\r
+ipoib_get_adapter_guids(\r
+       IN                              NDIS_HANDLE* const                      h_adapter,\r
+       IN      OUT                     ipoib_adapter_t                         *p_adapter );\r
+\r
+NDIS_STATUS\r
+ipoib_get_adapter_params(\r
+       IN                              NDIS_HANDLE* const                      wrapper_config_context,\r
+       IN      OUT                     ipoib_adapter_t                         *p_adapter,\r
+       OUT                             PUCHAR                                          *p_mac,\r
+       OUT                             UINT                                            *p_len);\r
+\r
+\r
+/* Implementation */\r
+ib_api_status_t\r
+ipoib_create_adapter(\r
+       IN                              NDIS_HANDLE                                     wrapper_config_context,\r
+       IN                              void* const                                     h_adapter,\r
+               OUT                     ipoib_adapter_t** const         pp_adapter )\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       ib_api_status_t         status;\r
+       cl_status_t                     cl_status;\r
+       PUCHAR                          mac;\r
+       UINT                            len;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_adapter = cl_zalloc( sizeof(ipoib_adapter_t) );\r
+       if( !p_adapter )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate ipoib_adapter_t (%d bytes)",\r
+                       sizeof(ipoib_adapter_t)) );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       adapter_construct( p_adapter );\r
+\r
+       p_adapter->h_adapter = h_adapter;\r
+\r
+       p_adapter->p_ifc = cl_zalloc( sizeof(ib_al_ifc_t) );\r
+       if( !p_adapter->p_ifc )\r
+       {\r
+               __adapter_free( &p_adapter->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_create_adapter failed to alloc ipoib_ifc_t %d bytes\n",\r
+                       sizeof(ib_al_ifc_t)) );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       /* Get the CA and port GUID from the bus driver. */\r
+       status = ipoib_get_adapter_guids( h_adapter,  p_adapter );\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               __adapter_free( &p_adapter->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_get_adapter_guids returned 0x%.8X.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Port %016I64x (CA %016I64x port %d) initializing\n",\r
+                       p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid,\r
+                       p_adapter->guids.port_num) );\r
+\r
+       cl_status = cl_obj_init( &p_adapter->obj, CL_DESTROY_SYNC,\r
+               __adapter_destroying, NULL, __adapter_free );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               __adapter_free( &p_adapter->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_obj_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       /* Read configuration parameters. */\r
+       status = ipoib_get_adapter_params( wrapper_config_context,\r
+               p_adapter , &mac, &len);\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               cl_obj_destroy( &p_adapter->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_get_adapter_params returned 0x%.8x.\n", status) );\r
+               return status;\r
+       }\r
+               \r
+       status = adapter_init( p_adapter );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               cl_obj_destroy( &p_adapter->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("adapter_init returned %s.\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, p_adapter->mac.addr );\r
+       /* If there is a NetworkAddress override in registry, use it */\r
+       if( (status == NDIS_STATUS_SUCCESS) && (len == HW_ADDR_LEN) )\r
+       {\r
+               if( ETH_IS_MULTICAST(mac) || ETH_IS_BROADCAST(mac) ||\r
+                       !ETH_IS_LOCALLY_ADMINISTERED(mac) )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
+                               ("Overriding NetworkAddress is invalid - "\r
+                               "%02x-%02x-%02x-%02x-%02x-%02x\n",\r
+                               mac[0], mac[1], mac[2],\r
+                               mac[3], mac[4], mac[5]) );\r
+               }\r
+               else\r
+       {\r
+                       ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, mac );\r
+               }\r
+       }\r
+\r
+       *pp_adapter = p_adapter;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ipoib_start_adapter(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       ib_api_status_t status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       status = __ipoib_pnp_reg( p_adapter,\r
+               IB_PNP_FLAG_REG_SYNC | IB_PNP_FLAG_REG_COMPLETE );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+void\r
+ipoib_destroy_adapter(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_adapter );\r
+\r
+       /*\r
+        * Flag the adapter as being removed.  We use the IB_PNP_PORT_REMOVE state\r
+        * for this purpose.  Note that we protect this state change with both the\r
+        * mutex and the lock.  The mutex provides synchronization as a whole\r
+        * between destruction and AL callbacks (PnP, Query, Destruction).\r
+        * The lock provides protection\r
+        */\r
+       KeWaitForMutexObject(\r
+               &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
+       cl_obj_lock( &p_adapter->obj );\r
+       p_adapter->state = IB_PNP_PORT_REMOVE;\r
+\r
+       /*\r
+        * Clear the pointer to the port object since the object destruction\r
+        * will cascade to child objects.  This prevents potential duplicate\r
+        * destruction (or worse, stale pointer usage).\r
+        */\r
+       p_adapter->p_port = NULL;\r
+\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       KeReleaseMutex( &p_adapter->mutex, FALSE );\r
+\r
+       cl_obj_destroy( &p_adapter->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+adapter_construct(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       cl_obj_construct( &p_adapter->obj, IPOIB_OBJ_INSTANCE );\r
+       cl_spinlock_construct( &p_adapter->send_stat_lock );\r
+       cl_spinlock_construct( &p_adapter->recv_stat_lock );\r
+       cl_qpool_construct( &p_adapter->item_pool );\r
+       KeInitializeMutex( &p_adapter->mutex, 0 );\r
+\r
+       cl_thread_construct(&p_adapter->destroy_thread);\r
+       \r
+       cl_vector_construct( &p_adapter->ip_vector );\r
+\r
+       cl_perf_construct( &p_adapter->perf );\r
+\r
+       p_adapter->state = IB_PNP_PORT_ADD;\r
+       p_adapter->port_rate = FOUR_X_IN_100BPS;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+adapter_init(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       cl_status_t                     cl_status;\r
+       ib_api_status_t         status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       cl_status = cl_perf_init( &p_adapter->perf, MaxPerf );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_perf_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       cl_status = cl_spinlock_init( &p_adapter->send_stat_lock );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_spinlock_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       cl_status = cl_spinlock_init( &p_adapter->recv_stat_lock );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_spinlock_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       cl_status = cl_qpool_init( &p_adapter->item_pool, ITEM_POOL_START, 0,\r
+               ITEM_POOL_GROW, sizeof(cl_pool_obj_t), NULL, NULL, NULL );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_qpool_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+\r
+       /* We manually manage the size and capacity of the vector. */\r
+       cl_status = cl_vector_init( &p_adapter->ip_vector, 0,\r
+               0, sizeof(net_address_item_t), NULL, NULL, p_adapter );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_vector_init for ip_vector returned %#x\n",\r
+                       cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       /* Validate the port GUID and generate the MAC address. */\r
+       status =\r
+               ipoib_mac_from_guid( p_adapter->guids.port_guid.guid, p_adapter->params.guid_mask, &p_adapter->mac);\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               if( status == IB_INVALID_GUID_MASK )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
+                               ("Invalid GUID mask received, rejecting it") );\r
+                       ipoib_create_log(p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+               }\r
+\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_mac_from_guid returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Open AL. */\r
+       status = p_adapter->p_ifc->open_al( &p_adapter->h_al );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_open_al returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__ipoib_pnp_reg(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              ib_pnp_class_t                          flags )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_pnp_req_t            pnp_req;\r
+       \r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( !p_adapter->h_pnp );\r
+       CL_ASSERT( !p_adapter->registering );\r
+\r
+       p_adapter->registering = TRUE;\r
+       \r
+       /* Register for PNP events. */\r
+       cl_memclr( &pnp_req, sizeof(pnp_req) );\r
+       pnp_req.pnp_class = IB_PNP_PORT | flags;\r
+       /*\r
+        * Context is the cl_obj of the adapter to allow passing cl_obj_deref\r
+        * to ib_dereg_pnp.\r
+        */\r
+       pnp_req.pnp_context = &p_adapter->obj;\r
+       pnp_req.pfn_pnp_cb = __ipoib_pnp_cb;\r
+       status = p_adapter->p_ifc->reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               p_adapter->registering = FALSE;\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_reg_pnp returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+       /*\r
+        * Reference the adapter on behalf of the PNP registration.\r
+        * This allows the destruction to block until the PNP deregistration\r
+        * completes.\r
+        */\r
+       cl_obj_ref( &p_adapter->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+static void\r
+__adapter_destroying(\r
+       IN                              cl_obj_t* const                         p_obj )\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );\r
+\r
+       /*\r
+        * The adapter's object will be dereferenced when the deregistration\r
+        * completes.  No need to lock here since all PnP related API calls\r
+        * are driven by NDIS (via the Init/Reset/Destroy paths).\r
+        */\r
+       if( p_adapter->h_pnp )\r
+       {\r
+               p_adapter->p_ifc->dereg_pnp( p_adapter->h_pnp, cl_obj_deref );\r
+               p_adapter->h_pnp = NULL;\r
+       }\r
+\r
+       if( p_adapter->packet_filter )\r
+       {\r
+               KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+               cl_obj_lock( &p_adapter->obj );\r
+\r
+               ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
+               cl_qlist_remove_item( &g_ipoib.adapter_list, &p_adapter->entry );\r
+\r
+               p_adapter->packet_filter = 0;\r
+\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               KeReleaseInStackQueuedSpinLock( &hdl );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__adapter_free(\r
+       IN                              cl_obj_t* const                         p_obj )\r
+{\r
+       ipoib_adapter_t *p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );\r
+\r
+       if( p_adapter->p_ifc )\r
+       {\r
+               if( p_adapter->h_al )\r
+                       p_adapter->p_ifc->close_al( p_adapter->h_al );\r
+\r
+               cl_free( p_adapter->p_ifc );\r
+               p_adapter->p_ifc = NULL;\r
+       }\r
+\r
+       cl_vector_destroy( &p_adapter->ip_vector );\r
+       cl_qpool_destroy( &p_adapter->item_pool );\r
+       cl_spinlock_destroy( &p_adapter->recv_stat_lock );\r
+       cl_spinlock_destroy( &p_adapter->send_stat_lock );\r
+       cl_obj_deinit( p_obj );\r
+\r
+       cl_perf_destroy( &p_adapter->perf, TRUE );\r
+\r
+       cl_free( p_adapter );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+ipoib_query_pkey_index(ipoib_adapter_t *p_adapter)\r
+{\r
+       ib_api_status_t                 status;\r
+       ib_ca_attr_t                *ca_attr;\r
+       uint32_t                            ca_size;\r
+       uint16_t index = 0;\r
+\r
+       /* Query the CA for Pkey table */\r
+       status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, NULL, &ca_size);\r
+       if(status != IB_INSUFFICIENT_MEMORY)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("ib_query_ca failed\n"));\r
+               return status;\r
+       }\r
+\r
+       ca_attr = (ib_ca_attr_t*)cl_zalloc(ca_size);\r
+       if      (!ca_attr)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("cl_zalloc can't allocate %d\n",ca_size));\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, ca_attr,&ca_size);  \r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("ib_query_ca returned %s\n", \r
+                                                p_adapter->p_ifc->get_err_str( status )) );\r
+               goto pkey_end;\r
+       }\r
+       CL_ASSERT(ca_attr->p_port_attr[p_adapter->p_port->port_num -1].p_pkey_table[0] == IB_DEFAULT_PKEY);\r
+       for(index = 0; index < ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys; index++)\r
+       {\r
+               if(cl_hton16(p_adapter->guids.port_guid.pkey) == ca_attr->p_port_attr[p_adapter->p_port->port_num -1].p_pkey_table[index])\r
+                       break;\r
+       }\r
+       if(index >= ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Pkey table is invalid, index not found\n"));\r
+               NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
+                       EVENT_IPOIB_PARTITION_ERR, 1, p_adapter->guids.port_guid.pkey );\r
+               status = IB_NOT_FOUND;\r
+               p_adapter->p_port->pkey_index = PKEY_INVALID_INDEX;\r
+               goto pkey_end;\r
+       }\r
+\r
+       p_adapter->p_port->pkey_index = index;\r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_IB,\r
+                                       ("for PKEY = 0x%04X got index = %d\n",p_adapter->guids.port_guid.pkey,index));\r
+\r
+pkey_end:\r
+       if(ca_attr)\r
+               cl_free(ca_attr);\r
+       return status;\r
+}\r
+\r
+static ib_api_status_t\r
+__ipoib_pnp_cb(\r
+       IN                              ib_pnp_rec_t                            *p_pnp_rec )\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       ipoib_port_t            *p_port;\r
+       ib_pnp_event_t          old_state;\r
+       ib_pnp_port_rec_t       *p_port_rec;\r
+       ib_api_status_t         status = IB_SUCCESS;\r
+       NDIS_LINK_STATE         link_state;\r
+       NDIS_STATUS_INDICATION  status_indication;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_PNP );\r
+\r
+       CL_ASSERT( p_pnp_rec );\r
+       NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
+       p_adapter =\r
+               PARENT_STRUCT( p_pnp_rec->pnp_context, ipoib_adapter_t, obj );\r
+\r
+       CL_ASSERT( p_adapter );\r
+\r
+       /* Synchronize with destruction */\r
+       KeWaitForMutexObject(\r
+               &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
+       cl_obj_lock( &p_adapter->obj );\r
+       old_state = p_adapter->state;\r
+       cl_obj_unlock( &p_adapter->obj );\r
+       if( old_state == IB_PNP_PORT_REMOVE )\r
+       {\r
+               KeReleaseMutex( &p_adapter->mutex, FALSE );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP,\r
+                       ("Aborting - Adapter destroying.\n") );\r
+               return IB_NOT_DONE;\r
+       }\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP,\r
+               ("p_pnp_rec->pnp_event = 0x%x (%s)\n",\r
+               p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
+\r
+       p_port_rec = (ib_pnp_port_rec_t*)p_pnp_rec;\r
+\r
+       switch( p_pnp_rec->pnp_event )\r
+       {\r
+       case IB_PNP_PORT_ADD:\r
+               CL_ASSERT( !p_pnp_rec->context );\r
+               /* Only process our port GUID. */\r
+               if( p_pnp_rec->guid != p_adapter->guids.port_guid.guid )\r
+               {\r
+                       status = IB_NOT_DONE;\r
+                       break;\r
+               }\r
+\r
+               /* Don't process if we're destroying. */\r
+               if( p_adapter->obj.state == CL_DESTROYING )\r
+               {\r
+                       status = IB_NOT_DONE;\r
+                       break;\r
+               }\r
+\r
+               CL_ASSERT( !p_adapter->p_port );\r
+               /* Allocate all IB resources. */\r
+               cl_obj_lock( &p_adapter->obj );\r
+               p_adapter->state = IB_PNP_PORT_ADD;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               status = ipoib_create_port( p_adapter, p_port_rec, &p_port );\r
+               cl_obj_lock( &p_adapter->obj );\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       p_adapter->state = old_state;\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       p_adapter->hung = TRUE;\r
+                       break;\r
+               }\r
+\r
+               p_pnp_rec->context = p_port;\r
+\r
+               p_adapter->p_port = p_port;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               break;\r
+\r
+       case IB_PNP_PORT_REMOVE:\r
+               /* Release all IB resources. */\r
+               CL_ASSERT( p_pnp_rec->context );\r
+\r
+               cl_obj_lock( &p_adapter->obj );\r
+               p_adapter->state = IB_PNP_PORT_REMOVE;\r
+               p_port = p_adapter->p_port;\r
+               p_adapter->p_port = NULL;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               ipoib_port_destroy( p_port );\r
+               p_pnp_rec->context = NULL;\r
+               status = IB_SUCCESS;\r
+               break;\r
+\r
+       case IB_PNP_PORT_ACTIVE:\r
+               /* Join multicast groups and put QP in RTS. */\r
+               CL_ASSERT( p_pnp_rec->context );\r
+\r
+               cl_obj_lock( &p_adapter->obj );\r
+               p_adapter->state = IB_PNP_PORT_INIT;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               ipoib_port_up( p_adapter->p_port, p_port_rec );\r
+\r
+               status = IB_SUCCESS;\r
+               break;\r
+\r
+       case IB_PNP_PORT_ARMED:\r
+               status = IB_SUCCESS;\r
+               break;\r
+\r
+       case IB_PNP_PORT_INIT:\r
+               /*\r
+                * Init could happen if the SM brings the port down\r
+                * without changing the physical link.\r
+                */\r
+       case IB_PNP_PORT_DOWN:\r
+               CL_ASSERT( p_pnp_rec->context );\r
+\r
+               cl_obj_lock( &p_adapter->obj );\r
+               old_state = p_adapter->state;\r
+               p_adapter->state = IB_PNP_PORT_DOWN;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               status = IB_SUCCESS;\r
+\r
+               if( !p_adapter->registering && old_state != IB_PNP_PORT_DOWN )\r
+               {\r
+                       link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+                       link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+                       link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+                       link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+                       link_state.MediaDuplexState = MediaDuplexStateFull;\r
+                       link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+                       IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                   p_adapter->h_adapter,\r
+                                   NDIS_STATUS_LINK_STATE,\r
+                                   (PVOID)&link_state,\r
+                                   sizeof(link_state));\r
+\r
+                       NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                               ("Link DOWN!\n") );\r
+\r
+                       ipoib_port_down( p_adapter->p_port );\r
+               }\r
+               break;\r
+\r
+       case IB_PNP_REG_COMPLETE:\r
+               if( p_adapter->registering )\r
+               {\r
+                       p_adapter->registering = FALSE;\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       old_state = p_adapter->state;\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+\r
+                       if( old_state == IB_PNP_PORT_DOWN )\r
+                       {\r
+                               /* If we were initializing, we might have pended some OIDs. */\r
+                               ipoib_resume_oids( p_adapter );\r
+\r
+                               link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+                               link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+                               link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+                               link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+                               link_state.MediaDuplexState = MediaDuplexStateFull;\r
+                               link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+                               IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                                                          p_adapter->h_adapter,\r
+                                                                          NDIS_STATUS_LINK_STATE,\r
+                                                                          (PVOID)&link_state,\r
+                                                                          sizeof(link_state));\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
+                       ("Indicate DISCONNECT\n") );\r
+                               NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);                 \r
+                       }\r
+               }\r
+\r
+               if( p_adapter->reset && p_adapter->state != IB_PNP_PORT_INIT )\r
+               {\r
+                       p_adapter->reset = FALSE;\r
+                       NdisMResetComplete(\r
+                               p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
+               }\r
+               status = IB_SUCCESS;\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("IPOIB: Received unhandled PnP event 0x%x (%s)\n",\r
+                       p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
+               /* Fall through. */\r
+\r
+               status = IB_SUCCESS;\r
+\r
+               /* We ignore events below if the link is not active. */\r
+               if( p_port_rec->p_port_attr->link_state != IB_LINK_ACTIVE )\r
+                       break;\r
+\r
+               case IB_PNP_PKEY_CHANGE:\r
+                       if(p_pnp_rec->pnp_event == IB_PNP_PKEY_CHANGE && \r
+                          p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
+                       {\r
+                               status = ipoib_query_pkey_index(p_adapter);\r
+                               if(status != IB_SUCCESS)\r
+                               {\r
+                                  cl_obj_lock( &p_adapter->obj );\r
+                                  p_adapter->state = IB_PNP_PORT_INIT;\r
+                                  cl_obj_unlock( &p_adapter->obj );\r
+                               }\r
+                       }\r
+\r
+               case IB_PNP_SM_CHANGE:\r
+               case IB_PNP_GID_CHANGE:\r
+               case IB_PNP_LID_CHANGE:\r
+\r
+               cl_obj_lock( &p_adapter->obj );\r
+               old_state = p_adapter->state;\r
+               switch( old_state )\r
+               {\r
+               case IB_PNP_PORT_DOWN:\r
+                       p_adapter->state = IB_PNP_PORT_INIT;\r
+                       break;\r
+\r
+               default:\r
+                       p_adapter->state = IB_PNP_PORT_DOWN;\r
+               }\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               \r
+               if( p_adapter->registering )\r
+                       break;\r
+\r
+               switch( old_state )\r
+               {\r
+               case IB_PNP_PORT_ACTIVE:\r
+               case IB_PNP_PORT_INIT:\r
+                       link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+                       link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+                       link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+                       link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+                       link_state.MediaDuplexState = MediaDuplexStateFull;\r
+                       link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+                       IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                                                  p_adapter->h_adapter,\r
+                                                                  NDIS_STATUS_LINK_STATE,\r
+                                                                  (PVOID)&link_state,\r
+                                                                  sizeof(link_state));\r
+\r
+                       NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);         \r
+\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                               ("Link DOWN!\n") );\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
+                       ("Indicate DISCONNECT\n") );\r
+\r
+                       ipoib_port_down( p_adapter->p_port );\r
+                       /* Fall through. */\r
+\r
+               case IB_PNP_PORT_DOWN:\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       p_adapter->state = IB_PNP_PORT_INIT;\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       ipoib_port_up( p_adapter->p_port, (ib_pnp_port_rec_t*)p_pnp_rec );\r
+               }\r
+               break;\r
+       }\r
+\r
+       KeReleaseMutex( &p_adapter->mutex, FALSE );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+\r
+/* Joins/leaves mcast groups based on currently programmed mcast MACs. */\r
+void\r
+ipoib_refresh_mcast(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              mac_addr_t* const                       p_mac_array,\r
+       IN              const   uint8_t                                         num_macs )\r
+{\r
+       uint8_t                         i, j;\r
+       ipoib_port_t            *p_port = NULL;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+       cl_obj_lock( &p_adapter->obj );\r
+       if( p_adapter->state == IB_PNP_PORT_ACTIVE )\r
+       {\r
+               p_port = p_adapter->p_port;\r
+               ipoib_port_ref( p_port, ref_refresh_mcast );\r
+       }\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       if( p_port )\r
+       {\r
+               /* Purge old entries. */\r
+               for( i = 0; i < p_adapter->mcast_array_size; i++ )\r
+               {\r
+                       for( j = 0; j < num_macs; j++ )\r
+                       {\r
+                               if( !cl_memcmp( &p_adapter->mcast_array[i], &p_mac_array[j],\r
+                                       sizeof(mac_addr_t) ) )\r
+                               {\r
+                                       break;\r
+                               }\r
+                       }\r
+                       if( j != num_macs )\r
+                               continue;\r
+\r
+                       ipoib_port_remove_endpt( p_port, p_adapter->mcast_array[i] );\r
+               }\r
+\r
+               /* Add new entries */\r
+               for( i = 0; i < num_macs; i++ )\r
+               {\r
+                       for( j = 0; j < p_adapter->mcast_array_size; j++ )\r
+                       {\r
+                               if( !cl_memcmp( &p_adapter->mcast_array[j], &p_mac_array[i],\r
+                                       sizeof(mac_addr_t) ) )\r
+                               {\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       if( j != p_adapter->mcast_array_size )\r
+                               continue;\r
+                       if ( ( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e &&\r
+                                  p_mac_array[i].addr[3] == 0 && p_mac_array[i].addr[4] == 0 && p_mac_array[i].addr[5] == 1 ) ||\r
+                                 !( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e )\r
+                               )\r
+                       {\r
+                               ipoib_port_join_mcast( p_port, p_mac_array[i], IB_MC_REC_STATE_FULL_MEMBER );\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* Copy the MAC array. */\r
+       NdisMoveMemory( p_adapter->mcast_array, p_mac_array,\r
+               num_macs * sizeof(mac_addr_t) );\r
+       p_adapter->mcast_array_size = num_macs;\r
+\r
+       if( p_port )\r
+               ipoib_port_deref( p_port, ref_refresh_mcast );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ipoib_reset_adapter(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_pnp_handle_t         h_pnp;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       if( p_adapter->reset )\r
+               return IB_INVALID_STATE;\r
+\r
+       p_adapter->hung = FALSE;\r
+       p_adapter->reset = TRUE;\r
+\r
+       if( p_adapter->h_pnp )\r
+       {\r
+               h_pnp = p_adapter->h_pnp;\r
+               p_adapter->h_pnp  = NULL;\r
+               status = p_adapter->p_ifc->dereg_pnp( h_pnp, __ipoib_pnp_dereg );\r
+               if( status == IB_SUCCESS )\r
+                       status = IB_NOT_DONE;\r
+       }\r
+       else\r
+       {\r
+               status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );\r
+               if( status == IB_SUCCESS )\r
+                       p_adapter->hung = FALSE;\r
+       }\r
+       if (status == IB_NOT_DONE) {\r
+               p_adapter->reset = TRUE;\r
+       }\r
+       else {\r
+               p_adapter->reset = FALSE;\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+static void\r
+__ipoib_pnp_dereg(\r
+       IN                              void*                                           context )\r
+{\r
+       ipoib_adapter_t*        p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_adapter = PARENT_STRUCT( context, ipoib_adapter_t, obj );\r
+\r
+       cl_thread_init(&p_adapter->destroy_thread, __ipoib_adapter_reset, (void*)p_adapter, "destroy_thread");\r
+       \r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+}\r
+\r
+static void\r
+__ipoib_adapter_reset(\r
+       IN                              void*   context)\r
+{\r
+\r
+       ipoib_adapter_t *p_adapter;\r
+       ipoib_port_t            *p_port;\r
+       ib_api_status_t         status;\r
+       ib_pnp_event_t          state;\r
+       \r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_adapter = (ipoib_adapter_t*)context;\r
+       \r
+       /* Synchronize with destruction */\r
+       KeWaitForMutexObject(\r
+               &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
+\r
+       cl_obj_lock( &p_adapter->obj );\r
+\r
+       CL_ASSERT( !p_adapter->h_pnp );\r
+\r
+       if( p_adapter->state != IB_PNP_PORT_REMOVE )\r
+               p_adapter->state = IB_PNP_PORT_ADD;\r
+\r
+       state = p_adapter->state;\r
+\r
+       /* Destroy the current port instance if it still exists. */\r
+       p_port = p_adapter->p_port;\r
+       p_adapter->p_port = NULL;\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       if( p_port )\r
+               ipoib_port_destroy( p_port );\r
+       ASSERT(p_adapter->reset == TRUE);\r
+       if( state != IB_PNP_PORT_REMOVE )\r
+       {\r
+               status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       p_adapter->reset = FALSE;\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("__ipoib_pnp_reg returned %s\n",\r
+                               p_adapter->p_ifc->get_err_str( status )) );\r
+                       NdisMResetComplete( \r
+                               p_adapter->h_adapter, NDIS_STATUS_HARD_ERRORS, TRUE );\r
+               }\r
+       }\r
+       else\r
+       {\r
+               p_adapter->reset = FALSE;\r
+               NdisMResetComplete(\r
+                       p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
+               status = IB_SUCCESS;\r
+       }\r
+\r
+       /* Dereference the adapter since the previous registration is now gone. */\r
+       cl_obj_deref( &p_adapter->obj );\r
+\r
+       KeReleaseMutex( &p_adapter->mutex, FALSE );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+void\r
+ipoib_set_rate(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   uint8_t                                         link_width, \r
+       IN              const   uint8_t                                         link_speed )\r
+{\r
+       uint32_t        rate;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /* Set the link speed based on the IB link speed (1x vs 4x, etc). */\r
+       switch( link_speed )\r
+       {\r
+       case IB_LINK_SPEED_ACTIVE_2_5:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Link speed is 2.5Gs\n") );\r
+               rate = IB_LINK_SPEED_ACTIVE_2_5;\r
+               break;\r
+\r
+       case IB_LINK_SPEED_ACTIVE_5:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Link speed is 5G\n") );\r
+               rate = IB_LINK_SPEED_ACTIVE_5;\r
+               break;\r
+\r
+       case IB_LINK_SPEED_ACTIVE_10:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Link speed is 10G\n") );\r
+               rate = IB_LINK_SPEED_ACTIVE_10;\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid link speed %d.\n", link_speed) );\r
+               rate = 0;\r
+       }\r
+\r
+       switch( link_width )\r
+       {\r
+       case IB_LINK_WIDTH_ACTIVE_1X:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Link width is 1X\n") );\r
+               rate *= ONE_X_IN_100BPS;\r
+               break;\r
+\r
+       case IB_LINK_WIDTH_ACTIVE_4X:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Link width is 4X\n") );\r
+               rate *= FOUR_X_IN_100BPS;\r
+               break;\r
+\r
+       case IB_LINK_WIDTH_ACTIVE_12X:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Link width is 12X\n") );\r
+               rate *= TWELVE_X_IN_100BPS;\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid link rate (%d).\n", link_width) );\r
+               rate = 0;\r
+       }\r
+\r
+       p_adapter->port_rate = rate;\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ipoib_set_active(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       ib_pnp_event_t  old_state;\r
+       uint8_t                 i;\r
+       ib_api_status_t status = IB_SUCCESS;\r
+       NDIS_LINK_STATE         link_state;\r
+       NDIS_STATUS_INDICATION  status_indication;\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
+       cl_obj_lock( &p_adapter->obj );\r
+       old_state = p_adapter->state;\r
+\r
+       /* Change the state to indicate that we are now connected and live. */\r
+       if( old_state == IB_PNP_PORT_INIT )\r
+               p_adapter->state = IB_PNP_PORT_ACTIVE;\r
+\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       /*\r
+        * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
+        * complete it now.\r
+        */\r
+       switch( old_state )\r
+       {\r
+       case IB_PNP_PORT_ADD:\r
+               ipoib_reg_addrs( p_adapter );\r
+               /* Fall through. */\r
+\r
+       case IB_PNP_PORT_REMOVE:\r
+               ipoib_resume_oids( p_adapter );\r
+               break;\r
+\r
+       default:\r
+               if (p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
+               {\r
+                       status = ipoib_query_pkey_index(p_adapter);\r
+                       if( IB_SUCCESS != status)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+               /* Join all programmed multicast groups. */\r
+               for( i = 0; i < p_adapter->mcast_array_size; i++ )\r
+               {\r
+                       ipoib_port_join_mcast(\r
+                               p_adapter->p_port, p_adapter->mcast_array[i] ,IB_MC_REC_STATE_FULL_MEMBER);\r
+               }\r
+\r
+               /* Register all existing addresses. */\r
+               ipoib_reg_addrs( p_adapter );\r
+\r
+               ipoib_resume_oids( p_adapter );\r
+\r
+               /*\r
+                * Now that we're in the broadcast group, notify that\r
+                * we have a link.\r
+                */\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Link UP!\n") );\r
+               NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
+                       EVENT_IPOIB_PORT_UP + (p_adapter->port_rate/ONE_X_IN_100BPS),\r
+                       1, p_adapter->port_rate );\r
+\r
+               if( !p_adapter->reset )\r
+               {\r
+                       link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+                       link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+                       link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+                       link_state.MediaConnectState = MediaConnectStateConnected;\r
+                       link_state.MediaDuplexState = MediaDuplexStateFull;\r
+                       link_state.XmitLinkSpeed = \r
+                       link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+                       link_state.PauseFunctions = NdisPauseFunctionsSendAndReceive;\r
+                       IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                                                  p_adapter->h_adapter,\r
+                                                                  NDIS_STATUS_LINK_STATE,\r
+                                                                  (PVOID)&link_state,\r
+                                                                  sizeof(link_state));\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("***************Indicate connect!\n") );\r
+                       NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
+               }\r
+       }\r
+\r
+       if( p_adapter->reset )\r
+       {\r
+               ASSERT(FALSE);\r
+               p_adapter->reset = FALSE;\r
+               NdisMResetComplete(\r
+                       p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return  status;\r
+}\r
+\r
+/*\r
+ * If something goes wrong after the port goes active, e.g.\r
+ *     - PortInfo query failure\r
+ *     - MC Join timeout\r
+ *     - etc\r
+ * Mark the port state as down, resume any pended OIDS, etc.\r
+ */\r
+void\r
+ipoib_set_inactive(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       ib_pnp_event_t  old_state;\r
+       NDIS_LINK_STATE         link_state;\r
+       NDIS_STATUS_INDICATION  status_indication;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
+       cl_obj_lock( &p_adapter->obj );\r
+       old_state = p_adapter->state;\r
+       if( old_state != IB_PNP_PORT_REMOVE )\r
+               p_adapter->state = IB_PNP_PORT_DOWN;\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       /*\r
+        * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
+        * complete it now.\r
+        */\r
+       if( old_state == IB_PNP_PORT_INIT )\r
+       {\r
+               link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+               link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+               link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+               link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+               link_state.MediaDuplexState = MediaDuplexStateFull;\r
+               link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+               IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                                          p_adapter->h_adapter,\r
+                                                          NDIS_STATUS_LINK_STATE,\r
+                                                          (PVOID)&link_state,\r
+                                                          sizeof(link_state));\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate Disconnect!\n") );\r
+               NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
+\r
+               ipoib_resume_oids( p_adapter );\r
+       }\r
+\r
+       if( p_adapter->reset )\r
+       {\r
+               p_adapter->reset = FALSE;\r
+               NdisMResetComplete(\r
+                       p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+NDIS_STATUS\r
+ipoib_get_gen_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       OUT             pending_oid_t* const            p_oid_info)\r
+{\r
+       PNDIS_STATISTICS_INFO StatisticsInfo;\r
+       IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+       if (p_oid_info->buf_len < sizeof(StatisticsInfo))\r
+       {\r
+               *p_oid_info->p_bytes_needed = sizeof(NDIS_STATISTICS_INFO);\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+       }\r
+\r
+       StatisticsInfo = (PNDIS_STATISTICS_INFO)p_oid_info->p_buf;\r
+    StatisticsInfo->Header.Revision = NDIS_OBJECT_REVISION_1;\r
+    StatisticsInfo->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+    StatisticsInfo->Header.Size = sizeof(NDIS_STATISTICS_INFO);\r
+    /*StatisticsInfo->SupportedStatistics = NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS          |\r
+                                          NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR             |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV   |\r
+                                          NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV  |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV  |\r
+                                          NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV             | \r
+                                          NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV   |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV       |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV        |\r
+\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS                     |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR            |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT  | \r
+                                          NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT                        |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT       |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT      |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT; */\r
+                                                                                 \r
+                                                                                 \r
+       StatisticsInfo->SupportedStatistics =  NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV |\r
+                                                                                       //The data in the ifHCInUcastPkts member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV |\r
+                                                                                       //The data in the ifHCInMulticastPkts member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV |\r
+                                                                                       //The data in the ifHCInBroadcastPkts member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV |\r
+                                                                                       //The data in the ifHCInOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS |\r
+                                                                                       //The data in the ifInDiscards member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR |\r
+                                                                                       //The data in the ifInErrors member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT |\r
+                                                                                       //The data in the ifHCOutUcastPkts member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |\r
+                                                                                       //The data in the ifHCOutMulticastPkts member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |\r
+                                                                                       //The data in the ifHCOutBroadcastPkts member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT |\r
+                                                                                       //The data in the ifHCOutOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR |\r
+                                                                                       //The data in the ifOutErrors member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS |\r
+                                                                                       //The data in the ifOutDiscards member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV |\r
+                                                                                       //The data in the ifHCInUcastOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV |\r
+                                                                                       //The data in the ifHCInMulticastOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV |\r
+                                                                                       //The data in the ifHCInBroadcastOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT |\r
+                                                                                       //The data in the ifHCOutUcastOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT |\r
+                                                                                       //The data in the ifHCOutMulticastOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT ;\r
+                                                                                       //The data in the ifHCOutBroadcastOctets member is valid\r
+\r
+    cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
+    StatisticsInfo->ifInDiscards = p_adapter->recv_stats.comp.dropped +\r
+                                   p_adapter->recv_stats.comp.error;            \r
+    StatisticsInfo->ifInErrors = p_adapter->recv_stats.comp.error;\r
+    StatisticsInfo->ifHCInOctets = p_adapter->recv_stats.ucast.bytes + \r
+                                                                  p_adapter->recv_stats.bcast.bytes + \r
+                                                                  p_adapter->recv_stats.mcast.bytes;       \r
+    StatisticsInfo->ifHCInUcastPkts       = p_adapter->recv_stats.ucast.frames;\r
+    StatisticsInfo->ifHCInMulticastPkts   = p_adapter->recv_stats.mcast.frames;  \r
+    StatisticsInfo->ifHCInBroadcastPkts   = p_adapter->recv_stats.bcast.frames;  \r
+       StatisticsInfo->ifHCInMulticastOctets = p_adapter->recv_stats.mcast.bytes;\r
+       StatisticsInfo->ifHCInBroadcastOctets = p_adapter->recv_stats.bcast.bytes;\r
+       StatisticsInfo->ifHCInUcastOctets     = p_adapter->recv_stats.ucast.bytes;\r
+       cl_spinlock_release( &p_adapter->recv_stat_lock );\r
+\r
+    cl_spinlock_acquire( &p_adapter->send_stat_lock ); \r
+    StatisticsInfo->ifHCOutOctets = p_adapter->send_stats.ucast.bytes + \r
+                                                                       p_adapter->send_stats.mcast.bytes + \r
+                                                                       p_adapter->send_stats.bcast.bytes;        \r
+    StatisticsInfo->ifHCOutUcastPkts       = p_adapter->send_stats.ucast.frames;     \r
+    StatisticsInfo->ifHCOutMulticastPkts   = p_adapter->send_stats.mcast.frames; \r
+    StatisticsInfo->ifHCOutBroadcastPkts   = p_adapter->send_stats.bcast.frames; \r
+    StatisticsInfo->ifOutErrors            = p_adapter->send_stats.comp.error;                                      \r
+    StatisticsInfo->ifOutDiscards          = p_adapter->send_stats.comp.dropped;\r
+       StatisticsInfo->ifHCOutUcastOctets     = p_adapter->send_stats.ucast.bytes;\r
+       StatisticsInfo->ifHCOutMulticastOctets = p_adapter->send_stats.mcast.bytes;\r
+       StatisticsInfo->ifHCOutBroadcastOctets = p_adapter->send_stats.bcast.bytes;\r
+    cl_spinlock_release( &p_adapter->send_stat_lock );\r
+\r
+       *p_oid_info->p_bytes_used = sizeof(NDIS_STATISTICS_INFO);\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+NDIS_STATUS\r
+ipoib_get_recv_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN                              pending_oid_t* const            p_oid_info )\r
+{\r
+       uint64_t        stat;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+       CL_ASSERT( p_adapter );\r
+\r
+       cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
+       switch( stat_sel )\r
+       {\r
+       case IP_STAT_SUCCESS:\r
+               stat = p_adapter->recv_stats.comp.success;\r
+               break;\r
+\r
+       case IP_STAT_ERROR:\r
+               stat = p_adapter->recv_stats.comp.error;\r
+               break;\r
+\r
+       case IP_STAT_DROPPED:\r
+               stat = p_adapter->recv_stats.comp.dropped;\r
+               break;\r
+\r
+       case IP_STAT_UCAST_BYTES:\r
+               stat = p_adapter->recv_stats.ucast.bytes;\r
+               break;\r
+\r
+       case IP_STAT_UCAST_FRAMES:\r
+               stat = p_adapter->recv_stats.ucast.frames;\r
+               break;\r
+\r
+       case IP_STAT_BCAST_BYTES:\r
+               stat = p_adapter->recv_stats.bcast.bytes;\r
+               break;\r
+\r
+       case IP_STAT_BCAST_FRAMES:\r
+               stat = p_adapter->recv_stats.bcast.frames;\r
+               break;\r
+\r
+       case IP_STAT_MCAST_BYTES:\r
+               stat = p_adapter->recv_stats.mcast.bytes;\r
+               break;\r
+\r
+       case IP_STAT_MCAST_FRAMES:\r
+               stat = p_adapter->recv_stats.mcast.frames;\r
+               break;\r
+\r
+       default:\r
+               stat = 0;\r
+       }\r
+       cl_spinlock_release( &p_adapter->recv_stat_lock );\r
+\r
+       *p_oid_info->p_bytes_needed = sizeof(uint64_t);\r
+\r
+       if( p_oid_info->buf_len >= sizeof(uint64_t) )\r
+       {\r
+               *((uint64_t*)p_oid_info->p_buf) = stat;\r
+               *p_oid_info->p_bytes_used = sizeof(uint64_t);\r
+       }\r
+       else if( p_oid_info->buf_len >= sizeof(uint32_t) )\r
+       {\r
+               *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;\r
+               *p_oid_info->p_bytes_used = sizeof(uint32_t);\r
+       }\r
+       else\r
+       {\r
+               *p_oid_info->p_bytes_used = 0;\r
+               IPOIB_EXIT( IPOIB_DBG_STAT );\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_STAT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+ipoib_inc_recv_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN              const   size_t                                          bytes OPTIONAL,\r
+       IN              const   size_t                                          packets OPTIONAL )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+       cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
+       switch( stat_sel )\r
+       {\r
+       case IP_STAT_ERROR:\r
+               p_adapter->recv_stats.comp.error++;\r
+               break;\r
+\r
+       case IP_STAT_DROPPED:\r
+               p_adapter->recv_stats.comp.dropped++;\r
+               break;\r
+\r
+       case IP_STAT_UCAST_BYTES:\r
+       case IP_STAT_UCAST_FRAMES:\r
+               p_adapter->recv_stats.comp.success++;\r
+               p_adapter->recv_stats.ucast.frames += packets;\r
+               p_adapter->recv_stats.ucast.bytes += bytes;\r
+               break;\r
+\r
+       case IP_STAT_BCAST_BYTES:\r
+       case IP_STAT_BCAST_FRAMES:\r
+               p_adapter->recv_stats.comp.success++;\r
+               p_adapter->recv_stats.bcast.frames += packets;\r
+               p_adapter->recv_stats.bcast.bytes += bytes;\r
+               break;\r
+\r
+       case IP_STAT_MCAST_BYTES:\r
+       case IP_STAT_MCAST_FRAMES:\r
+               p_adapter->recv_stats.comp.success++;\r
+               p_adapter->recv_stats.mcast.frames += packets;\r
+               p_adapter->recv_stats.mcast.bytes += bytes;\r
+               break;\r
+\r
+       default:\r
+               break;\r
+       }\r
+       cl_spinlock_release( &p_adapter->recv_stat_lock );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_STAT );\r
+}\r
+\r
+NDIS_STATUS\r
+ipoib_get_send_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN                              pending_oid_t* const            p_oid_info )\r
+{\r
+       uint64_t        stat;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+       CL_ASSERT( p_adapter );\r
+\r
+       cl_spinlock_acquire( &p_adapter->send_stat_lock );\r
+       switch( stat_sel )\r
+       {\r
+       case IP_STAT_SUCCESS:\r
+               stat = p_adapter->send_stats.comp.success;\r
+               break;\r
+\r
+       case IP_STAT_ERROR:\r
+               stat = p_adapter->send_stats.comp.error;\r
+               break;\r
+\r
+       case IP_STAT_DROPPED:\r
+               stat = p_adapter->send_stats.comp.dropped;\r
+               break;\r
+\r
+       case IP_STAT_UCAST_BYTES:\r
+               stat = p_adapter->send_stats.ucast.bytes;\r
+               break;\r
+\r
+       case IP_STAT_UCAST_FRAMES:\r
+               stat = p_adapter->send_stats.ucast.frames;\r
+               break;\r
+\r
+       case IP_STAT_BCAST_BYTES:\r
+               stat = p_adapter->send_stats.bcast.bytes;\r
+               break;\r
+\r
+       case IP_STAT_BCAST_FRAMES:\r
+               stat = p_adapter->send_stats.bcast.frames;\r
+               break;\r
+\r
+       case IP_STAT_MCAST_BYTES:\r
+               stat = p_adapter->send_stats.mcast.bytes;\r
+               break;\r
+\r
+       case IP_STAT_MCAST_FRAMES:\r
+               stat = p_adapter->send_stats.mcast.frames;\r
+               break;\r
+\r
+       default:\r
+               stat = 0;\r
+       }\r
+       cl_spinlock_release( &p_adapter->send_stat_lock );\r
+\r
+       *p_oid_info->p_bytes_needed = sizeof(uint64_t);\r
+\r
+       if( p_oid_info->buf_len >= sizeof(uint64_t) )\r
+       {\r
+               *((uint64_t*)p_oid_info->p_buf) = stat;\r
+               *p_oid_info->p_bytes_used = sizeof(uint64_t);\r
+       }\r
+       else if( p_oid_info->buf_len >= sizeof(uint32_t) )\r
+       {\r
+               *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;\r
+               *p_oid_info->p_bytes_used = sizeof(uint32_t);\r
+       }\r
+       else\r
+       {\r
+               *p_oid_info->p_bytes_used = 0;\r
+               IPOIB_EXIT( IPOIB_DBG_STAT );\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_STAT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+ipoib_inc_send_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN              const   size_t                                          bytes OPTIONAL )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+       cl_spinlock_acquire( &p_adapter->send_stat_lock );\r
+       switch( stat_sel )\r
+       {\r
+       case IP_STAT_ERROR:\r
+               p_adapter->send_stats.comp.error++;\r
+               break;\r
+\r
+       case IP_STAT_DROPPED:\r
+               p_adapter->send_stats.comp.dropped++;\r
+               break;\r
+\r
+       case IP_STAT_UCAST_BYTES:\r
+       case IP_STAT_UCAST_FRAMES:\r
+               p_adapter->send_stats.comp.success++;\r
+               p_adapter->send_stats.ucast.frames++;\r
+               p_adapter->send_stats.ucast.bytes += bytes;\r
+               break;\r
+\r
+       case IP_STAT_BCAST_BYTES:\r
+       case IP_STAT_BCAST_FRAMES:\r
+               p_adapter->send_stats.comp.success++;\r
+               p_adapter->send_stats.bcast.frames++;\r
+               p_adapter->send_stats.bcast.bytes += bytes;\r
+               break;\r
+\r
+       case IP_STAT_MCAST_BYTES:\r
+       case IP_STAT_MCAST_FRAMES:\r
+               p_adapter->send_stats.comp.success++;\r
+               p_adapter->send_stats.mcast.frames++;\r
+               p_adapter->send_stats.mcast.bytes += bytes;\r
+               break;\r
+\r
+       default:\r
+               break;\r
+       }\r
+       cl_spinlock_release( &p_adapter->send_stat_lock );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_STAT );\r
+}\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_adapter.h b/trunk/ulp/ipoib/kernel6/ipoib_adapter.h
new file mode 100644 (file)
index 0000000..f8ab4c4
--- /dev/null
@@ -0,0 +1,483 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_adapter.h 4226 2009-04-06 06:01:03Z xalex $\r
+ */\r
+\r
+\r
+#ifndef _IPOIB_ADAPTER_H_\r
+#define _IPOIB_ADAPTER_H_\r
+\r
+#include <iba/ipoib_ifc.h>\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_obj.h>\r
+#include <complib/cl_spinlock.h>\r
+#include <complib/cl_mutex.h>\r
+#include <complib/cl_qpool.h>\r
+#include <complib/cl_atomic.h>\r
+#include <complib/cl_perf.h>\r
+#include <complib/cl_vector.h>\r
+#include <ip_packet.h>\r
+#include "ip_stats.h"\r
+\r
+\r
+/*\r
+ * Definitions\r
+ */\r
+#define MAX_MCAST                              32\r
+\r
+#define IPV4_ADDR_SIZE                 4\r
+\r
+#define PORT_NUM_INDEX_IN_GUID 3 /* 0 based index into big endian GUID to get port number */\r
+\r
+/*\r
+ * Macros\r
+ */\r
+typedef enum \r
+{\r
+       CSUM_DISABLED = 0, \r
+       CSUM_ENABLED, \r
+       CSUM_BYPASS\r
+} csum_flag_t;\r
+\r
+typedef enum _ipoib_state\r
+{\r
+    IPOIB_PAUSED,\r
+    IPOIB_PAUSING,\r
+    IPOIB_RUNNING\r
+} ipoib_state_t;\r
+\r
+typedef struct _ipoib_params\r
+{\r
+       int32_t         rq_depth;\r
+       int32_t         rq_low_watermark;\r
+       int32_t         sq_depth;\r
+       csum_flag_t     send_chksum_offload;\r
+       csum_flag_t     recv_chksum_offload;\r
+       uint32_t        sa_timeout;\r
+       uint32_t        sa_retry_cnt;\r
+       uint32_t        recv_pool_ratio;\r
+       uint32_t        payload_mtu;\r
+       boolean_t       lso;\r
+       uint32_t        xfer_block_size;\r
+       mac_addr_t      conf_mac;\r
+       uint32_t        mc_leave_rescan;\r
+       uint32_t        guid_mask;\r
+       uint32_t        bc_join_retry;\r
+       boolean_t       cm_enabled;\r
+       uint32_t        cm_payload_mtu;\r
+       uint32_t        cm_xfer_block_size;\r
+}      ipoib_params_t;\r
+/*\r
+* FIELDS\r
+*      rq_depth\r
+*              Number of receive WQEs to allocate.\r
+*\r
+*      rq_low_watermark\r
+*              Receives are indicated with NDIS_STATUS_RESOURCES when the number of\r
+*              receives posted to the RQ falls bellow this value.\r
+*\r
+*      sq_depth\r
+*              Number of send WQEs to allocate.\r
+*\r
+*      send_chksum_offload\r
+*      recv_chksum_offload\r
+*              Flags to indicate whether to offload send/recv checksums.\r
+*              0 - No hardware cheksum\r
+*              1 - Try to offload if the device support it\r
+*              2 - Always report success (checksum bypass)\r
+*\r
+*      wsdp_enabled\r
+*              Flag to indicate whether WSDP is enabled for an adapter adapter.\r
+*\r
+*      static_lid\r
+*              LID to assign to the port if that port is down (not init) and has none.\r
+*              This feature allows a LID to be assigned, alowing locally targetted\r
+*              traffic to occur even on ports that are not plugged in.\r
+*\r
+*      sa_timeout\r
+*              Time, in milliseconds, to wait for a response before retransmitting an\r
+*              SA query request.\r
+*\r
+*      sa_retry_cnt\r
+*              Number of times to retry an SA query request.\r
+*\r
+*      recv_pool_ratio\r
+*              Initial ratio of receive pool size to receive queue depth.\r
+*\r
+*      grow_thresh\r
+*              Threshold at which to grow the receive pool.  Valid values start are\r
+*              powers of 2, excluding 1.  When zero, grows only when the pool is\r
+*              exhausted.  Other values indicate fractional values\r
+*              (i.e. 2 indicates 1/2, 4 indicates 1/4, etc.)\r
+*\r
+*      payload_mtu\r
+               The maximum available size of IPoIB transfer unit.\r
+               \r
+               If using UD mode:\r
+*              It should be decremented by size of IPoIB header (==4B)\r
+*              For example, if the HCA support 4K MTU, \r
+*              upper threshold for payload mtu is 4092B and not 4096B\r
+\r
+               If using CM mode:\r
+               MTU will be not limited by 4K threshold.\r
+               UD QP still may be used for different protocols (like ARP).\r
+               For these situations the threshold for the UD QP will take the default value\r
+               \r
+*\r
+*      lso\r
+*      It indicates if there's a support for hardware large/giant send offload\r
+*              \r
+*********/\r
+\r
+\r
+typedef struct _pending_oid\r
+{\r
+       NDIS_OID                        oid;\r
+       PVOID                           p_buf;\r
+       ULONG                           buf_len;\r
+       PULONG                          p_bytes_used;\r
+       PULONG                          p_bytes_needed;\r
+       PNDIS_OID_REQUEST       p_pending_oid;\r
+}      pending_oid_t;\r
+\r
+\r
+typedef struct _ipoib_adapter\r
+{\r
+       cl_obj_t                                obj;\r
+       NDIS_HANDLE                             h_adapter;\r
+       ipoib_ifc_data_t                guids;\r
+\r
+       cl_list_item_t                  entry;\r
+\r
+       ib_al_handle_t                  h_al;\r
+       ib_pnp_handle_t                 h_pnp;\r
+\r
+       ib_pnp_event_t                  state;\r
+       boolean_t                               hung;\r
+       boolean_t                               reset;\r
+       boolean_t                               registering;\r
+\r
+       boolean_t                               pending_query;\r
+       pending_oid_t                   query_oid;\r
+       boolean_t                               pending_set;\r
+       pending_oid_t                   set_oid;\r
+\r
+       struct _ipoib_port              *p_port;\r
+\r
+       uint32_t                                port_rate;\r
+\r
+       ipoib_params_t                  params;\r
+       cl_spinlock_t                   recv_stat_lock;\r
+       ip_stats_t                              recv_stats;\r
+       cl_spinlock_t                   send_stat_lock;\r
+       ip_stats_t                              send_stats;\r
+\r
+       boolean_t                               is_primary;\r
+       struct _ipoib_adapter   *p_primary;\r
+\r
+       uint32_t                                packet_filter;\r
+\r
+       mac_addr_t                              mac;\r
+       mac_addr_t                              mcast_array[MAX_MCAST];\r
+       uint8_t                                 mcast_array_size;\r
+\r
+       cl_qpool_t                              item_pool;\r
+\r
+       KMUTEX                                  mutex;\r
+\r
+       cl_thread_t                             destroy_thread;\r
+       cl_vector_t                             ip_vector;\r
+\r
+       cl_perf_t                               perf;\r
+    NDIS_HANDLE                        NdisMiniportDmaHandle;\r
+       ipoib_state_t                   ipoib_state;\r
+       ib_al_ifc_t                             *p_ifc;\r
+\r
+       ULONG                                   sg_list_size;\r
+\r
+}      ipoib_adapter_t;\r
+/*\r
+* FIELDS\r
+*      obj\r
+*              Complib object for reference counting and destruction synchronization.\r
+*\r
+*      h_adapter\r
+*              NDIS adapter handle.\r
+*\r
+*      guids\r
+*              CA and port GUIDs returned by the bus driver.\r
+*\r
+*      entry\r
+*              List item for storing all adapters in a list for address translation.\r
+*              We add adapters when their packet filter is set to a non-zero value,\r
+*              and remove them when their packet filter is cleared.  This is needed\r
+*              since user-mode removal events are generated after the packet filter\r
+*              is cleared, but before the adapter is destroyed.\r
+*\r
+*      h_al\r
+*              AL handle for all IB resources.\r
+*\r
+*      h_pnp\r
+*              PNP registration handle for port events.\r
+*\r
+*      state\r
+*              State of the adapter.  IB_PNP_PORT_ADD indicates that the adapter\r
+*              is ready to transfer data.\r
+*\r
+*      hung\r
+*              Boolean flag used to return whether we are hung or not.\r
+*\r
+*      p_port\r
+*              Pointer to an ipoib_port_t representing all resources for moving data\r
+*              on the IB fabric.\r
+*\r
+*      rate\r
+*              Rate, in 100bps increments, of the link.\r
+*\r
+*      params\r
+*              Configuration parameters.\r
+*\r
+*      pending_query\r
+*              Indicates that an query OID request is being processed asynchronously.\r
+*\r
+*      query_oid\r
+*              Information about the pended query OID request.\r
+*              Valid only if pending_query is TRUE.\r
+*\r
+*      pending_set\r
+*              Indicates that an set OID request is being processed asynchronously.\r
+*\r
+*      set_oid\r
+*              Information about the pended set OID request.\r
+*              Valid only if pending_set is TRUE.\r
+*\r
+*      recv_lock\r
+*              Spinlock protecting receive processing.\r
+*\r
+*      recv_stats\r
+*              Receive statistics.\r
+*\r
+*      send_lock\r
+*              Spinlock protecting send processing.\r
+*\r
+*      send_stats\r
+*              Send statistics.\r
+*\r
+*      is_primary\r
+*              Boolean flag to indicate if an adapter is the primary adapter\r
+*              of a bundle.\r
+*\r
+*      p_primary\r
+*              Pointer to the primary adapter for a bundle.\r
+*\r
+*      packet_filter\r
+*              Packet filter set by NDIS.\r
+*\r
+*      mac_addr\r
+*              Ethernet MAC address reported to NDIS.\r
+*\r
+*      mcast_array\r
+*              List of multicast MAC addresses programmed by NDIS.\r
+*\r
+*      mcast_array_size\r
+*              Number of entries in the multicat MAC address array;\r
+*\r
+*      item_pool\r
+*              Pool of cl_pool_obj_t structures to use for queueing pending\r
+*              packets for transmission.\r
+*\r
+*      mutex\r
+*              Mutex to synchronized PnP callbacks with destruction.\r
+*\r
+*      ip_vector\r
+*              Vector of assigned IP addresses.\r
+*\r
+*      p_ifc\r
+*              Pointer to transport interface.\r
+*\r
+*********/\r
+\r
+\r
+typedef struct _ats_reg\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       ib_reg_svc_handle_t     h_reg_svc;\r
+\r
+}      ats_reg_t;\r
+/*\r
+* FIELDS\r
+*      p_adapter\r
+*              Pointer to the adapter to which this address is assigned.\r
+*\r
+*      h_reg_svc\r
+*              Service registration handle.\r
+*********/\r
+\r
+\r
+typedef struct _net_address_item\r
+{\r
+       ats_reg_t                       *p_reg;\r
+       union _net_address_item_address\r
+       {\r
+               ULONG                   as_ulong;\r
+               UCHAR                   as_bytes[IPV4_ADDR_SIZE];\r
+       }       address;\r
+\r
+}      net_address_item_t;\r
+/*\r
+* FIELDS\r
+*      p_reg\r
+*              Pointer to the ATS registration assigned to this address.\r
+*\r
+*      address\r
+*              Union representing the IP address as an unsigned long or as\r
+*              an array of bytes.\r
+*\r
+*      as_ulong\r
+*              The IP address represented as an unsigned long.  Windows stores\r
+*              IPs this way.\r
+*\r
+*      as_bytes\r
+*              The IP address represented as an array of bytes.\r
+*********/\r
+\r
+\r
+ib_api_status_t\r
+ipoib_create_adapter(\r
+       IN              NDIS_HANDLE                     wrapper_config_context,\r
+       IN              void* const                     h_adapter,\r
+       OUT             ipoib_adapter_t**  const        pp_adapter );\r
+\r
+\r
+ib_api_status_t\r
+ipoib_start_adapter(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+\r
+void\r
+ipoib_destroy_adapter(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+\r
+/* Joins/leaves mcast groups based on currently programmed mcast MACs. */\r
+void\r
+ipoib_refresh_mcast(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              mac_addr_t* const                       p_mac_array,\r
+       IN              const   uint8_t                                         num_macs );\r
+/*\r
+* PARAMETERS\r
+*      p_adapter\r
+*              Instance whose multicast MAC address list to modify.\r
+*\r
+*      p_mac_array\r
+*              Array of multicast MAC addresses assigned to the adapter.\r
+*\r
+*      num_macs\r
+*              Number of MAC addresses in the array.\r
+*********/\r
+NDIS_STATUS\r
+ipoib_get_gen_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       OUT             pending_oid_t* const            p_oid_info );\r
+\r
+NDIS_STATUS\r
+ipoib_get_recv_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN                              pending_oid_t* const            p_oid_info );\r
+\r
+\r
+void\r
+ipoib_inc_recv_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN              const   size_t                                          bytes OPTIONAL,\r
+       IN              const   size_t                                          packets OPTIONAL );\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_get_send_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN                              pending_oid_t* const            p_oid_info );\r
+\r
+\r
+void\r
+ipoib_inc_send_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN              const   size_t                                          bytes OPTIONAL );\r
+\r
+\r
+void\r
+ipoib_set_rate(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   uint8_t                                         link_width,\r
+       IN              const   uint8_t                                         link_speed );\r
+\r
+\r
+ib_api_status_t\r
+ipoib_set_active(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+void\r
+ipoib_set_inactive(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+ib_api_status_t\r
+ipoib_reset_adapter(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+void\r
+ipoib_reg_addrs(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+void\r
+ipoib_dereg_addrs(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+#define IPOIB_INIT_NDIS_STATUS_INDICATION(_pStatusIndication, _M, _St, _Buf, _BufSize)        \\r
+    {                                                                                      \\r
+        NdisZeroMemory(_pStatusIndication, sizeof(NDIS_STATUS_INDICATION));                \\r
+        (_pStatusIndication)->Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;            \\r
+        (_pStatusIndication)->Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;         \\r
+        (_pStatusIndication)->Header.Size = sizeof(NDIS_STATUS_INDICATION);                \\r
+        (_pStatusIndication)->SourceHandle = _M;                                           \\r
+        (_pStatusIndication)->StatusCode = _St;                                            \\r
+        (_pStatusIndication)->StatusBuffer = _Buf;                                         \\r
+        (_pStatusIndication)->StatusBufferSize = _BufSize;                                 \\r
+    }\r
+\r
+//TODO rename to 4\r
+#define IPOIB_MEDIA_MAX_SPEED  10000000000\r
+\r
+#endif /* _IPOIB_ADAPTER_H_ */\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_cm.c b/trunk/ulp/ipoib/kernel6/ipoib_cm.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_debug.h b/trunk/ulp/ipoib/kernel6/ipoib_debug.h
new file mode 100644 (file)
index 0000000..69ec3c5
--- /dev/null
@@ -0,0 +1,303 @@
+/*\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: ipoib_debug.h 3719 2009-01-07 12:31:52Z reuven $\r
+ */\r
+\r
+\r
+#ifndef _IPOIB_DEBUG_H_\r
+#define _IPOIB_DEBUG_H_\r
+\r
+#if defined __MODULE__\r
+#undef __MODULE__\r
+#endif\r
+\r
+#define __MODULE__     "[IPoIB]"\r
+\r
+#include <complib/cl_debug.h>\r
+\r
+\r
+/* Object types for passing into complib. */\r
+#define IPOIB_OBJ_INSTANCE             1\r
+#define IPOIB_OBJ_PORT                 2\r
+#define IPOIB_OBJ_ENDPOINT             3\r
+\r
+\r
+extern uint32_t                g_ipoib_dbg_level;\r
+extern uint32_t                g_ipoib_dbg_flags;\r
+\r
+\r
+#if defined(EVENT_TRACING)\r
+//\r
+// Software Tracing Definitions\r
+//\r
+#define WPP_CONTROL_GUIDS \\r
+       WPP_DEFINE_CONTROL_GUID( \\r
+               IPOIBCtlGuid,(3F9BC73D, EB03, 453a, B27B, 20F9A664211A), \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_ERROR) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_INIT) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_PNP) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_SEND) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_RECV) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_ENDPT) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_IB) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_BUF) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_MCAST) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_ALLOC) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_OID) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_IOCTL) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_STAT) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_OBJ))\r
+\r
+\r
+\r
+#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \\r
+       (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level  >= lvl)\r
+#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags)\r
+#define WPP_FLAG_ENABLED(flags) \\r
+       (WPP_LEVEL_ENABLED(flags) && \\r
+       WPP_CONTROL(WPP_BIT_ ## flags).Level  >= TRACE_LEVEL_VERBOSE)\r
+#define WPP_FLAG_LOGGER(flags) WPP_LEVEL_LOGGER(flags)\r
+\r
+// begin_wpp config\r
+// IPOIB_ENTER(FLAG);\r
+// IPOIB_EXIT(FLAG);\r
+// USEPREFIX(IPOIB_PRINT, "%!STDPREFIX! [IPoIB] :%!FUNC!() :");\r
+// USEPREFIX(IPOIB_PRINT_EXIT, "%!STDPREFIX! [IPoIB] :%!FUNC!() :");\r
+// USESUFFIX(IPOIB_PRINT_EXIT, "[IpoIB] :%!FUNC!():]");\r
+// USESUFFIX(IPOIB_ENTER, " [IPoIB] :%!FUNC!():[");\r
+// USESUFFIX(IPOIB_EXIT, " [IPoIB] :%!FUNC!():]");\r
+// end_wpp\r
+\r
+#else\r
+\r
+#include <evntrace.h>\r
+\r
+\r
+/*\r
+ * Debug macros\r
+ */\r
+#define IPOIB_DBG_ERR  (1 << 0)\r
+#define IPOIB_DBG_INIT (1 << 1)\r
+#define IPOIB_DBG_PNP  (1 << 2)\r
+#define IPOIB_DBG_SEND (1 << 3)\r
+#define IPOIB_DBG_RECV (1 << 4)\r
+#define IPOIB_DBG_ENDPT        (1 << 5)\r
+#define IPOIB_DBG_IB   (1 << 6)\r
+#define IPOIB_DBG_BUF  (1 << 7)\r
+#define IPOIB_DBG_MCAST        (1 << 8)\r
+#define IPOIB_DBG_ALLOC        (1 << 9)\r
+#define IPOIB_DBG_OID  (1 << 10)\r
+#define IPOIB_DBG_IOCTL        (1 << 11)\r
+#define IPOIB_DBG_STAT (1 << 12)\r
+#define IPOIB_DBG_OBJ  (1 << 13)\r
+\r
+#define IPOIB_DBG_ERROR        (CL_DBG_ERROR | IPOIB_DBG_ERR)\r
+#define IPOIB_DBG_ALL  CL_DBG_ALL\r
+\r
+\r
+#if DBG\r
+\r
+// assignment of _level_ is need to to overcome warning C4127\r
+#define IPOIB_PRINT(_level_,_flag_,_msg_) \\r
+       { \\r
+               __pragma(warning(suppress:6326)) \\r
+               if( g_ipoib_dbg_level >= (_level_) ) \\r
+                       CL_TRACE( _flag_, g_ipoib_dbg_flags, _msg_ ); \\r
+       }\r
+\r
+#define IPOIB_PRINT_EXIT(_level_,_flag_,_msg_) \\r
+       { \\r
+               __pragma(warning(suppress:6326)) \\r
+               if( g_ipoib_dbg_level >= (_level_) ) \\r
+                       CL_TRACE( _flag_, g_ipoib_dbg_flags, _msg_ );\\r
+               IPOIB_EXIT(_flag_);\\r
+       }\r
+\r
+#define IPOIB_ENTER(_flag_) \\r
+       { \\r
+               __pragma(warning(suppress:6326)) \\r
+               if( g_ipoib_dbg_level >= TRACE_LEVEL_VERBOSE ) \\r
+                       CL_ENTER( _flag_, g_ipoib_dbg_flags ); \\r
+       }\r
+\r
+#define IPOIB_EXIT(_flag_)\\r
+       { \\r
+               __pragma(warning(suppress:6326)) \\r
+               if( g_ipoib_dbg_level >= TRACE_LEVEL_VERBOSE ) \\r
+                       CL_EXIT( _flag_, g_ipoib_dbg_flags ); \\r
+       }\r
+\r
+#define IPOIB_TRACE_BYTES( lvl, ptr, len )                                                                     \\r
+       {                                                                                                                                               \\r
+               __pragma(warning(suppress:6326))                                                                        \\r
+               if( g_ipoib_dbg_level >= (_level_) &&                                                           \\r
+                       (g_ipoib_dbg_flags & (_flag_)) )                                                                \\r
+               {                                                                                                                                       \\r
+                       size_t _loop_;                                                                                                  \\r
+                       for( _loop_ = 0; _loop_ < (len); ++_loop_ )                                             \\r
+                       {                                                                                                                               \\r
+                               cl_dbg_out( "0x%.2X ", ((uint8_t*)(ptr))[_loop_] );                     \\r
+                               if( (_loop_ + 1)% 16 == 0 )                                                                     \\r
+                                       cl_dbg_out("\n");                                                                                       \\r
+                               else if( (_loop_ % 4 + 1) == 0 )                                                        \\r
+                                       cl_dbg_out("  ");                                                                                       \\r
+                       }                                                                                                                               \\r
+                       cl_dbg_out("\n");                                                                                                       \\r
+               }                                                                                                                                       \\r
+       }\r
+\r
+#else\r
+\r
+#define IPOIB_PRINT(lvl, flags, msg)\r
+\r
+#define IPOIB_PRINT_EXIT(_level_,_flag_,_msg_)\r
+\r
+#define IPOIB_ENTER(_flag_)\r
+\r
+#define IPOIB_EXIT(_flag_)\r
+\r
+#define IPOIB_TRACE_BYTES( lvl, ptr, len )\r
+\r
+#endif\r
+\r
+#endif //EVENT_TRACING\r
+\r
+\r
+enum ipoib_perf_counters\r
+{\r
+       SendBundle,\r
+       SendPackets,\r
+               PortSend,\r
+                       GetEthHdr,\r
+                       SendMgrQueue,\r
+                               GetEndpt,\r
+                                       EndptQueue,\r
+                       QueuePacket,\r
+                       BuildSendDesc,\r
+                               SendMgrFilter,\r
+                                       FilterIp,\r
+                                               QueryIp,\r
+                                               SendTcp,\r
+                                               FilterUdp,\r
+                                                       QueryUdp,\r
+                                                       SendUdp,\r
+                                                       FilterDhcp,\r
+                                       FilterArp,\r
+                                       SendGen,\r
+                                               SendCopy,\r
+                       PostSend,\r
+                       ProcessFailedSends,\r
+       SendCompBundle,\r
+       SendCb,\r
+               PollSend,\r
+               SendComp,\r
+               FreeSendBuf,\r
+               RearmSend,\r
+               PortResume,\r
+       RecvCompBundle,\r
+       RecvCb,\r
+               PollRecv,\r
+               FilterRecv,\r
+                       GetRecvEndpts,\r
+                               GetEndptByGid,\r
+                               GetEndptByLid,\r
+                               EndptInsert,\r
+                       RecvTcp,\r
+                       RecvUdp,\r
+                       RecvDhcp,\r
+                       RecvArp,\r
+                       RecvGen,\r
+       BuildPktArray,\r
+               PreparePkt,\r
+                       GetNdisPkt,\r
+       RecvNdisIndicate,\r
+       PutRecvList,\r
+       RepostRecv,\r
+               GetRecv,\r
+               PostRecv,\r
+       RearmRecv,\r
+               ReturnPacket,\r
+               ReturnPutRecv,\r
+               ReturnRepostRecv,\r
+               ReturnPreparePkt,\r
+               ReturnNdisIndicate,\r
+\r
+       /* Must be last! */\r
+       MaxPerf\r
+\r
+};\r
+\r
+\r
+enum ref_cnt_buckets\r
+{\r
+       ref_init = 0,\r
+       ref_refresh_mcast,      /* only used in refresh_mcast */\r
+       ref_send_packets,       /* only in send_packets */\r
+       ref_get_recv,\r
+       ref_repost,             /* only in __recv_mgr_repost */\r
+       ref_recv_cb,    /* only in __recv_cb */\r
+       ref_send_cb,    /* only in __send_cb */\r
+       ref_port_up,\r
+       ref_get_bcast,\r
+       ref_bcast,              /* join and create, used as base only */\r
+       ref_join_mcast,\r
+       ref_leave_mcast,\r
+       ref_endpt_track,        /* used when endpt is in port's child list. */\r
+\r
+       ref_array_size, /* Used to size the array of ref buckets. */\r
+       ref_mask = 100, /* Used to differentiate derefs. */\r
+\r
+       ref_failed_recv_wc = 100 + ref_get_recv,\r
+       ref_recv_inv_len = 200 + ref_get_recv,\r
+       ref_recv_loopback = 300 + ref_get_recv,\r
+       ref_recv_filter = 400 + ref_get_recv,\r
+\r
+       ref_bcast_get_cb = 100 + ref_get_bcast,\r
+\r
+       ref_join_bcast = 100 + ref_bcast,\r
+       ref_create_bcast = 200 + ref_bcast,\r
+       ref_bcast_inv_state = 300 + ref_bcast,\r
+       ref_bcast_req_failed = 400 + ref_bcast,\r
+       ref_bcast_error = 500 + ref_bcast,\r
+       ref_bcast_join_failed = 600 + ref_bcast,\r
+       ref_bcast_create_failed = 700 + ref_bcast,\r
+\r
+       ref_mcast_inv_state = 100 + ref_join_mcast,\r
+       ref_mcast_req_failed = 200 + ref_join_mcast,\r
+       ref_mcast_no_endpt = 300 + ref_join_mcast,\r
+       ref_mcast_av_failed = 400 + ref_join_mcast,\r
+       ref_mcast_join_failed = 500 + ref_join_mcast,\r
+\r
+       ref_port_info_cb = 100 + ref_port_up\r
+\r
+};\r
+\r
+\r
+#endif /* _IPOIB_DEBUG_H_ */\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_driver.c b/trunk/ulp/ipoib/kernel6/ipoib_driver.c
new file mode 100644 (file)
index 0000000..95d67cd
--- /dev/null
@@ -0,0 +1,4057 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_driver.c 4226 2009-04-06 06:01:03Z xalex $\r
+ */\r
+\r
+#include "limits.h"\r
+#include "ipoib_driver.h"\r
+#include "ipoib_debug.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_driver.tmh"\r
+#endif\r
+\r
+#include "ipoib_port.h"\r
+#include "ipoib_ibat.h"\r
+#include <complib/cl_bus_ifc.h>\r
+#include <complib/cl_init.h>\r
+#include <initguid.h>\r
+#include <iba/ipoib_ifc.h>\r
+#include "ntstrsafe.h"\r
+#include "strsafe.h"\r
+#include <offload.h>\r
+\r
+\r
+\r
+#define MAJOR_DRIVER_VERSION 2\r
+#define MINOR_DRIVER_VERSION 1\r
+#if defined(NDIS60_MINIPORT)\r
+#define MAJOR_NDIS_VERSION 6\r
+#define MINOR_NDIS_VERSION 0\r
+\r
+#else\r
+#error NDIS Version not defined, try defining NDIS60_MINIPORT\r
+#endif\r
+\r
+PDRIVER_OBJECT                         g_p_drv_obj;\r
+\r
+\r
+\r
+static const NDIS_OID SUPPORTED_OIDS[] =\r
+{\r
+       OID_GEN_SUPPORTED_LIST,\r
+       OID_GEN_HARDWARE_STATUS,\r
+       OID_GEN_MEDIA_SUPPORTED,\r
+       OID_GEN_MEDIA_IN_USE,\r
+       OID_GEN_MAXIMUM_LOOKAHEAD,\r
+       OID_GEN_MAXIMUM_FRAME_SIZE,\r
+       OID_GEN_LINK_SPEED,\r
+       OID_GEN_TRANSMIT_BUFFER_SPACE,\r
+       OID_GEN_RECEIVE_BUFFER_SPACE,\r
+       OID_GEN_TRANSMIT_BLOCK_SIZE,\r
+       OID_GEN_RECEIVE_BLOCK_SIZE,\r
+       OID_GEN_VENDOR_ID,\r
+       OID_GEN_VENDOR_DESCRIPTION,\r
+       OID_GEN_CURRENT_PACKET_FILTER,\r
+       OID_GEN_CURRENT_LOOKAHEAD,\r
+       OID_GEN_DRIVER_VERSION,\r
+       OID_GEN_MAXIMUM_TOTAL_SIZE,\r
+       OID_GEN_PROTOCOL_OPTIONS,\r
+       OID_GEN_MAC_OPTIONS,\r
+       OID_GEN_MEDIA_CONNECT_STATUS,\r
+       OID_GEN_MAXIMUM_SEND_PACKETS,\r
+       OID_GEN_NETWORK_LAYER_ADDRESSES,\r
+       OID_GEN_VENDOR_DRIVER_VERSION,\r
+       OID_GEN_PHYSICAL_MEDIUM,\r
+       OID_GEN_XMIT_OK,\r
+       OID_GEN_RCV_OK,\r
+       OID_GEN_XMIT_ERROR,\r
+       OID_GEN_RCV_ERROR,\r
+       OID_GEN_RCV_NO_BUFFER,\r
+       OID_GEN_DIRECTED_BYTES_XMIT,\r
+       OID_GEN_DIRECTED_FRAMES_XMIT,\r
+       OID_GEN_MULTICAST_BYTES_XMIT,\r
+       OID_GEN_MULTICAST_FRAMES_XMIT,\r
+       OID_GEN_BROADCAST_BYTES_XMIT,\r
+       OID_GEN_BROADCAST_FRAMES_XMIT,\r
+       OID_GEN_DIRECTED_BYTES_RCV,\r
+       OID_GEN_DIRECTED_FRAMES_RCV,\r
+       OID_GEN_MULTICAST_BYTES_RCV,\r
+       OID_GEN_MULTICAST_FRAMES_RCV,\r
+       OID_GEN_BROADCAST_BYTES_RCV,\r
+       OID_GEN_BROADCAST_FRAMES_RCV,\r
+       OID_802_3_PERMANENT_ADDRESS,\r
+       OID_802_3_CURRENT_ADDRESS,\r
+       OID_802_3_MULTICAST_LIST,\r
+       OID_802_3_MAXIMUM_LIST_SIZE,\r
+       OID_802_3_MAC_OPTIONS,\r
+       OID_802_3_RCV_ERROR_ALIGNMENT,\r
+       OID_802_3_XMIT_ONE_COLLISION,\r
+       OID_802_3_XMIT_MORE_COLLISIONS,\r
+       OID_TCP_TASK_OFFLOAD\r
+};\r
+\r
+static const unsigned char VENDOR_ID[] = {0x00, 0x06, 0x6A, 0x00};\r
+\r
+#define VENDOR_DESCRIPTION "Internet Protocol over InfiniBand"\r
+\r
+#define IB_INFINITE_SERVICE_LEASE      0xFFFFFFFF\r
+\r
+//The mask is 8 bit and can't contain more than 6 non-zero bits\r
+#define MAX_GUID_MAX 0xFC\r
+\r
+\r
+/* Global driver debug level */\r
+uint32_t               g_ipoib_dbg_level = TRACE_LEVEL_ERROR;\r
+uint32_t               g_ipoib_dbg_flags = 0x00000fff;\r
+ipoib_globals_t        g_ipoib = {0};\r
+NDIS_HANDLE            g_IpoibMiniportDriverHandle = NULL;\r
+NDIS_HANDLE            g_IpoibDriverContext = NULL;\r
+\r
+\r
+\r
+typedef struct _IPOIB_REG_ENTRY\r
+{\r
+       NDIS_STRING RegName;                // variable name text\r
+       BOOLEAN     bRequired;              // 1 -> required, 0 -> optional\r
+       UINT        FieldOffset;            // offset in parent struct\r
+       UINT        FieldSize;              // size (in bytes) of the field\r
+       UINT        Default;                // default value to use\r
+       UINT        Min;                    // minimum value allowed\r
+       UINT        Max;                    // maximum value allowed\r
+} IPOIB_REG_ENTRY, *PIPOIB_REG_ENTRY;\r
+\r
+IPOIB_REG_ENTRY HCARegTable[] = {\r
+       // reg value name             If Required  Offset in parentr struct             Field size                  Default         Min     Max\r
+       {NDIS_STRING_CONST("GUIDMask"),         0, IPOIB_OFFSET(guid_mask),             IPOIB_SIZE(guid_mask),          0,          0,    MAX_GUID_MAX},\r
+       /* GUIDMask should be the first element */\r
+       {NDIS_STRING_CONST("RqDepth"),          1, IPOIB_OFFSET(rq_depth),              IPOIB_SIZE(rq_depth),           512,        128,    1024},\r
+       {NDIS_STRING_CONST("RqLowWatermark"),   0, IPOIB_OFFSET(rq_low_watermark),      IPOIB_SIZE(rq_low_watermark),   4,          2,      8},\r
+       {NDIS_STRING_CONST("SqDepth"),          1, IPOIB_OFFSET(sq_depth),              IPOIB_SIZE(sq_depth),           512,        128,    1024},\r
+       {NDIS_STRING_CONST("SendChksum"),       1, IPOIB_OFFSET(send_chksum_offload),   IPOIB_SIZE(send_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS},\r
+       {NDIS_STRING_CONST("RecvChksum"),       1, IPOIB_OFFSET(recv_chksum_offload),   IPOIB_SIZE(recv_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS},\r
+       {NDIS_STRING_CONST("SaTimeout"),        1, IPOIB_OFFSET(sa_timeout),            IPOIB_SIZE(sa_timeout),         1000,       250,    UINT_MAX},\r
+       {NDIS_STRING_CONST("SaRetries"),        1, IPOIB_OFFSET(sa_retry_cnt),          IPOIB_SIZE(sa_retry_cnt),       10,         1,      UINT_MAX},\r
+       {NDIS_STRING_CONST("RecvRatio"),        1, IPOIB_OFFSET(recv_pool_ratio),       IPOIB_SIZE(recv_pool_ratio),    1,          1,      10},\r
+       {NDIS_STRING_CONST("PayloadMtu"),       1, IPOIB_OFFSET(payload_mtu),           IPOIB_SIZE(payload_mtu),        2044,       512,   MAX_UD_PAYLOAD_MTU},\r
+       {NDIS_STRING_CONST("lso"),              0, IPOIB_OFFSET(lso),                   IPOIB_SIZE(lso),                0,          0,      1},\r
+       {NDIS_STRING_CONST("MCLeaveRescan"),    1, IPOIB_OFFSET(mc_leave_rescan),       IPOIB_SIZE(mc_leave_rescan),    260,        1,    3600},\r
+       {NDIS_STRING_CONST("BCJoinRetry"),          1, IPOIB_OFFSET(bc_join_retry),                 IPOIB_SIZE(bc_join_retry),      50,         0,    1000},\r
+       {NDIS_STRING_CONST("CmEnabled"),        0, IPOIB_OFFSET(cm_enabled),            IPOIB_SIZE(cm_enabled),         FALSE,     FALSE, TRUE},\r
+       {NDIS_STRING_CONST("CmPayloadMtu"),     1, IPOIB_OFFSET(cm_payload_mtu),        IPOIB_SIZE(cm_payload_mtu),     MAX_CM_PAYLOAD_MTU, 512, MAX_CM_PAYLOAD_MTU}\r
+\r
+};  \r
+\r
+#define IPOIB_NUM_REG_PARAMS (sizeof (HCARegTable) / sizeof(IPOIB_REG_ENTRY))\r
+\r
+\r
+void\r
+ipoib_create_log(\r
+       NDIS_HANDLE h_adapter,\r
+       UINT ind,\r
+       ULONG eventLogMsgId)\r
+\r
+{\r
+#define cMaxStrLen  40\r
+#define cArrLen  3\r
+\r
+       PWCHAR logMsgArray[cArrLen]; \r
+       WCHAR strVal[cMaxStrLen];\r
+       NDIS_STRING AdapterInstanceName;\r
+\r
+       IPOIB_INIT_NDIS_STRING(&AdapterInstanceName);\r
+       if (NdisMQueryAdapterInstanceName(&AdapterInstanceName, h_adapter)!= NDIS_STATUS_SUCCESS ){\r
+               ASSERT(FALSE);\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR, ("[IPoIB] Init:Failed to retreive adapter name.\n"));\r
+               return;\r
+       }\r
+       logMsgArray[0] = AdapterInstanceName.Buffer;\r
+       \r
+       if (RtlStringCbPrintfW(strVal, sizeof(strVal), L"0x%x", HCARegTable[ind].Default) != STATUS_SUCCESS) {\r
+               ASSERT(FALSE);\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,\r
+               ("[IPoIB] Init: Problem copying string value: exiting\n"));   \r
+               return;\r
+       }\r
+       \r
+       logMsgArray[0] = AdapterInstanceName.Buffer;\r
+       logMsgArray[1] = HCARegTable[ind].RegName.Buffer;\r
+       logMsgArray[2] = strVal;\r
+       \r
+       NdisWriteEventLogEntry(g_p_drv_obj, eventLogMsgId, 0, cArrLen, &logMsgArray, 0, NULL);\r
+\r
+}\r
+\r
+\r
+\r
+NTSTATUS\r
+DriverEntry(\r
+       IN                              PDRIVER_OBJECT                          p_drv_obj,\r
+       IN                              PUNICODE_STRING                         p_reg_path );\r
+\r
+VOID\r
+ipoib_unload(\r
+       IN                              PDRIVER_OBJECT                          p_drv_obj );\r
+\r
+NDIS_STATUS\r
+ipoib_initialize_ex(\r
+       IN                              NDIS_HANDLE                     h_adapter,\r
+    IN                                 NDIS_HANDLE             config_context,\r
+    IN PNDIS_MINIPORT_INIT_PARAMETERS  MiniportInitParameters);\r
+\r
+BOOLEAN\r
+ipoib_check_for_hang(\r
+       IN                              NDIS_HANDLE                                     adapter_context );\r
+\r
+void\r
+ipoib_halt_ex(\r
+       IN NDIS_HANDLE  adapter_context,\r
+       IN                      NDIS_HALT_ACTION            HaltAction);\r
+\r
+NDIS_STATUS\r
+ipoib_query_info(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              NDIS_OID                                        oid,\r
+       IN                              PVOID                                           info_buf,\r
+       IN                              ULONG                                           info_buf_len,\r
+               OUT                     PULONG                                          p_bytes_written,\r
+               OUT                     PULONG                                          p_bytes_needed );\r
+\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_reset(\r
+    IN  NDIS_HANDLE     adapter_context,\r
+    OUT PBOOLEAN        p_addr_reset);\r
+\r
+NDIS_STATUS\r
+ipoib_set_info(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              NDIS_OID                                        oid,\r
+       IN                              PVOID                                           info_buf,\r
+       IN                              ULONG                                           info_buf_length,\r
+               OUT                     PULONG                                          p_bytes_read,\r
+               OUT                     PULONG                                          p_bytes_needed );\r
+\r
+//NDIS60\r
+void\r
+ipoib_send_net_buffer_list(\r
+    IN  NDIS_HANDLE         adapter_context,\r
+    IN  PNET_BUFFER_LIST    net_buffer_list,\r
+    IN  NDIS_PORT_NUMBER    port_num,\r
+    IN  ULONG               send_flags);\r
+\r
+void\r
+ipoib_pnp_notify(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN PNET_DEVICE_PNP_EVENT  pnp_event);\r
+\r
+VOID\r
+ipoib_shutdown_ex(\r
+       IN NDIS_HANDLE  adapter_context,\r
+       IN NDIS_SHUTDOWN_ACTION  shutdown_action);\r
+\r
+\r
+void\r
+ipoib_cancel_xmit(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              PVOID                                           cancel_id );\r
+\r
+\r
+static void\r
+ipoib_complete_query(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              pending_oid_t* const            p_oid_info,\r
+       IN              const   NDIS_STATUS                                     status,\r
+       IN              const   void* const                                     p_buf,\r
+       IN              const   ULONG                                           buf_len );\r
+\r
+static NDIS_STATUS\r
+__ipoib_set_net_addr(\r
+       IN              ipoib_adapter_t *       p_adapter,\r
+       IN              PVOID                           info_buf,\r
+       IN              ULONG                           info_buf_len,\r
+               OUT     PULONG                          p_bytes_read,\r
+               OUT     PULONG                          p_bytes_needed );\r
+\r
+static NDIS_STATUS\r
+__ipoib_get_tcp_task_offload(\r
+       IN                              ipoib_adapter_t*                        p_adapter,\r
+       OUT                             pending_oid_t                           *pNdisRequest);\r
+\r
+static void\r
+__ipoib_ats_reg_cb(\r
+       IN                              ib_reg_svc_rec_t                        *p_reg_svc_rec );\r
+\r
+static void\r
+__ipoib_ats_dereg_cb(\r
+       IN                              void                                            *context );\r
+\r
+static NTSTATUS\r
+__ipoib_read_registry(\r
+       IN                              UNICODE_STRING* const           p_registry_path );\r
+\r
+static NDIS_STATUS\r
+ipoib_set_options(\r
+    IN NDIS_HANDLE  NdisMiniportDriverHandle,\r
+    IN NDIS_HANDLE  MiniportDriverContext);\r
+\r
+static NDIS_STATUS\r
+ipoib_oid_handler(\r
+    IN  NDIS_HANDLE         adapter_context,\r
+    IN  PNDIS_OID_REQUEST   pNdisRequest);\r
+\r
+static void\r
+ipoib_cancel_oid_request(\r
+    IN  NDIS_HANDLE            adapter_context,\r
+    IN  PVOID                  requestId);\r
+        \r
+static NDIS_STATUS \r
+ipoib_pause(\r
+    IN  NDIS_HANDLE                         adapter_context,    \r
+    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS     pause_parameters);\r
+\r
+static NDIS_STATUS \r
+ipoib_restart(\r
+    IN  NDIS_HANDLE                         adapter_context,    \r
+    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   restart_parameters);\r
+\r
+\r
+\r
+//! Standard Windows Device Driver Entry Point\r
+/*! DriverEntry is the first routine called after a driver is loaded, and\r
+is responsible for initializing the driver.  On W2k this occurs when the PnP\r
+Manager matched a PnP ID to one in an INF file that references this driver.\r
+Any not success return value will cause the driver to fail to load.\r
+IRQL = PASSIVE_LEVEL\r
+\r
+@param p_drv_obj Pointer to Driver Object for this device driver\r
+@param p_registry_path Pointer to unicode string containing path to this driver's registry area\r
+@return STATUS_SUCCESS, NDIS_STATUS_BAD_CHARACTERISTICS, NDIS_STATUS_BAD_VERSION,\r
+NDIS_STATUS_RESOURCES, or NDIS_STATUS_FAILURE\r
+*/\r
+NTSTATUS\r
+DriverEntry(\r
+       IN                              PDRIVER_OBJECT                          p_drv_obj,\r
+       IN                              PUNICODE_STRING                         p_registry_path )\r
+{\r
+       NDIS_STATUS                                             status;\r
+       NDIS_MINIPORT_DRIVER_CHARACTERISTICS characteristics;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       g_p_drv_obj = p_drv_obj;\r
+\r
+#ifdef _DEBUG_\r
+       PAGED_CODE();\r
+#endif\r
+#if defined(EVENT_TRACING)\r
+       WPP_INIT_TRACING(p_drv_obj, p_registry_path);\r
+#endif\r
+       status = CL_INIT;\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_init failed.\n") );\r
+               return status;\r
+       }\r
+\r
+       __ipoib_read_registry(p_registry_path);\r
+       \r
+       KeInitializeSpinLock( &g_ipoib.lock );\r
+       cl_qlist_init( &g_ipoib.adapter_list );\r
+\r
+    NdisZeroMemory(&characteristics, sizeof(characteristics));\r
+\r
+    characteristics.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS,\r
+    characteristics.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS);\r
+    characteristics.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;\r
+\r
+       characteristics.MajorNdisVersion                = MAJOR_NDIS_VERSION;\r
+       characteristics.MinorNdisVersion                = MINOR_NDIS_VERSION;\r
+    characteristics.MajorDriverVersion         = MAJOR_DRIVER_VERSION;\r
+    characteristics.MinorDriverVersion         = MINOR_DRIVER_VERSION;\r
+\r
+\r
+       characteristics.CheckForHangHandlerEx           = ipoib_check_for_hang;\r
+       characteristics.HaltHandlerEx                           = ipoib_halt_ex;\r
+       characteristics.InitializeHandlerEx             = ipoib_initialize_ex;\r
+       characteristics.OidRequestHandler                       = ipoib_oid_handler;\r
+       characteristics.CancelOidRequestHandler         = ipoib_cancel_oid_request;\r
+       characteristics.ResetHandlerEx                          = ipoib_reset;\r
+       characteristics.DevicePnPEventNotifyHandler     = ipoib_pnp_notify;\r
+       characteristics.ReturnNetBufferListsHandler     = ipoib_return_net_buffer_list;\r
+       characteristics.SendNetBufferListsHandler       = ipoib_send_net_buffer_list;\r
+\r
+       characteristics.SetOptionsHandler                       = ipoib_set_options;\r
+       characteristics.PauseHandler                            = ipoib_pause;\r
+       characteristics.RestartHandler                          = ipoib_restart;\r
+       characteristics.UnloadHandler                           = ipoib_unload;\r
+       characteristics.CancelSendHandler                       = ipoib_cancel_xmit;\r
+       characteristics.ShutdownHandlerEx                       = ipoib_shutdown_ex;\r
+\r
+\r
+\r
+//TODO NDIS60 set g_ prefix to global variables\r
+       status = NdisMRegisterMiniportDriver(\r
+               p_drv_obj, p_registry_path,(PNDIS_HANDLE)g_IpoibDriverContext, &characteristics,&g_IpoibMiniportDriverHandle );\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
+                       ("NdisMRegisterMiniportDriver failed with status of %d\n", status) );\r
+               CL_DEINIT;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+static NDIS_STATUS\r
+ipoib_set_options(\r
+    IN NDIS_HANDLE  NdisMiniportDriverHandle,\r
+    IN NDIS_HANDLE  MiniportDriverContext\r
+    )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+    UNREFERENCED_PARAMETER(NdisMiniportDriverHandle);\r
+    UNREFERENCED_PARAMETER(MiniportDriverContext);\r
+   \r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+    return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static NTSTATUS\r
+__ipoib_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[4];\r
+       UNICODE_STRING                                  param_path;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\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
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_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"DebugLevel";\r
+       table[0].EntryContext = &g_ipoib_dbg_level;\r
+       table[0].DefaultType = REG_DWORD;\r
+       table[0].DefaultData = &g_ipoib_dbg_level;\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 = &g_ipoib_dbg_flags;\r
+       table[1].DefaultType = REG_DWORD;\r
+       table[1].DefaultData = &g_ipoib_dbg_flags;\r
+       table[1].DefaultLength = sizeof(ULONG);\r
+\r
+       table[2].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
+       table[2].Name = L"bypass_check_bcast_rate";\r
+       table[2].EntryContext = &g_ipoib.bypass_check_bcast_rate;\r
+       table[2].DefaultType = REG_DWORD;\r
+       table[2].DefaultData = &g_ipoib.bypass_check_bcast_rate;\r
+       table[2].DefaultLength = sizeof(ULONG);\r
+\r
+       /* Have at it! */\r
+       status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
+               param_path.Buffer, table, NULL, NULL );\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("debug level %d debug flags 0x%.8x\n",\r
+                       g_ipoib_dbg_level,\r
+                       g_ipoib_dbg_flags));\r
+\r
+#if DBG\r
+       if( g_ipoib_dbg_flags & IPOIB_DBG_ERR )\r
+               g_ipoib_dbg_flags |= CL_DBG_ERROR;\r
+#endif\r
+\r
+       cl_free( param_path.Buffer );\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+VOID\r
+ipoib_unload(\r
+       IN                              PDRIVER_OBJECT                          p_drv_obj )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       UNREFERENCED_PARAMETER(p_drv_obj);\r
+       #if defined(EVENT_TRACING)\r
+       WPP_CLEANUP(p_drv_obj);\r
+       #endif\r
+       //NDIS6.0\r
+       NdisMDeregisterMiniportDriver(g_IpoibMiniportDriverHandle);\r
+       UNREFERENCED_PARAMETER( p_drv_obj );\r
+       CL_DEINIT;\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_get_adapter_params(\r
+       IN                              NDIS_HANDLE* const                      wrapper_config_context,\r
+       IN      OUT                     ipoib_adapter_t                         *p_adapter,\r
+       OUT                             PUCHAR                                          *p_mac,\r
+       OUT                             UINT                                            *p_len)\r
+{\r
+       NDIS_STATUS                                             status;\r
+       NDIS_HANDLE                                             h_config;\r
+    NDIS_CONFIGURATION_OBJECT          config_obj;\r
+       NDIS_CONFIGURATION_PARAMETER    *p_param;\r
+       UINT                                                    value;\r
+       PIPOIB_REG_ENTRY                                pRegEntry;\r
+       UINT                                                    i;\r
+       PUCHAR                                                  structPointer;\r
+       \r
+       int sq_depth_step = 128;\r
+\r
+       UNUSED_PARAM(wrapper_config_context);\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+    config_obj.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;\r
+    config_obj.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;\r
+    config_obj.Header.Size = sizeof(NDIS_CONFIGURATION_OBJECT);\r
+    config_obj.NdisHandle = p_adapter->h_adapter;\r
+    config_obj.Flags = 0;\r
+\r
+       status = NdisOpenConfigurationEx( &config_obj, &h_config);\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisOpenConfigurationEx returned 0x%.8x\n", status) );\r
+               return status;\r
+       }\r
+\r
+       // read all the registry values \r
+       for (i = 0, pRegEntry = HCARegTable; i < IPOIB_NUM_REG_PARAMS; ++i)\r
+       {\r
+               // initialize pointer to appropriate place inside 'params'\r
+               structPointer = (PUCHAR) &p_adapter->params + pRegEntry[i].FieldOffset;\r
+\r
+               // Get the configuration value for a specific parameter.  Under NT the\r
+               // parameters are all read in as DWORDs.\r
+               NdisReadConfiguration(\r
+                       &status,\r
+                       &p_param,\r
+                       h_config,\r
+                       &pRegEntry[i].RegName,\r
+                       NdisParameterInteger);\r
+\r
+               // If the parameter was present, then check its value for validity.\r
+               if (status == NDIS_STATUS_SUCCESS)\r
+               {\r
+                       // Check that param value is not too small or too large\r
+                       if (p_param->ParameterData.IntegerData < pRegEntry[i].Min ||\r
+                               p_param->ParameterData.IntegerData > pRegEntry[i].Max)\r
+                       {\r
+                               value = pRegEntry[i].Default;\r
+                               ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+                               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration.Registry %S value is out of range, setting default value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));                                \r
+\r
+                       }\r
+                       else\r
+                       {\r
+                               value = p_param->ParameterData.IntegerData;\r
+                               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));\r
+                       }\r
+               }\r
+\r
+               else\r
+               {\r
+                       value = pRegEntry[i].Default;\r
+                       status = NDIS_STATUS_SUCCESS;\r
+                       if (pRegEntry[i].bRequired)\r
+                       {\r
+                               ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_ERR);\r
+                               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, ("Read configuration.Registry %S value not found, setting default value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));\r
+                       }\r
+                       else\r
+                       {\r
+                               ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_INFO);\r
+                               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S value not found, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));\r
+                       }\r
+\r
+               }\r
+               //\r
+               // Store the value in the adapter structure.\r
+               //\r
+               switch(pRegEntry[i].FieldSize)\r
+               {\r
+                       case 1:\r
+                               *((PUCHAR) structPointer) = (UCHAR) value;\r
+                               break;\r
+\r
+                       case 2:\r
+                               *((PUSHORT) structPointer) = (USHORT) value;\r
+                               break;\r
+\r
+                       case 4:\r
+                               *((PULONG) structPointer) = (ULONG) value;\r
+                               break;\r
+\r
+                       default:\r
+                               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Bogus field size %d\n", pRegEntry[i].FieldSize));\r
+                               break;\r
+               }\r
+       }\r
+\r
+       // Send queue depth needs to be a power of two\r
+       //static const INT sq_depth_step = 128;\r
+\r
+       if (p_adapter->params.sq_depth % sq_depth_step) {\r
+               static const c_sq_ind = 2;\r
+               p_adapter->params.sq_depth = sq_depth_step *(\r
+                       p_adapter->params.sq_depth / sq_depth_step + !!( (p_adapter->params.sq_depth % sq_depth_step) > (sq_depth_step/2) ));\r
+               ipoib_create_log(p_adapter->h_adapter, c_sq_ind, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("SQ DEPTH value was rounded to the closest acceptable value of  0x%x\n", p_adapter->params.sq_depth ));\r
+\r
+       }\r
+\r
+\r
+       // Adjusting the low watermark parameter\r
+       p_adapter->params.rq_low_watermark =\r
+                       p_adapter->params.rq_depth / p_adapter->params.rq_low_watermark;\r
+       \r
+       /* disable CM if LSO is active */\r
+       if( p_adapter->params.cm_enabled )\r
+       {\r
+               p_adapter->params.cm_enabled = !p_adapter->params.lso;\r
+               if( !p_adapter->params.cm_enabled )\r
+               {\r
+                       NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
+                               EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de0 );\r
+               }\r
+       }\r
+\r
+       if( p_adapter->params.cm_enabled )\r
+       {\r
+               p_adapter->params.cm_xfer_block_size = \r
+                       (sizeof(eth_hdr_t) + p_adapter->params.cm_payload_mtu);\r
+       }\r
+\r
+               p_adapter->params.xfer_block_size = \r
+                       (sizeof(eth_hdr_t) + p_adapter->params.payload_mtu);\r
+\r
+       NdisReadNetworkAddress( &status, p_mac, p_len, h_config );\r
+\r
+       NdisCloseConfiguration( h_config );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_get_adapter_guids(\r
+       IN                              NDIS_HANDLE* const                      h_adapter,\r
+       IN      OUT                     ipoib_adapter_t                         *p_adapter )\r
+{\r
+       NTSTATUS                        status;\r
+       ib_al_ifc_data_t        data;\r
+       IO_STACK_LOCATION       io_stack, *p_fwd_io_stack;\r
+       DEVICE_OBJECT           *p_pdo;\r
+       IRP                                     *p_irp;\r
+       KEVENT                          event;\r
+       IO_STATUS_BLOCK         io_status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       NdisMGetDeviceProperty( h_adapter, &p_pdo, NULL, NULL, NULL, NULL );\r
+\r
+       /* Query for our interface */\r
+       data.size = sizeof(ipoib_ifc_data_t);\r
+       data.version = IPOIB_INTERFACE_DATA_VERSION;\r
+       data.type = &GUID_IPOIB_INTERFACE_DATA;\r
+       data.p_data = &p_adapter->guids;\r
+\r
+       io_stack.MinorFunction = IRP_MN_QUERY_INTERFACE;\r
+       io_stack.Parameters.QueryInterface.Version = AL_INTERFACE_VERSION;\r
+       io_stack.Parameters.QueryInterface.Size = sizeof(ib_al_ifc_t);\r
+       io_stack.Parameters.QueryInterface.Interface =\r
+               (INTERFACE*)p_adapter->p_ifc;\r
+       io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data;\r
+       io_stack.Parameters.QueryInterface.InterfaceType = \r
+               &GUID_IB_AL_INTERFACE;\r
+\r
+       KeInitializeEvent( &event, NotificationEvent, FALSE );\r
+\r
+       /* Build the IRP for the HCA. */\r
+       p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_pdo,\r
+               NULL, 0, NULL, &event, &io_status );\r
+       if( !p_irp )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate query interface IRP.\n") );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       /* Copy the request query parameters. */\r
+       p_fwd_io_stack = IoGetNextIrpStackLocation( p_irp );\r
+       p_fwd_io_stack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
+       p_fwd_io_stack->Parameters.QueryInterface =\r
+               io_stack.Parameters.QueryInterface;\r
+       p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
+\r
+       /* Send the IRP. */\r
+       status = IoCallDriver( p_pdo, p_irp );\r
+       if( status == STATUS_PENDING )\r
+       {\r
+               KeWaitForSingleObject( &event, Executive, KernelMode,\r
+                       FALSE, NULL );\r
+               status = io_status.Status;\r
+       }\r
+\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Query interface for IPOIB interface returned %08x.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       /*\r
+        * Dereference the interface now so that the bus driver doesn't fail a\r
+        * query remove IRP.  We will always get unloaded before the bus driver\r
+        * since we're a child device.\r
+        */\r
+       if (p_adapter->p_ifc)\r
+       p_adapter->p_ifc->wdm.InterfaceDereference(\r
+               p_adapter->p_ifc->wdm.Context );\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+//! Initialization function called for each IOC discovered\r
+/*  The MiniportInitialize function is a required function that sets up a\r
+NIC (or virtual NIC) for network I/O operations, claims all hardware\r
+resources necessary to the NIC in the registry, and allocates resources\r
+the driver needs to carry out network I/O operations.\r
+IRQL = PASSIVE_LEVEL\r
+\r
+@param p_open_status Pointer to a status field set if this function returns NDIS_STATUS_OPEN_ERROR\r
+@param p_selected_medium_index Pointer to unsigned integer noting index into medium_array for this NIC\r
+@param medium_array Array of mediums for this NIC\r
+@param medium_array_size Number of elements in medium_array\r
+@param h_adapter Handle assigned by NDIS for this NIC\r
+@param wrapper_config_context Handle used for Ndis initialization functions\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_UNSUPPORTED_MEDIA, NDIS_STATUS_RESOURCES,\r
+NDIS_STATUS_NOT_SUPPORTED \r
+*/\r
+\r
+/*void foo1(int i)\r
+{\r
+               char temp[5200];\r
+               if (i ==0) return;\r
+               cl_msg_out("i = %d\n", i);\r
+               foo1(i-1);\r
+        \r
+}*/\r
+       \r
+NDIS_STATUS\r
+SetDeviceRegistrationAttributes(\r
+       ipoib_adapter_t *p_adapter,\r
+    NDIS_HANDLE        h_adapter\r
+    )\r
+{\r
+    NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES atr;\r
+    NTSTATUS Status;\r
+\r
+    NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES));\r
+\r
+    //\r
+    // setting registration attributes\r
+    //\r
+    atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES;\r
+    atr.Header.Revision = NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+    atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+\r
+\r
+    atr.MiniportAddDeviceContext = (NDIS_HANDLE)p_adapter;\r
+    atr.Flags = 0; \r
+\r
+    Status = NdisMSetMiniportAttributes(h_adapter,\r
+                    (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr);\r
+\r
+    return Status;\r
+}\r
+\r
+//NDIS 6.1\r
+#if 0\r
+NDIS_STATUS\r
+SetHardwareAssistAttributes(\r
+    ipoib_adapter_t *p_adapter,\r
+    NDIS_HANDLE        h_adapter\r
+    )\r
+{\r
+    NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES atr;\r
+    NTSTATUS Status;\r
+\r
+    NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES));\r
+\r
+    //\r
+    // setting registration attributes\r
+    //\r
+    atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES;\r
+    atr.Header.Revision = NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;\r
+    atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;\r
+\r
+    NDIS_HD_SPLIT_ATTRIBUTES nhsa;\r
+    NdisZeroMemory(&nhsa, sizeof(nhsa));\r
+\r
+    nhsa.Header.Type = NDIS_OBJECT_TYPE_HD_SPLIT_ATTRIBUTES;\r
+    nhsa.Header.Revision = NDIS_OFFLOAD_REVISION_1;\r
+    nhsa.Header.Size = NDIS_SIZEOF_HD_SPLIT_ATTRIBUTES_REVISION_1;\r
+\r
+    // BUGBUG: We are just cheating here ...\r
+    nhsa.HardwareCapabilities = NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT;\r
+#if 0\r
+    ... Only supported on B0\r
+\r
+                                 NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV4_OPTIONS |\r
+                                 NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV6_EXTENSION_HEADERS |\r
+                                 NDIS_HD_SPLIT_CAPS_SUPPORTS_TCP_OPTIONS;\r
+#endif\r
+\r
+    // The bellow should be left zero\r
+    if (pPort->Config.HeaderDataSplit) {\r
+        nhsa.CurrentCapabilities = NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT;\r
+    } else {\r
+        nhsa.CurrentCapabilities = 0;\r
+    }\r
+\r
+    nhsa.HDSplitFlags = 0;\r
+    nhsa.BackfillSize = 0;\r
+    nhsa.MaxHeaderSize = 0;    \r
+\r
+    atr.HDSplitAttributes = &nhsa;\r
+\r
+    Status = NdisMSetMiniportAttributes(h_adapter,\r
+                    (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr);\r
+\r
+    if (nhsa.HDSplitFlags & NDIS_HD_SPLIT_ENABLE_HEADER_DATA_SPLIT) {\r
+        ASSERT(pPort->Config.HeaderDataSplit == TRUE);\r
+        pPort->Config.HeaderDataSplit = TRUE;\r
+    } \r
+    else {\r
+        ASSERT(pPort->Config.HeaderDataSplit == FALSE);\r
+        pPort->Config.HeaderDataSplit = FALSE;\r
+    }\r
+\r
+    return Status;\r
+}\r
+#endif\r
+\r
+/*++\r
+Routine Description:\r
+    the routine sets attributes that are associated with a miniport adapter.\r
+\r
+Arguments:\r
+    pPort - Pointer to port object\r
+\r
+Return Value:\r
+    NDIS_STATUS\r
+\r
+Note:\r
+    Should be called in PASSIVE_LEVEL\r
+    \r
+--*/\r
+NDIS_STATUS\r
+SetAdapterRegistrationAttributes(\r
+       ipoib_adapter_t *p_adapter,\r
+       NDIS_HANDLE     h_adapter\r
+       )\r
+       {\r
+       NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES atr;\r
+       NTSTATUS Status;\r
+\r
+       NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));\r
+\r
+       /* setting registration attributes */\r
+\r
+       atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;\r
+       atr.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+       atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+       //TODO NDIS60 Port or adapter\r
+       atr.MiniportAdapterContext = (NDIS_HANDLE)p_adapter; //(NDIS_HANDLE)pPort->p_adapter;\r
+       atr.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER;\r
+       atr.CheckForHangTimeInSeconds = 10;\r
+       atr.InterfaceType = NdisInterfacePci ;   // ???? UH\r
+       //TODO NDIS60 PNP or PCI ?\r
+       //RegistrationAttributes.InterfaceType = NdisInterfacePNPBus;\r
+\r
+       Status = NdisMSetMiniportAttributes(h_adapter,\r
+                       (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr);\r
+\r
+       return Status;\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+    the routine sets generic attributes that are associated with a miniport \r
+    adapter.\r
+\r
+Arguments:\r
+    pPort - Pointer to port object\r
+\r
+Return Value:\r
+    NDIS_STATUS\r
+\r
+Note:\r
+    Should be called in PASSIVE_LEVEL\r
+    \r
+--*/\r
+NDIS_STATUS\r
+SetGenericAttributes(\r
+    ipoib_adapter_t *p_adapter,\r
+    NDIS_HANDLE        h_adapter\r
+    )\r
+{\r
+    NDIS_STATUS Status;\r
+\r
+    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES gat;\r
+    NdisZeroMemory(&gat, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));\r
+\r
+       /* set up generic attributes */\r
+\r
+       gat.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;\r
+       gat.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;\r
+       gat.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);\r
+\r
+       gat.MediaType = NdisMedium802_3;    \r
+       gat.MaxXmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+       gat.MaxRcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+       gat.XmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED; //TODO NDIS60 NDIS_LINK_SPEED_UNKNOWN\r
+       gat.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; // TODO NDIS60 NDIS_LINK_SPEED_UNKNOWN ???\r
+\r
+       gat.MediaConnectState = MediaConnectStateConnected; //TODO NDIS60 Check the current state\r
+       gat.MediaDuplexState = MediaDuplexStateFull;\r
+\r
+       gat.MtuSize = MAX_IB_MTU;\r
+       gat.LookaheadSize = MAX_XFER_BLOCK_SIZE;\r
+       gat.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \r
+                                        NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
+                                        NDIS_MAC_OPTION_NO_LOOPBACK |\r
+                                        NDIS_MAC_OPTION_FULL_DUPLEX;\r
+                                       //NDIS_MAC_OPTION_8021P_PRIORITY; //TODO NDIS60\r
+                                       // DT: Enable for Header Data Split WHQL\r
+                                       // |  NDIS_MAC_OPTION_8021Q_VLAN;\r
+\r
+       gat.SupportedPacketFilters =    NDIS_PACKET_TYPE_DIRECTED |\r
+                                                                       NDIS_PACKET_TYPE_MULTICAST |\r
+                                                                       //NDIS_PACKET_TYPE_ALL_MULTICAST |\r
+                                                                       NDIS_PACKET_TYPE_BROADCAST;\r
+                                        \r
+       gat.MaxMulticastListSize = MAX_MCAST;\r
+\r
+       gat.MacAddressLength = HW_ADDR_LEN;\r
+       \r
+       NdisMoveMemory(gat.PermanentMacAddress,\r
+                                       p_adapter->mac.addr,\r
+                                       HW_ADDR_LEN);\r
+\r
+       NdisMoveMemory(gat.CurrentMacAddress,\r
+                                       p_adapter->params.conf_mac.addr,\r
+                                       HW_ADDR_LEN);\r
+\r
+\r
+       gat.PhysicalMediumType = NdisPhysicalMedium802_3;\r
+       gat.AccessType = NET_IF_ACCESS_BROADCAST; \r
+\r
+       gat.SupportedOidList = (PNDIS_OID)SUPPORTED_OIDS;\r
+       gat.SupportedOidListLength = sizeof(SUPPORTED_OIDS);\r
+\r
+\r
+       gat.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; \r
+       gat.ConnectionType = NET_IF_CONNECTION_DEDICATED; \r
+       gat.IfType = IF_TYPE_ETHERNET_CSMACD; \r
+       gat.IfConnectorPresent = TRUE; \r
+       //TODO NDIS60 This value is absent for ETH driver\r
+       gat.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter\r
+\r
+\r
+       //TODO NDIS60 is it possible to reduce unsupported statistics\r
+       gat.SupportedStatistics = \r
+                               NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
+                               NDIS_STATISTICS_RCV_OK_SUPPORTED |\r
+                               NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |\r
+                               NDIS_STATISTICS_RCV_ERROR_SUPPORTED |\r
+                               NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED |\r
+                               NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED |\r
+                               NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED;\r
+\r
+       //SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
+                                                       // NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;\r
+\r
+\r
+    //\r
+    // Set power management capabilities\r
+    //\r
+    gat.PowerManagementCapabilities = NULL;\r
+#if 0\r
+    NDIS_PNP_CAPABILITIES PowerManagementCapabilities;\r
+    NdisZeroMemory(&PowerManagementCapabilities, sizeof(NDIS_PNP_CAPABILITIES));\r
+    if (MPIsPoMgmtSupported(pPort))\r
+    {\r
+        MPFillPoMgmtCaps(pPort, &PowerManagementCapabilities, &Status, &unUsed);\r
+        ASSERT(NT_SUCCESS(Status)); \r
+        gat.PowerManagementCapabilities = &PowerManagementCapabilities;\r
+    } \r
+    else\r
+    {\r
+        \r
+    }\r
+#endif\r
+\r
+    //\r
+    // Set RSS attributes\r
+    //\r
+    gat.RecvScaleCapabilities = NULL;\r
+#if 0\r
+    NDIS_RECEIVE_SCALE_CAPABILITIES RssCapabilities;\r
+    NdisZeroMemory(&RssCapabilities, sizeof(PNDIS_RECEIVE_SCALE_CAPABILITIES));\r
+    Status = MPFillRssCapabilities(pPort, &RssCapabilities, &unUsed);\r
+    if (NT_SUCCESS(Status)) \r
+    {\r
+        gat.RecvScaleCapabilities = &RssCapabilities;\r
+    } \r
+    else\r
+    {\r
+        //\r
+        // do not fail the call because of failure to get PM caps\r
+        //\r
+        Status = NDIS_STATUS_SUCCESS;\r
+        gat.RecvScaleCapabilities = NULL;\r
+    }\r
+#endif\r
+\r
+       Status = NdisMSetMiniportAttributes(h_adapter,\r
+                       (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&gat);\r
+\r
+       return Status;\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+    The routine sets an NDIS_OFFLOAD structure indicates the current offload \r
+    capabilities that are provided by the miniport adapter \r
+    \r
+Arguments:\r
+    pPort - a pointer to port object\r
+    offload - reference to NDIS_OFFLOAD object that should be filled\r
+\r
+Return Value:\r
+    None.\r
+    \r
+--*/\r
+static\r
+void\r
+OffloadConfig(\r
+       ipoib_adapter_t *p_adapter,\r
+       NDIS_OFFLOAD *p_offload\r
+       )\r
+{ \r
+\r
+       ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q;\r
+\r
+       NdisZeroMemory(p_offload, NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1);\r
+\r
+       p_offload->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;\r
+       p_offload->Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008\r
+       p_offload->Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;\r
+\r
+       p_offload->Checksum.IPv4Transmit.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv4Transmit.IpOptionsSupported = \r
+       p_offload->Checksum.IPv4Transmit.TcpOptionsSupported = \r
+       p_offload->Checksum.IPv4Transmit.TcpChecksum = \r
+       p_offload->Checksum.IPv4Transmit.UdpChecksum = \r
+       p_offload->Checksum.IPv4Transmit.IpChecksum =!!(p_adapter->params.send_chksum_offload);\r
+\r
+       p_offload->Checksum.IPv4Receive.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv4Receive.IpOptionsSupported = \r
+       p_offload->Checksum.IPv4Receive.TcpOptionsSupported = \r
+       p_offload->Checksum.IPv4Receive.TcpChecksum = \r
+       p_offload->Checksum.IPv4Receive.UdpChecksum = \r
+       p_offload->Checksum.IPv4Receive.IpChecksum = !!(p_adapter->params.recv_chksum_offload); //TODO NDIS60\r
+\r
+\r
+       p_offload->Checksum.IPv6Transmit.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv6Transmit.IpExtensionHeadersSupported = \r
+       p_offload->Checksum.IPv6Transmit.TcpOptionsSupported =\r
+       p_offload->Checksum.IPv6Transmit.TcpChecksum = \r
+       p_offload->Checksum.IPv6Transmit.UdpChecksum = FALSE;\r
+\r
+\r
+       p_offload->Checksum.IPv6Receive.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv6Receive.IpExtensionHeadersSupported = \r
+       p_offload->Checksum.IPv6Receive.TcpOptionsSupported = \r
+       p_offload->Checksum.IPv6Receive.TcpChecksum = \r
+       p_offload->Checksum.IPv6Receive.UdpChecksum = FALSE;\r
+\r
+       if (p_adapter->params.lso)\r
+       {\r
+               p_offload->LsoV1.IPv4.Encapsulation = ulEncapsulation;\r
+               p_offload->LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+#define LSO_MIN_SEG_COUNT 2\r
+               p_offload->LsoV1.IPv4.MinSegmentCount = LSO_MIN_SEG_COUNT;\r
+       \r
+               \r
+               p_offload->LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+               p_offload->LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+\r
+               p_offload->LsoV2.IPv4.Encapsulation = ulEncapsulation;\r
+               p_offload->LsoV2.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+               p_offload->LsoV2.IPv4.MinSegmentCount = LSO_MIN_SEG_COUNT;\r
+\r
+               p_offload->LsoV2.IPv6.Encapsulation = ulEncapsulation;\r
+               p_offload->LsoV2.IPv6.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+               p_offload->LsoV2.IPv6.MinSegmentCount = LSO_MIN_SEG_COUNT;\r
+\r
+               p_offload->LsoV2.IPv6.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+               p_offload->LsoV2.IPv6.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;\r
+       }\r
+\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+    The routine sets an NDIS_OFFLOAD structure that indicates all the task \r
+    offload capabilites that are supported by the NIC. These capabilities include\r
+    capabilities that are currently disabled by standardized keywords in the registry. \r
+    \r
+Arguments:\r
+    offload - reference to NDIS_OFFLOAD object that should be filled\r
+\r
+Return Value:\r
+    None.\r
+    \r
+--*/\r
+static\r
+void\r
+OffloadCapabilities(\r
+       NDIS_OFFLOAD    *p_offload\r
+       )\r
+{ \r
+       ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q ;\r
+       NdisZeroMemory(p_offload, NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1);    \r
+\r
+       p_offload->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;\r
+       p_offload->Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008\r
+       p_offload->Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;\r
+\r
+       p_offload->Checksum.IPv4Transmit.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv4Transmit.IpOptionsSupported = TRUE;\r
+       p_offload->Checksum.IPv4Transmit.TcpOptionsSupported = TRUE;\r
+       p_offload->Checksum.IPv4Transmit.TcpChecksum = TRUE;\r
+       p_offload->Checksum.IPv4Transmit.UdpChecksum = TRUE;\r
+       p_offload->Checksum.IPv4Transmit.IpChecksum = TRUE;\r
+\r
+       p_offload->Checksum.IPv4Receive.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv4Receive.IpOptionsSupported = TRUE;\r
+       p_offload->Checksum.IPv4Receive.TcpOptionsSupported = TRUE;\r
+       p_offload->Checksum.IPv4Receive.TcpChecksum = TRUE;\r
+       p_offload->Checksum.IPv4Receive.UdpChecksum = TRUE; \r
+       p_offload->Checksum.IPv4Receive.IpChecksum = TRUE;\r
+\r
+\r
+       //\r
+       //  BUGBUG::\r
+       //  During a HW bug that didn't handle correctly packets with \r
+       //  IPv6 Extension Headers -> we set IpExtensionHeadersSupported to TRUE\r
+       //\r
+       p_offload->Checksum.IPv6Transmit.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv6Transmit.IpExtensionHeadersSupported = TRUE;\r
+       p_offload->Checksum.IPv6Transmit.TcpOptionsSupported = TRUE;\r
+       p_offload->Checksum.IPv6Transmit.TcpChecksum = TRUE;\r
+       p_offload->Checksum.IPv6Transmit.UdpChecksum = TRUE;\r
+\r
+\r
+       p_offload->Checksum.IPv6Receive.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv6Receive.IpExtensionHeadersSupported = TRUE;\r
+       p_offload->Checksum.IPv6Receive.TcpOptionsSupported = TRUE;\r
+       p_offload->Checksum.IPv6Receive.TcpChecksum = TRUE;\r
+       p_offload->Checksum.IPv6Receive.UdpChecksum = TRUE;\r
+\r
+       p_offload->LsoV1.IPv4.Encapsulation = ulEncapsulation;\r
+       p_offload->LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+       p_offload->LsoV1.IPv4.MinSegmentCount = 2;\r
+       p_offload->LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+       p_offload->LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+\r
+       p_offload->LsoV2.IPv4.Encapsulation = ulEncapsulation;\r
+       p_offload->LsoV2.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+       p_offload->LsoV2.IPv4.MinSegmentCount = 2;\r
+\r
+       p_offload->LsoV2.IPv6.Encapsulation = ulEncapsulation;\r
+       p_offload->LsoV2.IPv6.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+       p_offload->LsoV2.IPv6.MinSegmentCount = 2;\r
+\r
+       p_offload->LsoV2.IPv6.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+       p_offload->LsoV2.IPv6.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;\r
+\r
+       }\r
+\r
+\r
+/*++\r
+Routine Description:\r
+    The routine sets offload attributes that are associated with a miniport \r
+    adapter.\r
+\r
+Arguments:\r
+    pPort - Pointer to port object\r
+\r
+Return Value:\r
+    NDIS_STATUS\r
+\r
+Note:\r
+    Should be called in PASSIVE_LEVEL\r
+    \r
+--*/\r
+NDIS_STATUS\r
+SetOffloadAttributes(\r
+       ipoib_adapter_t *p_adapter,\r
+       NDIS_HANDLE     h_adapter\r
+       )\r
+{\r
+       NDIS_STATUS Status;\r
+       NDIS_OFFLOAD offload,hwOffload;\r
+       //ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q;\r
+\r
+       NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES oat;    \r
+       NdisZeroMemory(&oat, sizeof(NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES));\r
+\r
+       oat.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;\r
+       oat.Header.Revision = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;\r
+       oat.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;\r
+\r
+\r
+       OffloadConfig(p_adapter, &offload);\r
+\r
+\r
+       OffloadCapabilities(&hwOffload);\r
+\r
+       oat.DefaultOffloadConfiguration = &offload;\r
+       oat.HardwareOffloadCapabilities = &hwOffload;\r
+\r
+       Status = NdisMSetMiniportAttributes(h_adapter,\r
+                               (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&oat);\r
+\r
+       return Status;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+    An NDIS 6.0 miniport driver must call NdisMSetMiniportAttributes\r
+    at least twice. The first call is to register itself with NDIS.\r
+    The second call is to register the miniport driver's general\r
+    attributes with NDIS.\r
+\r
+    NdisMSetMiniportAttributes takes a parameter of type\r
+    NDIS_MINIPORT_ADAPTER_ATTRIBUTES, which is a union of several miniport\r
+    adapter attributes. Miniport drivers must first call\r
+    NdisMSetMiniportAttributes and pass in an\r
+    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES structure\r
+    that contains the pointer to its own context area, attribute flags,\r
+    check-for-hang time, and interface type.\r
+\r
+    All NDIS 6.0 miniport drivers are deserialized by default.\r
+\r
+Arguments:\r
+    pPort - Pointer to port object\r
+\r
+Return Value:\r
+    NDIS_STATUS\r
+\r
+Note:\r
+    Should be called in PASSIVE_LEVEL\r
+    \r
+--*/\r
+       NDIS_STATUS\r
+       SetAttributes(\r
+       ipoib_adapter_t *p_adapter,\r
+       NDIS_HANDLE     h_adapter\r
+       )\r
+       {\r
+       NTSTATUS Status;\r
+\r
+\r
+       Status = SetDeviceRegistrationAttributes(p_adapter, h_adapter);\r
+       if (Status != NDIS_STATUS_SUCCESS)\r
+       {\r
+               //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set device registration failed Error=0x%x\n", Status);\r
+               return Status;\r
+       }\r
+\r
+\r
+       Status = SetAdapterRegistrationAttributes(p_adapter, h_adapter);\r
+       if (Status != NDIS_STATUS_SUCCESS)\r
+       {\r
+               //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set adapter attributes failed Error=0x%x\n", Status);\r
+               return Status;\r
+       }\r
+\r
+       Status = SetOffloadAttributes(p_adapter, h_adapter);\r
+       if (Status != NDIS_STATUS_SUCCESS)\r
+       {\r
+               //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set OFFLOAD attributes failed Error=0x%x\n", Status);\r
+               return Status;\r
+       }\r
+       \r
+#if 0\r
+       if(!pPort->Config.fWHQL)\r
+       {\r
+               Status = SetHardwareAssistAttributes(pPort);\r
+               if (Status != NDIS_STATUS_SUCCESS)\r
+               {\r
+                   //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set Hardware Assist Attributes failed Error=0x%x\n", Status);\r
+                   return Status;\r
+               }\r
+       }\r
+#endif\r
+\r
+       Status = SetGenericAttributes(p_adapter, h_adapter);\r
+       if (Status != NDIS_STATUS_SUCCESS)\r
+       {\r
+           //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set generic attributes failed Error=0x%x\n", Status);\r
+           return Status;\r
+       }\r
+\r
+       return Status;\r
+}\r
+\r
+\r
+//TODO Don't pass h_adapter inside the function, use pPort->p_adapter->h_adapter\r
+NDIS_STATUS\r
+InitNdisScatterGatherDma(\r
+       ipoib_adapter_t *p_adapter,\r
+       NDIS_HANDLE             h_adapter\r
+       )\r
+{\r
+       NDIS_STATUS                                             status;\r
+       NDIS_SG_DMA_DESCRIPTION                 DmaDescription;\r
+       \r
+       NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));\r
+\r
+       DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;\r
+       DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;\r
+       DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);\r
+       DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS; \r
+       //\r
+       // Even if offload is enabled, the packet size for mapping shouldn't change\r
+       //\r
+       DmaDescription.MaximumPhysicalMapping = LARGE_SEND_OFFLOAD_SIZE + LSO_MAX_HEADER;\r
+\r
+       DmaDescription.ProcessSGListHandler = ipoib_process_sg_list;\r
+       DmaDescription.SharedMemAllocateCompleteHandler = NULL;\r
+\r
+       DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;\r
+       DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;\r
+       DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);//NDIS_SIZEOF_SG_DMA_DESCRIPTION_REVISION_1;\r
+\r
+       DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS;\r
+       //DmaDescription.MaximumPhysicalMapping = pPort->p_adapter->params.xfer_block_size;\r
+\r
+       DmaDescription.ProcessSGListHandler = ipoib_process_sg_list;\r
+       DmaDescription.SharedMemAllocateCompleteHandler = NULL;\r
+       \r
+       status = NdisMRegisterScatterGatherDma(\r
+                                       h_adapter,\r
+                                       &DmaDescription,\r
+                                       &p_adapter->NdisMiniportDmaHandle);\r
+\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               //TODO NDIS60\r
+               //ipoib_destroy_adapter( p_adapter );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                                ("NdisMRegisterScatterGatherDma returned 0x%.8x.\n", status) );\r
+               \r
+       }\r
+       //NDIS sets this value before it returns from NdisMRegisterScatterGatherDma. \r
+               //Miniport drivers should use this size to preallocate memory for each scatter/gather list. \r
+       p_adapter->sg_list_size = DmaDescription.ScatterGatherListSize ;\r
+       \r
+       return status;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_initialize_ex(\r
+               IN NDIS_HANDLE  h_adapter,\r
+               IN NDIS_HANDLE  config_context,\r
+               IN PNDIS_MINIPORT_INIT_PARAMETERS  MiniportInitParameters)\r
+       {\r
+               NDIS_STATUS             status;\r
+               ib_api_status_t         ib_status;\r
+               ipoib_adapter_t         *p_adapter;\r
+               //NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES RegistrationAttributes;\r
+               //NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES              GeneralAttributes;\r
+#if IPOIB_USE_DMA\r
+               //NDIS_SG_DMA_DESCRIPTION       DmaDescription;\r
+#endif\r
+               IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       \r
+#ifdef _DEBUG_\r
+               PAGED_CODE();\r
+#endif\r
+               \r
+               UNUSED_PARAM( config_context );\r
+               UNUSED_PARAM( MiniportInitParameters );\r
+               \r
+               //foo1(100);\r
+               /* Create the adapter adapter */\r
+               ib_status = ipoib_create_adapter(config_context, h_adapter, &p_adapter );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ipoib_create_adapter returned status %d.\n", ib_status ) );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               p_adapter->ipoib_state = IPOIB_PAUSED;\r
+               status  = SetAttributes(p_adapter, h_adapter);\r
+               if (status != NDIS_STATUS_SUCCESS) {\r
+                       ASSERT(FALSE);\r
+               }\r
+#if 0\r
+               NdisZeroMemory(&RegistrationAttributes, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));\r
+               NdisZeroMemory(&GeneralAttributes, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));\r
+       \r
+               /* setting registration attributes */\r
+               RegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;\r
+               RegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+               RegistrationAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+       \r
+               RegistrationAttributes.MiniportAdapterContext = (NDIS_HANDLE)p_adapter;\r
+               RegistrationAttributes.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER;\r
+                                                                                                               \r
+               RegistrationAttributes.CheckForHangTimeInSeconds = 10;\r
+               RegistrationAttributes.InterfaceType = NdisInterfacePNPBus;\r
+       \r
+               status = NdisMSetMiniportAttributes(h_adapter,\r
+                                                                                  (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&RegistrationAttributes);\r
+       \r
+               if (status != NDIS_STATUS_SUCCESS)\r
+               {\r
+                       ipoib_destroy_adapter( p_adapter );\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("NdisMSetMiniportAttributes returned 0x%.8x.\n", status) );\r
+                       return status;\r
+               }\r
+       \r
+               /* set up generic attributes */\r
+       \r
+                GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;\r
+                GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;\r
+                GeneralAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);\r
+       \r
+                GeneralAttributes.MediaType = NdisMedium802_3;\r
+               //TODO\r
+                GeneralAttributes.MtuSize = MAX_IB_MTU;\r
+                GeneralAttributes.MaxXmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+                GeneralAttributes.MaxRcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+                GeneralAttributes.XmitLinkSpeed = NDIS_LINK_SPEED_UNKNOWN;\r
+                GeneralAttributes.RcvLinkSpeed = NDIS_LINK_SPEED_UNKNOWN;\r
+                GeneralAttributes.MediaConnectState = MediaConnectStateUnknown;\r
+                GeneralAttributes.MediaDuplexState = MediaDuplexStateUnknown;\r
+                GeneralAttributes.LookaheadSize = MAX_XFER_BLOCK_SIZE;\r
+       \r
+                GeneralAttributes.PowerManagementCapabilities = NULL;\r
+       \r
+                GeneralAttributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |\r
+                                                                               NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
+                                                                               NDIS_MAC_OPTION_NO_LOOPBACK |\r
+                                                                               NDIS_MAC_OPTION_FULL_DUPLEX;\r
+       \r
+                GeneralAttributes.SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED |\r
+                                                                                                       NDIS_PACKET_TYPE_MULTICAST |\r
+                                                                                                       NDIS_PACKET_TYPE_ALL_MULTICAST |\r
+                                                                                                       NDIS_PACKET_TYPE_BROADCAST;\r
+                       \r
+                GeneralAttributes.MaxMulticastListSize = MAX_MCAST;\r
+                GeneralAttributes.MacAddressLength = HW_ADDR_LEN;\r
+       \r
+                NdisMoveMemory(GeneralAttributes.PermanentMacAddress,\r
+                                               p_adapter->mac.addr,\r
+                                               HW_ADDR_LEN);\r
+       \r
+                NdisMoveMemory(GeneralAttributes.CurrentMacAddress,\r
+                                               p_adapter->params.conf_mac.addr,\r
+                                               HW_ADDR_LEN);\r
+       \r
+                       \r
+                GeneralAttributes.PhysicalMediumType = NdisPhysicalMediumUnspecified;\r
+                GeneralAttributes.RecvScaleCapabilities = NULL;\r
+                GeneralAttributes.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter\r
+                GeneralAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; // NET_IF_DIRECTION_SENDRECEIVE for a typical ethernet adapter\r
+                GeneralAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED;  // NET_IF_CONNECTION_DEDICATED for a typical ethernet adapter\r
+                GeneralAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; // IF_TYPE_ETHERNET_CSMACD for a typical ethernet adapter (regardless of speed)\r
+                GeneralAttributes.IfConnectorPresent = TRUE; // RFC 2665 TRUE if physical adapter\r
+       \r
+                GeneralAttributes.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_RCV_OK_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_RCV_ERROR_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;\r
+                                                 \r
+                GeneralAttributes.SupportedOidList = (PNDIS_OID)SUPPORTED_OIDS;\r
+                GeneralAttributes.SupportedOidListLength = sizeof(SUPPORTED_OIDS);\r
+       \r
+                status = NdisMSetMiniportAttributes(h_adapter,\r
+                                                                                       (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&GeneralAttributes);\r
+       \r
+                if (status != NDIS_STATUS_SUCCESS)\r
+                {\r
+                        IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                ("NdisMSetMiniportAttributes returned 0x%.8x.\n", status) );\r
+                }\r
+       \r
+#if IPOIB_USE_DMA\r
+       \r
+                NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));\r
+       \r
+                DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;\r
+                DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;\r
+                DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);//NDIS_SIZEOF_SG_DMA_DESCRIPTION_REVISION_1;\r
+       \r
+                DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS;\r
+                DmaDescription.MaximumPhysicalMapping = p_adapter->params.xfer_block_size;\r
+               \r
+                DmaDescription.ProcessSGListHandler = ipoib_process_sg_list;\r
+                DmaDescription.SharedMemAllocateCompleteHandler = NULL;\r
+       \r
+                status = NdisMRegisterScatterGatherDma(\r
+                                               p_adapter->h_adapter,\r
+                                               &DmaDescription,\r
+                                               &p_adapter->NdisMiniportDmaHandle);\r
+                                               \r
+                if( status != NDIS_STATUS_SUCCESS )\r
+                {\r
+                        ipoib_destroy_adapter( p_adapter );\r
+                        IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                                        ("NdisMRegisterScatterGatherDma returned 0x%.8x.\n", status) );\r
+                        return status;\r
+                }\r
+\r
+               \r
+               \r
+#endif\r
+#endif //if 0\r
+\r
+\r
+\r
+#if IPOIB_USE_DMA\r
+\r
+               InitNdisScatterGatherDma(p_adapter, h_adapter);\r
+\r
+\r
+\r
+#endif\r
+               /* Create the adapter adapter */\r
+               ib_status = ipoib_start_adapter( p_adapter );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       NdisWriteErrorLogEntry( h_adapter,\r
+                               NDIS_ERROR_CODE_HARDWARE_FAILURE, 0 );\r
+#if  IPOIB_USE_DMA\r
+                       NdisMDeregisterScatterGatherDma(p_adapter->NdisMiniportDmaHandle);\r
+#endif\r
+                       ipoib_destroy_adapter( p_adapter );\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ipoib_start_adapter returned status %d.\n", ib_status ) );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+       \r
+               ipoib_ref_ibat();\r
+       \r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return status;\r
+       }\r
+\r
+\r
+//! Deallocates resources when the NIC is removed and halts the NIC..\r
+//TODO: Dispatch or Passive ?\r
+/*  IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+*/\r
+void\r
+ipoib_halt_ex(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                      NDIS_HALT_ACTION            HaltAction )\r
+{\r
+       ipoib_adapter_t *p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       UNUSED_PARAM(HaltAction);\r
+               \r
+       ipoib_deref_ibat();\r
+\r
+       CL_ASSERT( adapter_context );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Port %016I64x (CA %016I64x port %d) halting\n",\r
+                       p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid,\r
+                       p_adapter->guids.port_num) );\r
+\r
+#if IPOIB_USE_DMA\r
+       if (p_adapter->NdisMiniportDmaHandle != NULL)\r
+       {\r
+               NdisMDeregisterScatterGatherDma(p_adapter->NdisMiniportDmaHandle);\r
+               p_adapter->NdisMiniportDmaHandle = NULL;\r
+       }\r
+#endif\r
+       ipoib_destroy_adapter( p_adapter );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+//! Reports the state of the NIC, or monitors the responsiveness of an underlying device driver.\r
+/*  IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+@return TRUE if the driver determines that its NIC is not operating\r
+*/\r
+BOOLEAN\r
+ipoib_check_for_hang(\r
+       IN                              NDIS_HANDLE                                     adapter_context )\r
+{\r
+       ipoib_adapter_t *p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( adapter_context );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+       if( p_adapter->reset )\r
+       {\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return FALSE;\r
+       }\r
+       if (p_adapter->hung) {\r
+               ipoib_resume_oids(p_adapter);\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return (p_adapter->hung? TRUE:FALSE);\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+       The routine sets an NDIS_OFFLOAD structure indicates the current offload \r
+       capabilities that are provided by the miniport adapter \r
+\r
+Arguments:\r
+       pPort - a pointer to port object\r
+       offload - reference to NDIS_OFFLOAD object that should be filled\r
+\r
+Return Value:\r
+       None.\r
+\r
+--*/\r
+//TODO\r
+#if 0\r
+static\r
+void\r
+__ipoib_get_offload_config(\r
+       ipoib_port_t *pPort,\r
+       NDIS_OFFLOAD *p_offload\r
+       )\r
+{\r
+       NDIS_STATUS Status;\r
+       ULONG TxChksumOffload = ((MP_GET_PORT_CONFIG(pPort, TxChksumOffload) == TRUE) ? NDIS_OFFLOAD_SET_ON : NDIS_OFFLOAD_SET_OFF);\r
+       ULONG RxChksumOffload = ((MP_GET_PORT_CONFIG(pPort, RxChksumOffload) == TRUE) ? NDIS_OFFLOAD_SET_ON : NDIS_OFFLOAD_SET_OFF);\r
+       BOOLEAN fLargeSendOffload = MP_GET_PORT_CONFIG(pPort, LargeSendOffload);\r
+       ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q;\r
+           \r
+       NdisZeroMemory(&*p_offload, sizeof(NDIS_OFFLOAD));\r
+       *p_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;\r
+       *p_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008\r
+       *p_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;\r
+\r
+       *p_offload.Checksum.IPv4Transmit.Encapsulation = ulEncapsulation;\r
+       *p_offload.Checksum.IPv4Transmit.IpOptionsSupported = TxChksumOffload;\r
+       *p_offload.Checksum.IPv4Transmit.TcpOptionsSupported = TxChksumOffload;\r
+       *p_offload.Checksum.IPv4Transmit.TcpChecksum = TxChksumOffload;\r
+       *p_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+       *p_offload.Checksum.IPv4Transmit.IpChecksum = TxChksumOffload;\r
+\r
+       *p_offload.Checksum.IPv4Receive.Encapsulation = ulEncapsulation;\r
+       *p_offload.Checksum.IPv4Receive.IpOptionsSupported = RxChksumOffload;\r
+       *p_offload.Checksum.IPv4Receive.TcpOptionsSupported = RxChksumOffload;\r
+       *p_offload.Checksum.IPv4Receive.TcpChecksum = RxChksumOffload;\r
+       *p_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED; \r
+       *p_offload.Checksum.IPv4Receive.IpChecksum = RxChksumOffload;\r
+\r
+       *p_offload.Checksum.IPv6Transmit.Encapsulation = ulEncapsulation;\r
+       *p_offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = TxChksumOffload;\r
+       *p_offload.Checksum.IPv6Transmit.TcpOptionsSupported = TxChksumOffload;\r
+       *p_offload.Checksum.IPv6Transmit.TcpChecksum = TxChksumOffload;\r
+       *p_offload.Checksum.IPv6Transmit.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+\r
+\r
+       *p_offload.Checksum.IPv6Receive.Encapsulation = ulEncapsulation;\r
+       *p_offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = RxChksumOffload;\r
+       *p_offload.Checksum.IPv6Receive.TcpOptionsSupported = RxChksumOffload;\r
+       *p_offload.Checksum.IPv6Receive.TcpChecksum = RxChksumOffload;\r
+       *p_offload.Checksum.IPv6Receive.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+\r
+       if (fLargeSendOffload)\r
+       {\r
+           *p_offload.LsoV1.IPv4.Encapsulation = ulEncapsulation;\r
+           *p_offload.LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+           *p_offload.LsoV1.IPv4.MinSegmentCount = 1;\r
+           *p_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+           *p_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+       }\r
+}\r
+#endif\r
+\r
+//! Returns information about the capabilities and status of the driver and/or its NIC.\r
+/*  IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+@param oid Object ID representing the query operation to be carried out\r
+@param info_buf Buffer containing any input for this query and location for output\r
+@param info_buf_len Number of bytes available in info_buf\r
+@param p_bytes_written Pointer to number of bytes written into info_buf\r
+@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
+NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_NOT_ACCEPTED, NDIS_STATUS_NOT_SUPPORTED,\r
+NDIS_STATUS_RESOURCES\r
+*/\r
+       NDIS_STATUS\r
+ipoib_query_info(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              NDIS_OID                                        oid,\r
+       IN                              PVOID                                           info_buf,\r
+       IN                              ULONG                                           info_buf_len,\r
+               OUT                     PULONG                                          p_bytes_written,\r
+               OUT                     PULONG                                          p_bytes_needed )\r
+       {\r
+       ipoib_adapter_t         *p_adapter;\r
+               NDIS_STATUS             status;\r
+               USHORT                          version;\r
+       ULONG                           info;\r
+               PVOID                           src_buf;\r
+               ULONG                           buf_len;\r
+               pending_oid_t           oid_info;\r
+       uint8_t                         port_num;\r
+               \r
+               IPOIB_ENTER( IPOIB_DBG_OID );\r
+               \r
+               oid_info.oid = oid;\r
+               oid_info.p_buf = info_buf;\r
+               oid_info.buf_len = info_buf_len;\r
+               oid_info.p_bytes_used = p_bytes_written;\r
+               oid_info.p_bytes_needed = p_bytes_needed;\r
+               \r
+               CL_ASSERT( adapter_context );\r
+               p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+               CL_ASSERT( p_bytes_written );\r
+               CL_ASSERT( p_bytes_needed );\r
+               CL_ASSERT( !p_adapter->pending_query );\r
+               \r
+                       status = NDIS_STATUS_SUCCESS;\r
+                       src_buf = &info;\r
+               buf_len = sizeof(info);\r
+       \r
+               port_num = p_adapter->guids.port_num;\r
+       \r
+               switch( oid )\r
+               {\r
+               /* Required General */\r
+               case OID_GEN_SUPPORTED_LIST:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_SUPPORTED_LIST\n", port_num) );\r
+                       src_buf = (PVOID)SUPPORTED_OIDS;\r
+                       buf_len = sizeof(SUPPORTED_OIDS);\r
+                       break;\r
+       \r
+               case OID_GEN_HARDWARE_STATUS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_HARDWARE_STATUS\n", port_num) );\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       switch( p_adapter->state )\r
+                       {\r
+                       case IB_PNP_PORT_ADD:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NdisHardwareStatusInitializing\n", port_num) );\r
+                               info = NdisHardwareStatusInitializing;\r
+                               break;\r
+                               \r
+                       case IB_PNP_PORT_ACTIVE:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NdisHardwareStatusReady\n", port_num) );\r
+                               info = NdisHardwareStatusReady;\r
+                               break;\r
+       \r
+                       default:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NdisHardwareStatusNotReady\n", port_num) );\r
+                               info = NdisHardwareStatusNotReady;\r
+                       }\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       break;\r
+       \r
+               case OID_GEN_MEDIA_SUPPORTED:\r
+               case OID_GEN_MEDIA_IN_USE:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MEDIA_SUPPORTED "\r
+                               "or OID_GEN_MEDIA_IN_USE\n", port_num) );\r
+                       info = NdisMedium802_3;\r
+                       break;\r
+       \r
+               case OID_GEN_MAXIMUM_FRAME_SIZE:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MAXIMUM_FRAME_SIZE\n", port_num) );\r
+                       if( p_adapter->params.cm_enabled )\r
+                       {\r
+                               info = p_adapter->params.cm_payload_mtu;\r
+                       }\r
+                       else\r
+                       {\r
+                               info = p_adapter->params.payload_mtu;\r
+                       }\r
+                       break;\r
+       \r
+               case OID_GEN_LINK_SPEED:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_LINK_SPEED\n", port_num) );\r
+                       if (info_buf_len < buf_len)\r
+                       {\r
+                               break;\r
+                       }\r
+       \r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       switch( p_adapter->state )\r
+                       {\r
+                       case IB_PNP_PORT_ADD:\r
+                               /* Mark the adapter as pending an OID */\r
+                               p_adapter->pending_query = TRUE;\r
+       \r
+                               /* Save the request parameters. */\r
+                               p_adapter->query_oid = oid_info;\r
+       \r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NDIS_STATUS_PENDING\n", port_num) );\r
+                               status = NDIS_STATUS_PENDING;\r
+                               break;\r
+       \r
+                       case IB_PNP_PORT_REMOVE:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) );\r
+                               status = NDIS_STATUS_NOT_ACCEPTED;\r
+                               break;\r
+       \r
+                       default:\r
+                               CL_ASSERT( p_adapter->p_port );\r
+                               info = p_adapter->port_rate;\r
+                               break;\r
+                       }\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       break;\r
+       \r
+               case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE\n", port_num) );\r
+                       if( p_adapter->params.cm_enabled )\r
+                               info = p_adapter->params.sq_depth * p_adapter->params.cm_xfer_block_size;\r
+                       else\r
+                               info = p_adapter->params.sq_depth * p_adapter->params.xfer_block_size;\r
+                       break;\r
+       \r
+               case OID_GEN_RECEIVE_BUFFER_SPACE:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE "\r
+                               "or OID_GEN_RECEIVE_BUFFER_SPACE\n", port_num) );\r
+                       if( p_adapter->params.cm_enabled )\r
+                               info = p_adapter->params.rq_depth * p_adapter->params.cm_xfer_block_size;\r
+                       else\r
+                               info = p_adapter->params.rq_depth * p_adapter->params.xfer_block_size;\r
+                       break;\r
+       \r
+               case OID_GEN_MAXIMUM_LOOKAHEAD:\r
+               case OID_GEN_CURRENT_LOOKAHEAD:\r
+               case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
+               case OID_GEN_RECEIVE_BLOCK_SIZE:\r
+               case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MAXIMUM_LOOKAHEAD "\r
+                               "or OID_GEN_CURRENT_LOOKAHEAD or "\r
+                               "OID_GEN_TRANSMIT_BLOCK_SIZE or "\r
+                               "OID_GEN_RECEIVE_BLOCK_SIZE or "\r
+                               "OID_GEN_MAXIMUM_TOTAL_SIZE\n", port_num) );\r
+                       if( p_adapter->params.cm_enabled )\r
+                               info = p_adapter->params.cm_xfer_block_size;\r
+                       else\r
+                               info = p_adapter->params.xfer_block_size;\r
+                       break;\r
+       \r
+               case OID_GEN_VENDOR_ID:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_VENDOR_ID\n", port_num) );\r
+                       src_buf = (void*)VENDOR_ID;\r
+               buf_len = sizeof(VENDOR_ID);\r
+                       break;\r
+       \r
+               case OID_GEN_VENDOR_DESCRIPTION:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, \r
+                               ("Port %d received query for OID_GEN_VENDOR_DESCRIPTION\n", port_num) );\r
+                       src_buf = VENDOR_DESCRIPTION;\r
+               buf_len = sizeof(VENDOR_DESCRIPTION);\r
+                       break;\r
+       \r
+               case OID_GEN_VENDOR_DRIVER_VERSION:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_VENDOR_DRIVER_VERSION\n", port_num) );\r
+                       src_buf = &version;\r
+               buf_len = sizeof(version);\r
+                       //TODO: Figure out what the right version is.\r
+                       version = 1 << 8 | 1;\r
+                       break;\r
+       \r
+               case OID_GEN_PHYSICAL_MEDIUM:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_PHYSICAL_MEDIUM\n", port_num) );\r
+                       info = NdisPhysicalMediumUnspecified;\r
+                       break;\r
+       \r
+               case OID_GEN_CURRENT_PACKET_FILTER:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_CURRENT_PACKET_FILTER\n", port_num) );\r
+                       info = p_adapter->packet_filter;\r
+                       break;\r
+       \r
+               case OID_GEN_DRIVER_VERSION:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_DRIVER_VERSION\n", port_num) );\r
+                       src_buf = &version;\r
+               buf_len = sizeof(version);\r
+                       version = MAJOR_NDIS_VERSION << 8 | MINOR_NDIS_VERSION;\r
+                       break;\r
+       \r
+               case OID_GEN_MAC_OPTIONS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MAC_OPTIONS\n", port_num) );\r
+                       info = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |\r
+                               NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
+                               NDIS_MAC_OPTION_NO_LOOPBACK |\r
+                               NDIS_MAC_OPTION_FULL_DUPLEX;\r
+       //TODO: Figure out if we will support priority and VLANs.\r
+       //                              NDIS_MAC_OPTION_8021P_PRIORITY;\r
+       //#ifdef NDIS51_MINIPORT\r
+       //                      info |= NDIS_MAC_OPTION_8021Q_VLAN;\r
+       //#endif\r
+                       break;\r
+       \r
+               case OID_GEN_MEDIA_CONNECT_STATUS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MEDIA_CONNECT_STATUS\n", port_num) );\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       switch( p_adapter->state )\r
+                       {\r
+                       case IB_PNP_PORT_ADD:\r
+                       case IB_PNP_PORT_INIT:\r
+                               /*\r
+                                * Delay reporting media state until we know whether the port is\r
+                                * either up or down.\r
+                                */\r
+                               p_adapter->pending_query = TRUE;\r
+                               p_adapter->query_oid = oid_info;\r
+       \r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NDIS_STATUS_PENDING\n", port_num) );\r
+                               status = NDIS_STATUS_PENDING;\r
+                               break;\r
+       \r
+                       case IB_PNP_PORT_ACTIVE:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NdisMediaStateConnected\n", port_num) );\r
+                               info = NdisMediaStateConnected;\r
+                               break;\r
+       \r
+                       case IB_PNP_PORT_REMOVE:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) );\r
+                               status = NDIS_STATUS_NOT_ACCEPTED;\r
+                               break;\r
+       \r
+                       default:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NdisMediaStateDisconnected\n", port_num) );\r
+                               info = NdisMediaStateDisconnected;\r
+                       }\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       break;\r
+       \r
+               case OID_GEN_MAXIMUM_SEND_PACKETS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MAXIMUM_SEND_PACKETS\n", port_num) );\r
+                       info = MINIPORT_MAX_SEND_PACKETS;\r
+                       break;\r
+       \r
+               /* Required General Statistics */\r
+               case OID_GEN_STATISTICS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_STATISTICS\n", port_num) );\r
+                       src_buf = NULL;   \r
+                        buf_len =  sizeof(NDIS_STATISTICS_INFO);\r
+                       if (info_buf_len < buf_len)\r
+                       {\r
+                          break;\r
+                       } \r
+                       status = ipoib_get_gen_stat(p_adapter, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_XMIT_OK:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_XMIT_OK\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_SUCCESS, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_RCV_OK:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_RCV_OK\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_SUCCESS, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_XMIT_ERROR:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_XMIT_ERROR\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_ERROR, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_RCV_ERROR:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_RCV_ERROR\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_ERROR, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_RCV_NO_BUFFER:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_RCV_NO_BUFFER\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_DROPPED, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_DIRECTED_BYTES_XMIT:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_DIRECTED_BYTES_XMIT\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_DIRECTED_FRAMES_XMIT:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_DIRECTED_FRAMES_XMIT\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_MULTICAST_BYTES_XMIT:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MULTICAST_BYTES_XMIT\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_MULTICAST_FRAMES_XMIT:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MULTICAST_FRAMES_XMIT\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_BROADCAST_BYTES_XMIT:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_BROADCAST_BYTES_XMIT\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_BROADCAST_FRAMES_XMIT:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_BROADCAST_FRAMES_XMIT\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_DIRECTED_BYTES_RCV:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_DIRECTED_BYTES_RCV\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_DIRECTED_FRAMES_RCV:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_DIRECTED_FRAMES_RCV\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_MULTICAST_BYTES_RCV:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MULTICAST_BYTES_RCV\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_MULTICAST_FRAMES_RCV:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MULTICAST_FRAMES_RCV\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_BROADCAST_BYTES_RCV:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_BROADCAST_BYTES_RCV\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_BROADCAST_FRAMES_RCV:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_BROADCAST_FRAMES_RCV\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info );\r
+                       break;\r
+       \r
+               /* Required Ethernet operational characteristics */\r
+               case OID_802_3_PERMANENT_ADDRESS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_802_3_PERMANENT_ADDRESS\n", port_num) );\r
+                       src_buf = &p_adapter->mac;\r
+               buf_len = sizeof(p_adapter->mac);\r
+                       break;\r
+       \r
+               case OID_802_3_CURRENT_ADDRESS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_802_3_CURRENT_ADDRESS\n", port_num) );\r
+                       src_buf = &p_adapter->params.conf_mac;\r
+               buf_len = sizeof(p_adapter->params.conf_mac);\r
+                       break;\r
+       \r
+               case OID_802_3_MULTICAST_LIST:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_802_3_MULTICAST_LIST\n", port_num) );\r
+                       src_buf = p_adapter->mcast_array;\r
+               buf_len = p_adapter->mcast_array_size * sizeof(mac_addr_t);\r
+                       break;\r
+       \r
+               case OID_802_3_MAXIMUM_LIST_SIZE:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_802_3_MAXIMUM_LIST_SIZE\n", port_num) );\r
+                       info = MAX_MCAST;\r
+                       break;\r
+       \r
+               case OID_802_3_MAC_OPTIONS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_802_3_MAC_OPTIONS\n", port_num) );\r
+                       info = 0;\r
+                       break;\r
+       \r
+               /* Required Ethernet stats */\r
+               case OID_802_3_RCV_ERROR_ALIGNMENT:\r
+               case OID_802_3_XMIT_ONE_COLLISION:\r
+               case OID_802_3_XMIT_MORE_COLLISIONS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_802_3_RCV_ERROR_ALIGNMENT or "\r
+                               "OID_802_3_XMIT_ONE_COLLISION or "\r
+                               "OID_802_3_XMIT_MORE_COLLISIONS\n", port_num) );\r
+                       info = 0;\r
+                       break;\r
+       \r
+               case OID_TCP_TASK_OFFLOAD:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = __ipoib_get_tcp_task_offload( p_adapter, &oid_info );\r
+                       break;\r
+       \r
+               /* Optional General */\r
+               case OID_GEN_SUPPORTED_GUIDS:\r
+#ifdef NDIS51_MINIPORT\r
+               case OID_GEN_VLAN_ID:\r
+#endif\r
+       \r
+               /* Optional General Stats */\r
+               case OID_GEN_RCV_CRC_ERROR:\r
+               case OID_GEN_TRANSMIT_QUEUE_LENGTH:\r
+       \r
+               /* Optional Ethernet Stats */\r
+               case OID_802_3_XMIT_DEFERRED:\r
+               case OID_802_3_XMIT_MAX_COLLISIONS:\r
+               case OID_802_3_RCV_OVERRUN:\r
+               case OID_802_3_XMIT_UNDERRUN:\r
+               case OID_802_3_XMIT_HEARTBEAT_FAILURE:\r
+               case OID_802_3_XMIT_TIMES_CRS_LOST:\r
+               case OID_802_3_XMIT_LATE_COLLISIONS:\r
+               case OID_PNP_CAPABILITIES:\r
+                       status = NDIS_STATUS_NOT_SUPPORTED;\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid) );\r
+                       break;\r
+       \r
+               case OID_GEN_PROTOCOL_OPTIONS:\r
+               case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
+               case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
+               case OID_PNP_ENABLE_WAKE_UP:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_PROTOCOL_OPTIONS or OID_GEN_NETWORK_LAYER_ADDRESSES or OID_GEN_TRANSPORT_HEADER_OFFSET  OID_PNP_ENABLE_WAKE_UPn", port_num) );\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Number of OID: 0x%.8X!\n", oid) );\r
+                       status = NDIS_STATUS_SUCCESS; \r
+                       break;\r
+                       \r
+               case OID_PNP_QUERY_POWER:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
+                       // Status is pre-set in this routine to Success\r
+                       status = NDIS_STATUS_SUCCESS; \r
+                       break;\r
+       \r
+               case OID_TCP_OFFLOAD_CURRENT_CONFIG:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_PNP_QUERY_POWER\n", port_num) );\r
+                               //ulBytesAvailable = ulInfoLen = sizeof(NDIS_OFFLOAD);\r
+                               if (info_buf_len <  sizeof(NDIS_OFFLOAD))\r
+                               {\r
+                                       status = NDIS_STATUS_BUFFER_TOO_SHORT;\r
+                                       *p_bytes_needed = sizeof(NDIS_OFFLOAD) ;\r
+                                       break;\r
+                               }\r
+       \r
+                               //ipoib_offload_config(pPort, &offload);\r
+                               //pInfo = &offload;\r
+                               break;\r
+       \r
+               default:\r
+                       status = NDIS_STATUS_INVALID_OID;\r
+               //      IPOIB_PRINT( TRACE_LEVEL_ERROR,IPOIB_DBG_OID,\r
+                       //      ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid) );\r
+                       break;\r
+               }\r
+       \r
+               /*\r
+                * Complete the request as if it was handled asynchronously to maximize\r
+                * code reuse for when we really handle the requests asynchronously.\r
+                * Note that this requires the QueryInformation entry point to always\r
+                * return NDIS_STATUS_PENDING\r
+                */\r
+               if( status != NDIS_STATUS_PENDING )\r
+               {\r
+                       ipoib_complete_query(\r
+                               p_adapter, &oid_info, status, src_buf, buf_len );\r
+                       return status;\r
+               }\r
+       \r
+               IPOIB_EXIT( IPOIB_DBG_OID );\r
+               return NDIS_STATUS_PENDING;\r
+       }\r
+       \r
+\r
+static void\r
+ipoib_complete_query(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              pending_oid_t* const            p_oid_info,\r
+       IN              const   NDIS_STATUS                                     status,\r
+       IN              const   void* const                                     p_buf,\r
+       IN              const   ULONG                                           buf_len )\r
+{\r
+       NDIS_STATUS             oid_status = status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       CL_ASSERT( status != NDIS_STATUS_PENDING );\r
+\r
+       if( status == NDIS_STATUS_SUCCESS )\r
+       {\r
+               if( p_oid_info->buf_len < buf_len )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Insufficient buffer space.  "\r
+                               "Returning NDIS_STATUS_INVALID_LENGTH.\n") );\r
+                       oid_status = NDIS_STATUS_INVALID_LENGTH;\r
+                       *p_oid_info->p_bytes_needed = buf_len;\r
+                       *p_oid_info->p_bytes_used = 0;\r
+               }\r
+               else if( p_oid_info->p_buf )\r
+               {\r
+                       /* Only copy if we have a distinct source buffer. */\r
+                       if( p_buf )\r
+                       {\r
+                               NdisMoveMemory( p_oid_info->p_buf, p_buf, buf_len );\r
+                               *p_oid_info->p_bytes_used = buf_len;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Returning NDIS_NOT_ACCEPTED") );\r
+                       oid_status = NDIS_STATUS_NOT_ACCEPTED;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               *p_oid_info->p_bytes_used = 0;\r
+       }\r
+\r
+       if (p_adapter->query_oid.p_pending_oid)\r
+       {\r
+               NdisMOidRequestComplete(p_adapter->h_adapter,p_adapter->query_oid.p_pending_oid,oid_status); \r
+               p_adapter->query_oid.p_pending_oid = NULL;\r
+       }\r
+       p_adapter->pending_query = FALSE;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__ipoib_get_tcp_task_offload(\r
+       IN                              ipoib_adapter_t*                        p_adapter,\r
+       OUT                             pending_oid_t                           *pNdisRequest )\r
+{\r
+#ifndef NDIS60_MINIPORT\r
+       NDIS_TASK_OFFLOAD_HEADER        *p_offload_hdr;\r
+       NDIS_TASK_OFFLOAD                       *p_offload_task;\r
+       NDIS_TASK_TCP_IP_CHECKSUM       *p_offload_chksum;\r
+\r
+       NDIS_TASK_TCP_LARGE_SEND        *p_offload_lso;\r
+       ULONG                                           buf_len;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+               ("Port %d received query for OID_TCP_TASK_OFFLOAD\n",\r
+               p_adapter->guids.port_num) );\r
+\r
+       buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
+               offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +\r
+               sizeof(NDIS_TASK_TCP_IP_CHECKSUM) +\r
+               (p_adapter->params.lso  ? \r
+                       sizeof(NDIS_TASK_OFFLOAD) + sizeof(NDIS_TASK_TCP_LARGE_SEND)\r
+                       : 0);\r
+\r
+       pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = buf_len;\r
+\r
+       if( pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength < buf_len )\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+\r
+       p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;\r
+       if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
+               return NDIS_STATUS_INVALID_DATA;\r
+\r
+       if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
+               IEEE_802_3_Encapsulation )\r
+       {\r
+               return NDIS_STATUS_INVALID_DATA;\r
+       }\r
+\r
+       p_offload_hdr->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER);\r
+       p_offload_task = (NDIS_TASK_OFFLOAD*)(p_offload_hdr + 1);\r
+       p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;\r
+       p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);\r
+       p_offload_task->Task = TcpIpChecksumNdisTask;\r
+       p_offload_task->OffsetNextTask = 0;\r
+       p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);\r
+       p_offload_chksum =\r
+               (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
+       \r
+       p_offload_chksum->V4Transmit.IpOptionsSupported =\r
+       p_offload_chksum->V4Transmit.TcpOptionsSupported =\r
+       p_offload_chksum->V4Transmit.TcpChecksum =\r
+       p_offload_chksum->V4Transmit.UdpChecksum =\r
+       p_offload_chksum->V4Transmit.IpChecksum =\r
+               !!(p_adapter->params.send_chksum_offload);\r
+\r
+       p_offload_chksum->V4Receive.IpOptionsSupported =\r
+       p_offload_chksum->V4Receive.TcpOptionsSupported =\r
+       p_offload_chksum->V4Receive.TcpChecksum =\r
+       p_offload_chksum->V4Receive.UdpChecksum =\r
+       p_offload_chksum->V4Receive.IpChecksum =\r
+               !!(p_adapter->params.recv_chksum_offload);\r
+\r
+       p_offload_chksum->V6Transmit.IpOptionsSupported = FALSE;\r
+       p_offload_chksum->V6Transmit.TcpOptionsSupported = FALSE;\r
+       p_offload_chksum->V6Transmit.TcpChecksum = FALSE;\r
+       p_offload_chksum->V6Transmit.UdpChecksum = FALSE;\r
+\r
+       p_offload_chksum->V6Receive.IpOptionsSupported = FALSE;\r
+       p_offload_chksum->V6Receive.TcpOptionsSupported = FALSE;\r
+       p_offload_chksum->V6Receive.TcpChecksum = FALSE;\r
+       p_offload_chksum->V6Receive.UdpChecksum = FALSE;\r
+\r
+\r
+       if (p_adapter->params.lso) {\r
+               // set the previous pointer to the correct place\r
+               p_offload_task->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) +\r
+                                               p_offload_task->TaskBufferLength;\r
+               // set the LSO packet\r
+               p_offload_task = (PNDIS_TASK_OFFLOAD)\r
+                                               ((PUCHAR)p_offload_task + p_offload_task->OffsetNextTask);\r
+\r
+               p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;\r
+               p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);\r
+               p_offload_task->Task = TcpLargeSendNdisTask;\r
+               p_offload_task->OffsetNextTask = 0;\r
+               p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);\r
+\r
+               p_offload_lso = (PNDIS_TASK_TCP_LARGE_SEND) p_offload_task->TaskBuffer;\r
+\r
+               p_offload_lso->Version = 0;\r
+               //TODO optimal size: 60000, 64000 or 65536\r
+               //TODO LSO_MIN_SEG_COUNT to be 1\r
+               p_offload_lso->MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; \r
+#define LSO_MIN_SEG_COUNT 2\r
+               p_offload_lso->MinSegmentCount = LSO_MIN_SEG_COUNT;\r
+               p_offload_lso->TcpOptions = TRUE;\r
+               p_offload_lso->IpOptions = TRUE;\r
+       }\r
+\r
+               pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten = buf_len\r
+\r
+       return NDIS_STATUS_SUCCESS;\r
+#endif\r
+       UNUSED_PARAM(p_adapter);\r
+       UNUSED_PARAM(pNdisRequest);\r
+       return NDIS_STATUS_NOT_SUPPORTED;\r
+\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__ipoib_set_tcp_task_offload(\r
+       IN                              ipoib_adapter_t*                        p_adapter,\r
+       IN                              void* const                                     p_info_buf,\r
+       IN                              ULONG* const                            p_info_len )\r
+{\r
+#ifndef NDIS60_MINIPORT\r
+       NDIS_TASK_OFFLOAD_HEADER        *p_offload_hdr;\r
+       NDIS_TASK_OFFLOAD                       *p_offload_task;\r
+       NDIS_TASK_TCP_IP_CHECKSUM       *p_offload_chksum;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+               ("Port %d received set for OID_TCP_TASK_OFFLOAD\n",\r
+               p_adapter->guids.port_num) );\r
+\r
+       p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_info_buf;\r
+\r
+       if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+\r
+       if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
+               return NDIS_STATUS_INVALID_DATA;\r
+\r
+       if( p_offload_hdr->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+\r
+       if( !p_offload_hdr->OffsetFirstTask )\r
+               return NDIS_STATUS_SUCCESS;\r
+\r
+       if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
+               IEEE_802_3_Encapsulation )\r
+       {\r
+               return NDIS_STATUS_INVALID_DATA;\r
+       }\r
+\r
+       p_offload_task = (NDIS_TASK_OFFLOAD*)\r
+               (((UCHAR*)p_offload_hdr) + p_offload_hdr->OffsetFirstTask);\r
+\r
+       if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
+               offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +\r
+               sizeof(NDIS_TASK_TCP_IP_CHECKSUM) )\r
+       {\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+       }\r
+\r
+       if( p_offload_task->Version != NDIS_TASK_OFFLOAD_VERSION )\r
+               return NDIS_STATUS_INVALID_DATA;\r
+       p_offload_chksum =\r
+               (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
+\r
+       if( !p_adapter->params.send_chksum_offload &&\r
+               (p_offload_chksum->V4Transmit.IpOptionsSupported ||\r
+               p_offload_chksum->V4Transmit.TcpOptionsSupported ||\r
+               p_offload_chksum->V4Transmit.TcpChecksum ||\r
+               p_offload_chksum->V4Transmit.UdpChecksum ||\r
+               p_offload_chksum->V4Transmit.IpChecksum) )\r
+       {\r
+               return NDIS_STATUS_NOT_SUPPORTED;\r
+       }\r
+\r
+       if( !p_adapter->params.recv_chksum_offload &&\r
+               (p_offload_chksum->V4Receive.IpOptionsSupported ||\r
+               p_offload_chksum->V4Receive.TcpOptionsSupported ||\r
+               p_offload_chksum->V4Receive.TcpChecksum ||\r
+               p_offload_chksum->V4Receive.UdpChecksum ||\r
+               p_offload_chksum->V4Receive.IpChecksum) )\r
+       {\r
+               return NDIS_STATUS_NOT_SUPPORTED;\r
+       }\r
+\r
+       return NDIS_STATUS_SUCCESS;\r
+#endif \r
+       UNUSED_PARAM(p_adapter);\r
+       UNUSED_PARAM(p_info_buf);\r
+       UNUSED_PARAM(p_info_len);\r
+       return NDIS_STATUS_NOT_SUPPORTED;\r
+}\r
+\r
+\r
+//! Issues a hardware reset to the NIC and/or resets the driver's software state.\r
+/*  Tear down the connection and start over again.  This is only called when there is a problem.\r
+For example, if a send, query info, or set info had a time out.  MiniportCheckForHang will\r
+be called first.\r
+IRQL = DISPATCH_LEVEL\r
+\r
+@param p_addr_resetPointer to BOOLLEAN that is set to TRUE if the NDIS\r
+library should call MiniportSetInformation to restore addressing information to the current values.\r
+@param adapter_context The adapter context allocated at start\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_NOT_RESETTABLE,\r
+NDIS_STATUS_RESET_IN_PROGRESS, NDIS_STATUS_SOFT_ERRORS, NDIS_STATUS_HARD_ERRORS\r
+*/\r
+NDIS_STATUS\r
+ipoib_reset(\r
+    IN  NDIS_HANDLE     adapter_context,\r
+    OUT PBOOLEAN        p_addr_reset)\r
+{\r
+       ipoib_adapter_t* p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_addr_reset );\r
+       CL_ASSERT( adapter_context );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+       switch( ipoib_reset_adapter( p_adapter ) )\r
+       {\r
+       case IB_NOT_DONE:\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return NDIS_STATUS_PENDING;\r
+\r
+       case IB_SUCCESS:\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               *p_addr_reset = TRUE;\r
+               return NDIS_STATUS_SUCCESS;\r
+\r
+       case IB_INVALID_STATE:\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return NDIS_STATUS_RESET_IN_PROGRESS;\r
+\r
+       default:\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return NDIS_STATUS_HARD_ERRORS;\r
+       }\r
+}\r
+\r
+\r
+//! Request changes in the state information that the miniport driver maintains\r
+/*  For example, this is used to set multicast addresses and the packet filter.\r
+IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+@param oid Object ID representing the set operation to be carried out\r
+@param info_buf Buffer containing input for this set and location for any output\r
+@param info_buf_len Number of bytes available in info_buf\r
+@param p_bytes_read Pointer to number of bytes read from info_buf\r
+@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
+NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_INVALID_DATA, NDIS_STATUS_NOT_ACCEPTED,\r
+NDIS_STATUS_NOT_SUPPORTED, NDIS_STATUS_RESOURCES\r
+*/\r
+NDIS_STATUS\r
+ipoib_set_info(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              NDIS_OID                                        oid,\r
+       IN                              PVOID                                           info_buf,\r
+       IN                              ULONG                                           info_buf_len,\r
+               OUT                     PULONG                                          p_bytes_read,\r
+               OUT                     PULONG                                          p_bytes_needed )\r
+{\r
+       ipoib_adapter_t*        p_adapter;\r
+       NDIS_STATUS                     status;\r
+\r
+       ULONG                           buf_len;\r
+       uint8_t                         port_num;\r
+\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+       \r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       CL_ASSERT( adapter_context );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+       CL_ASSERT( p_bytes_read );\r
+       CL_ASSERT( p_bytes_needed );\r
+       CL_ASSERT( !p_adapter->pending_set );\r
+\r
+       status = NDIS_STATUS_SUCCESS;\r
+       *p_bytes_needed = 0;\r
+       buf_len = sizeof(ULONG);\r
+\r
+       port_num = p_adapter->guids.port_num;\r
+       \r
+       cl_obj_lock( &p_adapter->obj );\r
+\r
+       if( p_adapter->state == IB_PNP_PORT_REMOVE )\r
+       {\r
+               *p_bytes_read = 0;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               return NDIS_STATUS_NOT_ACCEPTED;\r
+       }\r
+\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       switch( oid )\r
+       {\r
+       /* Required General */\r
+       case OID_GEN_CURRENT_PACKET_FILTER:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num));\r
+               if( info_buf_len < sizeof(p_adapter->packet_filter) )\r
+               {\r
+                       status = NDIS_STATUS_INVALID_LENGTH;\r
+               }\r
+               else if( !info_buf )\r
+               {\r
+                       status = NDIS_STATUS_INVALID_DATA;\r
+               }\r
+               else\r
+               {\r
+                       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       switch( p_adapter->state )\r
+                       {\r
+                       case IB_PNP_PORT_ADD:\r
+                               p_adapter->set_oid.oid = oid;\r
+                               p_adapter->set_oid.p_buf = info_buf;\r
+                               p_adapter->set_oid.buf_len = info_buf_len;\r
+                               p_adapter->set_oid.p_bytes_used = p_bytes_read;\r
+                               p_adapter->set_oid.p_bytes_needed = p_bytes_needed;\r
+                               p_adapter->pending_set = TRUE;\r
+                               status = NDIS_STATUS_PENDING;\r
+                               break;\r
+\r
+                       case IB_PNP_PORT_REMOVE:\r
+                               status = NDIS_STATUS_NOT_ACCEPTED;\r
+                               break;\r
+\r
+                       default:\r
+                               if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) )\r
+                               {\r
+                                       cl_qlist_insert_tail(\r
+                                               &g_ipoib.adapter_list, &p_adapter->entry );\r
+\r
+                                       /*\r
+                                        * Filter was zero, now non-zero.  Register IP addresses\r
+                                        * with SA.\r
+                                        */\r
+                                       ipoib_reg_addrs( p_adapter );\r
+                               }\r
+                               else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) )\r
+                               {\r
+                                       /*\r
+                                        * Filter was non-zero, now zero.  Deregister IP addresses.\r
+                                        */\r
+                                       ipoib_dereg_addrs( p_adapter );\r
+\r
+                                       ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
+                                       cl_qlist_remove_item(\r
+                                               &g_ipoib.adapter_list, &p_adapter->entry );\r
+                               }\r
+\r
+                               p_adapter->packet_filter = *(uint32_t*)info_buf;\r
+                       }\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       KeReleaseInStackQueuedSpinLock( &hdl );\r
+               }\r
+               break;\r
+\r
+       case OID_GEN_CURRENT_LOOKAHEAD:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num));\r
+               if( info_buf_len < buf_len )\r
+                       status = NDIS_STATUS_INVALID_LENGTH;\r
+               break;\r
+\r
+       case OID_GEN_PROTOCOL_OPTIONS:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num));\r
+               if( info_buf_len < buf_len )\r
+                       status = NDIS_STATUS_INVALID_LENGTH;\r
+               break;\r
+\r
+       case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
+               status = __ipoib_set_net_addr( p_adapter, info_buf, info_buf_len, p_bytes_read, p_bytes_needed);\r
+               break;\r
+\r
+#ifdef NDIS51_MINIPORT\r
+       case OID_GEN_MACHINE_NAME:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) );\r
+               break;\r
+#endif\r
+\r
+       /* Required Ethernet operational characteristics */\r
+       case OID_802_3_MULTICAST_LIST:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) );\r
+               if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) );\r
+                       status = NDIS_STATUS_MULTICAST_FULL;\r
+                       *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t);\r
+               }\r
+               else if( info_buf_len % sizeof(mac_addr_t) )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
+                       status = NDIS_STATUS_INVALID_DATA;\r
+               }\r
+               else if( !info_buf && info_buf_len )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
+                       status = NDIS_STATUS_INVALID_DATA;\r
+               }\r
+               else\r
+               {\r
+                       ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf,\r
+                               (uint8_t)(info_buf_len / sizeof(mac_addr_t)) );\r
+\r
+                       buf_len = info_buf_len;\r
+                       /*\r
+                        * Note that we don't return pending.  It will likely take longer\r
+                        * for our SA transactions to complete than NDIS will give us\r
+                        * before reseting the adapter.  If an SA failure is encountered,\r
+                        * the adapter will be marked as hung and we will get reset.\r
+                        */\r
+                       status = NDIS_STATUS_SUCCESS;\r
+               }\r
+               break;\r
+\r
+       case OID_TCP_TASK_OFFLOAD:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
+\r
+               buf_len = info_buf_len;\r
+               status =\r
+                       __ipoib_set_tcp_task_offload( p_adapter, info_buf, &buf_len );\r
+               break;\r
+\r
+       /* Optional General */\r
+       case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
+#ifdef NDIS51_MINIPORT\r
+       case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
+       case OID_GEN_VLAN_ID:\r
+#endif\r
+               status = NDIS_STATUS_NOT_SUPPORTED;\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid));\r
+               break;\r
+\r
+       case OID_GEN_SUPPORTED_LIST:\r
+       case OID_GEN_HARDWARE_STATUS:\r
+       case OID_GEN_MEDIA_SUPPORTED:\r
+       case OID_GEN_MEDIA_IN_USE:\r
+       case OID_GEN_MAXIMUM_FRAME_SIZE:\r
+       case OID_GEN_LINK_SPEED:\r
+       case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
+       case OID_GEN_RECEIVE_BUFFER_SPACE:\r
+       case OID_GEN_MAXIMUM_LOOKAHEAD:\r
+       case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
+       case OID_GEN_RECEIVE_BLOCK_SIZE:\r
+       case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
+       case OID_GEN_VENDOR_ID:\r
+       case OID_GEN_VENDOR_DESCRIPTION:\r
+       case OID_GEN_VENDOR_DRIVER_VERSION:\r
+       case OID_GEN_DRIVER_VERSION:\r
+       case OID_GEN_MAC_OPTIONS:\r
+       case OID_GEN_MEDIA_CONNECT_STATUS:\r
+       case OID_GEN_MAXIMUM_SEND_PACKETS:\r
+       case OID_GEN_SUPPORTED_GUIDS:\r
+       case OID_GEN_PHYSICAL_MEDIUM:\r
+       default:\r
+               status = NDIS_STATUS_INVALID_OID;\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid));\r
+               break;\r
+       }\r
+\r
+       if( status == NDIS_STATUS_SUCCESS )\r
+       {\r
+               *p_bytes_read = buf_len;\r
+       }\r
+       else\r
+       {\r
+               if( status == NDIS_STATUS_INVALID_LENGTH )\r
+               {\r
+                       if ( !*p_bytes_needed )\r
+                       {\r
+                               *p_bytes_needed = buf_len;\r
+                       }\r
+               }\r
+\r
+               *p_bytes_read = 0;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+       return status;\r
+}\r
+\r
+#ifdef NNN\r
+NDIS_STATUS\r
+ipoib_set_info(\r
+       ipoib_adapter_t*           p_adapter,\r
+       IN PNDIS_OID_REQUEST   pNdisRequest)\r
+{\r
+       NDIS_STATUS                     status;\r
+       NDIS_OID            oid;\r
+       UINT                            info_buf_len;\r
+       UINT                            buf_len;\r
+       uint8_t                         port_num;\r
+       PVOID                           info_buf;\r
+       UINT                            *p_bytes_needed;\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+    oid                        = pNdisRequest->DATA.SET_INFORMATION.Oid;\r
+    info_buf           = pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;\r
+    info_buf_len       = pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;\r
+       p_bytes_needed  = &pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;\r
+       status = NDIS_STATUS_SUCCESS;\r
+\r
+       buf_len = sizeof(UINT);\r
+       port_num = p_adapter->guids.port_num;\r
+\r
+       switch( oid )\r
+       {\r
+       /* Required General */\r
+       case OID_GEN_CURRENT_PACKET_FILTER:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num));\r
+               if( info_buf_len < sizeof(p_adapter->packet_filter) )\r
+               {\r
+                       status = NDIS_STATUS_INVALID_LENGTH;\r
+               }\r
+               else if( !info_buf )\r
+               {\r
+                       status = NDIS_STATUS_INVALID_DATA;\r
+               }\r
+               else\r
+               {\r
+                       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       switch( p_adapter->state )\r
+                       {\r
+                       case IB_PNP_PORT_ADD:\r
+                               p_adapter->p_oid_request = pNdisRequest;\r
+                               status = NDIS_STATUS_PENDING;\r
+                               break;\r
+\r
+                       case IB_PNP_PORT_REMOVE:\r
+                               status = NDIS_STATUS_NOT_ACCEPTED;\r
+                               break;\r
+\r
+                       default:\r
+                               if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) )\r
+                               {\r
+                                       cl_qlist_insert_tail(\r
+                                               &g_ipoib.adapter_list, &p_adapter->entry );\r
+\r
+                                       /*\r
+                                        * Filter was zero, now non-zero.  Register IP addresses\r
+                                        * with SA.\r
+                                        */\r
+                                       ipoib_reg_addrs( p_adapter );\r
+                               }\r
+                               else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) )\r
+                               {\r
+                                       /*\r
+                                        * Filter was non-zero, now zero.  Deregister IP addresses.\r
+                                        */\r
+                                       ipoib_dereg_addrs( p_adapter );\r
+\r
+                                       ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
+                                       cl_qlist_remove_item(\r
+                                               &g_ipoib.adapter_list, &p_adapter->entry );\r
+                               }\r
+\r
+                               p_adapter->packet_filter = *(uint32_t*)info_buf;\r
+                       }\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       KeReleaseInStackQueuedSpinLock( &hdl );\r
+               }\r
+               break;\r
+\r
+       case OID_GEN_CURRENT_LOOKAHEAD:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num));\r
+               if( info_buf_len < buf_len )\r
+                       status = NDIS_STATUS_INVALID_LENGTH;\r
+               break;\r
+\r
+       case OID_GEN_PROTOCOL_OPTIONS:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num));\r
+               if( info_buf_len < buf_len )\r
+                       status = NDIS_STATUS_INVALID_LENGTH;\r
+               break;\r
+\r
+       case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
+               status = __ipoib_set_net_addr( p_adapter, pNdisRequest);\r
+               break;\r
+\r
+       case OID_GEN_MACHINE_NAME:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) );\r
+               break;\r
+\r
+\r
+       /* Required Ethernet operational characteristics */\r
+       case OID_802_3_MULTICAST_LIST:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) );\r
+               if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) );\r
+                       status = NDIS_STATUS_MULTICAST_FULL;\r
+                       *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t);\r
+               }\r
+               else if( info_buf_len % sizeof(mac_addr_t) )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
+                       status = NDIS_STATUS_INVALID_DATA;\r
+               }\r
+               else if( !info_buf && info_buf_len )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
+                       status = NDIS_STATUS_INVALID_DATA;\r
+               }\r
+               else\r
+               {\r
+                       ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf,\r
+                               (uint8_t)(info_buf_len / sizeof(mac_addr_t)) );\r
+\r
+                       buf_len = info_buf_len;\r
+                       /*\r
+                        * Note that we don't return pending.  It will likely take longer\r
+                        * for our SA transactions to complete than NDIS will give us\r
+                        * before reseting the adapter.  If an SA failure is encountered,\r
+                        * the adapter will be marked as hung and we will get reset.\r
+                        */\r
+                       status = NDIS_STATUS_SUCCESS;\r
+               }\r
+               break;\r
+\r
+       case OID_TCP_TASK_OFFLOAD:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
+\r
+               buf_len = info_buf_len;\r
+               status =\r
+                       __ipoib_set_tcp_task_offload( p_adapter, pNdisRequest );\r
+               break;\r
+\r
+       /* Optional General */\r
+       case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
+#ifdef NDIS51_MINIPORT\r
+       case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
+       case OID_GEN_VLAN_ID:\r
+#endif\r
+               status = NDIS_STATUS_NOT_SUPPORTED;\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid));\r
+               break;\r
+\r
+       case OID_GEN_SUPPORTED_LIST:\r
+       case OID_GEN_HARDWARE_STATUS:\r
+       case OID_GEN_MEDIA_SUPPORTED:\r
+       case OID_GEN_MEDIA_IN_USE:\r
+       case OID_GEN_MAXIMUM_FRAME_SIZE:\r
+       case OID_GEN_LINK_SPEED:\r
+       case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
+       case OID_GEN_RECEIVE_BUFFER_SPACE:\r
+       case OID_GEN_MAXIMUM_LOOKAHEAD:\r
+       case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
+       case OID_GEN_RECEIVE_BLOCK_SIZE:\r
+       case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
+       case OID_GEN_VENDOR_ID:\r
+       case OID_GEN_VENDOR_DESCRIPTION:\r
+       case OID_GEN_VENDOR_DRIVER_VERSION:\r
+       case OID_GEN_DRIVER_VERSION:\r
+       case OID_GEN_MAC_OPTIONS:\r
+       case OID_GEN_MEDIA_CONNECT_STATUS:\r
+       case OID_GEN_MAXIMUM_SEND_PACKETS:\r
+       case OID_GEN_SUPPORTED_GUIDS:\r
+       case OID_GEN_PHYSICAL_MEDIUM:\r
+       default:\r
+               status = NDIS_STATUS_INVALID_OID;\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid));\r
+               break;\r
+       }\r
+\r
+       if( status == NDIS_STATUS_SUCCESS )\r
+       {\r
+               pNdisRequest->DATA.SET_INFORMATION.BytesRead = buf_len;\r
+       }\r
+       else\r
+       {\r
+               if( status == NDIS_STATUS_INVALID_LENGTH )\r
+               {\r
+                       if ( !*p_bytes_needed )\r
+                       {\r
+                               *p_bytes_needed = buf_len;\r
+                       }\r
+               }\r
+\r
+               pNdisRequest->DATA.SET_INFORMATION.BytesRead = 0;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+       return status;\r
+}\r
+#endif\r
+static NDIS_STATUS\r
+ipoib_oid_handler(\r
+    IN  NDIS_HANDLE         adapter_context,\r
+    IN  PNDIS_OID_REQUEST   pNdisRequest)\r
+{\r
+    NDIS_REQUEST_TYPE       RequestType;\r
+       NDIS_STATUS     status = NDIS_STATUS_SUCCESS;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       RequestType = pNdisRequest->RequestType;\r
+\r
+       switch(RequestType)\r
+       {\r
+        case NdisRequestSetInformation:            \r
+            status = ipoib_set_info(adapter_context,\r
+                                               pNdisRequest->DATA.SET_INFORMATION.Oid,\r
+                                               pNdisRequest->DATA.SET_INFORMATION.InformationBuffer,\r
+                                               pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength,\r
+                                               (PULONG)&pNdisRequest->DATA.SET_INFORMATION.BytesRead,\r
+                                               (PULONG)&pNdisRequest->DATA.SET_INFORMATION.BytesNeeded);\r
+            break;\r
+                \r
+        case NdisRequestQueryInformation:\r
+        case NdisRequestQueryStatistics:\r
+            status = ipoib_query_info(adapter_context,\r
+                                               pNdisRequest->DATA.QUERY_INFORMATION.Oid,\r
+                                               pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,\r
+                                               pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,\r
+                                               (PULONG)&pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten,\r
+                                               (PULONG)&pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);\r
+                                               \r
+            break;\r
+\r
+        default:\r
+            status = NDIS_STATUS_NOT_SUPPORTED;\r
+            break;\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+       return status;\r
+}\r
+\r
+//! Transfers some number of packets, specified as an array of packet pointers, over the network. \r
+/*  For a deserialized driver, these packets are completed asynchronously\r
+using NdisMSendComplete.\r
+IRQL <= DISPATCH_LEVEL\r
+\r
+@param adapter_context Pointer to ipoib_adapter_t structure with per NIC state\r
+@param packet_array Array of packets to send\r
+@param numPackets Number of packets in the array\r
+*/\r
+void\r
+ipoib_send_net_buffer_list(\r
+    IN  NDIS_HANDLE         adapter_context,\r
+    IN  PNET_BUFFER_LIST    net_buffer_list,\r
+    IN  NDIS_PORT_NUMBER    port_num,\r
+    IN  ULONG               send_flags\r
+    )\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       ipoib_port_t            *p_port;\r
+       ULONG                           send_complete_flags;\r
+    PNET_BUFFER_LIST    curr_net_buffer_list;\r
+    PNET_BUFFER_LIST    next_net_buffer_list;\r
+       NDIS_STATUS     status = NDIS_STATUS_SUCCESS;\r
+       \r
+       UNREFERENCED_PARAMETER(port_num);\r
+       PERF_DECLARE( SendPackets );\r
+       PERF_DECLARE( PortSend );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+       cl_perf_start( SendPackets );\r
+\r
+       CL_ASSERT( adapter_context );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+       p_port = p_adapter->p_port;\r
+\r
+       cl_obj_lock( &p_adapter->obj );\r
+       if( p_adapter->ipoib_state == IPOIB_PAUSING ||\r
+               p_adapter->ipoib_state == IPOIB_PAUSED)\r
+       {\r
+               status = NDIS_STATUS_PAUSED; \r
+               cl_obj_unlock( &p_adapter->obj );\r
+               goto compl_status;\r
+       }\r
+\r
+       if( p_adapter->state != IB_PNP_PORT_ACTIVE || !p_adapter->p_port )\r
+       {\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               status = NDIS_STATUS_FAILURE; \r
+               goto compl_status;\r
+       }\r
+\r
+       p_port = p_adapter->p_port;\r
+       ipoib_port_ref( p_port, ref_send_packets );\r
+       cl_obj_unlock( &p_adapter->obj );\r
+       //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+       //                      ("Starting NET BUFFER LIST \n") );\r
+       for (curr_net_buffer_list = net_buffer_list;\r
+               curr_net_buffer_list != NULL;\r
+               curr_net_buffer_list = next_net_buffer_list)\r
+       {\r
+               next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(curr_net_buffer_list);\r
+               cl_perf_start( PortSend );\r
+               \r
+               ipoib_port_send( p_port, curr_net_buffer_list, send_flags);\r
+               cl_perf_stop( &adapter->perf, PortSend );\r
+       }\r
+       ipoib_port_deref( p_port, ref_send_packets );\r
+\r
+       cl_perf_stop( &p_adapter->perf, SendPackets );\r
+\r
+       cl_perf_log( &p_adapter->perf, SendBundle, num_packets );\r
+\r
+compl_status:\r
+    if (status != NDIS_STATUS_SUCCESS)\r
+       {\r
+               //ASSERT(FALSE); //????\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Got bad status \n") );\r
+               send_complete_flags = 0;\r
+           \r
+               for (curr_net_buffer_list = net_buffer_list;\r
+                                curr_net_buffer_list != NULL;\r
+                                curr_net_buffer_list = next_net_buffer_list)\r
+               {\r
+                       next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(curr_net_buffer_list);\r
+                       NET_BUFFER_LIST_STATUS(curr_net_buffer_list) = status;\r
+                       ipoib_inc_send_stat( p_adapter, IP_STAT_DROPPED, 0 );\r
+               }\r
+\r
+\r
+               if (NDIS_TEST_SEND_AT_DISPATCH_LEVEL(send_flags))\r
+               {\r
+                       NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
+               }\r
+                     \r
+               NdisMSendNetBufferListsComplete(\r
+                       p_adapter->h_adapter,\r
+                       net_buffer_list,\r
+                       send_complete_flags);  \r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+void\r
+ipoib_pnp_notify(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN PNET_DEVICE_PNP_EVENT  pnp_event)\r
+{\r
+       ipoib_adapter_t *p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_PNP );\r
+\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP, ("Event %d\n", pnp_event->DevicePnPEvent) );\r
+       if( pnp_event->DevicePnPEvent != NdisDevicePnPEventPowerProfileChanged )\r
+       {\r
+               cl_obj_lock( &p_adapter->obj );\r
+               p_adapter->state = IB_PNP_PORT_REMOVE;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+\r
+               ipoib_resume_oids( p_adapter );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_PNP );\r
+}\r
+\r
+\r
+VOID\r
+ipoib_shutdown_ex(\r
+       IN NDIS_HANDLE  adapter_context,\r
+       IN NDIS_SHUTDOWN_ACTION  shutdown_action)\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       UNUSED_PARAM( adapter_context );\r
+       UNUSED_PARAM( shutdown_action );\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+void\r
+ipoib_resume_oids(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       ULONG                           info;\r
+       NDIS_STATUS                     status;\r
+       boolean_t                       pending_query, pending_set;\r
+       pending_oid_t           query_oid = {0};\r
+       pending_oid_t           set_oid = {0};\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       cl_obj_lock( &p_adapter->obj );\r
+       /*\r
+        * Set the status depending on our state.  Fail OID requests that\r
+        * are pending while we reset the adapter.\r
+        */\r
+       switch( p_adapter->state )\r
+       {\r
+       case IB_PNP_PORT_ADD:\r
+               status = NDIS_STATUS_FAILURE;\r
+               break;\r
+\r
+       case IB_PNP_PORT_REMOVE:\r
+               status = NDIS_STATUS_NOT_ACCEPTED;\r
+               break;\r
+               \r
+       default:\r
+               status = NDIS_STATUS_SUCCESS;\r
+       }\r
+\r
+       pending_query = p_adapter->pending_query;\r
+       if( pending_query )\r
+       {\r
+               query_oid = p_adapter->query_oid;\r
+               p_adapter->pending_query = FALSE;\r
+       }\r
+       pending_set = p_adapter->pending_set;\r
+       if( pending_set )\r
+       {\r
+               set_oid = p_adapter->set_oid;\r
+               p_adapter->pending_set = FALSE;\r
+       }\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       /*\r
+        * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
+        * complete it now.  Note that we hold the object lock since\r
+        * NdisMQueryInformationComplete is called at DISPATCH_LEVEL.\r
+        */\r
+       if( pending_query )\r
+       {\r
+               switch( query_oid.oid )\r
+               {\r
+               case OID_GEN_LINK_SPEED:\r
+                       ipoib_complete_query( p_adapter, &query_oid,\r
+                               status, &p_adapter->port_rate, sizeof(p_adapter->port_rate) );\r
+                       break;\r
+\r
+               case OID_GEN_MEDIA_CONNECT_STATUS:\r
+                       info = NdisMediaStateConnected;\r
+                       ipoib_complete_query( p_adapter, &query_oid,\r
+                               status, &info, sizeof(info) );\r
+                       break;\r
+\r
+               default:\r
+                       CL_ASSERT( query_oid.oid == OID_GEN_LINK_SPEED ||\r
+                               query_oid.oid == OID_GEN_MEDIA_CONNECT_STATUS );\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if( pending_set )\r
+       {\r
+               switch( set_oid.oid )\r
+               {\r
+               case OID_GEN_CURRENT_PACKET_FILTER:\r
+                       /* Validation already performed in the SetInformation path. */\r
+\r
+                       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       if( !p_adapter->packet_filter && (*(PULONG)set_oid.p_buf) )\r
+                       {\r
+                               cl_qlist_insert_tail(\r
+                                       &g_ipoib.adapter_list, &p_adapter->entry );\r
+                               /*\r
+                                * Filter was zero, now non-zero.  Register IP addresses\r
+                                * with SA.\r
+                                */\r
+                               ipoib_reg_addrs( p_adapter );\r
+                       }\r
+                       else if( p_adapter->packet_filter && !(*(PULONG)set_oid.p_buf) )\r
+                       {\r
+                               /* Filter was non-zero, now zero.  Deregister IP addresses. */\r
+                               ipoib_dereg_addrs( p_adapter );\r
+\r
+                               ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
+                               cl_qlist_remove_item(\r
+                                       &g_ipoib.adapter_list, &p_adapter->entry );\r
+                       }\r
+                       p_adapter->packet_filter = *(PULONG)set_oid.p_buf;\r
+\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       KeReleaseInStackQueuedSpinLock( &hdl );\r
+                       p_adapter->set_oid.p_pending_oid = NULL;\r
+                       NdisMOidRequestComplete( p_adapter->h_adapter, set_oid.p_pending_oid, status );\r
+                       break;\r
+\r
+               case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
+                       status = __ipoib_set_net_addr( p_adapter,\r
+                                                                                  p_adapter->set_oid.p_buf,\r
+                                                                                  p_adapter->set_oid.buf_len,\r
+                                                                                  p_adapter->set_oid.p_bytes_used,\r
+                                                                                  p_adapter->set_oid.p_bytes_needed );\r
+\r
+                       if( status != NDIS_STATUS_PENDING )\r
+                       {\r
+                               p_adapter->set_oid.p_pending_oid = NULL;\r
+                               NdisMOidRequestComplete( p_adapter->h_adapter, set_oid.p_pending_oid, status );\r
+                       }\r
+                       break;\r
+\r
+               default:\r
+                       CL_ASSERT( set_oid.oid && 0 );\r
+                       break;\r
+               }\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__ipoib_set_net_addr(\r
+       IN              ipoib_adapter_t *       p_adapter,\r
+       IN              PVOID                           info_buf,\r
+       IN              ULONG                           info_buf_len,\r
+               OUT     PULONG                          p_bytes_read,\r
+               OUT     PULONG                          p_bytes_needed )\r
+{\r
+       NDIS_STATUS                             status;\r
+       PNETWORK_ADDRESS_LIST   p_net_addrs;\r
+       PNETWORK_ADDRESS                p_net_addr_oid;\r
+       PNETWORK_ADDRESS_IP             p_ip_addr;\r
+\r
+       net_address_item_t              *p_addr_item;\r
+\r
+       cl_status_t                             cl_status;\r
+\r
+       size_t                                  idx;\r
+       LONG                                    i;\r
+       ULONG                                   addr_size;\r
+       ULONG                                   total_size;\r
+\r
+       uint8_t                                 port_num;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       status = NDIS_STATUS_SUCCESS;\r
+       port_num = p_adapter->guids.port_num;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+               ("Port %d received set for OID_GEN_NETWORK_LAYER_ADDRESSES\n",\r
+               port_num) );\r
+\r
+       if( !info_buf )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                       "NULL buffer\n", port_num) );\r
+               IPOIB_EXIT( IPOIB_DBG_OID );\r
+               return NDIS_STATUS_INVALID_DATA;\r
+       }\r
+\r
+       /*\r
+        * Must use field offset because the structures define array's of size one\r
+        * of a the incorrect type for what is really stored.\r
+        */\r
+       if( info_buf_len < FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
+                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                       "bad length of %d, not enough "\r
+                       "for NETWORK_ADDRESS_LIST (%d)\n", port_num, info_buf_len,\r
+                       FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address)) );\r
+               *p_bytes_needed = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address);\r
+               IPOIB_EXIT( IPOIB_DBG_OID );\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+       }\r
+\r
+       p_net_addrs = (PNETWORK_ADDRESS_LIST)info_buf;\r
+       if( p_net_addrs->AddressCount == 0)\r
+       {\r
+               if( p_net_addrs->AddressType == NDIS_PROTOCOL_ID_TCP_IP )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                               ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                               "clear TCP/IP addresses\n", port_num) );\r
+               }\r
+               else\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                               ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                               "Non TCP/IP address type of 0x%.4X on clear\n",\r
+                               port_num, p_net_addrs->AddressType) );\r
+                       IPOIB_EXIT( IPOIB_DBG_OID );\r
+                       return NDIS_STATUS_SUCCESS;\r
+               }\r
+       }\r
+\r
+       addr_size = FIELD_OFFSET(NETWORK_ADDRESS, Address) +\r
+               NETWORK_ADDRESS_LENGTH_IP;\r
+       total_size = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) +\r
+               addr_size * p_net_addrs->AddressCount;\r
+\r
+       if( info_buf_len < total_size )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                       "bad length of %d, %d required for %d addresses\n",\r
+                       port_num, info_buf_len, total_size, p_net_addrs->AddressCount) );\r
+               *p_bytes_needed = total_size;\r
+               IPOIB_EXIT( IPOIB_DBG_OID );\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+       }\r
+\r
+       /* Lock lists for duration since SA callbacks can occur on other CPUs */\r
+       cl_obj_lock( &p_adapter->obj );\r
+\r
+       /* Set the capacity of the vector to accomodate all assinged addresses. */\r
+       cl_status = cl_vector_set_capacity(\r
+               &p_adapter->ip_vector, p_net_addrs->AddressCount );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                       "Failed to set IP vector capacity: %#x\n", port_num,\r
+                       cl_status) );\r
+               IPOIB_EXIT( IPOIB_DBG_OID );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+\r
+       *p_bytes_read = total_size;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+               ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - List contains %d addresses\n",\r
+                       port_num, p_net_addrs->AddressCount));\r
+\r
+       /* First look for addresses we had that should be removed */\r
+       for( idx = 0; idx != cl_vector_get_size( &p_adapter->ip_vector ); idx++ )\r
+       {\r
+               p_addr_item = (net_address_item_t*)\r
+                       cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
+               p_net_addr_oid = (PNETWORK_ADDRESS)p_net_addrs->Address;\r
+\r
+               for( i = 0; i < p_net_addrs->AddressCount; ++i, p_net_addr_oid =\r
+                       (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid +\r
+                       FIELD_OFFSET(NETWORK_ADDRESS, Address) +\r
+                       p_net_addr_oid->AddressLength) )\r
+               {\r
+\r
+                       if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
+                                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, "\r
+                                               "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType,\r
+                                               NDIS_PROTOCOL_ID_TCP_IP));\r
+                               continue;\r
+                       }\r
+\r
+                       if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP)\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
+                                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, "\r
+                                               "should be %d\n", port_num, i, p_net_addr_oid->AddressLength,\r
+                                               NETWORK_ADDRESS_LENGTH_IP));\r
+                               continue;\r
+                       }\r
+\r
+                       p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address;\r
+                       if( !cl_memcmp( &p_ip_addr->in_addr,\r
+                               &p_addr_item->address.as_ulong, sizeof(ULONG) ) )\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if( i == p_net_addrs->AddressCount )\r
+               {\r
+                       /* Didn't find a match, delete from SA */\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Deleting Address %d.%d.%d.%d\n",\r
+                                       port_num,\r
+                                       p_addr_item->address.as_bytes[0],\r
+                                       p_addr_item->address.as_bytes[1],\r
+                                       p_addr_item->address.as_bytes[2],\r
+                                       p_addr_item->address.as_bytes[3]));\r
+\r
+                       if( p_addr_item->p_reg )\r
+                       {\r
+                               if( p_addr_item->p_reg->h_reg_svc )\r
+                               {\r
+                                       p_adapter->p_ifc->dereg_svc(\r
+                                               p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
+                               }\r
+                               else\r
+                               {\r
+                                       cl_free( p_addr_item->p_reg );\r
+                               }\r
+                               p_addr_item->p_reg = NULL;\r
+                       }\r
+                       p_addr_item->address.as_ulong = 0;\r
+               }\r
+       }\r
+\r
+       /* Now look for new addresses */\r
+       p_net_addr_oid = (NETWORK_ADDRESS *)p_net_addrs->Address;\r
+       idx = 0;\r
+       for( i = 0; i < p_net_addrs->AddressCount; i++, p_net_addr_oid =\r
+               (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid +\r
+               FIELD_OFFSET(NETWORK_ADDRESS, Address) + p_net_addr_oid->AddressLength) )\r
+       {\r
+\r
+               if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP )\r
+               {\r
+                       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                               ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, "\r
+                                       "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType,\r
+                                       NDIS_PROTOCOL_ID_TCP_IP));\r
+                       continue;\r
+               }\r
+\r
+               if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP)\r
+               {\r
+                       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                               ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, "\r
+                                       "should be %d\n", port_num, i, p_net_addr_oid->AddressLength,\r
+                                       NETWORK_ADDRESS_LENGTH_IP));\r
+                       continue;\r
+               }\r
+\r
+               p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address;\r
+\r
+               /* Size the vector as needed. */\r
+               if( cl_vector_get_size( &p_adapter->ip_vector ) <= idx )\r
+                       cl_vector_set_size( &p_adapter->ip_vector, idx + 1 );\r
+\r
+               p_addr_item = cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
+               if( !cl_memcmp( &p_ip_addr->in_addr, &p_addr_item->address.as_ulong,\r
+                       sizeof(ULONG) ) )\r
+               {\r
+                       idx++;\r
+                       /* Already have this address - no change needed */\r
+                       continue;\r
+               }\r
+\r
+               /*\r
+                * Copy the address information, but don't register yet - the port\r
+                * could be down.\r
+                */\r
+               if( p_addr_item->p_reg )\r
+               {\r
+                       /* If in use by some other address, deregister. */\r
+                       if( p_addr_item->p_reg->h_reg_svc )\r
+                       {\r
+                               p_adapter->p_ifc->dereg_svc(\r
+                                       p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
+                       }\r
+                       else\r
+                       {\r
+                               cl_free( p_addr_item->p_reg );\r
+                       }\r
+                       p_addr_item->p_reg = NULL;\r
+               }\r
+               memcpy ((void *)&p_addr_item->address.as_ulong, (const void *)&p_ip_addr->in_addr, sizeof(ULONG) );\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Adding Address %d.%d.%d.%d\n",\r
+                       port_num,\r
+                       p_addr_item->address.as_bytes[0],\r
+                       p_addr_item->address.as_bytes[1],\r
+                       p_addr_item->address.as_bytes[2],\r
+                       p_addr_item->address.as_bytes[3]) );\r
+               idx++;\r
+       }\r
+\r
+       /* Now clear any extra entries that shouldn't be there. */\r
+       while( idx < cl_vector_get_size( &p_adapter->ip_vector ) )\r
+       {\r
+               p_addr_item = (net_address_item_t*)\r
+                       cl_vector_get_ptr( &p_adapter->ip_vector,\r
+                       cl_vector_get_size( &p_adapter->ip_vector ) - 1 );\r
+\r
+               if( p_addr_item->p_reg )\r
+               {\r
+                       if( p_addr_item->p_reg->h_reg_svc )\r
+                       {\r
+                               p_adapter->p_ifc->dereg_svc(\r
+                                       p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
+                       }\r
+                       else\r
+                       {\r
+                               cl_free( p_addr_item->p_reg );\r
+                       }\r
+                       p_addr_item->p_reg = NULL;\r
+                       p_addr_item->address.as_ulong = 0;\r
+               }\r
+\r
+               /* No need to check return value - shrinking always succeeds. */\r
+               cl_vector_set_size( &p_adapter->ip_vector,\r
+                       cl_vector_get_size( &p_adapter->ip_vector ) - 1 );\r
+       }\r
+\r
+       if( p_adapter->state == IB_PNP_PORT_ACTIVE && p_adapter->packet_filter )\r
+               ipoib_reg_addrs( p_adapter );\r
+\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+/* Object lock is held when this function is called. */\r
+void\r
+ipoib_reg_addrs(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       net_address_item_t              *p_addr_item;\r
+\r
+       size_t                                  idx;\r
+\r
+       uint8_t                                 port_num;\r
+\r
+       ib_api_status_t                 ib_status;\r
+       ib_reg_svc_req_t                ib_service;\r
+       ib_gid_t                                port_gid;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       if(p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,\r
+               ("ATS Service available for default pkey only\n"));      \r
+               return;\r
+       }\r
+       port_num = p_adapter->guids.port_num;\r
+\r
+       /* Setup our service call with things common to all calls */\r
+       cl_memset( &ib_service, 0, sizeof(ib_service) );\r
+\r
+       /* BUGBUG Only register local subnet GID prefix for now */\r
+       ib_gid_set_default( &port_gid, p_adapter->guids.port_guid.guid );\r
+       ib_service.svc_rec.service_gid          = port_gid;\r
+\r
+       ib_service.svc_rec.service_pkey         = IB_DEFAULT_PKEY;\r
+       ib_service.svc_rec.service_lease        = IB_INFINITE_SERVICE_LEASE;\r
+\r
+       /* Must cast here because the service name is an array of unsigned chars but\r
+        * strcpy want a pointer to a signed char */\r
+       if ( StringCchCopy( (char *)ib_service.svc_rec.service_name, \r
+               sizeof(ib_service.svc_rec.service_name) / sizeof(char), ATS_NAME ) != S_OK) {\r
+               ASSERT(FALSE);\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,\r
+               ("Problem copying ATS name: exiting\n"));\r
+               return;\r
+       }\r
+    \r
+       /* IP Address in question will be put in below */\r
+       ib_service.port_guid            = p_adapter->guids.port_guid.guid;\r
+       ib_service.timeout_ms           = p_adapter->params.sa_timeout;\r
+       ib_service.retry_cnt            = p_adapter->params.sa_retry_cnt;\r
+\r
+       /* Can't set IB_FLAGS_SYNC here because I can't wait at dispatch */\r
+       ib_service.flags                        = 0;\r
+\r
+       /* Service context will be put in below */\r
+\r
+       ib_service.svc_data_mask        = IB_SR_COMPMASK_SID            |\r
+                                                                 IB_SR_COMPMASK_SGID           |\r
+                                                                 IB_SR_COMPMASK_SPKEY          |\r
+                                                                 IB_SR_COMPMASK_SLEASE         |\r
+                                                                 IB_SR_COMPMASK_SNAME          |\r
+                                                                 IB_SR_COMPMASK_SDATA8_12      |\r
+                                                                 IB_SR_COMPMASK_SDATA8_13      |\r
+                                                                 IB_SR_COMPMASK_SDATA8_14      |\r
+                                                                 IB_SR_COMPMASK_SDATA8_15;\r
+       ib_service.pfn_reg_svc_cb = __ipoib_ats_reg_cb;\r
+\r
+       for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ )\r
+       {\r
+               p_addr_item = (net_address_item_t*)\r
+                       cl_vector_get_ptr(  &p_adapter->ip_vector, idx );\r
+\r
+               if( p_addr_item->p_reg )\r
+                       continue;\r
+\r
+               p_addr_item->p_reg = cl_zalloc( sizeof(ats_reg_t) );\r
+               if( !p_addr_item->p_reg )\r
+                       break;\r
+\r
+               p_addr_item->p_reg->p_adapter = p_adapter;\r
+\r
+               ib_service.svc_context          = p_addr_item->p_reg;\r
+\r
+               ib_service.svc_rec.service_id =\r
+                       ATS_SERVICE_ID & CL_HTON64(0xFFFFFFFFFFFFFF00);\r
+               /* ATS service IDs start at 0x10000CE100415453 */\r
+               ib_service.svc_rec.service_id |= ((uint64_t)(idx + 0x53)) << 56;\r
+\r
+               cl_memcpy( &ib_service.svc_rec.service_data8[ATS_IPV4_OFFSET],\r
+                       p_addr_item->address.as_bytes, IPV4_ADDR_SIZE );\r
+\r
+               /* Take a reference for each service request. */\r
+               cl_obj_ref(&p_adapter->obj);\r
+               ib_status = p_adapter->p_ifc->reg_svc(\r
+                       p_adapter->h_al, &ib_service, &p_addr_item->p_reg->h_reg_svc );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       if( ib_status == IB_INVALID_GUID )\r
+                       {\r
+                               /* If this occurs, we log the error but do not fail the OID yet */\r
+                               IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
+                                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                                       "Failed to register IP Address "\r
+                                       "of %d.%d.%d.%d with error IB_INVALID_GUID\n",\r
+                                       port_num,\r
+                                       p_addr_item->address.as_bytes[0],\r
+                                       p_addr_item->address.as_bytes[1],\r
+                                       p_addr_item->address.as_bytes[2],\r
+                                       p_addr_item->address.as_bytes[3]) );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Fatal error. */\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address "\r
+                                       "of %d.%d.%d.%d with error %s\n",\r
+                                       port_num,\r
+                                       p_addr_item->address.as_bytes[0],\r
+                                       p_addr_item->address.as_bytes[1],\r
+                                       p_addr_item->address.as_bytes[2],\r
+                                       p_addr_item->address.as_bytes[3],\r
+                                       p_adapter->p_ifc->get_err_str( ib_status )) );\r
+                               p_adapter->hung = TRUE;\r
+                       }\r
+                       cl_obj_deref(&p_adapter->obj);\r
+                       cl_free( p_addr_item->p_reg );\r
+                       p_addr_item->p_reg = NULL;\r
+               }\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
+\r
+\r
+/* Object lock is held when this function is called. */\r
+void\r
+ipoib_dereg_addrs(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       net_address_item_t              *p_addr_item;\r
+\r
+       size_t                                  idx;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ )\r
+       {\r
+               p_addr_item = (net_address_item_t*)\r
+                       cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
+\r
+               if( !p_addr_item->p_reg )\r
+                       continue;\r
+\r
+               if( p_addr_item->p_reg->h_reg_svc )\r
+               {\r
+                       p_adapter->p_ifc->dereg_svc(\r
+                               p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
+               }\r
+               else\r
+               {\r
+                       cl_free( p_addr_item->p_reg );\r
+               }\r
+               p_addr_item->p_reg = NULL;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
+\r
+\r
+void\r
+ipoib_cancel_xmit(\r
+       IN                              NDIS_HANDLE             adapter_context,\r
+       IN                              PVOID                   cancel_id )\r
+{\r
+       ipoib_adapter_t* const p_adapter =\r
+               (ipoib_adapter_t* const )adapter_context;\r
+\r
+       if( p_adapter && p_adapter->p_port )\r
+       {\r
+               ipoib_port_cancel_xmit( p_adapter->p_port, cancel_id );\r
+       }\r
+}\r
+\r
+\r
+static void\r
+__ipoib_ats_reg_cb(\r
+       IN                              ib_reg_svc_rec_t                        *p_reg_svc_rec )\r
+{\r
+       ats_reg_t                               *p_reg;\r
+       uint8_t                                 port_num;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       CL_ASSERT( p_reg_svc_rec );\r
+       CL_ASSERT( p_reg_svc_rec->svc_context );\r
+\r
+       p_reg = (ats_reg_t*)p_reg_svc_rec->svc_context;\r
+       port_num = p_reg->p_adapter->guids.port_num;\r
+\r
+       cl_obj_lock( &p_reg->p_adapter->obj );\r
+\r
+       if( p_reg_svc_rec->req_status == IB_SUCCESS &&\r
+               !p_reg_svc_rec->resp_status )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                        ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Registered IP Address "\r
+                                         "of %d.%d.%d.%d\n",\r
+                                         port_num,\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET],\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1],\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2],\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3]) );\r
+       }\r
+       else if( p_reg_svc_rec->req_status != IB_CANCELED )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OID,\r
+                                        ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address "\r
+                                         "of %d.%d.%d.%d with error %s\n",\r
+                                         port_num,\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET],\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1],\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2],\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3],\r
+                                         p_reg->p_adapter->p_ifc->get_err_str( p_reg_svc_rec->resp_status )) );\r
+               p_reg->p_adapter->hung = TRUE;\r
+               p_reg->h_reg_svc = NULL;\r
+       }\r
+\r
+       cl_obj_unlock( &p_reg->p_adapter->obj );\r
+       cl_obj_deref(&p_reg->p_adapter->obj);\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
+\r
+\r
+static void\r
+__ipoib_ats_dereg_cb(\r
+       IN                              void                                            *context )\r
+{\r
+       cl_free( context );\r
+}\r
+\r
+static NDIS_STATUS \r
+ipoib_pause(\r
+    IN  NDIS_HANDLE                         adapter_context,    \r
+    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS     pause_parameters)\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+\r
+       UNREFERENCED_PARAMETER(pause_parameters);\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT(adapter_context);\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+       CL_ASSERT(p_adapter->ipoib_state == IPOIB_RUNNING);\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+       p_adapter->ipoib_state = IPOIB_PAUSING;\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+       //TODO: \r
+       ipoib_port_resume(p_adapter->p_port,FALSE);\r
+//     ASSERT(FALSE);\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+       p_adapter->ipoib_state = IPOIB_PAUSED;\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static NDIS_STATUS \r
+ipoib_restart(\r
+    IN  NDIS_HANDLE                         adapter_context,    \r
+    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   restart_parameters)\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+    PNDIS_RESTART_ATTRIBUTES     NdisRestartAttributes;\r
+    PNDIS_RESTART_GENERAL_ATTRIBUTES  NdisGeneralAttributes;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+       NdisRestartAttributes = restart_parameters->RestartAttributes;\r
+\r
+    if (NdisRestartAttributes != NULL)\r
+    {\r
+        CL_ASSERT(NdisRestartAttributes->Oid == OID_GEN_MINIPORT_RESTART_ATTRIBUTES);\r
+        NdisGeneralAttributes = (PNDIS_RESTART_GENERAL_ATTRIBUTES)NdisRestartAttributes->Data;   \r
+        //\r
+        // Check to see if we need to change any attributes\r
+    }\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+       p_adapter->ipoib_state = IPOIB_RUNNING;\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+    return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+/*++\r
+Routine Description:\r
+\r
+    This function aborts the request pending in the miniport.\r
+\r
+Arguments:\r
+\r
+    MiniportAdapterContext  Pointer to the adapter structure\r
+    RequestId               Specify the request to be cancelled.\r
+    \r
+Return Value:\r
+    \r
+--*/\r
+static void\r
+ipoib_cancel_oid_request(\r
+    IN  NDIS_HANDLE            adapter_context,\r
+    IN  PVOID                  requestId\r
+    )\r
+{\r
+    PNDIS_OID_REQUEST    pending_request;\r
+       ipoib_adapter_t          *p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+    cl_obj_lock( &p_adapter->obj );\r
+    \r
+    if ( p_adapter->query_oid.p_pending_oid &&\r
+               p_adapter->query_oid.p_pending_oid->RequestId == requestId)\r
+       {\r
+               pending_request = p_adapter->query_oid.p_pending_oid;\r
+               p_adapter->query_oid.p_pending_oid = NULL;\r
+               p_adapter->pending_query = FALSE;\r
+       }\r
+       else if(p_adapter->set_oid.p_pending_oid && \r
+                       p_adapter->set_oid.p_pending_oid->RequestId == requestId)\r
+       {\r
+                pending_request = p_adapter->set_oid.p_pending_oid;\r
+                p_adapter->set_oid.p_pending_oid = NULL;\r
+                p_adapter->pending_set = FALSE;\r
+       }\r
+       else\r
+       {\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+               ("No Pending OID found\n") );\r
+               return;\r
+       }\r
+    cl_obj_unlock( &p_adapter->obj );\r
+\r
+    NdisMOidRequestComplete(p_adapter->h_adapter, \r
+                            pending_request, \r
+                            NDIS_STATUS_REQUEST_ABORTED);\r
+\r
+    IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_driver.h b/trunk/ulp/ipoib/kernel6/ipoib_driver.h
new file mode 100644 (file)
index 0000000..5ba79d9
--- /dev/null
@@ -0,0 +1,162 @@
+/*\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: ipoib_driver.h 4226 2009-04-06 06:01:03Z xalex $\r
+ */\r
+\r
+\r
+#ifndef _IPOIB_DRIVER_H_\r
+#define _IPOIB_DRIVER_H_\r
+\r
+\r
+#include "ipoib_log.h"\r
+#include "ipoib_adapter.h"\r
+#include <complib/cl_spinlock.h>\r
+#include <complib/cl_qlist.h>\r
+#include "ipoib_debug.h"\r
+\r
+\r
+/*\r
+ * Definitions\r
+ */\r
+#define MAX_BUNDLE_ID_LENGTH   32\r
+\r
+/* The maximum number of send packets the MiniportSendPackets function can accept */\r
+#define MINIPORT_MAX_SEND_PACKETS      200\r
+\r
+/* MLX4 supports 4K MTU */\r
+#define MAX_IB_MTU                     4096\r
+#define DEFAULT_MTU                    2048\r
+/*\r
+ * Header length as defined by IPoIB spec:\r
+ * http://www.ietf.org/internet-drafts/draft-ietf-ipoib-ip-over-infiniband-04.txt\r
+ */\r
\r
+#define MAX_UD_PAYLOAD_MTU             (MAX_IB_MTU - sizeof(ipoib_hdr_t))\r
+#define DEFAULT_PAYLOAD_MTU            (DEFAULT_MTU - sizeof(ipoib_hdr_t))\r
+#define MAX_CM_PAYLOAD_MTU             (65520)\r
+#define MAX_WRS_PER_MSG                        ((MAX_CM_PAYLOAD_MTU/DEFAULT_PAYLOAD_MTU)+1)\r
+/*\r
+ * Only the protocol type is sent as part of the UD payload\r
+ * since the rest of the Ethernet header is encapsulated in the\r
+ * various IB headers.  We report out buffer space as if we\r
+ * transmit the ethernet headers.\r
+ */\r
+#define MAX_XFER_BLOCK_SIZE            (sizeof(eth_hdr_t) + MAX_UD_PAYLOAD_MTU)\r
+#define DATA_OFFSET                            (sizeof(eth_hdr_t) - sizeof(ipoib_hdr_t))\r
+\r
+#define IPOIB_CM_FLAG_RC               (0x80)\r
+#define IPOIB_CM_FLAG_UC               (0x40)\r
+#define IPOIB_CM_FLAG_SVCID            (0x10) // OFED set IETF bit this way ( open OFED PR 1121 )\r
+\r
+#define MAX_SEND_SGE                   (8)\r
+\r
+/* Amount of physical memory to register. */\r
+#define MEM_REG_SIZE   0xFFFFFFFFFFFFFFFF\r
+\r
+/* Number of work completions to chain for send and receive polling. */\r
+#define MAX_SEND_WC            5\r
+#define MAX_RECV_WC            16\r
+\r
+typedef struct _ipoib_globals\r
+{\r
+       KSPIN_LOCK              lock;\r
+       cl_qlist_t              adapter_list;\r
+       cl_qlist_t              bundle_list;\r
+\r
+       atomic32_t              laa_idx;\r
+\r
+       NDIS_HANDLE             h_ndis_wrapper;\r
+       PDEVICE_OBJECT  h_ibat_dev;\r
+       volatile LONG   ibat_ref;\r
+       uint32_t                bypass_check_bcast_rate;\r
+\r
+}      ipoib_globals_t;\r
+/*\r
+* FIELDS\r
+*      lock\r
+*              Spinlock to protect list access.\r
+*\r
+*      adapter_list\r
+*              List of all adapter instances.  Used for address translation support.\r
+*\r
+*      bundle_list\r
+*              List of all adapter bundles.\r
+*\r
+*      laa_idx\r
+*              Global counter for generating LAA MACs\r
+*\r
+*      h_ibat_dev\r
+*              Device handle returned by NdisMRegisterDevice.\r
+*********/\r
+\r
+extern ipoib_globals_t g_ipoib;\r
+\r
+\r
+typedef struct _ipoib_bundle\r
+{\r
+       cl_list_item_t  list_item;\r
+       char                    bundle_id[MAX_BUNDLE_ID_LENGTH];\r
+       cl_qlist_t              adapter_list;\r
+\r
+}      ipoib_bundle_t;\r
+/*\r
+* FIELDS\r
+*      list_item\r
+*              List item for storing the bundle in a quick list.\r
+*\r
+*      bundle_id\r
+*              Bundle identifier.\r
+*\r
+*      adapter_list\r
+*              List of adapters in the bundle.  The adapter at the head is the\r
+*              primary adapter of the bundle.\r
+*********/\r
+void\r
+ipoib_create_log(\r
+       NDIS_HANDLE h_adapter,\r
+       UINT ind,\r
+       ULONG eventLogMsgId);\r
+\r
+#define GUID_MASK_LOG_INDEX 0\r
+\r
+void\r
+ipoib_resume_oids(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+#define IPOIB_OFFSET(field)   ((UINT)FIELD_OFFSET(ipoib_params_t,field))\r
+#define IPOIB_SIZE(field)     sizeof(((ipoib_params_t*)0)->field)\r
+#define IPOIB_INIT_NDIS_STRING(str)                        \\r
+    (str)->Length = 0;                                  \\r
+    (str)->MaximumLength = 0;                           \\r
+    (str)->Buffer = NULL;\r
+\r
+\r
+\r
+#endif /* _IPOIB_DRIVER_H_ */\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_endpoint.c b/trunk/ulp/ipoib/kernel6/ipoib_endpoint.c
new file mode 100644 (file)
index 0000000..1e82e5a
--- /dev/null
@@ -0,0 +1,1170 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_endpoint.c 4226 2009-04-06 06:01:03Z xalex $\r
+ */\r
+\r
+\r
+\r
+#include "ipoib_endpoint.h"\r
+#include "ipoib_port.h"\r
+#include "ipoib_debug.h"\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_endpoint.tmh"\r
+#endif\r
+#include <complib/cl_atomic.h>\r
+#include <complib/cl_math.h>\r
+\r
+\r
+static void\r
+__endpt_destroying(\r
+       IN                              cl_obj_t*                                       p_obj );\r
+\r
+static void\r
+__endpt_cleanup(\r
+       IN                              cl_obj_t*                                       p_obj );\r
+\r
+static void\r
+__endpt_free(\r
+       IN                              cl_obj_t*                                       p_obj );\r
+\r
+static ib_api_status_t\r
+__create_mcast_av(\r
+       IN                              ib_pd_handle_t                          h_pd,\r
+       IN                              uint8_t                                         port_num,\r
+       IN                              ib_member_rec_t* const          p_member_rec,\r
+               OUT                     ib_av_handle_t* const           ph_av );\r
+\r
+static inline ipoib_port_t*\r
+__endpt_parent(\r
+       IN                              ipoib_endpt_t* const            p_endpt );\r
+\r
+static void\r
+__path_query_cb(\r
+       IN                              ib_query_rec_t                          *p_query_rec );\r
+\r
+static void\r
+__endpt_resolve(\r
+       IN                              ipoib_endpt_t* const            p_endpt );\r
+\r
+static void\r
+__endpt_cm_send_cb(\r
+       IN              const   ib_cq_handle_t                  h_cq,\r
+       IN                              void                                    *cq_context );\r
+static void\r
+__endpt_cm_recv_cb(\r
+       IN              const   ib_cq_handle_t                  h_cq,\r
+       IN                              void                                    *cq_context );\r
+\r
+static void\r
+__endpt_cm_buf_mgr_construct(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr );\r
+static void\r
+__conn_reply_cb(\r
+       IN              ib_cm_rep_rec_t                 *p_cm_rep );\r
+\r
+static void\r
+__conn_mra_cb(\r
+       IN              ib_cm_mra_rec_t                 *p_mra_rec );\r
+\r
+static void\r
+__conn_rej_cb(\r
+       IN              ib_cm_rej_rec_t                 *p_rej_rec );\r
+\r
+static void\r
+__conn_dreq_cb(\r
+        IN     ib_cm_dreq_rec_t                        *p_dreq_rec );\r
+\r
+#if 0 //CM\r
+static cl_status_t\r
+__cm_recv_desc_ctor(\r
+       IN              void* const                                     p_object,\r
+       IN              void*                                           context,\r
+       OUT             cl_pool_item_t** const          pp_pool_item );\r
+\r
+static void\r
+__cm_recv_desc_dtor(\r
+       IN              const   cl_pool_item_t* const           p_pool_item,\r
+       IN                              void                                            *context );\r
+\r
+static NDIS_PACKET*\r
+__endpt_cm_get_ndis_pkt(\r
+       IN              ipoib_port_t* const                     p_port,\r
+       IN              ipoib_cm_desc_t* const          p_desc );\r
+\r
+static inline ipoib_cm_desc_t*\r
+__endpt_cm_buf_mgr_get_recv(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr );\r
+\r
+static boolean_t\r
+__cm_recv_is_dhcp(\r
+       IN              const ipoib_pkt_t* const        p_ipoib );\r
+\r
+static ib_api_status_t\r
+__endpt_cm_recv_arp(\r
+       IN              ipoib_port_t* const                     p_port,\r
+       IN              const   ipoib_pkt_t* const      p_ipoib,\r
+       OUT             eth_pkt_t* const                        p_eth,\r
+       IN              ipoib_endpt_t* const            p_src_endpt );\r
+\r
+static ib_api_status_t\r
+__endpt_cm_recv_udp(\r
+       IN              ipoib_port_t* const                     p_port,\r
+       IN              ib_wc_t* const                          p_wc,\r
+       IN              const   ipoib_pkt_t* const      p_ipoib,\r
+       OUT             eth_pkt_t* const                        p_eth,\r
+       IN              ipoib_endpt_t* const            p_src_endpt );\r
+#endif\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_create(\r
+       IN              const   ib_gid_t* const                         p_dgid,\r
+       IN              const   net16_t                                         dlid,\r
+       IN              const   net32_t                                         qpn )\r
+{\r
+       ipoib_endpt_t   *p_endpt;\r
+       cl_status_t             status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       p_endpt = cl_zalloc( sizeof(ipoib_endpt_t) );\r
+       if( !p_endpt )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate endpoint (%d bytes)\n",\r
+                       sizeof(ipoib_endpt_t)) );\r
+               return NULL;\r
+       }\r
+\r
+       cl_obj_construct( &p_endpt->obj, IPOIB_OBJ_ENDPOINT );\r
+\r
+       status = cl_obj_init( &p_endpt->obj, CL_DESTROY_ASYNC,\r
+               __endpt_destroying, __endpt_cleanup, __endpt_free );\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+               ("Created endpoint: [ %p ] DLID: %#x QPN: %#x \n", \r
+               p_endpt, cl_ntoh16(dlid), cl_ntoh32(qpn) ) );\r
+\r
+       p_endpt->dgid = *p_dgid;\r
+       p_endpt->dlid = dlid;\r
+       p_endpt->qpn = qpn;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return p_endpt;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__create_mcast_av(\r
+       IN                              ib_pd_handle_t                          h_pd,\r
+       IN                              uint8_t                                         port_num,\r
+       IN                              ib_member_rec_t* const          p_member_rec,\r
+               OUT                     ib_av_handle_t* const           ph_av )\r
+{\r
+       ib_av_attr_t    av_attr;\r
+       uint32_t                flow_lbl;\r
+       uint8_t                 hop_lmt;\r
+       ib_api_status_t status;\r
+       ipoib_endpt_t   *p_endpt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+       p_endpt = PARENT_STRUCT(ph_av, ipoib_endpt_t, h_av );\r
+\r
+       cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
+       av_attr.port_num = port_num;\r
+       ib_member_get_sl_flow_hop( p_member_rec->sl_flow_hop,\r
+               &av_attr.sl, &flow_lbl, &hop_lmt );\r
+       av_attr.dlid = p_member_rec->mlid;\r
+       av_attr.grh_valid = TRUE;\r
+       av_attr.grh.hop_limit = hop_lmt;\r
+       av_attr.grh.dest_gid = p_member_rec->mgid;\r
+       av_attr.grh.src_gid = p_member_rec->port_gid;\r
+       av_attr.grh.ver_class_flow =\r
+               ib_grh_set_ver_class_flow( 6, p_member_rec->tclass, flow_lbl );\r
+       av_attr.static_rate = p_member_rec->rate & IB_PATH_REC_BASE_MASK;\r
+       av_attr.path_bits = 0;\r
+       /* port is not attached to endpoint at this point, so use endpt ifc reference */\r
+       status = p_endpt->p_ifc->create_av( h_pd, &av_attr, ph_av );\r
+\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_av returned %s\n",\r
+                       p_endpt->p_ifc->get_err_str( status )) );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+       return status;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ipoib_endpt_set_mcast(\r
+       IN                              ipoib_endpt_t* const            p_endpt,\r
+       IN                              ib_pd_handle_t                          h_pd,\r
+       IN                              uint8_t                                         port_num,\r
+       IN                              ib_mcast_rec_t* const           p_mcast_rec )\r
+{\r
+       ib_api_status_t status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+               ("Create av for MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+               p_endpt->mac.addr[0], p_endpt->mac.addr[1],\r
+               p_endpt->mac.addr[2], p_endpt->mac.addr[3],\r
+               p_endpt->mac.addr[4], p_endpt->mac.addr[5]) );\r
+               \r
+       status = __create_mcast_av( h_pd, port_num, p_mcast_rec->p_member_rec,\r
+               &p_endpt->h_av );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__create_mcast_av returned %s\n", \r
+                       p_endpt->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+       p_endpt->h_mcast = p_mcast_rec->h_mcast;\r
+       CL_ASSERT(p_endpt->dlid == 0);\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+__endpt_destroying(\r
+       IN                              cl_obj_t*                                       p_obj )\r
+{\r
+       ipoib_endpt_t   *p_endpt;\r
+       ipoib_port_t    *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
+       p_port = __endpt_parent( p_endpt );\r
+\r
+       cl_obj_lock( p_obj );\r
+       if( p_endpt->h_query )\r
+       {\r
+               p_port->p_adapter->p_ifc->cancel_query(\r
+                       p_port->p_adapter->h_al, p_endpt->h_query );\r
+               p_endpt->h_query = NULL;\r
+       }\r
+\r
+       /* Leave the multicast group if it exists. */\r
+       if( p_endpt->h_mcast )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+                       ("Leaving MCast group\n") );\r
+               ipoib_port_ref(p_port, ref_leave_mcast);\r
+               p_port->p_adapter->p_ifc->leave_mcast( p_endpt->h_mcast, ipoib_leave_mcast_cb );\r
+       }\r
+#if 0\r
+       else if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               p_endpt->cm_flag = 0;\r
+               CL_ASSERT( endpt_cm_get_state( p_endpt ) == IPOIB_CM_DISCONNECTED );\r
+       }\r
+#endif\r
+\r
+       cl_obj_unlock( p_obj );\r
+       \r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+static void\r
+__endpt_cleanup(\r
+       IN                              cl_obj_t*                                       p_obj )\r
+{\r
+       ipoib_endpt_t   *p_endpt;\r
+       ipoib_port_t    *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
+       p_port = __endpt_parent( p_endpt );\r
+\r
+       /* Destroy the AV if it exists. */\r
+       if( p_endpt->h_av )\r
+               p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+static void\r
+__endpt_free(\r
+       IN                              cl_obj_t*                                       p_obj )\r
+{\r
+       ipoib_endpt_t   *p_endpt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
+\r
+       cl_obj_deinit( p_obj );\r
+       cl_free( p_endpt );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+static inline ipoib_port_t*\r
+__endpt_parent(\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       return PARENT_STRUCT( p_endpt->rel.p_parent_obj, ipoib_port_t, obj );\r
+}\r
+\r
+ipoib_port_t*\r
+ipoib_endpt_parent(\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       return __endpt_parent( p_endpt );\r
+}\r
+\r
+/*\r
+ * This function is called with the port object's send lock held and\r
+ * a reference held on the endpoint.  If we fail, we release the reference.\r
+ */\r
+NDIS_STATUS\r
+ipoib_endpt_queue(\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       ib_api_status_t status;\r
+       ipoib_port_t    *p_port;\r
+       ib_av_attr_t    av_attr;\r
+       net32_t                 flow_lbl;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       if( p_endpt->h_av )\r
+       {\r
+               IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+               return NDIS_STATUS_SUCCESS;\r
+       }\r
+\r
+       if( p_endpt->qpn == CL_HTON32(0x00FFFFFF) )\r
+       {\r
+               /*\r
+                * Handle a race between the mcast callback and a receive/send.  The QP\r
+                * is joined to the MC group before the MC callback is received, so it\r
+                * can receive packets, and NDIS can try to respond.  We need to delay\r
+                * a response until the MC callback runs and sets the AV.\r
+                */\r
+               ipoib_endpt_deref( p_endpt );\r
+               IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+               return NDIS_STATUS_PENDING;\r
+       }\r
+\r
+       /* This is the first packet for this endpoint.  Create the AV. */\r
+       p_port = __endpt_parent( p_endpt );\r
+\r
+       cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
+\r
+       av_attr.port_num = p_port->port_num;\r
+\r
+       ib_member_get_sl_flow_hop(\r
+               p_port->ib_mgr.bcast_rec.sl_flow_hop,\r
+               &av_attr.sl,\r
+               &flow_lbl,\r
+               &av_attr.grh.hop_limit\r
+               );\r
+\r
+       av_attr.dlid = p_endpt->dlid;\r
+\r
+       /*\r
+        * We always send the GRH so that we preferably lookup endpoints\r
+        * by GID rather than by LID.  This allows certain WHQL tests\r
+        * such as the 2c_MediaCheck test to succeed since they don't use\r
+        * IP.  This allows endpoints to be created on the fly for requests\r
+        * for which there is no match, something that doesn't work when\r
+        * using LIDs only.\r
+        */\r
+       av_attr.grh_valid = TRUE;\r
+       av_attr.grh.ver_class_flow = ib_grh_set_ver_class_flow(\r
+               6, p_port->ib_mgr.bcast_rec.tclass, flow_lbl );\r
+       av_attr.grh.resv1 = 0;\r
+       av_attr.grh.resv2 = 0;\r
+       ib_gid_set_default( &av_attr.grh.src_gid, p_port->p_adapter->guids.port_guid.guid );\r
+       av_attr.grh.dest_gid = p_endpt->dgid;\r
+\r
+       av_attr.static_rate = p_port->ib_mgr.bcast_rec.rate;\r
+       av_attr.path_bits = 0;\r
+\r
+       /* Create the AV. */\r
+       status = p_port->p_adapter->p_ifc->create_av(\r
+               p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               p_port->p_adapter->hung = TRUE;\r
+               ipoib_endpt_deref( p_endpt );\r
+               cl_obj_unlock( &p_endpt->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_av failed with %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return NDIS_STATUS_FAILURE;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+#if 0\r
+\r
+static void\r
+__endpt_cm_buf_mgr_construct(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       cl_qpool_construct( &p_buf_mgr->recv_pool );\r
+\r
+       p_buf_mgr->h_packet_pool = NULL;\r
+       p_buf_mgr->h_buffer_pool = NULL;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+ib_api_status_t\r
+endpt_cm_buf_mgr_init(\r
+       IN                              ipoib_port_t* const                             p_port )\r
+{\r
+       cl_status_t             cl_status;\r
+       NDIS_STATUS             ndis_status;\r
+       ib_api_status_t ib_status = IB_SUCCESS;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       if( p_port->cm_buf_mgr.pool_init )\r
+               return ib_status;\r
+\r
+       cl_qlist_init( &p_port->cm_buf_mgr.posted_list );\r
+\r
+       __endpt_cm_buf_mgr_construct( &p_port->cm_buf_mgr );\r
+       p_port->cm_recv_mgr.rq_depth = \r
+               min( (uint32_t)p_port->p_adapter->params.rq_depth * 8,\r
+                               p_port->p_ca_attrs->max_srq_wrs/2 );\r
+       p_port->cm_recv_mgr.depth = 0;\r
+       /* Allocate the receive descriptors pool */\r
+       cl_status = cl_qpool_init( &p_port->cm_buf_mgr.recv_pool,\r
+               p_port->cm_recv_mgr.rq_depth ,\r
+               0,\r
+               0,\r
+               sizeof( ipoib_cm_desc_t ),\r
+               __cm_recv_desc_ctor,\r
+               __cm_recv_desc_dtor,\r
+               p_port );\r
+\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_POOL, 1, cl_status );\r
+               \r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_qpool_init for cm recvs returned %#x\n", cl_status) );\r
+               \r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       /* Allocate the NDIS buffer and packet pools for receive indication. */\r
+       NdisAllocatePacketPool( &ndis_status, \r
+                                                       &p_port->cm_buf_mgr.h_packet_pool,\r
+                                                       p_port->cm_recv_mgr.rq_depth, \r
+                                                       PROTOCOL_RESERVED_SIZE_IN_PACKET );\r
+       if( ndis_status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_PKT_POOL, 1, ndis_status );\r
+\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisAllocatePacketPool returned %08X\n", ndis_status) );\r
+               \r
+               ib_status = IB_INSUFFICIENT_RESOURCES;\r
+               goto pkt_pool_failed;\r
+       }\r
+\r
+       NdisAllocateBufferPool( &ndis_status, \r
+                                                       &p_port->cm_buf_mgr.h_buffer_pool,\r
+                                                       p_port->cm_recv_mgr.rq_depth );\r
+       if( ndis_status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_BUF_POOL, 1, ndis_status );\r
+               \r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
+               \r
+               ib_status = IB_INSUFFICIENT_RESOURCES;\r
+               goto buf_pool_failed;\r
+       }\r
+       //NDIS60\r
+       //p_port->cm_recv_mgr.recv_pkt_array = \r
+               //cl_zalloc( sizeof(NDIS_PACKET*) * p_port->cm_recv_mgr.rq_depth );\r
+       p_port->cm_recv_mgr.recv_lst_array = \r
+               cl_zalloc( sizeof(NET_BUFFER_LIST*) * p_port->cm_recv_mgr.rq_depth );\r
+       \r
+               \r
+\r
+       if( !p_port->cm_recv_mgr.recv_pkt_array )\r
+       {\r
+               //NDIS60\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_zalloc for NET_BUFFER_LIST array failed.\n") );\r
+               \r
+               ib_status = IB_INSUFFICIENT_MEMORY;\r
+               goto pkt_array_failed;\r
+       }\r
+\r
+       p_port->cm_buf_mgr.pool_init = TRUE;\r
+       return IB_SUCCESS;\r
+\r
+pkt_array_failed:\r
+       if( p_port->cm_buf_mgr.h_buffer_pool )\r
+               NdisFreeBufferPool( p_port->cm_buf_mgr.h_buffer_pool );\r
+buf_pool_failed:\r
+       if( p_port->cm_buf_mgr.h_packet_pool )\r
+               NdisFreePacketPool( p_port->cm_buf_mgr.h_packet_pool );\r
+pkt_pool_failed:\r
+               cl_qpool_destroy( &p_port->cm_buf_mgr.recv_pool );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return ib_status;\r
+}\r
+\r
+void\r
+endpt_cm_buf_mgr_reset(\r
+       IN              ipoib_port_t* const             p_port )\r
+{\r
+       cl_list_item_t          *p_item;\r
+\r
+       if( !p_port->cm_buf_mgr.pool_init )\r
+               return;\r
+\r
+       if( cl_qlist_count( &p_port->cm_buf_mgr.posted_list ) )\r
+       {\r
+               for( p_item = cl_qlist_remove_head( &p_port->cm_buf_mgr.posted_list );\r
+                       p_item != cl_qlist_end( &p_port->cm_buf_mgr.posted_list );\r
+                       p_item =  cl_qlist_remove_head( &p_port->cm_buf_mgr.posted_list ) )\r
+               {\r
+                       cl_qpool_put( &p_port->cm_buf_mgr.recv_pool, \r
+                               &( PARENT_STRUCT( p_item, ipoib_cm_desc_t, list_item ))->item );\r
+               }\r
+       }\r
+}\r
+\r
+void\r
+endpt_cm_buf_mgr_destroy(\r
+       IN              ipoib_port_t* const             p_port )\r
+{\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_port );\r
+       \r
+       /* Free the receive descriptors. */\r
+       if( !p_port->cm_buf_mgr.pool_init )\r
+               return;\r
+\r
+       endpt_cm_buf_mgr_reset( p_port );\r
+\r
+       p_port->cm_buf_mgr.pool_init = FALSE;\r
+       \r
+       if( p_port->cm_recv_mgr.recv_pkt_array )\r
+       {\r
+               cl_free( p_port->cm_recv_mgr.recv_pkt_array );\r
+       }\r
+\r
+       /* Destroy the receive packet and buffer pools. */\r
+       if( p_port->cm_buf_mgr.h_buffer_pool )\r
+               NdisFreeBufferPool( p_port->cm_buf_mgr.h_buffer_pool );\r
+       if( p_port->cm_buf_mgr.h_packet_pool )\r
+               NdisFreePacketPool( p_port->cm_buf_mgr.h_packet_pool );\r
+\r
+       cl_qpool_destroy( &p_port->cm_buf_mgr.recv_pool );\r
+       \r
+       IPOIB_EXIT(  IPOIB_DBG_INIT );\r
+}\r
+\r
+static cl_status_t\r
+__cm_recv_desc_ctor(\r
+       IN                              void* const                                     p_object,\r
+       IN                              void*                                           context,\r
+               OUT                     cl_pool_item_t** const          pp_pool_item )\r
+{\r
+       ipoib_cm_desc_t*        p_desc;\r
+       ipoib_port_t*           p_port;\r
+       ib_mr_create_t          create_mr;\r
+       net32_t                         rkey;\r
+\r
+       CL_ASSERT( p_object );\r
+       CL_ASSERT( context );\r
+\r
+       p_desc = (ipoib_cm_desc_t*)p_object;\r
+       p_port = (ipoib_port_t*)context;\r
+\r
+#define BUF_ALIGN              (16)\r
+\r
+       p_desc->alloc_buf_size = \r
+               ROUNDUP( p_port->p_adapter->params.cm_xfer_block_size, BUF_ALIGN );\r
+       \r
+       p_desc->p_alloc_buf = (uint8_t *)ExAllocatePoolWithTag( \r
+               NonPagedPool, p_desc->alloc_buf_size, 'DOMC' );\r
+\r
+       if( p_desc->p_alloc_buf == NULL )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate receive buffer size %d bytes.\n", p_desc->alloc_buf_size ) );\r
+               return CL_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       create_mr.vaddr  = p_desc->p_alloc_buf;\r
+       create_mr.length  = p_desc->alloc_buf_size;\r
+       create_mr.access_ctrl = IB_AC_LOCAL_WRITE;\r
+\r
+       \r
+       if( p_port->p_adapter->p_ifc->reg_mem( \r
+                                                       p_port->ib_mgr.h_pd,\r
+                                                       &create_mr,\r
+                                                       &p_desc->lkey,\r
+                                                       &rkey,\r
+                                                       &p_desc->h_mr ) != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to create Memory Region size %d bytes.\n", p_desc->alloc_buf_size ) );\r
+               goto ctor_failed;\r
+       }\r
+       p_desc->p_buf = p_desc->p_alloc_buf + (BUF_ALIGN - sizeof( ipoib_hdr_t));\r
+       p_desc->buf_size = p_desc->alloc_buf_size - (BUF_ALIGN - sizeof( ipoib_hdr_t));\r
+\r
+       /* Setup the local data segment. */\r
+       p_desc->local_ds[0].vaddr = (uint64_t)(uintn_t)p_desc->p_buf;\r
+       p_desc->local_ds[0].length = p_desc->buf_size;\r
+       p_desc->local_ds[0].lkey = p_desc->lkey;\r
+\r
+       /* Setup the work request. */\r
+       p_desc->wr.wr_id = (uintn_t)p_desc;\r
+       p_desc->wr.ds_array = p_desc->local_ds;\r
+       p_desc->wr.num_ds = 1;\r
+       p_desc->type = PKT_TYPE_CM_UCAST;\r
+       \r
+       *pp_pool_item = &p_desc->item;\r
+       return CL_SUCCESS;\r
+\r
+ctor_failed:\r
+       ExFreePoolWithTag( p_desc->p_alloc_buf, 'DOMC' );\r
+       return CL_INSUFFICIENT_MEMORY;\r
+}\r
+\r
+static void\r
+__cm_recv_desc_dtor(\r
+       IN              const   cl_pool_item_t* const           p_pool_item,\r
+       IN                              void                                            *context )\r
+{\r
+       ipoib_cm_desc_t *p_desc;\r
+       ipoib_port_t*   p_port;\r
+\r
+       if( p_pool_item == NULL || context == NULL )\r
+               return;\r
+\r
+       p_port = (ipoib_port_t*)context;\r
+       p_desc = PARENT_STRUCT( p_pool_item, ipoib_cm_desc_t, item );\r
+\r
+       if( p_desc->h_mr )\r
+               p_port->p_adapter->p_ifc->dereg_mr( p_desc->h_mr );\r
+\r
+       if( p_desc->p_alloc_buf )\r
+               ExFreePoolWithTag( p_desc->p_alloc_buf, 'DOMC' );\r
+}\r
+\r
+\r
+static NDIS_PACKET*\r
+__endpt_cm_get_ndis_pkt(\r
+       IN              ipoib_port_t* const                     p_port,\r
+       IN              ipoib_cm_desc_t* const  p_desc )\r
+{\r
+       NDIS_STATUS                             status;\r
+       NDIS_PACKET                             *p_packet;\r
+       NDIS_BUFFER                             *p_buffer;\r
+       \r
+       IPOIB_ENTER(  IPOIB_DBG_RECV );\r
+\r
+       NdisDprAllocatePacketNonInterlocked( &status, &p_packet,\r
+                       p_port->cm_buf_mgr.h_packet_pool );\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate NDIS_PACKET: %08x\n", status) );\r
+               return NULL;\r
+       }\r
+\r
+       IPOIB_PORT_FROM_PACKET( p_packet ) = p_port;\r
+       IPOIB_RECV_FROM_PACKET( p_packet ) = p_desc;\r
+\r
+       NdisAllocateBuffer( \r
+                       &status, \r
+                       &p_buffer,\r
+                       p_port->cm_buf_mgr.h_buffer_pool, \r
+                       (void *)(p_desc->p_buf - DATA_OFFSET),\r
+                       p_desc->len + DATA_OFFSET );\r
+\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate NDIS_BUFFER: %08x\n", status) );\r
+               NdisDprFreePacketNonInterlocked( p_packet );\r
+               return NULL;\r
+       }\r
+\r
+       NdisChainBufferAtFront( p_packet, p_buffer );\r
+       NDIS_SET_PACKET_HEADER_SIZE( p_packet, sizeof(eth_hdr_t) );\r
+\r
+       IPOIB_EXIT(  IPOIB_DBG_RECV );\r
+       return p_packet;\r
+}\r
+\r
+static inline ipoib_cm_desc_t*\r
+__endpt_cm_buf_mgr_get_recv(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr )\r
+{\r
+       ipoib_cm_desc_t *p_desc;\r
+\r
+       p_desc = (ipoib_cm_desc_t*)cl_qpool_get( &p_buf_mgr->recv_pool );\r
+       if( p_desc )\r
+               cl_qlist_insert_tail( &p_buf_mgr->posted_list, &p_desc->list_item );\r
+\r
+       return p_desc;\r
+}\r
+\r
+void\r
+endpt_cm_buf_mgr_put_recv(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr,\r
+       IN              ipoib_cm_desc_t* const  p_desc )\r
+{\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_RECV );\r
+\r
+       /* Return the descriptor to it's pool. */\r
+       cl_qlist_remove_item( &p_buf_mgr->posted_list, &p_desc->list_item );\r
+       cl_qpool_put( &p_buf_mgr->recv_pool, &p_desc->item );\r
+\r
+       IPOIB_EXIT(  IPOIB_DBG_RECV );\r
+}\r
+\r
+void\r
+endpt_cm_buf_mgr_put_recv_list(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr,\r
+       IN              cl_qlist_t* const                       p_list )\r
+{\r
+       cl_qpool_put_list( &p_buf_mgr->recv_pool, p_list );\r
+}\r
+\r
+uint32_t\r
+endpt_cm_recv_mgr_build_pkt_array(\r
+       IN                      ipoib_port_t* const                     p_port,\r
+       IN                      ipoib_endpt_t* const            p_endpt,\r
+       IN                      cl_qlist_t* const                       p_done_list,\r
+       IN OUT          uint32_t*                                       p_bytes_recv )\r
+{\r
+       cl_list_item_t                  *p_item;\r
+       ipoib_cm_desc_t         *p_desc;\r
+       uint32_t                                i = 0;\r
+       NDIS_PACKET                             *p_packet;\r
+       NDIS_TCP_IP_CHECKSUM_PACKET_INFO        chksum;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+       UNUSED_PARAM( p_endpt );\r
+\r
+       p_item = cl_qlist_remove_head( p_done_list );\r
+       \r
+       *p_bytes_recv = 0;\r
+\r
+       for( p_item; p_item != cl_qlist_end( p_done_list );\r
+               p_item = cl_qlist_remove_head( p_done_list ) )\r
+       {\r
+               p_desc = (ipoib_cm_desc_t*)p_item;\r
+\r
+               p_packet = __endpt_cm_get_ndis_pkt( p_port, p_desc );\r
+               if( !p_packet )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get Packet from descriptor\n" ) );\r
+                       endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_desc );\r
+                       p_port->cm_recv_mgr.depth--;\r
+                       continue;\r
+               }\r
+               chksum.Value = 0;\r
+               switch( p_port->p_adapter->params.recv_chksum_offload )\r
+               {\r
+               default:\r
+                       CL_ASSERT( FALSE );\r
+               case CSUM_DISABLED:\r
+               case CSUM_ENABLED:\r
+               NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo ) =\r
+                               (void*)(uintn_t)chksum.Value;\r
+                       break;\r
+               case CSUM_BYPASS:\r
+                       /* Flag the checksums as having been calculated. */\r
+                       chksum.Receive.NdisPacketTcpChecksumSucceeded = TRUE;\r
+                       chksum.Receive.NdisPacketUdpChecksumSucceeded = TRUE;\r
+                       chksum.Receive.NdisPacketIpChecksumSucceeded = TRUE;\r
+                       NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo ) =\r
+                               (void*)(uintn_t)chksum.Value;\r
+                       break;\r
+               }\r
+\r
+               NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_SUCCESS );\r
+               p_port->cm_recv_mgr.recv_pkt_array[i] = p_packet;\r
+               i++;            \r
+               *p_bytes_recv += p_desc->len;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return i;\r
+}\r
+void\r
+endpt_cm_flush_recv(\r
+       IN                              ipoib_port_t* const             p_port,\r
+       IN                              ipoib_endpt_t* const    p_endpt )\r
+{\r
+       ib_api_status_t         ib_status = IB_SUCCESS;\r
+       ib_qp_mod_t                     mod_attr;\r
+       ib_wc_t                         wc[MAX_RECV_WC];\r
+       ib_wc_t                         *p_free_wc;\r
+       ib_wc_t                         *p_done_wc;\r
+       ib_wc_t                         *p_wc;\r
+       ipoib_cm_desc_t         *p_desc;\r
+       size_t                          i;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       CL_ASSERT( p_endpt );\r
+\r
+       if( p_endpt->conn.h_recv_qp )\r
+       {\r
+               cl_memclr( &mod_attr, sizeof( mod_attr ) );\r
+               mod_attr.req_state = IB_QPS_ERROR;\r
+               p_port->p_adapter->p_ifc->modify_qp( p_endpt->conn.h_send_qp, &mod_attr );\r
+               p_port->p_adapter->p_ifc->modify_qp( p_endpt->conn.h_recv_qp, &mod_attr );\r
+\r
+               for( i = 0; i < MAX_RECV_WC; i++ )\r
+                       wc[i].p_next = &wc[i + 1];\r
+               wc[MAX_RECV_WC - 1].p_next = NULL;\r
+\r
+               do\r
+               {\r
+                       p_free_wc = wc;\r
+                       ib_status = \r
+                               p_port->p_adapter->p_ifc->poll_cq( p_endpt->conn.h_recv_cq, \r
+                               &p_free_wc, &p_done_wc );\r
+                       if( ib_status != IB_SUCCESS && \r
+                               ib_status != IB_NOT_FOUND )\r
+                       {\r
+                               /* connection CQ failed */\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Poll Recv CQ failed status %#x\n", ib_status ) );\r
+                               break;\r
+                       }\r
+                       cl_spinlock_acquire( &p_port->recv_lock );\r
+                       for( p_wc = p_done_wc; p_wc; p_wc = p_wc->p_next )\r
+                       {\r
+                               p_desc = (ipoib_cm_desc_t *)(uintn_t)p_wc->wr_id;\r
+                               endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_desc );\r
+                               p_port->cm_recv_mgr.depth--;\r
+                       }\r
+                       cl_spinlock_release( &p_port->recv_lock );\r
+               } while( !p_free_wc );\r
+\r
+               ib_status = p_port->p_adapter->p_ifc->destroy_qp( p_endpt->conn.h_recv_qp, NULL );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Destroy Recv QP failed status %#x\n", ib_status ) );\r
+               }\r
+               p_endpt->conn.h_recv_qp = NULL;\r
+       }\r
+\r
+       if( p_endpt->conn.h_send_qp )\r
+       {\r
+               ib_status = p_port->p_adapter->p_ifc->destroy_qp( p_endpt->conn.h_send_qp, NULL );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Destroy Send QP failed status %#x\n", ib_status ) );\r
+               }\r
+               p_endpt->conn.h_send_qp = NULL;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+int32_t\r
+endpt_cm_recv_mgr_filter(\r
+       IN              ipoib_endpt_t* const            p_endpt,\r
+       IN              ib_wc_t* const                          p_done_wc_list,\r
+       OUT             cl_qlist_t* const                       p_done_list,\r
+       OUT             cl_qlist_t* const                       p_bad_list )\r
+{\r
+       ib_api_status_t                 ib_status;\r
+       ipoib_cm_desc_t                 *p_desc;\r
+       ib_wc_t                                 *p_wc;\r
+       ipoib_pkt_t                             *p_ipoib;\r
+       eth_pkt_t                               *p_eth;\r
+       ipoib_port_t*                   p_port;\r
+       int32_t                                 recv_cnt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       p_port = ipoib_endpt_parent( p_endpt );\r
+\r
+       for( p_wc = p_done_wc_list, recv_cnt = 0; p_wc; p_wc = p_wc->p_next )\r
+       {\r
+               p_desc = (ipoib_cm_desc_t *)(uintn_t)p_wc->wr_id;\r
+               recv_cnt++;\r
+               if(  p_wc->status != IB_WCS_SUCCESS )\r
+               {\r
+                       if( p_wc->status != IB_WCS_WR_FLUSHED_ERR )\r
+                       {\r
+                               \r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Failed completion %s  (vendor specific %#x)\n",\r
+                                       p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
+                                       (int)p_wc->vendor_specific) );\r
+                       }\r
+                       else\r
+                       {\r
+                               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+                                       ("Flushed completion %s\n",\r
+                                       p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status )) );\r
+                       }\r
+                       \r
+                       ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+\r
+                       cl_qlist_remove_item( &p_port->cm_buf_mgr.posted_list,&p_desc->list_item );\r
+                       cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                       continue;\r
+               }\r
+\r
+               /* Successful completion                \r
+                Setup the ethernet/ip/arp header and queue descriptor for report. */\r
+               ib_status = IB_SUCCESS;\r
+               p_ipoib = (ipoib_pkt_t *)((uint8_t*)p_desc->p_buf );\r
+               p_eth = (eth_pkt_t *)((uint8_t*)p_desc->p_buf - DATA_OFFSET );\r
+               \r
+               switch( p_ipoib->hdr.type )\r
+               {\r
+               case ETH_PROT_TYPE_ARP:\r
+                       if( p_wc->length < (sizeof(ipoib_hdr_t) + sizeof(ipoib_arp_pkt_t)) )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Received ARP packet too short\n") );\r
+                               ib_status = IB_ERROR;\r
+                               break;\r
+                       }\r
+                       ib_status = \r
+                               __endpt_cm_recv_arp( p_port, p_ipoib, p_eth, p_endpt );\r
+                       break;\r
+               case ETH_PROT_TYPE_IP:\r
+                       if( p_wc->length < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Received IP packet too short\n") );\r
+                               ib_status = IB_ERROR;\r
+                               break;\r
+                       }\r
+                       if( p_ipoib->type.ip.hdr.prot == IP_PROT_UDP )\r
+                       {\r
+                               ib_status = \r
+                                       __endpt_cm_recv_udp( p_port, p_wc, p_ipoib, p_eth, p_endpt );\r
+                       }\r
+               \r
+                       break;\r
+               }\r
+\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+                       cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                       continue;\r
+               }\r
+\r
+               p_eth->hdr.type = p_ipoib->hdr.type;\r
+               p_eth->hdr.src = p_endpt->mac;\r
+               p_eth->hdr.dst = p_port->p_adapter->mac;\r
+\r
+               /* save payload length */\r
+               p_desc->len = p_wc->length;\r
+               \r
+               cl_qlist_insert_tail( p_done_list, &p_desc->item.list_item );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return recv_cnt;\r
+}\r
+\r
+ib_api_status_t\r
+endpt_cm_post_recv(\r
+       IN              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t         ib_status = IB_SUCCESS;\r
+       ipoib_cm_desc_t         *p_head_desc = NULL;\r
+       ipoib_cm_desc_t         *p_tail_desc = NULL;\r
+       ipoib_cm_desc_t         *p_next_desc;\r
+       ib_recv_wr_t            *p_failed_wc = NULL;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       while( cl_qpool_count( &p_port->cm_buf_mgr.recv_pool )  > 1  )\r
+       {\r
+                       /* Pull receives out of the pool and chain them up. */\r
+               p_next_desc = __endpt_cm_buf_mgr_get_recv( \r
+                                                                       &p_port->cm_buf_mgr );\r
+               if( !p_next_desc )\r
+               {\r
+                       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+                               ("Out of receive descriptors! Endpt recv queue depth 0x%x\n",\r
+                               p_port->cm_recv_mgr.depth ) );\r
+                       break;\r
+               }\r
+\r
+               if( !p_tail_desc )\r
+               {\r
+                       p_tail_desc = p_next_desc;\r
+                       p_next_desc->wr.p_next = NULL;\r
+               }\r
+               else\r
+               {\r
+                       p_next_desc->wr.p_next = &p_head_desc->wr;\r
+               }\r
+\r
+               p_head_desc = p_next_desc;\r
+\r
+               p_port->cm_recv_mgr.depth++;\r
+       }\r
+\r
+       if( p_head_desc )\r
+       {\r
+               ib_status = p_port->p_adapter->p_ifc->post_srq_recv(\r
+                       p_port->ib_mgr.h_srq, &p_head_desc->wr, &p_failed_wc );\r
+\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ip_post_recv returned %s\n", \r
+                               p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+                       \r
+                       /* put descriptors back to the pool */\r
+                       while( p_failed_wc )\r
+                       {\r
+                               p_head_desc = PARENT_STRUCT( p_failed_wc, ipoib_cm_desc_t, wr );\r
+                               p_failed_wc = p_failed_wc->p_next;\r
+                               endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_head_desc );\r
+                               p_port->cm_recv_mgr.depth--;\r
+                       }\r
+               }\r
+       }\r
+\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return( ib_status );\r
+}\r
+\r
+static ib_api_status_t\r
+__endpt_cm_recv_arp(\r
+       IN              ipoib_port_t* const                             p_port,\r
+       IN              const   ipoib_pkt_t* const              p_ipoib,\r
+       OUT             eth_pkt_t* const                                p_eth,\r
+       IN              ipoib_endpt_t* const                    p_src_endpt )\r
+{\r
+       const ipoib_arp_pkt_t   *p_ib_arp;\r
+       arp_pkt_t                               *p_arp;\r
+       \r
+       p_ib_arp = &p_ipoib->type.arp;\r
+       p_arp = &p_eth->type.arp;\r
+       \r
+       if( p_ib_arp->hw_type != ARP_HW_TYPE_IB ||\r
+               p_ib_arp->hw_size != sizeof(ipoib_hw_addr_t) ||\r
+               p_ib_arp->prot_type != ETH_PROT_TYPE_IP )\r
+       {\r
+               return IB_ERROR;\r
+       }\r
+       \r
+       p_arp->hw_type = ARP_HW_TYPE_ETH;\r
+       p_arp->hw_size = sizeof(mac_addr_t);\r
+       p_arp->src_hw = p_src_endpt->mac;\r
+       p_arp->src_ip = p_ib_arp->src_ip;\r
+       p_arp->dst_hw = p_port->p_local_endpt->mac;\r
+       p_arp->dst_ip = p_ib_arp->dst_ip;\r
+\r
+       return IB_SUCCESS;      \r
+}\r
+\r
+static ib_api_status_t\r
+__endpt_cm_recv_udp(\r
+       IN      ipoib_port_t* const     p_port,\r
+       IN                      ib_wc_t* const                          p_wc,\r
+       IN              const   ipoib_pkt_t* const              p_ipoib,\r
+       OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                      ipoib_endpt_t* const            p_src_endpt )\r
+{\r
+       ib_api_status_t                 ib_status = IB_SUCCESS;\r
+\r
+       if( p_wc->length <\r
+               (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Received UDP packet too short\n") );\r
+               return IB_ERROR;\r
+       }\r
+       if( __cm_recv_is_dhcp( p_ipoib ) )\r
+       {\r
+               ib_status = ipoib_recv_dhcp(\r
+                       p_port, p_ipoib, p_eth, p_src_endpt, p_port->p_local_endpt );\r
+       }\r
+\r
+       return ib_status;\r
+}\r
+\r
+static boolean_t\r
+__cm_recv_is_dhcp(\r
+       IN      const ipoib_pkt_t* const        p_ipoib )\r
+{\r
+       return( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_SERVER &&\r
+                               p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) ||\r
+                               (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT &&\r
+                               p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_SERVER) );\r
+}\r
+#endif\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_endpoint.h b/trunk/ulp/ipoib/kernel6/ipoib_endpoint.h
new file mode 100644 (file)
index 0000000..547d465
--- /dev/null
@@ -0,0 +1,257 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_endpoint.h 4226 2009-04-06 06:01:03Z xalex $\r
+ */\r
+\r
+\r
+#ifndef _IPOIB_ENDPOINT_H_\r
+#define _IPOIB_ENDPOINT_H_\r
+\r
+\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_qlist.h>\r
+#include <complib/cl_qmap.h>\r
+#include <complib/cl_fleximap.h>\r
+#include <complib/cl_obj.h>\r
+#include "iba/ipoib_ifc.h"\r
+#include <ip_packet.h>\r
+#include "ipoib_debug.h"\r
+\r
+\r
+typedef struct _endpt_buf_mgr\r
+{\r
+       cl_qpool_t                      recv_pool;\r
+       NDIS_HANDLE                     h_packet_pool;\r
+       NDIS_HANDLE                     h_buffer_pool;\r
+       cl_qlist_t                      posted_list;\r
+       boolean_t                       pool_init;\r
+} endpt_buf_mgr_t;\r
+\r
+typedef struct _endpt_recv_mgr\r
+{\r
+       int32_t                 depth;\r
+       int32_t                 rq_depth;\r
+       //NDIS60\r
+       //NDIS_PACKET           **recv_pkt_array;\r
+       NET_BUFFER_LIST *recv_lst_array;\r
+\r
+}      endpt_recv_mgr_t;\r
+\r
+\r
+typedef enum _cm_state \r
+{\r
+       IPOIB_CM_DISCONNECTED,\r
+       IPOIB_CM_INIT,\r
+       IPOIB_CM_CONNECT,\r
+       IPOIB_CM_CONNECTED,\r
+       IPOIB_CM_LISTEN,\r
+       IPOIB_CM_DREP_SENT,\r
+       IPOIB_CM_DREQ_SENT,\r
+       IPOIB_CM_REJ_RECVD,\r
+       IPOIB_CM_DESTROY\r
+} cm_state_t;\r
+\r
+typedef struct _cm_private_data \r
+{\r
+       ib_net32_t              ud_qpn;\r
+       ib_net32_t              recv_mtu;\r
+} cm_private_data_t;\r
+\r
+typedef struct _endpt_conn \r
+{\r
+       ib_net64_t                      service_id;\r
+       cm_private_data_t       private_data;\r
+       ib_qp_handle_t          h_send_qp;\r
+       ib_qp_handle_t          h_recv_qp;\r
+       ib_qp_handle_t          h_work_qp;\r
+       ib_cq_handle_t          h_send_cq;\r
+       ib_cq_handle_t          h_recv_cq;\r
+       ib_listen_handle_t  h_cm_listen;\r
+       cm_state_t                      state;\r
+\r
+} endpt_conn_t;\r
+\r
+typedef struct _ipoib_endpt\r
+{\r
+       cl_obj_t                                obj;\r
+       cl_obj_rel_t                    rel;\r
+       cl_map_item_t                   mac_item;\r
+       cl_fmap_item_t                  gid_item;\r
+       cl_map_item_t                   lid_item;\r
+       cl_fmap_item_t                  conn_item;\r
+       LIST_ENTRY                              list_item;\r
+       ib_query_handle_t               h_query;\r
+       ib_mcast_handle_t               h_mcast;\r
+       mac_addr_t                              mac;\r
+       ib_gid_t                                dgid;\r
+       net16_t                                 dlid;\r
+       net32_t                                 qpn;\r
+       uint8_t                                 cm_flag;\r
+       ib_av_handle_t                  h_av;\r
+       endpt_conn_t                    conn;\r
+\r
+       ib_al_ifc_t                             *p_ifc;\r
+       boolean_t                       is_in_use;\r
+       boolean_t                               is_mcast_listener;\r
+}      ipoib_endpt_t;\r
+/*\r
+* FIELDS\r
+*      mac_item\r
+*              Map item for storing the endpoint in a map.  The key is the\r
+*              destination MAC address.\r
+*\r
+*      lid_item\r
+*              Map item for storing the endpoint in a map.  The key is the\r
+*              destination LID.\r
+*\r
+*      gid_item\r
+*              Map item for storing the endpoint in a map.  The key is the\r
+*              destination GID.\r
+*\r
+*      h_query\r
+*              Query handle for cancelling SA queries.\r
+*\r
+*      h_mcast\r
+*              For multicast endpoints, the multicast handle.\r
+*\r
+*      mac\r
+*              MAC address.\r
+*\r
+*      dgid\r
+*              Destination GID.\r
+*\r
+*      dlid\r
+*              Destination LID.  The destination LID is only set for endpoints\r
+*              that are on the same subnet.  It is used as key in the LID map.\r
+*\r
+*      qpn\r
+*              Destination queue pair number.\r
+*\r
+*      h_av\r
+*              Address vector for sending data.\r
+*\r
+*      expired\r
+*              Flag to indicate that the endpoint should be flushed.\r
+*\r
+*      connection\r
+*              for connected mode endpoints\r
+*\r
+*      p_ifc\r
+*              Reference to transport functions, can be used\r
+*              while endpoint is not attached to port yet.\r
+*\r
+* NOTES\r
+*      If the h_mcast member is set, the endpoint is never expired.\r
+*********/\r
+\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_create(\r
+       IN              const   ib_gid_t* const                         p_dgid,\r
+       IN              const   net16_t                                         dlid,\r
+       IN              const   net32_t                                         qpn );\r
+\r
+\r
+ib_api_status_t\r
+ipoib_endpt_set_mcast(\r
+       IN                              ipoib_endpt_t* const            p_endpt,\r
+       IN                              ib_pd_handle_t                          h_pd,\r
+       IN                              uint8_t                                         port_num,\r
+       IN                              ib_mcast_rec_t* const           p_mcast_rec );\r
+\r
+\r
+static inline void\r
+ipoib_endpt_ref(\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       CL_ASSERT( p_endpt );\r
+\r
+       cl_obj_ref( &p_endpt->obj );\r
+       /*\r
+        * Anytime we reference the endpoint, we're either receiving data\r
+        * or trying to send data to that endpoint.  Clear the expired flag\r
+        * to prevent the AV from being flushed.\r
+        */\r
+}\r
+\r
+\r
+static inline void\r
+ipoib_endpt_deref(\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       cl_obj_deref( &p_endpt->obj );\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_endpt_queue(\r
+       IN                              ipoib_endpt_t* const            p_endpt );\r
+\r
+struct _ipoib_port *\r
+ipoib_endpt_parent(\r
+       IN              ipoib_endpt_t* const            p_endpt );\r
+\r
+inline cm_state_t\r
+endpt_cm_set_state(\r
+       IN              ipoib_endpt_t* const            p_endpt,\r
+       IN              cm_state_t                                      state )\r
+{\r
+       return(cm_state_t)InterlockedExchange( \r
+                               (volatile LONG *)&p_endpt->conn.state, \r
+                               (LONG)state );\r
+}\r
+\r
+inline cm_state_t\r
+endpt_cm_get_state(\r
+       IN              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       return( cm_state_t )InterlockedCompareExchange( \r
+                               (volatile LONG *)&p_endpt->conn.state, \r
+                               IPOIB_CM_DISCONNECTED, IPOIB_CM_DISCONNECTED );\r
+}\r
+\r
+ib_api_status_t\r
+endpt_cm_create_qp( \r
+       IN              ipoib_endpt_t*  const   p_endpt,\r
+       IN              ib_qp_handle_t* const   p_h_qp );\r
+\r
+ib_api_status_t\r
+ipoib_endpt_connect(\r
+       IN              ipoib_endpt_t* const            p_endpt );\r
+\r
+int32_t\r
+endpt_cm_recv_mgr_filter(\r
+       IN              ipoib_endpt_t* const            p_endpt,\r
+       IN              ib_wc_t* const                          p_done_wc_list,\r
+       OUT             cl_qlist_t* const                       p_done_list,\r
+       OUT             cl_qlist_t* const                       p_bad_list );\r
+\r
+#endif /* _IPOIB_ENDPOINT_H_ */\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_ibat.c b/trunk/ulp/ipoib/kernel6/ipoib_ibat.c
new file mode 100644 (file)
index 0000000..ba89e00
--- /dev/null
@@ -0,0 +1,666 @@
+/*\r
+ * Copyright (c) 2005 Mellanox Technologies.  All rights reserved.\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_ibat.c 4226 2009-04-06 06:01:03Z xalex $\r
+ */\r
+\r
+\r
+#include "ipoib_driver.h"\r
+#include "ipoib_adapter.h"\r
+#include "ipoib_port.h"\r
+#include "ipoib_debug.h"\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_ibat.tmh"\r
+#endif\r
+#include <iba/ib_at_ioctl.h>\r
+\r
+extern PDRIVER_OBJECT                          g_p_drv_obj;\r
+\r
+static NTSTATUS\r
+__ipoib_create(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp );\r
+\r
+static NTSTATUS\r
+__ipoib_cleanup(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp );\r
+\r
+static NTSTATUS\r
+__ipoib_close(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp );\r
+\r
+static NTSTATUS\r
+__ipoib_dispatch(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp );\r
+\r
+\r
+static NTSTATUS\r
+__ibat_get_ports(\r
+       IN                              IRP                                                     *pIrp,\r
+       IN                              IO_STACK_LOCATION                       *pIoStack )\r
+{\r
+       IOCTL_IBAT_PORTS_IN             *pIn;\r
+       IOCTL_IBAT_PORTS_OUT    *pOut;\r
+       KLOCK_QUEUE_HANDLE              hdl;\r
+       cl_list_item_t                  *pItem;\r
+       ipoib_adapter_t                 *pAdapter;\r
+       LONG                                    nPorts;\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+       if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+               sizeof(IOCTL_IBAT_PORTS_IN) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid input buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+       \r
+       if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength <\r
+               sizeof(IOCTL_IBAT_PORTS_OUT) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid output buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       pIn = pIrp->AssociatedIrp.SystemBuffer;\r
+       pOut = pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+       if( pIn->Version != IBAT_IOCTL_VERSION )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid version.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+       nPorts = (LONG)cl_qlist_count( &g_ipoib.adapter_list );\r
+       switch( nPorts )\r
+       {\r
+       case 0:\r
+               cl_memclr( pOut->Ports, sizeof(pOut->Ports) );\r
+               /* Fall through */\r
+       case 1:\r
+               pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT);\r
+               break;\r
+\r
+       default:\r
+               pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT) + \r
+                       (sizeof(IBAT_PORT_RECORD) * (nPorts - 1));\r
+               break;\r
+       }\r
+\r
+       pIrp->IoStatus.Information = pOut->Size;\r
+\r
+       if( pOut->Size > pIoStack->Parameters.DeviceIoControl.OutputBufferLength )\r
+       {\r
+               nPorts = 1 +\r
+                       (pIoStack->Parameters.DeviceIoControl.OutputBufferLength -\r
+                       sizeof(IOCTL_IBAT_PORTS_OUT)) / sizeof(IBAT_PORT_RECORD);\r
+\r
+               pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_PORTS_OUT) +\r
+                       ((nPorts - 1) * sizeof(IBAT_PORT_RECORD));\r
+       }\r
+\r
+       pOut->NumPorts = 0;\r
+       pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+       while( pOut->NumPorts != nPorts )\r
+       {\r
+               pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+               pOut->Ports[pOut->NumPorts].CaGuid = pAdapter->guids.ca_guid;\r
+               pOut->Ports[pOut->NumPorts].PortGuid = pAdapter->guids.port_guid.guid;\r
+               pOut->Ports[pOut->NumPorts].PKey = IB_DEFAULT_PKEY;\r
+               pOut->Ports[pOut->NumPorts].PortNum = pAdapter->guids.port_num;\r
+               pOut->NumPorts++;\r
+\r
+               pItem = cl_qlist_next( pItem );\r
+       }\r
+\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ibat_get_ips(\r
+       IN                              IRP                                                     *pIrp,\r
+       IN                              IO_STACK_LOCATION                       *pIoStack )\r
+{\r
+       IOCTL_IBAT_IP_ADDRESSES_IN      *pIn;\r
+       IOCTL_IBAT_IP_ADDRESSES_OUT     *pOut;\r
+       KLOCK_QUEUE_HANDLE                      hdl;\r
+       cl_list_item_t                          *pItem;\r
+       ipoib_adapter_t                         *pAdapter;\r
+       LONG                                            nIps, maxIps;\r
+       size_t                                          idx;\r
+       net_address_item_t                      *pAddr;\r
+       UINT64                                          PortGuid;\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+       if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+               sizeof(IOCTL_IBAT_IP_ADDRESSES_IN) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid input buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+       \r
+       if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength <\r
+               sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid output buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       pIn = pIrp->AssociatedIrp.SystemBuffer;\r
+       pOut = pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+       if( pIn->Version != IBAT_IOCTL_VERSION )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid version.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       PortGuid = pIn->PortGuid;\r
+\r
+       nIps = 0;\r
+       pOut->AddressCount = 0;\r
+       maxIps = 1 +\r
+               ((pIoStack->Parameters.DeviceIoControl.OutputBufferLength -\r
+               sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT)) / sizeof(IP_ADDRESS));\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+       for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+               pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
+               pItem = cl_qlist_next( pItem ) )\r
+       {\r
+               pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+               if( PortGuid && pAdapter->guids.port_guid.guid != PortGuid )\r
+                       continue;\r
+\r
+               cl_obj_lock( &pAdapter->obj );\r
+               nIps += (LONG)cl_vector_get_size( &pAdapter->ip_vector );\r
+\r
+               for( idx = 0;\r
+                       idx < cl_vector_get_size( &pAdapter->ip_vector );\r
+                       idx++ )\r
+               {\r
+                       if( pOut->AddressCount == maxIps )\r
+                               break;\r
+\r
+                       pAddr = (net_address_item_t*)\r
+                               cl_vector_get_ptr( &pAdapter->ip_vector, idx );\r
+\r
+                       pOut->Address[pOut->AddressCount].IpVersion = 4;\r
+                       cl_memclr( &pOut->Address[pOut->AddressCount].Address,\r
+                               sizeof(IP_ADDRESS) );\r
+                       cl_memcpy( &pOut->Address[pOut->AddressCount].Address[12],\r
+                               pAddr->address.as_bytes, IPV4_ADDR_SIZE );\r
+\r
+                       pOut->AddressCount++;\r
+               }\r
+               cl_obj_unlock( &pAdapter->obj );\r
+       }\r
+\r
+       pOut->Size = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);\r
+       if( --nIps )\r
+               pOut->Size += sizeof(IP_ADDRESS) * nIps;\r
+\r
+       pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);\r
+       if( --maxIps < nIps )\r
+               pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * maxIps);\r
+       else\r
+               pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * nIps);\r
+\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ibat_mac_to_gid(\r
+       IN                              IRP                                                     *pIrp,\r
+       IN                              IO_STACK_LOCATION                       *pIoStack )\r
+{\r
+       NTSTATUS                                        status = STATUS_INVALID_PARAMETER;\r
+       IOCTL_IBAT_MAC_TO_GID_IN        *pIn;\r
+       IOCTL_IBAT_MAC_TO_GID_OUT       *pOut;\r
+       KLOCK_QUEUE_HANDLE                      hdl;\r
+       cl_list_item_t                          *pItem;\r
+       ipoib_adapter_t                         *pAdapter;\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+       if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+               sizeof(IOCTL_IBAT_MAC_TO_GID_IN) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid input buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+       \r
+       if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
+               sizeof(IOCTL_IBAT_MAC_TO_GID_OUT) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid output buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       pIn = pIrp->AssociatedIrp.SystemBuffer;\r
+       pOut = pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+       if( pIn->Version != IBAT_IOCTL_VERSION )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid version.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+\r
+       for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+               pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
+               pItem = cl_qlist_next( pItem ) )\r
+       {\r
+               pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+               if( pIn->PortGuid != pAdapter->guids.port_guid.guid )\r
+                       continue;\r
+\r
+               /* Found the port - lookup the MAC. */\r
+               cl_obj_lock( &pAdapter->obj );\r
+               if( pAdapter->p_port )\r
+               {\r
+                       status = ipoib_mac_to_gid(\r
+                               pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->DestGid );\r
+                       if( NT_SUCCESS( status ) )\r
+                       {\r
+                               pIrp->IoStatus.Information =\r
+                                       sizeof(IOCTL_IBAT_MAC_TO_GID_OUT);\r
+                       }\r
+               }\r
+               cl_obj_unlock( &pAdapter->obj );\r
+               break;\r
+       }\r
+\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ibat_mac_to_path(\r
+       IN                              IRP                                                     *pIrp,\r
+       IN                              IO_STACK_LOCATION                       *pIoStack )\r
+{\r
+       NTSTATUS                                        status = STATUS_INVALID_PARAMETER;\r
+       IOCTL_IBAT_MAC_TO_PATH_IN       *pIn;\r
+       IOCTL_IBAT_MAC_TO_PATH_OUT      *pOut;\r
+       KLOCK_QUEUE_HANDLE                      hdl;\r
+       cl_list_item_t                          *pItem;\r
+       ipoib_adapter_t                         *pAdapter;\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+       if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+               sizeof(IOCTL_IBAT_MAC_TO_PATH_IN) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid input buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+       \r
+       if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
+               sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid output buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       pIn = pIrp->AssociatedIrp.SystemBuffer;\r
+       pOut = pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+       if( pIn->Version != IBAT_IOCTL_VERSION )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid version.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+\r
+       for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+               pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
+               pItem = cl_qlist_next( pItem ) )\r
+       {\r
+               pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+               if( pIn->PortGuid != pAdapter->guids.port_guid.guid )\r
+                       continue;\r
+\r
+               /* Found the port - lookup the MAC. */\r
+               cl_obj_lock( &pAdapter->obj );\r
+               if( pAdapter->p_port )\r
+               {\r
+                       status = ipoib_mac_to_path(\r
+                               pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->Path );\r
+\r
+                       if( NT_SUCCESS( status ) )\r
+                       {\r
+                               pIrp->IoStatus.Information =\r
+                                       sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT);\r
+                       }\r
+               }\r
+               cl_obj_unlock( &pAdapter->obj );\r
+               break;\r
+       }\r
+\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ibat_ip_to_port(\r
+       IN                              IRP                                                     *pIrp,\r
+       IN                              IO_STACK_LOCATION                       *pIoStack )\r
+{\r
+       IOCTL_IBAT_IP_TO_PORT_IN        *pIn;\r
+       IOCTL_IBAT_IP_TO_PORT_OUT       *pOut;\r
+       KLOCK_QUEUE_HANDLE                      hdl;\r
+       cl_list_item_t                                  *pItem;\r
+       ipoib_adapter_t                         *pAdapter;\r
+       size_t                                          idx;\r
+       net_address_item_t                      *pAddr;\r
+       NTSTATUS status = STATUS_NOT_FOUND;\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+       if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+               sizeof(IOCTL_IBAT_IP_TO_PORT_IN) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid input buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+       \r
+       if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
+               sizeof(IOCTL_IBAT_IP_TO_PORT_OUT) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid output buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       pIn = pIrp->AssociatedIrp.SystemBuffer;\r
+       pOut = pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+       if( pIn->Version != IBAT_IOCTL_VERSION )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid version.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (pIn->Address.IpVersion != 4)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid IP version (%d). Supported only 4\n", pIn->Address.IpVersion) );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+       for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+               pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
+               pItem = cl_qlist_next( pItem ) )\r
+       {\r
+               pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+\r
+               cl_obj_lock( &pAdapter->obj );\r
+\r
+               for( idx = 0;\r
+                       idx < cl_vector_get_size( &pAdapter->ip_vector );\r
+                       idx++ )\r
+               {\r
+                       pAddr = (net_address_item_t*)\r
+                               cl_vector_get_ptr( &pAdapter->ip_vector, idx );\r
+\r
+                       if (!memcmp( &pIn->Address.Address[12], pAddr->address.as_bytes, IPV4_ADDR_SIZE))\r
+                       {\r
+                               pOut->Port.CaGuid = pAdapter->guids.ca_guid;\r
+                               pOut->Port.PortGuid = pAdapter->guids.port_guid.guid;\r
+                               pOut->Port.PKey = IB_DEFAULT_PKEY;\r
+                               pOut->Port.PortNum = pAdapter->guids.port_num;\r
+                               pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_TO_PORT_OUT);\r
+                               status = STATUS_SUCCESS;\r
+                               break;\r
+                       }\r
+               }\r
+               cl_obj_unlock( &pAdapter->obj );\r
+               if (status == STATUS_SUCCESS)\r
+                       break;\r
+       }\r
+\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return status;\r
+}\r
+\r
+void\r
+ipoib_ref_ibat()\r
+{\r
+       NTSTATUS                        status;\r
+       NDIS_STRING                     DeviceName;\r
+       NDIS_STRING                     DeviceLinkUnicodeString;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+       if( InterlockedIncrement( &g_ipoib.ibat_ref ) == 1 )\r
+       {\r
+               NdisInitUnicodeString( &DeviceName, IBAT_DEV_NAME );\r
+               NdisInitUnicodeString( &DeviceLinkUnicodeString, IBAT_DOS_DEV_NAME );\r
+\r
+               g_p_drv_obj->MajorFunction[IRP_MJ_CREATE] = __ipoib_create;\r
+               g_p_drv_obj->MajorFunction[IRP_MJ_CLEANUP] = __ipoib_cleanup;\r
+               g_p_drv_obj->MajorFunction[IRP_MJ_CLOSE] = __ipoib_close;\r
+               g_p_drv_obj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = __ipoib_dispatch;\r
+               g_p_drv_obj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = __ipoib_dispatch;\r
+               status = IoCreateDevice(g_p_drv_obj, 0,&DeviceName,\r
+               FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &g_ipoib.h_ibat_dev);\r
+\r
+               if( status != STATUS_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
+                               ("NdisMRegisterDevice failed with status of %d\n", status) );\r
+               }\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+}\r
+\r
+\r
+void\r
+ipoib_deref_ibat()\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+       if( InterlockedDecrement( &g_ipoib.ibat_ref ) )\r
+       {\r
+               IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+               return;\r
+       }\r
+\r
+       if( g_ipoib.h_ibat_dev )\r
+       {\r
+               IoDeleteDevice( g_ipoib.h_ibat_dev );\r
+               g_ipoib.h_ibat_dev = NULL;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ipoib_create(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+       UNREFERENCED_PARAMETER( pDevObj );\r
+\r
+       ipoib_ref_ibat();\r
+\r
+       pIrp->IoStatus.Status = STATUS_SUCCESS;\r
+       pIrp->IoStatus.Information = 0;\r
+       IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ipoib_cleanup(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+       UNREFERENCED_PARAMETER( pDevObj );\r
+\r
+       ipoib_deref_ibat();\r
+\r
+       pIrp->IoStatus.Status = STATUS_SUCCESS;\r
+       pIrp->IoStatus.Information = 0;\r
+       IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ipoib_close(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+       UNREFERENCED_PARAMETER( pDevObj );\r
+\r
+       pIrp->IoStatus.Status = STATUS_SUCCESS;\r
+       pIrp->IoStatus.Information = 0;\r
+       IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ipoib_dispatch(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp )\r
+{\r
+       IO_STACK_LOCATION       *pIoStack;\r
+       NTSTATUS                        status = STATUS_SUCCESS;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+       UNREFERENCED_PARAMETER( pDevObj );\r
+\r
+       pIoStack = IoGetCurrentIrpStackLocation( pIrp );\r
+\r
+       pIrp->IoStatus.Information = 0;\r
+\r
+       switch( pIoStack->Parameters.DeviceIoControl.IoControlCode )\r
+       {\r
+       case IOCTL_IBAT_PORTS:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+                       ("IOCTL_IBAT_PORTS received\n") );\r
+               status = __ibat_get_ports( pIrp, pIoStack );\r
+               break;\r
+\r
+       case IOCTL_IBAT_IP_ADDRESSES:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+                       ("IOCTL_IBAT_IP_ADDRESSES received\n" ));\r
+               status = __ibat_get_ips( pIrp, pIoStack );\r
+               break;\r
+\r
+       case IOCTL_IBAT_MAC_TO_GID:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+                       ("IOCTL_IBAT_MAC_TO_GID received\n" ));\r
+               status = __ibat_mac_to_gid( pIrp, pIoStack );\r
+               break;\r
+\r
+       case IOCTL_IBAT_IP_TO_PORT:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+                       ("IOCTL_IBAT_IP_TO_PORT received\n" ));\r
+               status = __ibat_ip_to_port( pIrp, pIoStack );\r
+               break;\r
+\r
+       case IOCTL_IBAT_MAC_TO_PATH:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+                       ("IOCTL_IBAT_MAC_TO_PATH received\n" ));\r
+               status = __ibat_mac_to_path( pIrp, pIoStack );\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_IOCTL,\r
+                       ("unknow IOCTL code = 0x%x\n",\r
+                       pIoStack->Parameters.DeviceIoControl.IoControlCode) );\r
+               status = STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       pIrp->IoStatus.Status = status;\r
+       IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return status;\r
+}\r
+\r
+\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_ibat.h b/trunk/ulp/ipoib/kernel6/ipoib_ibat.h
new file mode 100644 (file)
index 0000000..efcb0a6
--- /dev/null
@@ -0,0 +1,45 @@
+/*\r
+ * Copyright (c) 2005 Mellanox Technologies.  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
+ * $Id: ipoib_ibat.h 1611 2006-08-20 14:48:55Z sleybo $\r
+ */\r
+\r
+\r
+#ifndef _IPOIB_IBAT_H_\r
+#define _IPOIB_IBAT_H_\r
+\r
+\r
+void\r
+ipoib_ref_ibat();\r
+\r
+void\r
+ipoib_deref_ibat();\r
+\r
+\r
+#endif /* _IPOIB_IBAT_H_ */\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_log.mc b/trunk/ulp/ipoib/kernel6/ipoib_log.mc
new file mode 100644 (file)
index 0000000..bb7d1c1
--- /dev/null
@@ -0,0 +1,334 @@
+;/*++\r
+;=============================================================================\r
+;Copyright (c) 2001 Mellanox Technologies\r
+;\r
+;Module Name:\r
+;\r
+;    ipoiblog.mc\r
+;\r
+;Abstract:\r
+;\r
+;    IPoIB Driver event log messages\r
+;\r
+;Authors:\r
+;\r
+;    Yossi Leybovich\r
+;\r
+;Environment:\r
+;\r
+;   Kernel Mode .\r
+;\r
+;=============================================================================\r
+;--*/\r
+;\r
+MessageIdTypedef = NDIS_ERROR_CODE\r
+\r
+SeverityNames = (\r
+       Success                 = 0x0:STATUS_SEVERITY_SUCCESS\r
+       Informational   = 0x1:STATUS_SEVERITY_INFORMATIONAL\r
+       Warning                 = 0x2:STATUS_SEVERITY_WARNING\r
+       Error                   = 0x3:STATUS_SEVERITY_ERROR\r
+       )\r
+\r
+FacilityNames = (\r
+       System                  = 0x0\r
+       RpcRuntime              = 0x2:FACILITY_RPC_RUNTIME\r
+       RpcStubs                = 0x3:FACILITY_RPC_STUBS\r
+       Io                              = 0x4:FACILITY_IO_ERROR_CODE\r
+       IPoIB                   = 0x7:FACILITY_IPOIB_ERROR_CODE\r
+       )\r
+\r
+\r
+MessageId=0x0001\r
+Facility=IPoIB\r
+Severity=Warning\r
+SymbolicName=EVENT_IPOIB_PORT_DOWN\r
+Language=English\r
+%2: Network controller link is down.\r
+.\r
+\r
+MessageId=0x0002\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP\r
+Language=English\r
+%2: Network controller link is up.\r
+.\r
+\r
+\r
+MessageId=0x0003\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP1\r
+Language=English\r
+%2: Network controller link is up at 2.5Gbps.\r
+.\r
+\r
+MessageId=0x0004\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP2\r
+Language=English\r
+%2: Network controller link is up at 5Gbps.\r
+.\r
+\r
+MessageId=0x0006\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP3\r
+Language=English\r
+%2: Network controller link is up at 10Gbps.\r
+.\r
+\r
+MessageId=0x000a\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP4\r
+Language=English\r
+%2: Network controller link is up at 20Gps.\r
+.\r
+\r
+MessageId=0x000e\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP5\r
+Language=English\r
+%2: Network controller link is up at 30Gps.\r
+.\r
+\r
+MessageId=0x0012\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP6\r
+Language=English\r
+%2: Network controller link is up at 40Gps.\r
+.\r
+\r
+MessageId=0x001a\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP7\r
+Language=English\r
+%2: Network controller link is up at 60Gps.\r
+.\r
+\r
+MessageId=0x0032\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP8\r
+Language=English\r
+%2: Network controller link is up at 120Gps.\r
+.\r
+\r
+MessageId=0x0040\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_INIT_SUCCESS\r
+Language=English\r
+%2: Driver Initialized succesfully.\r
+.\r
+\r
+MessageId=0x0041\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_OPEN_CA\r
+Language=English\r
+%2: Failed to open Channel Adapter.\r
+.\r
+\r
+MessageId=0x0042\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_ALLOC_PD\r
+Language=English\r
+%2: Failed to allocate Protection Domain.\r
+.\r
+\r
+MessageId=0x0043\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_CREATE_RECV_CQ\r
+Language=English\r
+%2: Failed to create receive Completion Queue.\r
+.\r
+\r
+MessageId=0x0044\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_CREATE_SEND_CQ\r
+Language=English\r
+%2: Failed to create send Completion Queue.\r
+.\r
+\r
+MessageId=0x0045\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_CREATE_QP\r
+Language=English\r
+%2: Failed to create Queue Pair.\r
+.\r
+\r
+MessageId=0x0046\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_QUERY_QP\r
+Language=English\r
+%2: Failed to get Queue Pair number.\r
+.\r
+\r
+MessageId=0x0047\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_REG_PHYS\r
+Language=English\r
+%2: Failed to create DMA Memory Region.\r
+.\r
+\r
+MessageId=0x0048\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_RECV_POOL\r
+Language=English\r
+%2: Failed to create receive descriptor pool.\r
+.\r
+\r
+MessageId=0x0049\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_RECV_PKT_POOL\r
+Language=English\r
+%2: Failed to create NDIS_PACKET pool for receive indications.\r
+.\r
+\r
+MessageId=0x004A\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_RECV_BUF_POOL\r
+Language=English\r
+%2: Failed to create NDIS_BUFFER pool for receive indications.\r
+.\r
+\r
+MessageId=0x004B\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_SEND_PKT_POOL\r
+Language=English\r
+%2: Failed to create NDIS_PACKET pool for send processing.\r
+.\r
+\r
+MessageId=0x004C\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_SEND_BUF_POOL\r
+Language=English\r
+%2: Failed to create NDIS_BUFFER pool for send processing.\r
+.\r
+\r
+MessageId=0x004D\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_RECV_PKT_ARRAY\r
+Language=English\r
+%2: Failed to allocate receive indication array.\r
+.\r
+\r
+MessageId=0x004E\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_PORT_INFO_TIMEOUT\r
+Language=English\r
+%2: Subnet Administrator query for port information timed out. \r
+Make sure the SA is functioning properly.  Increasing the number\r
+of retries and retry timeout adapter parameters may solve the\r
+issue.\r
+.\r
+\r
+MessageId=0x004F\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_PORT_INFO_REJECT\r
+Language=English\r
+%2: Subnet Administrator failed the query for port information.\r
+Make sure the SA is functioning properly and compatible.\r
+.\r
+\r
+MessageId=0x0050\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_QUERY_PORT_INFO\r
+Language=English\r
+%2: Subnet Administrator query for port information failed.\r
+.\r
+\r
+MessageId=0x0055\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_BCAST_GET\r
+Language=English\r
+%2: Subnet Administrator failed query for broadcast group information.\r
+.\r
+\r
+MessageId=0x0056\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_BCAST_JOIN\r
+Language=English\r
+%2: Subnet Administrator failed request to joing broadcast group.\r
+.\r
+\r
+MessageId=0x0057\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_BCAST_RATE\r
+Language=English\r
+%2: The local port rate is too slow for the existing broadcast MC group.\r
+.\r
+\r
+MessageId=0x0058\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_WRONG_PARAMETER_ERR\r
+Language=English\r
+%2: Incorrect value or non-existing registry  for the required IPoIB parameter %3, overriding it by default value: %4\r
+.\r
+\r
+MessageId=0x0059\r
+Facility=IPoIB\r
+Severity=Warning\r
+SymbolicName=EVENT_IPOIB_WRONG_PARAMETER_WRN\r
+Language=English\r
+%2: Incorrect value or non-existing registry entry  for the required IPoIB parameter %3, overriding it by default value: %4\r
+.\r
+\r
+MessageId=0x005A\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_WRONG_PARAMETER_INFO\r
+Language=English\r
+%2: Incorrect value or non-existing registry  for the optional IPoIB parameter %3, overriding it by default value: %4\r
+.\r
+\r
+MessageId=0x005B\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_PARTITION_ERR\r
+Language=English\r
+%2: Pkey index not found for partition , change switch pkey configuration.\r
+.\r
+\r
+MessageId=0x005C\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_CONNECTED_MODE_ERR\r
+Language=English\r
+%2: Connected Mode failed to initialize, disabled. Interface will use default UD QP transport.\r
+.\r
+\r
+MessageId=0x005D\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_CONNECTED_MODE_UP\r
+Language=English\r
+%2: Connected Mode initialized and operational.\r
+.\r
+\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_port.c b/trunk/ulp/ipoib/kernel6/ipoib_port.c
new file mode 100644 (file)
index 0000000..da57d2c
--- /dev/null
@@ -0,0 +1,8098 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_port.c 4226 2009-04-06 06:01:03Z xalex $\r
+ */\r
+\r
+\r
+\r
+#include "ipoib_endpoint.h"\r
+#include "ipoib_port.h"\r
+#include "ipoib_adapter.h"\r
+#include "ipoib_debug.h"\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_port.tmh"\r
+#endif\r
+#include <offload.h>\r
+\r
+#include "wdm.h"\r
+#include <ntddk.h>\r
+\r
+\r
+\r
+ib_gid_t       bcast_mgid_template = {\r
+       0xff,                                                           /* multicast field */\r
+       0x12,                                                           /* scope (to be filled in) */\r
+       0x40, 0x1b,                                                     /* IPv4 signature */\r
+       0xff, 0xff,                                                     /* 16 bits of P_Key (to be filled in) */\r
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     /* 48 bits of zeros */\r
+       0xff, 0xff, 0xff, 0xff,                         /* 32 bit IPv4 broadcast address */\r
+};\r
+\r
+\r
+#ifdef _DEBUG_\r
+/* Handy pointer for debug use. */\r
+ipoib_port_t   *gp_ipoib_port;\r
+#endif\r
+\r
+static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2);\r
+static void __port_do_mcast_garbage(ipoib_port_t* const        p_port );\r
+\r
+\r
+static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2);\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Declarations\r
+*\r
+******************************************************************************/\r
+static void\r
+__port_construct(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static ib_api_status_t\r
+__port_init(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              ib_pnp_port_rec_t* const        p_pnp_rec );\r
+\r
+static void\r
+__port_destroying(\r
+       IN                              cl_obj_t* const                         p_obj );\r
+\r
+static void\r
+__port_cleanup(\r
+       IN                              cl_obj_t* const                         p_obj );\r
+\r
+static void\r
+__port_free(\r
+       IN                              cl_obj_t* const                         p_obj );\r
+\r
+static ib_api_status_t\r
+__port_query_ca_attrs( \r
+       IN              ipoib_port_t* const                                     p_port,\r
+       IN              ib_ca_attr_t**                                          pp_ca_attrs );\r
+\r
+static void\r
+__srq_async_event_cb(\r
+IN                     ib_async_event_rec_t            *p_event_rec );\r
+\r
+/******************************************************************************\r
+*\r
+* IB resource manager operations\r
+*\r
+******************************************************************************/\r
+static void\r
+__ib_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static ib_api_status_t\r
+__ib_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__ib_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__qp_event(\r
+       IN                              ib_async_event_rec_t            *p_event_rec );\r
+\r
+static void\r
+__cq_event(\r
+       IN                              ib_async_event_rec_t            *p_event_rec );\r
+\r
+static ib_api_status_t\r
+__ib_mgr_activate(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+/******************************************************************************\r
+*\r
+* Buffer manager operations.\r
+*\r
+******************************************************************************/\r
+static void\r
+__buf_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static ib_api_status_t\r
+__buf_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__buf_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static cl_status_t\r
+__recv_ctor(\r
+       IN                              void* const                                     p_object,\r
+       IN                              void*                                           context,\r
+               OUT                     cl_pool_item_t** const          pp_pool_item );\r
+\r
+#if !IPOIB_INLINE_RECV\r
+static void\r
+__recv_dtor(\r
+       IN              const   cl_pool_item_t* const           p_pool_item,\r
+       IN                              void                                            *context );\r
+#endif /* IPOIB_INLINE_RECV */\r
+\r
+static inline ipoib_send_desc_t*\r
+__buf_mgr_get_send(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static inline void\r
+__buf_mgr_put_send(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc );\r
+\r
+static inline ipoib_recv_desc_t*\r
+__buf_mgr_get_recv(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static inline void\r
+__buf_mgr_put_recv(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc,\r
+       IN                              NET_BUFFER_LIST* const          p_net_buffer_list OPTIONAL );\r
+\r
+static inline void\r
+__buf_mgr_put_recv_list(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              cl_qlist_t* const                       p_list );\r
+\r
+//NDIS60\r
+static inline NET_BUFFER_LIST*\r
+__buf_mgr_get_ndis_pkt(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc );\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Receive manager operations.\r
+*\r
+******************************************************************************/\r
+static void\r
+__recv_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static ib_api_status_t\r
+__recv_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__recv_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+/* Posts receive buffers to the receive queue. */\r
+static ib_api_status_t\r
+__recv_mgr_repost(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__recv_cb(\r
+       IN              const   ib_cq_handle_t                          h_cq,\r
+       IN                              void                                            *cq_context );\r
+\r
+static void\r
+__recv_get_endpts(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc,\r
+       IN                              ib_wc_t* const                          p_wc,\r
+               OUT                     ipoib_endpt_t** const           pp_src,\r
+               OUT                     ipoib_endpt_t** const           pp_dst );\r
+\r
+static int32_t\r
+__recv_mgr_filter(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_wc_t* const                          p_done_wc_list,\r
+               OUT                     cl_qlist_t* const                       p_done_list,\r
+               OUT                     cl_qlist_t* const                       p_bad_list );\r
+\r
+static ib_api_status_t\r
+__recv_gen(\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t* const            p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst );\r
+\r
+static ib_api_status_t\r
+__recv_dhcp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t* const            p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst );\r
+\r
+static ib_api_status_t\r
+__recv_arp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_wc_t* const                          p_wc,\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t** const           p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst );\r
+\r
+static ib_api_status_t\r
+__recv_mgr_prepare_pkt(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc,\r
+               OUT                     NET_BUFFER_LIST** const         pp_net_buffer_list );\r
+\r
+static uint32_t\r
+__recv_mgr_build_pkt_array(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              int32_t                                         shortage,\r
+               OUT                     cl_qlist_t* const                       p_done_list,\r
+               OUT                     int32_t* const                          p_discarded );\r
+\r
+/******************************************************************************\r
+*\r
+* Send manager operations.\r
+*\r
+******************************************************************************/\r
+static void\r
+__send_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__send_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static NDIS_STATUS\r
+__send_gen(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN                              INT                                             lso_data_index);\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_ip(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc );\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_igmp_v2(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+    IN         const   ip_hdr_t* const                         p_ip_hdr,\r
+       IN                              size_t                                          iph_options_size,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len );\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_udp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ip_hdr_t* const                         p_ip_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc );\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_dhcp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   udp_hdr_t* const                        p_udp_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc );\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_arp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc );\r
+\r
+static void\r
+__process_failed_send(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc,\r
+       IN              const   NDIS_STATUS                                     status,\r
+       IN              ULONG                                           send_complete_flags );\r
+\r
+static inline NDIS_STATUS\r
+__send_mgr_queue(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              eth_hdr_t* const                        p_eth_hdr,\r
+               OUT                     ipoib_endpt_t** const           pp_endpt );\r
+\r
+static NDIS_STATUS\r
+__build_send_desc(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL* const                                      p_mdl,\r
+       IN              const   size_t                                          mdl_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc );\r
+\r
+\r
+static void\r
+__send_cb(\r
+       IN              const   ib_cq_handle_t                          h_cq,\r
+       IN                              void                                            *cq_context );\r
+\r
+static NDIS_STATUS \r
+GetLsoHeaderSize(\r
+       IN              PNET_BUFFER             pNetBuffer,\r
+       IN              LsoData                 *pLsoData,\r
+       OUT     UINT                    *IndexOfData,\r
+       IN              ipoib_hdr_t *ipoib_hdr );\r
+\r
+\r
+static NDIS_STATUS\r
+__build_lso_desc(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc,\r
+       IN                              ULONG                                           mss,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN                              int32_t                                         hdr_idx,\r
+       IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info );\r
+\r
+static NDIS_STATUS\r
+__send_fragments(\r
+       IN              ipoib_port_t* const                                     p_port,\r
+       IN              ipoib_send_desc_t* const                        p_desc,\r
+       IN              eth_hdr_t* const                                        p_eth_hdr,\r
+       IN              ip_hdr_t* const                                         p_ip_hdr,\r
+       IN              uint32_t                                                        buf_len,\r
+       IN              NDIS_BUFFER*                                            p_ndis_buf );\r
+\r
+static void\r
+__update_fragment_ip_hdr(\r
+IN             ip_hdr_t* const         p_ip_hdr,\r
+IN             uint16_t                        fragment_size, \r
+IN             uint16_t                        fragment_offset, \r
+IN             BOOLEAN                         more_fragments );\r
+\r
+static void\r
+__copy_ip_options(\r
+IN             uint8_t*                        p_buf,\r
+IN             uint8_t*                        p_options,\r
+IN             uint32_t                        options_len,\r
+IN             BOOLEAN                         copy_all );\r
+/******************************************************************************\r
+*\r
+* Endpoint manager operations\r
+*\r
+******************************************************************************/\r
+static void\r
+__endpt_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__endpt_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+/****f* IPoIB/__endpt_mgr_remove_all\r
+* NAME\r
+*      __endpt_mgr_remove_all\r
+*\r
+* DESCRIPTION\r
+*      Removes all enpoints from the port, dereferencing them to initiate\r
+*      destruction.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static void\r
+__endpt_mgr_remove_all(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+/*\r
+********/\r
+\r
+static void\r
+__endpt_mgr_remove(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_endpt_t* const            p_endpt );\r
+\r
+static void\r
+__endpt_mgr_reset_all(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static inline NDIS_STATUS\r
+__endpt_mgr_ref(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ipoib_endpt_t** const           pp_endpt );\r
+\r
+static inline NDIS_STATUS\r
+__endpt_mgr_get_gid_qpn(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ib_gid_t* const                         p_gid,\r
+               OUT                     UNALIGNED net32_t* const        p_qpn );\r
+\r
+static inline ipoib_endpt_t*\r
+__endpt_mgr_get_by_gid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ib_gid_t* const                         p_gid );\r
+\r
+static inline ipoib_endpt_t*\r
+__endpt_mgr_get_by_lid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   net16_t                                         lid );\r
+\r
+static inline ib_api_status_t\r
+__endpt_mgr_insert_locked(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+       IN                              ipoib_endpt_t* const            p_endpt );\r
+\r
+static inline ib_api_status_t\r
+__endpt_mgr_insert(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+       IN                              ipoib_endpt_t* const            p_endpt );\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_add_local(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_port_info_t* const           p_port_info );\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_add_bcast(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_mcast_rec_t                          *p_mcast_rec );\r
+\r
+/******************************************************************************\r
+*\r
+* MCast operations.\r
+*\r
+******************************************************************************/\r
+static ib_api_status_t\r
+__port_get_bcast(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static ib_api_status_t\r
+__port_join_bcast(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_member_rec_t* const          p_member_rec );\r
+\r
+static ib_api_status_t\r
+__port_create_bcast(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+\r
+\r
+static void\r
+__bcast_get_cb(\r
+       IN                              ib_query_rec_t                          *p_query_rec );\r
+\r
+\r
+static void\r
+__bcast_cb(\r
+       IN                              ib_mcast_rec_t                          *p_mcast_rec );\r
+\r
+\r
+static void\r
+__mcast_cb(\r
+       IN                              ib_mcast_rec_t                          *p_mcast_rec );\r
+\r
+void\r
+__leave_error_mcast_cb(\r
+       IN                              void                            *context );\r
+\r
+\r
+static intn_t\r
+__gid_cmp(\r
+       IN              const   void* const                                     p_key1,\r
+       IN              const   void* const                                     p_key2 )\r
+{\r
+       return cl_memcmp( p_key1, p_key2, sizeof(ib_gid_t) );\r
+}\r
+\r
+\r
+inline void ipoib_port_ref( ipoib_port_t * p_port, int type )\r
+{\r
+       cl_obj_ref( &p_port->obj );\r
+#if DBG\r
+       cl_atomic_inc( &p_port->ref[type % ref_mask] );\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
+               ("ref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) );\r
+#else\r
+       UNREFERENCED_PARAMETER(type);\r
+#endif\r
+}\r
+\r
+\r
+inline void ipoib_port_deref(ipoib_port_t * p_port, int type)\r
+{\r
+#if DBG\r
+       cl_atomic_dec( &p_port->ref[type % ref_mask] );\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
+               ("deref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) );\r
+#else\r
+       UNREFERENCED_PARAMETER(type);\r
+#endif\r
+       cl_obj_deref( &p_port->obj );\r
+\r
+}\r
+\r
+/* function returns pointer to payload that is going after IP header.\r
+*  asssuming that payload and IP header are in the same buffer\r
+*/\r
+static void* GetIpPayloadPtr(const     ip_hdr_t* const p_ip_hdr)\r
+{\r
+       return (void*)((uint8_t*)p_ip_hdr + IP_HEADER_LENGTH(p_ip_hdr));\r
+}\r
+\r
+/******************************************************************************\r
+*\r
+* Implementation\r
+*\r
+******************************************************************************/\r
+ib_api_status_t\r
+ipoib_create_port(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              ib_pnp_port_rec_t* const        p_pnp_rec,\r
+               OUT                     ipoib_port_t** const            pp_port )\r
+{\r
+       ib_api_status_t         status;\r
+       ipoib_port_t            *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( !p_adapter->p_port );\r
+\r
+       p_port = cl_zalloc( sizeof(ipoib_port_t) +\r
+               (sizeof(ipoib_hdr_t) * (p_adapter->params.sq_depth - 1)) );\r
+       if( !p_port )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate ipoib_port_t (%d bytes)\n",\r
+                       sizeof(ipoib_port_t)) );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+#ifdef _DEBUG_\r
+       gp_ipoib_port = p_port;\r
+#endif\r
+\r
+       __port_construct( p_port );\r
+\r
+       status = __port_init( p_port, p_adapter, p_pnp_rec );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_port_init returned %s.\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               __port_cleanup( &p_port->obj );\r
+               __port_free( &p_port->obj );\r
+               return status;\r
+       }\r
+\r
+       *pp_port = p_port;\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+ipoib_port_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_port );\r
+       CL_ASSERT( p_port->p_adapter );\r
+       CL_ASSERT( !p_port->p_adapter->p_port );\r
+\r
+       cl_obj_destroy( &p_port->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__port_construct(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_port->state = IB_QPS_RESET;\r
+\r
+       cl_obj_construct( &p_port->obj, IPOIB_OBJ_PORT );\r
+       cl_spinlock_construct( &p_port->send_lock );\r
+       cl_spinlock_construct( &p_port->recv_lock );\r
+       __ib_mgr_construct( p_port );\r
+       __buf_mgr_construct( p_port );\r
+\r
+       __recv_mgr_construct( p_port );\r
+       __send_mgr_construct( p_port );\r
+\r
+       __endpt_mgr_construct( p_port );\r
+\r
+       KeInitializeEvent( &p_port->sa_event, NotificationEvent, TRUE );\r
+       KeInitializeEvent( &p_port->leave_mcast_event, NotificationEvent, TRUE );\r
+       \r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__port_init(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              ib_pnp_port_rec_t* const        p_pnp_rec )\r
+{\r
+       cl_status_t                     cl_status;\r
+       ib_api_status_t         status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_port->port_num = p_pnp_rec->p_port_attr->port_num;\r
+       p_port->p_adapter = p_adapter;\r
+\r
+       cl_status = cl_spinlock_init( &p_port->send_lock );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_spinlock_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       cl_status = cl_spinlock_init( &p_port->recv_lock );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_spinlock_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       /* Initialize the IB resource manager. */\r
+       status = __ib_mgr_init( p_port );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__ib_mgr_init returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Initialize the buffer manager. */\r
+       status = __buf_mgr_init( p_port );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__buf_mgr_init returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Initialize the receive manager. */\r
+       status = __recv_mgr_init( p_port );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__recv_mgr_init returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Initialize the endpoint manager. */\r
+       status = __endpt_mgr_init( p_port );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__endpt_mgr_init returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+        KeInitializeDpc(&p_port->recv_dpc,(PKDEFERRED_ROUTINE)__recv_cb_dpc,p_port);\r
+\r
+\r
+        /* Initialize multicast garbage collector timer and DPC object */\r
+        KeInitializeDpc(&p_port->gc_dpc,(PKDEFERRED_ROUTINE)__port_mcast_garbage_dpc,p_port);\r
+        KeInitializeTimerEx(&p_port->gc_timer,SynchronizationTimer);\r
+\r
+       /* We only ever destroy from the PnP callback thread. */\r
+       cl_status = cl_obj_init( &p_port->obj, CL_DESTROY_SYNC,\r
+               __port_destroying, __port_cleanup, __port_free );\r
+\r
+#if DBG\r
+       cl_atomic_inc( &p_port->ref[ref_init] );\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
+               ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) );\r
+#endif\r
+\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_obj_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       cl_status = cl_obj_insert_rel( &p_port->rel, &p_adapter->obj, &p_port->obj );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_obj_insert_rel returned %#x\n", cl_status) );\r
+               cl_obj_destroy( &p_port->obj );\r
+               return IB_ERROR;\r
+       }\r
+\r
+#if DBG\r
+       cl_atomic_inc( &p_port->ref[ref_init] );\r
+       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OBJ,\r
+               ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) );\r
+#endif\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+__port_destroying(\r
+       IN                              cl_obj_t* const                         p_obj )\r
+{\r
+       ipoib_port_t    *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_obj );\r
+\r
+       p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
+\r
+       ipoib_port_down( p_port );\r
+\r
+       __endpt_mgr_remove_all( p_port );\r
+\r
+#if 0\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               endpt_cm_buf_mgr_destroy(  p_port );\r
+               ipoib_port_srq_destroy( p_port );\r
+               p_port->endpt_mgr.thread_is_done = 1;\r
+               cl_event_signal( &p_port->endpt_mgr.event );\r
+       }\r
+#endif\r
+       ASSERT(FALSE);\r
+       //TODO NDIS6.0\r
+       ipoib_port_resume( p_port, FALSE );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__port_cleanup(\r
+       IN                              cl_obj_t* const                         p_obj )\r
+{\r
+       ipoib_port_t    *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_obj );\r
+\r
+       p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
+\r
+       /* Wait for all sends and receives to get flushed. */\r
+       while( p_port->send_mgr.depth || p_port->recv_mgr.depth )\r
+               cl_thread_suspend( 0 );\r
+\r
+       /* Destroy the send and receive managers before closing the CA. */\r
+       __ib_mgr_destroy( p_port );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__port_free(\r
+       IN                              cl_obj_t* const                         p_obj )\r
+{\r
+       ipoib_port_t    *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_obj );\r
+\r
+       p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
+\r
+       KeCancelTimer(&p_port->gc_timer);\r
+       KeFlushQueuedDpcs();\r
+       __endpt_mgr_destroy( p_port );\r
+       __recv_mgr_destroy( p_port );\r
+       __send_mgr_destroy( p_port );\r
+       __buf_mgr_destroy( p_port );\r
+\r
+       cl_spinlock_destroy( &p_port->send_lock );\r
+       cl_spinlock_destroy( &p_port->recv_lock );\r
+\r
+       cl_obj_deinit( p_obj );\r
+       if( p_port->p_ca_attrs )\r
+       {\r
+               cl_free ( p_port->p_ca_attrs );\r
+       }\r
+       cl_free( p_port );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* IB resource manager implementation.\r
+*\r
+******************************************************************************/\r
+static void\r
+__ib_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       cl_memclr( &p_port->ib_mgr, sizeof(ipoib_ib_mgr_t) );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__ib_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_cq_create_t          cq_create;\r
+       ib_qp_create_t          qp_create;\r
+       ib_phys_create_t        phys_create;\r
+       ib_phys_range_t         phys_range;\r
+       uint64_t                        vaddr;\r
+       net32_t                         rkey;\r
+       ib_qp_attr_t            qp_attr;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /* Open the CA. */\r
+       status = p_port->p_adapter->p_ifc->open_ca(\r
+               p_port->p_adapter->h_al, p_port->p_adapter->guids.ca_guid,\r
+               NULL, p_port, &p_port->ib_mgr.h_ca );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_OPEN_CA, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_open_ca returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       status = __port_query_ca_attrs( p_port, &p_port->p_ca_attrs );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Query CA attributes failed\n" ) );\r
+               return status;\r
+       }\r
+#if 0\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               uint32_t payload_mtu = __port_attr_to_mtu_size( \r
+                       p_port->p_ca_attrs->p_port_attr[p_port->port_num - 1].mtu )\r
+                       - sizeof(ipoib_hdr_t);\r
+               /* adjust ipoib UD payload MTU to actual port MTU size. */\r
+               p_port->p_adapter->params.payload_mtu = \r
+                               max( DEFAULT_PAYLOAD_MTU, payload_mtu );\r
+               p_port->p_adapter->params.xfer_block_size = \r
+                       (sizeof(eth_hdr_t) + p_port->p_adapter->params.payload_mtu);\r
+       }\r
+#endif\r
+#if IPOIB_USE_DMA\r
+       /* init DMA only once while running MiniportInitialize */\r
+       if ( !p_port->p_adapter->reset )\r
+       {\r
+               ULONG max_phys_mapping;\r
+               if( p_port->p_adapter->params.cm_enabled )\r
+               {\r
+                       max_phys_mapping = p_port->p_adapter->params.cm_xfer_block_size;\r
+               }\r
+               else if( p_port->p_adapter->params.lso )\r
+               {\r
+                       max_phys_mapping = LARGE_SEND_OFFLOAD_SIZE;\r
+               }\r
+               else\r
+               {\r
+                       max_phys_mapping = p_port->p_adapter->params.xfer_block_size;\r
+               }\r
+               /*if( NdisMInitializeScatterGatherDma( p_port->p_adapter->h_adapter,\r
+                                                       TRUE, max_phys_mapping )!= NDIS_STATUS_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("NdisMInitializeScatterGatherDma failed\n" ) );\r
+                       return IB_INSUFFICIENT_RESOURCES;\r
+               }*/\r
+       }\r
+#endif\r
+\r
+       /* Allocate the PD. */\r
+       status = p_port->p_adapter->p_ifc->alloc_pd(\r
+               p_port->ib_mgr.h_ca, IB_PDT_UD, p_port, &p_port->ib_mgr.h_pd );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_ALLOC_PD, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_alloc_pd returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Allocate receive CQ. */\r
+       cq_create.size = p_port->p_adapter->params.rq_depth;\r
+       cq_create.pfn_comp_cb = __recv_cb;\r
+       cq_create.h_wait_obj = NULL;\r
+\r
+       status = p_port->p_adapter->p_ifc->create_cq(\r
+               p_port->ib_mgr.h_ca, &cq_create, p_port,\r
+               __cq_event, &p_port->ib_mgr.h_recv_cq );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_CREATE_RECV_CQ, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_cq returned %s.\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Allocate send CQ. */\r
+       cq_create.size = p_port->p_adapter->params.sq_depth;\r
+       cq_create.pfn_comp_cb = __send_cb;\r
+\r
+       status = p_port->p_adapter->p_ifc->create_cq(\r
+               p_port->ib_mgr.h_ca, &cq_create, p_port,\r
+               __cq_event, &p_port->ib_mgr.h_send_cq );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_CREATE_SEND_CQ, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_cq returned %s.\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+       \r
+       /* Allocate the QP. */\r
+       cl_memclr( &qp_create, sizeof(qp_create) );\r
+       qp_create.qp_type = IB_QPT_UNRELIABLE_DGRM;\r
+       qp_create.rq_depth = p_port->p_adapter->params.rq_depth;\r
+       qp_create.rq_sge = 2;   /* To support buffers spanning pages. */\r
+       qp_create.h_rq_cq = p_port->ib_mgr.h_recv_cq;\r
+       qp_create.sq_depth = p_port->p_adapter->params.sq_depth;\r
+\r
+#define UD_QP_USED_SGE 3\r
+       qp_create.sq_sge = MAX_SEND_SGE < p_port->p_ca_attrs->max_sges ? \r
+                       MAX_SEND_SGE  : ( p_port->p_ca_attrs->max_sges - UD_QP_USED_SGE );\r
+       if ( !p_port->p_ca_attrs->ipoib_csum ) \r
+       { \r
+               /* checksum is not supported by device\r
+               user must specify BYPASS to explicitly cancel checksum calculation */\r
+               if (p_port->p_adapter->params.send_chksum_offload == CSUM_ENABLED)\r
+                       p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED;\r
+               if (p_port->p_adapter->params.recv_chksum_offload == CSUM_ENABLED)\r
+                       p_port->p_adapter->params.recv_chksum_offload = CSUM_DISABLED;\r
+       }\r
+\r
+       qp_create.h_sq_cq = p_port->ib_mgr.h_send_cq;\r
+       qp_create.sq_signaled = FALSE;\r
+       status = p_port->p_adapter->p_ifc->create_qp(\r
+               p_port->ib_mgr.h_pd, &qp_create, p_port,\r
+               __qp_event, &p_port->ib_mgr.h_qp );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_CREATE_QP, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_qp returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+       /* Query the QP so we can get our QPN. */\r
+       status = p_port->p_adapter->p_ifc->query_qp(\r
+               p_port->ib_mgr.h_qp, &qp_attr );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_QUERY_QP, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_query_qp returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+       p_port->ib_mgr.qpn = qp_attr.num;\r
+\r
+       /* Register all of physical memory */\r
+       phys_create.length = MEM_REG_SIZE;\r
+       phys_create.num_ranges = 1;\r
+       phys_create.range_array = &phys_range;\r
+       phys_create.buf_offset = 0;\r
+       phys_create.hca_page_size = PAGE_SIZE;\r
+       phys_create.access_ctrl = IB_AC_LOCAL_WRITE;\r
+       phys_range.base_addr = 0;\r
+       phys_range.size = MEM_REG_SIZE;\r
+       vaddr = 0;\r
+       status = p_port->p_adapter->p_ifc->reg_phys(\r
+               p_port->ib_mgr.h_pd, &phys_create, &vaddr,\r
+               &p_port->ib_mgr.lkey, &rkey, &p_port->ib_mgr.h_mr );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_REG_PHYS, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_reg_phys returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       status = ipoib_port_srq_init( p_port );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_port_srq_init failed %s\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               /* disable further CM initialization */\r
+               p_port->p_adapter->params.cm_enabled = FALSE;\r
+\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                               EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de1 );\r
+\r
+       }\r
+//CM\r
+#if 0\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               status = endpt_cm_buf_mgr_init( p_port );\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("CM Init buf mgr failed status %#x\n", status ) );\r
+                       ipoib_port_srq_destroy( p_port );\r
+                       p_port->p_adapter->params.cm_enabled = FALSE;\r
+\r
+                       NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                               EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de2 );\r
+               }\r
+               else \r
+               {\r
+                       if ( p_port->p_adapter->params.send_chksum_offload )\r
+                       p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED;\r
+               }\r
+       }\r
+#endif\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+static void\r
+__srq_async_event_cb(\r
+IN                     ib_async_event_rec_t            *p_event_rec )\r
+{\r
+       ipoib_port_t* p_port = \r
+               (ipoib_port_t *)p_event_rec->context;\r
+\r
+       switch( p_event_rec->code )\r
+       {\r
+       case IB_AE_SRQ_LIMIT_REACHED:\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("SRQ ASYNC EVENT CODE %d: %s\n", \r
+                       p_event_rec->code, "IB_AE_SRQ_LIMIT_REACHED" ) );\r
+                       break;\r
+       case IB_AE_SRQ_CATAS_ERROR:\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("SRQ ASYNC EVENT CODE %d: %s\n", \r
+                               p_event_rec->code, "IB_AE_SRQ_CATAS_ERROR" ) );\r
+                       /*SRQ is in err state, must reinitialize */\r
+                       p_port->p_adapter->hung = TRUE;\r
+                       break;\r
+       case IB_AE_SRQ_QP_LAST_WQE_REACHED:\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("SRQ ASYNC EVENT CODE %d: %s\n", \r
+                               p_event_rec->code, "IB_AE_SRQ_QP_LAST_WQE_REACHED" ) );\r
+                       /*SRQ is in err state, must reinitialize */\r
+                       p_port->p_adapter->hung = TRUE;\r
+                       break;\r
+       default:\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ASYNC EVENT CODE ARRIVED %d(%#x)\n", \r
+                               p_event_rec->code, p_event_rec->code ) );\r
+       }\r
+}\r
+\r
+ib_api_status_t\r
+ipoib_port_srq_init(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t         ib_status;\r
+       ib_srq_handle_t         h_srq;\r
+       ib_srq_attr_t           srq_attr;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       \r
+       if( !p_port->p_adapter->params.cm_enabled )\r
+               return IB_SUCCESS;\r
+\r
+       srq_attr.max_sge = min( 2, p_port->p_ca_attrs->max_srq_sges );\r
+       srq_attr.srq_limit = 10;\r
+       srq_attr.max_wr = \r
+               min( (uint32_t)p_port->p_adapter->params.rq_depth * 8,\r
+                               p_port->p_ca_attrs->max_srq_wrs/2 );\r
+\r
+       ib_status = p_port->p_adapter->p_ifc->create_srq( \r
+                                                               p_port->ib_mgr.h_pd, \r
+                                                               &srq_attr, \r
+                                                               p_port, \r
+                                                               __srq_async_event_cb, \r
+                                                               &h_srq );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_CREATE_QP, 1, ib_status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_srq failed status %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+               return ib_status;\r
+       }\r
+       p_port->ib_mgr.h_srq = h_srq;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+\r
+       return ib_status;\r
+}\r
+\r
+/*  __port_query_ca_attrs() \r
+ *  returns a pointer to allocated memory.\r
+ *  must be released by caller.\r
+ */\r
+static ib_api_status_t\r
+__port_query_ca_attrs( \r
+       IN              ipoib_port_t* const             p_port,\r
+       IN              ib_ca_attr_t**                  pp_ca_attrs )\r
+{\r
+       ib_api_status_t         ib_status;\r
+       uint32_t                        attr_size;\r
+       ib_ca_attr_t*           p_ca_attrs;\r
+\r
+       *pp_ca_attrs = NULL;\r
+\r
+       ib_status = \r
+               p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, NULL , &attr_size );\r
+       if( ib_status != IB_INSUFFICIENT_MEMORY )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_query_ca failed status %s\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+               goto done;\r
+       }\r
+       CL_ASSERT( attr_size );\r
+\r
+       p_ca_attrs = cl_zalloc( attr_size );\r
+       if ( p_ca_attrs == NULL )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Allocate %d bytes failed for CA Attributes\n", attr_size ));\r
+               ib_status = IB_INSUFFICIENT_MEMORY;\r
+               goto done;\r
+       }\r
+\r
+       ib_status = \r
+               p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, p_ca_attrs , &attr_size );\r
+       if ( ib_status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("CA attributes query failed\n") );\r
+               cl_free ( p_ca_attrs );\r
+               goto done;\r
+       }\r
+\r
+       *pp_ca_attrs = p_ca_attrs;\r
+done:\r
+       return ib_status;\r
+}\r
+\r
+void\r
+ipoib_port_srq_destroy( \r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t status;\r
+\r
+       if( p_port->ib_mgr.h_srq )\r
+       {\r
+               status =\r
+                       p_port->p_adapter->p_ifc->destroy_srq( p_port->ib_mgr.h_srq, NULL );\r
+               CL_ASSERT( status == IB_SUCCESS );\r
+               p_port->ib_mgr.h_srq = NULL;\r
+       }\r
+}\r
+\r
+static void\r
+__ib_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       if( p_port->ib_mgr.h_ca )\r
+       {\r
+               status =\r
+                       p_port->p_adapter->p_ifc->close_ca( p_port->ib_mgr.h_ca, NULL );\r
+               CL_ASSERT( status == IB_SUCCESS );\r
+               p_port->ib_mgr.h_ca = NULL;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Buffer manager implementation.\r
+*\r
+******************************************************************************/\r
+static void\r
+__buf_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       cl_qpool_construct( &p_port->buf_mgr.recv_pool );\r
+\r
+       p_port->buf_mgr.h_packet_pool = NULL;\r
+       p_port->buf_mgr.h_buffer_pool = NULL;\r
+\r
+       NdisInitializeNPagedLookasideList( &p_port->buf_mgr.send_buf_list,\r
+               NULL, NULL, 0, MAX_XFER_BLOCK_SIZE, 'bipi', 0 );\r
+\r
+       p_port->buf_mgr.h_send_pkt_pool = NULL;\r
+       p_port->buf_mgr.h_send_buf_pool = NULL;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__buf_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       cl_status_t             cl_status;\r
+       ipoib_params_t  *p_params;\r
+       NET_BUFFER_LIST_POOL_PARAMETERS pool_parameters;\r
+       IPOIB_ENTER(IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_port );\r
+       CL_ASSERT( p_port->p_adapter );\r
+\r
+       p_params = &p_port->p_adapter->params;\r
+\r
+       /* Allocate the receive descriptor pool */\r
+       cl_status = cl_qpool_init( &p_port->buf_mgr.recv_pool,\r
+               p_params->rq_depth * p_params->recv_pool_ratio,\r
+#if IPOIB_INLINE_RECV\r
+               0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, NULL, p_port );\r
+#else  /* IPOIB_INLINE_RECV */\r
+               0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, __recv_dtor, p_port );\r
+#endif /* IPOIB_INLINE_RECV */\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_POOL, 1, cl_status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_qpool_init for recvs returned %#x\n",\r
+                       cl_status) );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       /* Allocate the NET BUFFER list pools for receive indication. */\r
+       NdisZeroMemory(&pool_parameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));\r
+    pool_parameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+    pool_parameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;\r
+    pool_parameters.Header.Size = sizeof(pool_parameters);\r
+    pool_parameters.ProtocolId = 0;\r
+    pool_parameters.ContextSize = 0;\r
+    pool_parameters.fAllocateNetBuffer = TRUE;\r
+    pool_parameters.PoolTag = 'CRPI';\r
+\r
+    p_port->buf_mgr.h_packet_pool = NdisAllocateNetBufferListPool(\r
+                p_port->p_adapter->h_adapter,\r
+                &pool_parameters); \r
+\r
+       if( !p_port->buf_mgr.h_packet_pool )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_PKT_POOL, 1, NDIS_STATUS_RESOURCES  );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+/*\r
+       NdisAllocateBufferPool( &ndis_status, &p_port->buf_mgr.h_buffer_pool,\r
+               p_params->rq_depth );\r
+       if( ndis_status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_BUF_POOL, 1, ndis_status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+*/\r
+       /* Allocate the NET buffer list pool for send formatting. */\r
+    pool_parameters.PoolTag = 'XTPI';\r
+\r
+    p_port->buf_mgr.h_send_pkt_pool = NdisAllocateNetBufferListPool(\r
+                p_port->p_adapter->h_adapter,\r
+                &pool_parameters); \r
+       if( !p_port->buf_mgr.h_send_pkt_pool)\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_SEND_PKT_POOL, 1, NDIS_STATUS_RESOURCES );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+/*\r
+       NdisAllocateBufferPool( &ndis_status,\r
+               &p_port->buf_mgr.h_send_buf_pool, 1 );\r
+       if( ndis_status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_SEND_BUF_POOL, 1, ndis_status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+*/\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+__buf_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER(IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_port );\r
+\r
+       /* Destroy the send packet and buffer pools. \r
+       if( p_port->buf_mgr.h_send_buf_pool )\r
+               NdisFreeBufferPool( p_port->buf_mgr.h_send_buf_pool );*/\r
+       if( p_port->buf_mgr.h_send_pkt_pool )\r
+               NdisFreeNetBufferListPool ( p_port->buf_mgr.h_send_pkt_pool );\r
+\r
+       /* Destroy the receive packet and buffer pools. \r
+       if( p_port->buf_mgr.h_buffer_pool )\r
+               NdisFreeBufferPool( p_port->buf_mgr.h_buffer_pool );*/\r
+       if( p_port->buf_mgr.h_packet_pool )\r
+               NdisFreeNetBufferListPool ( p_port->buf_mgr.h_packet_pool );\r
+\r
+       /* Free the receive and send descriptors. */\r
+       cl_qpool_destroy( &p_port->buf_mgr.recv_pool );\r
+\r
+       /* Free the lookaside list of scratch buffers. */\r
+       NdisDeleteNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+\r
+       IPOIB_EXIT(  IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static cl_status_t\r
+__recv_ctor(\r
+       IN                              void* const                                     p_object,\r
+       IN                              void*                                           context,\r
+               OUT                     cl_pool_item_t** const          pp_pool_item )\r
+{\r
+       ipoib_recv_desc_t       *p_desc;\r
+       ipoib_port_t            *p_port;\r
+\r
+#if IPOIB_INLINE_RECV\r
+       uint32_t                        ds0_len;\r
+#endif\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ALLOC );\r
+\r
+       CL_ASSERT( p_object );\r
+       CL_ASSERT( context );\r
+\r
+       p_desc = (ipoib_recv_desc_t*)p_object;\r
+       p_port = (ipoib_port_t*)context;\r
+\r
+       /* Setup the work request. */\r
+       p_desc->wr.ds_array = p_desc->local_ds;\r
+       p_desc->wr.wr_id = (uintn_t)p_desc;\r
+\r
+#if IPOIB_INLINE_RECV\r
+       /* Sanity check on the receive buffer layout */\r
+       CL_ASSERT( (void*)&p_desc->buf.eth.pkt.type ==\r
+               (void*)&p_desc->buf.ib.pkt.type );\r
+       CL_ASSERT( sizeof(recv_buf_t) == sizeof(ipoib_pkt_t) + sizeof(ib_grh_t) );\r
+\r
+       /* Setup the local data segment. */\r
+       p_desc->local_ds[0].vaddr = cl_get_physaddr( &p_desc->buf );\r
+       p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey;\r
+       ds0_len =\r
+               PAGE_SIZE - ((uint32_t)p_desc->local_ds[0].vaddr & (PAGE_SIZE - 1));\r
+       if( ds0_len >= sizeof(recv_buf_t) )\r
+       {\r
+               /* The whole buffer is within a page. */\r
+               p_desc->local_ds[0].length = ds0_len;\r
+               p_desc->wr.num_ds = 1;\r
+       }\r
+       else\r
+       {\r
+               /* The buffer crosses page boundaries. */\r
+               p_desc->local_ds[0].length = ds0_len;\r
+               p_desc->local_ds[1].vaddr = cl_get_physaddr( \r
+                       ((uint8_t*)&p_desc->buf) + ds0_len );\r
+               p_desc->local_ds[1].lkey = p_port->ib_mgr.lkey;\r
+               p_desc->local_ds[1].length = sizeof(recv_buf_t) - ds0_len;\r
+               p_desc->wr.num_ds = 2;\r
+       }\r
+#else  /* IPOIB_INLINE_RECV */\r
+       /* Allocate the receive buffer. */\r
+       p_desc->p_buf = (recv_buf_t*)cl_zalloc( sizeof(recv_buf_t) );\r
+       if( !p_desc->p_buf )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate receive buffer.\n") );\r
+               return CL_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       /* Sanity check on the receive buffer layout */\r
+       CL_ASSERT( (void*)&p_desc->p_buf->eth.pkt.type ==\r
+               (void*)&p_desc->p_buf->ib.pkt.type );\r
+\r
+       /* Setup the local data segment. */\r
+       p_desc->local_ds[0].vaddr = cl_get_physaddr( p_desc->p_buf );\r
+       p_desc->local_ds[0].length = sizeof(ipoib_pkt_t) + sizeof(ib_grh_t);\r
+       p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey;\r
+       p_desc->wr.num_ds = 1;\r
+#endif /* IPOIB_INLINE_RECV */\r
+\r
+       *pp_pool_item = &p_desc->item;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ALLOC );\r
+       return CL_SUCCESS;\r
+}\r
+\r
+\r
+#if !IPOIB_INLINE_RECV\r
+static void\r
+__recv_dtor(\r
+       IN              const   cl_pool_item_t* const           p_pool_item,\r
+       IN                              void                                            *context )\r
+{\r
+       ipoib_recv_desc_t       *p_desc;\r
+\r
+       IPOIB_ENTER(  IPOIB_DBG_ALLOC );\r
+\r
+       UNUSED_PARAM( context );\r
+\r
+       p_desc = PARENT_STRUCT( p_pool_item, ipoib_recv_desc_t, item );\r
+\r
+       if( p_desc->p_buf )\r
+               cl_free( p_desc->p_buf );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ALLOC );\r
+}\r
+#endif\r
+\r
+\r
+static inline ipoib_recv_desc_t*\r
+__buf_mgr_get_recv(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ipoib_recv_desc_t       *p_desc;\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+       p_desc = (ipoib_recv_desc_t*)cl_qpool_get( &p_port->buf_mgr.recv_pool );\r
+       /* Reference the port object for the send. */\r
+       if( p_desc )\r
+       {\r
+               ipoib_port_ref( p_port, ref_get_recv );\r
+               CL_ASSERT( p_desc->wr.wr_id == (uintn_t)p_desc );\r
+#if IPOIB_INLINE_RECV\r
+               CL_ASSERT( p_desc->local_ds[0].vaddr ==\r
+                       cl_get_physaddr( &p_desc->buf ) );\r
+#else  /* IPOIB_INLINE_RECV */\r
+               CL_ASSERT( p_desc->local_ds[0].vaddr ==\r
+                       cl_get_physaddr( p_desc->p_buf ) );\r
+               CL_ASSERT( p_desc->local_ds[0].length ==\r
+                       (sizeof(ipoib_pkt_t) + sizeof(ib_grh_t)) );\r
+#endif /* IPOIB_INLINE_RECV */\r
+               CL_ASSERT( p_desc->local_ds[0].lkey == p_port->ib_mgr.lkey );\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return p_desc;\r
+}\r
+\r
+\r
+//NDIS60\r
+static inline void\r
+__buf_mgr_put_recv(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc,\r
+       IN                              NET_BUFFER_LIST* const          p_net_buffer_list OPTIONAL )\r
+{\r
+       NET_BUFFER              *p_buf = NULL;\r
+       MDL                             *p_mdl = NULL;\r
+       IPOIB_ENTER(IPOIB_DBG_RECV );\r
+\r
+       if( p_net_buffer_list )\r
+       {\r
+               NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+               p_buf = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list);\r
+               CL_ASSERT( p_buf );\r
+               p_mdl = NET_BUFFER_FIRST_MDL(p_buf);\r
+               CL_ASSERT( p_mdl );\r
+               NdisFreeMdl(p_mdl);\r
+               NdisFreeNetBufferList(p_net_buffer_list);\r
+       }\r
+\r
+       /* Return the descriptor to its pools. */\r
+       cl_qpool_put( &p_port->buf_mgr.recv_pool, &p_desc->item );\r
+\r
+       /*\r
+        * Dereference the port object since the receive is no longer outstanding.\r
+        */\r
+       ipoib_port_deref( p_port, ref_get_recv );\r
+       IPOIB_EXIT(  IPOIB_DBG_RECV );\r
+}\r
+\r
+\r
+static inline void\r
+__buf_mgr_put_recv_list(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              cl_qlist_t* const                       p_list )\r
+{\r
+       //IPOIB_ENTER(  IPOIB_DBG_RECV );\r
+       cl_qpool_put_list( &p_port->buf_mgr.recv_pool, p_list );\r
+       //IPOIB_EXIT(  IPOIB_DBG_RECV );\r
+}\r
+\r
+\r
+static inline NET_BUFFER_LIST*\r
+__buf_mgr_get_ndis_pkt(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc )\r
+{\r
+       NET_BUFFER_LIST                 *p_net_buffer_list;\r
+       MDL                                             *p_mdl;\r
+\r
+       IPOIB_ENTER(  IPOIB_DBG_RECV );\r
+\r
+       p_mdl = NdisAllocateMdl(p_port->p_adapter->h_adapter,\r
+                                                       &p_desc->buf.eth.pkt,\r
+                                                       p_desc->len );\r
+       if( !p_mdl )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate MDL\n") );\r
+               return NULL;\r
+       }\r
+\r
+       p_net_buffer_list = NdisAllocateNetBufferAndNetBufferList(\r
+                                               p_port->buf_mgr.h_packet_pool,\r
+                                               0,\r
+                                               0,\r
+                                               p_mdl,\r
+                                               0,\r
+                                               0);\r
+\r
+       if( !p_net_buffer_list )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate NET_BUFFER_LIST\n") );\r
+               NdisFreeMdl(p_mdl);\r
+               return NULL;\r
+       }\r
+\r
+       NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+       IPOIB_PORT_FROM_PACKET( p_net_buffer_list ) = p_port;\r
+       IPOIB_RECV_FROM_PACKET( p_net_buffer_list ) = p_desc;\r
+       p_net_buffer_list->SourceHandle = p_port->p_adapter->h_adapter;\r
+\r
+       IPOIB_EXIT(  IPOIB_DBG_RECV );\r
+       return p_net_buffer_list;\r
+}\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Receive manager implementation.\r
+*\r
+******************************************************************************/\r
+static void\r
+__recv_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       cl_qlist_init( &p_port->recv_mgr.done_list );\r
+\r
+       p_port->recv_mgr.recv_pkt_array = NULL;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /* Allocate the NDIS_PACKET pointer array for indicating receives. */\r
+       p_port->recv_mgr.recv_pkt_array = cl_malloc(\r
+               sizeof(NET_BUFFER_LIST*) * p_port->p_adapter->params.rq_depth );\r
+       if( !p_port->recv_mgr.recv_pkt_array )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_PKT_ARRAY, 0 );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_malloc for PNDIS_PACKET array failed.\n") );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+__recv_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( cl_is_qlist_empty( &p_port->recv_mgr.done_list ) );\r
+       CL_ASSERT( !p_port->recv_mgr.depth );\r
+\r
+       if( p_port->recv_mgr.recv_pkt_array )\r
+               cl_free( p_port->recv_mgr.recv_pkt_array );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+/*\r
+ * Posts receive buffers to the receive queue and returns the number\r
+ * of receives needed to bring the RQ to its low water mark.  Note\r
+ * that the value is signed, and can go negative.  All tests must\r
+ * be for > 0.\r
+ */\r
+static int32_t\r
+__recv_mgr_repost(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ipoib_recv_desc_t       *p_head = NULL, *p_tail = NULL, *p_next;\r
+       ib_api_status_t         status;\r
+       ib_recv_wr_t            *p_failed;\r
+       PERF_DECLARE( GetRecv );\r
+       PERF_DECLARE( PostRecv );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       CL_ASSERT( p_port );\r
+       cl_obj_lock( &p_port->obj );\r
+       if( p_port->state != IB_QPS_RTS )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+                       ("Port in invalid state.  Not reposting.\n") );\r
+               return 0;\r
+       }\r
+       ipoib_port_ref( p_port, ref_repost );\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       while( p_port->recv_mgr.depth < p_port->p_adapter->params.rq_depth )\r
+       {\r
+               /* Pull receives out of the pool and chain them up. */\r
+               cl_perf_start( GetRecv );\r
+               p_next = __buf_mgr_get_recv( p_port );\r
+               cl_perf_stop( &p_port->p_adapter->perf, GetRecv );\r
+               if( !p_next )\r
+               {\r
+                       IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
+                               ("Out of receive descriptors! recv queue depth 0x%x\n",p_port->recv_mgr.depth) );\r
+                       break;\r
+               }\r
+\r
+               if( !p_tail )\r
+               {\r
+                       p_tail = p_next;\r
+                       p_next->wr.p_next = NULL;\r
+               }\r
+               else\r
+               {\r
+                       p_next->wr.p_next = &p_head->wr;\r
+               }\r
+\r
+               p_head = p_next;\r
+\r
+               p_port->recv_mgr.depth++;\r
+       }\r
+\r
+       if( p_head )\r
+       {\r
+               cl_perf_start( PostRecv );\r
+               status = p_port->p_adapter->p_ifc->post_recv(\r
+                       p_port->ib_mgr.h_qp, &p_head->wr, &p_failed );\r
+               cl_perf_stop( &p_port->p_adapter->perf, PostRecv );\r
+\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ip_post_recv returned %s\n", \r
+                               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                       /* return the descriptors to the pool */\r
+                       while( p_failed )\r
+                       {\r
+                               p_head = PARENT_STRUCT( p_failed, ipoib_recv_desc_t, wr );\r
+                               p_failed = p_failed->p_next;\r
+\r
+                               __buf_mgr_put_recv( p_port, p_head, NULL );\r
+                               p_port->recv_mgr.depth--;\r
+                       }\r
+               }\r
+       }\r
+\r
+       ipoib_port_deref( p_port, ref_repost );\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return p_port->p_adapter->params.rq_low_watermark - p_port->recv_mgr.depth;\r
+}\r
+\r
+void\r
+ipoib_return_net_buffer_list(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              NET_BUFFER_LIST                         *p_net_buffer_lists,\r
+       IN                              ULONG                                           return_flags)\r
+{\r
+       cl_list_item_t          *p_item;\r
+       ipoib_port_t            *p_port;\r
+       ipoib_recv_desc_t       *p_desc;\r
+       NET_BUFFER_LIST         *cur_net_buffer_list,*next_net_buffer_list;\r
+       ib_api_status_t         status = IB_NOT_DONE;\r
+       int32_t                         shortage;\r
+       ULONG                           complete_flags = 0;\r
+       PERF_DECLARE( ReturnPacket );\r
+       PERF_DECLARE( ReturnPutRecv );\r
+       PERF_DECLARE( ReturnRepostRecv );\r
+       PERF_DECLARE( ReturnPreparePkt );\r
+       PERF_DECLARE( ReturnNdisIndicate );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       p_port = ((ipoib_adapter_t*)adapter_context)->p_port;\r
+       CL_ASSERT( p_net_buffer_lists );\r
+\r
+       cl_perf_start( ReturnPacket );\r
+       cl_spinlock_acquire( &p_port->recv_lock );\r
+       for (cur_net_buffer_list = p_net_buffer_lists;\r
+                cur_net_buffer_list != NULL;\r
+                cur_net_buffer_list = next_net_buffer_list)\r
+       {\r
+               next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(cur_net_buffer_list);\r
+\r
+               /* Get the port and descriptor from the packet. */\r
+               CL_ASSERT(p_port == IPOIB_PORT_FROM_PACKET( cur_net_buffer_list ));\r
+               p_desc = IPOIB_RECV_FROM_PACKET( cur_net_buffer_list );\r
+\r
+               \r
+               //TODO: NDIS60, rewrite this block\r
+               /* Get descriptor from the packet. */\r
+#if 0\r
+               if( p_desc->type == PKT_TYPE_CM_UCAST )\r
+               {\r
+                       NDIS_BUFFER             *p_buf;\r
+\r
+                       /* Unchain the NDIS buffer. */\r
+                       NdisUnchainBufferAtFront( p_packet, &p_buf );\r
+                       CL_ASSERT( p_buf );\r
+                       /* Return the NDIS packet and NDIS buffer to their pools. */\r
+                       NdisDprFreePacketNonInterlocked( p_packet );\r
+                       NdisFreeBuffer( p_buf );\r
+\r
+                       endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, (ipoib_cm_desc_t *)p_desc );\r
+                       status = endpt_cm_post_recv( p_port );\r
+                       if(  status != IB_SUCCESS )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Post Recv QP failed\n" ) );\r
+                       }\r
+                       cl_spinlock_release( &p_port->recv_lock );\r
+                       return;\r
+               }\r
+#endif\r
+\r
+               cl_perf_start( ReturnPutRecv );\r
+               __buf_mgr_put_recv( p_port, p_desc, cur_net_buffer_list );\r
+               cl_perf_stop( &p_port->p_adapter->perf, ReturnPutRecv );\r
+       }\r
+#if 0           \r
+       /* Repost buffers. */\r
+       cl_perf_start( ReturnRepostRecv );\r
+       shortage = __recv_mgr_repost( p_port );\r
+       cl_perf_stop( &p_port->p_adapter->perf, ReturnRepostRecv );\r
+\r
+       for( p_item = cl_qlist_remove_head( &p_port->recv_mgr.done_list );\r
+               p_item != cl_qlist_end( &p_port->recv_mgr.done_list );\r
+               p_item = cl_qlist_remove_head( &p_port->recv_mgr.done_list ) )\r
+       {\r
+               p_desc = (ipoib_recv_desc_t*)p_item;\r
+\r
+               cl_perf_start( ReturnPreparePkt );\r
+               status = __recv_mgr_prepare_pkt( p_port, p_desc, &cur_net_buffer_list );\r
+               cl_perf_stop( &p_port->p_adapter->perf, ReturnPreparePkt );\r
+               if( status == IB_SUCCESS )\r
+               {\r
+                       if( shortage > 0 )\r
+                               NET_BUFFER_LIST_STATUS( cur_net_buffer_list) = NDIS_STATUS_RESOURCES;\r
+                       else\r
+                               NET_BUFFER_LIST_STATUS( cur_net_buffer_list) = NDIS_STATUS_SUCCESS;\r
+\r
+                       cl_spinlock_release( &p_port->recv_lock );\r
+                       NET_BUFFER_LIST_NEXT_NBL(cur_net_buffer_list) = NULL;\r
+                       cl_perf_start( ReturnNdisIndicate );\r
+                       NdisMRecvIndicate( p_port->p_adapter->h_adapter,\r
+                               cur_net_buffer_list, complete_flags );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, ReturnNdisIndicate );\r
+                       cl_spinlock_acquire( &p_port->recv_lock );\r
+\r
+                       if( shortage > 0 )\r
+                       {\r
+                               cl_perf_start( ReturnPutRecv );\r
+                               __buf_mgr_put_recv( p_port, p_desc, cur_net_buffer_list );\r
+                               cl_perf_stop( &p_port->p_adapter->perf, ReturnPutRecv );\r
+\r
+                               /* Repost buffers. */\r
+                               cl_perf_start( ReturnRepostRecv );\r
+                               shortage = __recv_mgr_repost( p_port );\r
+                               cl_perf_stop( &p_port->p_adapter->perf, ReturnRepostRecv );\r
+                       }\r
+               }\r
+               else if( status != IB_NOT_DONE )\r
+               {\r
+                       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+                               ("__recv_mgr_prepare_pkt returned %s\n",\r
+                               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                       /* Return the item to the head of the list. */\r
+                       cl_qlist_insert_head( &p_port->recv_mgr.done_list, p_item );\r
+                       break;\r
+               }\r
+       }\r
+       #endif\r
+       cl_spinlock_release( &p_port->recv_lock );\r
+       cl_perf_stop( &p_port->p_adapter->perf, ReturnPacket );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void * s_arg1 , void * s_arg2)\r
+{\r
+\r
+       ipoib_port_t *p_port = context;\r
+\r
+       UNREFERENCED_PARAMETER(p_gc_dpc);\r
+       UNREFERENCED_PARAMETER(s_arg1);\r
+       UNREFERENCED_PARAMETER(s_arg2);\r
+\r
+\r
+       __recv_cb(NULL, p_port);\r
+       ipoib_port_deref( p_port, ref_recv_cb );\r
+\r
+\r
+}\r
+\r
+\r
+static void\r
+__recv_cb(\r
+       IN              const   ib_cq_handle_t                          h_cq,\r
+       IN                              void                                            *cq_context )\r
+{\r
+       ipoib_port_t            *p_port;\r
+       ib_api_status_t         status;\r
+       ib_wc_t                         wc[MAX_RECV_WC], *p_free, *p_wc;\r
+       int32_t                         pkt_cnt, recv_cnt = 0, shortage, discarded;\r
+       cl_qlist_t                      done_list, bad_list;\r
+       size_t                          i;\r
+       ULONG                           recv_complete_flags = 0;\r
+\r
+       PERF_DECLARE( RecvCompBundle );\r
+       PERF_DECLARE( RecvCb );\r
+       PERF_DECLARE( PollRecv );\r
+       PERF_DECLARE( RepostRecv );\r
+       PERF_DECLARE( FilterRecv );\r
+       PERF_DECLARE( BuildPktArray );\r
+       PERF_DECLARE( RecvNdisIndicate );\r
+       PERF_DECLARE( RearmRecv );\r
+       PERF_DECLARE( PutRecvList );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       cl_perf_clr( RecvCompBundle );\r
+\r
+       cl_perf_start( RecvCb );\r
+//return ;\r
+       UNUSED_PARAM( h_cq );\r
+\r
+       NDIS_SET_SEND_COMPLETE_FLAG(recv_complete_flags, NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL );\r
+\r
+       p_port = (ipoib_port_t*)cq_context;\r
+\r
+       cl_qlist_init( &done_list );\r
+       cl_qlist_init( &bad_list );\r
+\r
+       ipoib_port_ref( p_port, ref_recv_cb );\r
+       for( i = 0; i < MAX_RECV_WC; i++ )\r
+               wc[i].p_next = &wc[i + 1];\r
+       wc[MAX_RECV_WC - 1].p_next = NULL;\r
+\r
+       /*\r
+        * We'll be accessing the endpoint map so take a reference\r
+        * on it to prevent modifications.\r
+        */\r
+       cl_obj_lock( &p_port->obj );\r
+       cl_atomic_inc( &p_port->endpt_rdr );\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       do\r
+       {\r
+               /* If we get here, then the list of WCs is intact. */\r
+               p_free = wc;\r
+\r
+               cl_perf_start( PollRecv );\r
+               status = p_port->p_adapter->p_ifc->poll_cq(\r
+                       p_port->ib_mgr.h_recv_cq, &p_free, &p_wc );\r
+               cl_perf_stop( &p_port->p_adapter->perf, PollRecv );\r
+               CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND );\r
+\r
+               /* Look at the payload now and filter ARP and DHCP packets. */\r
+               cl_perf_start( FilterRecv );\r
+               recv_cnt += __recv_mgr_filter( p_port, p_wc, &done_list, &bad_list );\r
+               cl_perf_stop( &p_port->p_adapter->perf, FilterRecv );\r
+\r
+       } while( (!p_free) && (recv_cnt < 128));\r
+\r
+       /* We're done looking at the endpoint map, release the reference. */\r
+       cl_atomic_dec( &p_port->endpt_rdr );\r
+\r
+       cl_perf_log( &p_port->p_adapter->perf, RecvCompBundle, recv_cnt );\r
+\r
+       cl_spinlock_acquire( &p_port->recv_lock );\r
+\r
+       /* Update our posted depth. */\r
+       p_port->recv_mgr.depth -= recv_cnt;\r
+\r
+       /* Return any discarded receives to the pool */\r
+       cl_perf_start( PutRecvList );\r
+       __buf_mgr_put_recv_list( p_port, &bad_list );\r
+       cl_perf_stop( &p_port->p_adapter->perf, PutRecvList );\r
+\r
+       do\r
+       {\r
+               int32_t cnt;\r
+               /* Repost ASAP so we don't starve the RQ. */\r
+               cl_perf_start( RepostRecv );\r
+               shortage = __recv_mgr_repost( p_port );\r
+               cl_perf_stop( &p_port->p_adapter->perf, RepostRecv );\r
+\r
+               cl_perf_start( BuildPktArray );\r
+               /* Notify NDIS of any and all possible receive buffers. */\r
+               pkt_cnt = __recv_mgr_build_pkt_array(\r
+                       p_port, shortage, &done_list, &discarded );\r
+               cl_perf_stop( &p_port->p_adapter->perf, BuildPktArray );\r
+\r
+               /* Only indicate receives if we actually had any. */\r
+               if( discarded && shortage > 0 )\r
+               {\r
+                       /* We may have thrown away packets, and have a shortage */\r
+                       cl_perf_start( RepostRecv );\r
+                       __recv_mgr_repost( p_port );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, RepostRecv );\r
+               }\r
+\r
+               if( !pkt_cnt )\r
+                       break;\r
+\r
+               cl_spinlock_release( &p_port->recv_lock );\r
+               for( cnt = 0; cnt < pkt_cnt -1; cnt++)\r
+               {\r
+                       NET_BUFFER_LIST_NEXT_NBL(p_port->recv_mgr.recv_pkt_array[cnt]) = \r
+                               p_port->recv_mgr.recv_pkt_array[cnt + 1];\r
+               }\r
+               cl_perf_start( RecvNdisIndicate );\r
+#ifndef NDIS_DEFAULT_PORT_NUMBER\r
+#define NDIS_DEFAULT_PORT_NUMBER 0\r
+#endif\r
+               /*IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Indicate NDIS with  %d received NBs\n",\r
+                                       pkt_cnt) );*/\r
+               NdisMIndicateReceiveNetBufferLists(\r
+                       p_port->p_adapter->h_adapter,\r
+                       p_port->recv_mgr.recv_pkt_array[0],\r
+                       NDIS_DEFAULT_PORT_NUMBER,\r
+                       pkt_cnt,\r
+                       recv_complete_flags);\r
+\r
+               cl_perf_stop( &p_port->p_adapter->perf, RecvNdisIndicate );\r
+\r
+               /*\r
+                * Cap the number of receives to put back to what we just indicated\r
+                * with NDIS_STATUS_RESOURCES.\r
+                */\r
+               if( shortage > 0 )\r
+               {\r
+                       if( pkt_cnt < shortage )\r
+                               shortage = pkt_cnt;\r
+\r
+                       /* Return all but the last packet to the pool. */\r
+                       cl_spinlock_acquire( &p_port->recv_lock );\r
+                       while( shortage-- > 1 )\r
+                       {\r
+                               __buf_mgr_put_recv( p_port,\r
+                                       (ipoib_recv_desc_t *)IPOIB_RECV_FROM_PACKET( p_port->recv_mgr.recv_pkt_array[shortage] ),\r
+                                       p_port->recv_mgr.recv_pkt_array[shortage] );\r
+                       }\r
+                       cl_spinlock_release( &p_port->recv_lock );\r
+\r
+                       /*\r
+                        * Return the last packet as if NDIS returned it, so that we repost\r
+                        * and report any other pending receives.\r
+                        */\r
+                       ipoib_return_net_buffer_list( NULL, p_port->recv_mgr.recv_pkt_array[0],recv_complete_flags );\r
+               }\r
+               cl_spinlock_acquire( &p_port->recv_lock );\r
+\r
+       } while( pkt_cnt );\r
+       cl_spinlock_release( &p_port->recv_lock );\r
+\r
+       if (p_free ) {\r
+               /*\r
+                * Rearm after filtering to prevent contention on the enpoint maps\r
+                * and eliminate the possibility of having a call to\r
+                * __endpt_mgr_insert find a duplicate.\r
+                */\r
+               cl_perf_start( RearmRecv );\r
+               status = p_port->p_adapter->p_ifc->rearm_cq(\r
+                       p_port->ib_mgr.h_recv_cq, FALSE );\r
+               cl_perf_stop( &p_port->p_adapter->perf, RearmRecv );\r
+               CL_ASSERT( status == IB_SUCCESS );\r
+\r
+               ipoib_port_deref( p_port, ref_recv_cb );\r
+       } else {\r
+               // Please note the reference is still up\r
+               KeInsertQueueDpc(&p_port->recv_dpc, NULL, NULL);\r
+       }\r
+\r
+       cl_perf_stop( &p_port->p_adapter->perf, RecvCb );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+\r
+static void\r
+__recv_get_endpts(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc,\r
+       IN                              ib_wc_t* const                          p_wc,\r
+               OUT                     ipoib_endpt_t** const           pp_src,\r
+               OUT                     ipoib_endpt_t** const           pp_dst )\r
+{\r
+       ib_api_status_t         status;\r
+       mac_addr_t                      mac;\r
+       PERF_DECLARE( GetEndptByGid );\r
+       PERF_DECLARE( GetEndptByLid );\r
+       PERF_DECLARE( EndptInsert );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       /* Setup our shortcut pointers based on whether GRH is valid. */\r
+       if( p_wc->recv.ud.recv_opt & IB_RECV_OPT_GRH_VALID )\r
+       {\r
+               /* Lookup the source endpoints based on GID. */\r
+               cl_perf_start( GetEndptByGid );\r
+               *pp_src =\r
+#if IPOIB_INLINE_RECV\r
+                       __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.src_gid );\r
+#else  /* IPOIB_INLINE_RECV */\r
+                       __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.src_gid );\r
+#endif /* IPOIB_INLINE_RECV */\r
+               cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid );\r
+\r
+               /*\r
+                * Lookup the destination endpoint based on GID.\r
+                * This is used along with the packet filter to determine\r
+                * whether to report this to NDIS.\r
+                */\r
+               cl_perf_start( GetEndptByGid );\r
+               *pp_dst =\r
+#if IPOIB_INLINE_RECV\r
+                       __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.dest_gid );\r
+#else  /* IPOIB_INLINE_RECV */\r
+                       __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.dest_gid );\r
+#endif /* IPOIB_INLINE_RECV */\r
+               cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid );\r
+\r
+               /*\r
+                * Create the source endpoint if it does not exist.  Note that we\r
+                * can only do this for globally routed traffic since we need the\r
+                * information from the GRH to generate the MAC.\r
+                */\r
+               if( !*pp_src )\r
+               {\r
+                       status = ipoib_mac_from_guid(\r
+#if IPOIB_INLINE_RECV\r
+                               p_desc->buf.ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
+#else  /* IPOIB_INLINE_RECV */\r
+                               p_desc->p_buf->ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
+#endif /* IPOIB_INLINE_RECV */\r
+                       if( status != IB_SUCCESS )\r
+                       {\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("ipoib_mac_from_guid returned %s\n",\r
+                                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                               return;\r
+                       }\r
+\r
+                       /* Create the endpoint. */\r
+#if IPOIB_INLINE_RECV\r
+                       *pp_src = ipoib_endpt_create( &p_desc->buf.ib.grh.src_gid,\r
+#else  /* IPOIB_INLINE_RECV */\r
+                       *pp_src = ipoib_endpt_create( &p_desc->p_buf->ib.grh.src_gid,\r
+#endif /* IPOIB_INLINE_RECV */\r
+                               p_wc->recv.ud.remote_lid, p_wc->recv.ud.remote_qp );\r
+                       if( !*pp_src )\r
+                       {\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("ipoib_endpt_create failed\n") );\r
+                               return;\r
+                       }\r
+                       cl_perf_start( EndptInsert );\r
+                       cl_obj_lock( &p_port->obj );\r
+                       status = __endpt_mgr_insert( p_port, mac, *pp_src );\r
+                       if( status != IB_SUCCESS )\r
+                       {\r
+                               cl_obj_unlock( &p_port->obj );\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("__endpt_mgr_insert returned %s\n",\r
+                                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                               *pp_src = NULL;\r
+                               return;\r
+                       }\r
+                       cl_obj_unlock( &p_port->obj );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, EndptInsert );\r
+               }\r
+       }\r
+       else\r
+       {\r
+               /*\r
+                * Lookup the remote endpoint based on LID.  Note that only\r
+                * unicast traffic can be LID routed.\r
+                */\r
+               cl_perf_start( GetEndptByLid );\r
+               *pp_src = __endpt_mgr_get_by_lid( p_port, p_wc->recv.ud.remote_lid );\r
+               cl_perf_stop( &p_port->p_adapter->perf, GetEndptByLid );\r
+               *pp_dst = p_port->p_local_endpt;\r
+               CL_ASSERT( *pp_dst );\r
+       }\r
+\r
+       if( *pp_src && !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) &&\r
+               (*pp_src)->qpn != p_wc->recv.ud.remote_qp )\r
+       {\r
+               /* Update the QPN for the endpoint. */\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+                       ("Updating QPN for MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+                       (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1],\r
+                       (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3],\r
+                       (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5]) );\r
+//             (*pp_src)->qpn = p_wc->recv.ud.remote_qp;\r
+       }\r
+\r
+       if( *pp_src && *pp_dst )\r
+       {\r
+               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
+                       ("Recv:\n"\r
+                       "\tsrc MAC: %02X-%02X-%02X-%02X-%02X-%02X\n"\r
+                       "\tdst MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+                       (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1],\r
+                       (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3],\r
+                       (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5],\r
+                       (*pp_dst )->mac.addr[0], (*pp_dst )->mac.addr[1],\r
+                       (*pp_dst )->mac.addr[2], (*pp_dst )->mac.addr[3],\r
+                       (*pp_dst )->mac.addr[4], (*pp_dst )->mac.addr[5]) );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+\r
+static int32_t\r
+__recv_mgr_filter(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_wc_t* const                          p_done_wc_list,\r
+               OUT                     cl_qlist_t* const                       p_done_list,\r
+               OUT                     cl_qlist_t* const                       p_bad_list )\r
+{\r
+       ipoib_recv_desc_t               *p_desc;\r
+       ib_wc_t                                 *p_wc;\r
+       ipoib_pkt_t                             *p_ipoib;\r
+       eth_pkt_t                               *p_eth;\r
+       ipoib_endpt_t                   *p_src, *p_dst;\r
+       ib_api_status_t                 status;\r
+       uint32_t                                len;\r
+       int32_t                                 recv_cnt = 0;\r
+       PERF_DECLARE( GetRecvEndpts );\r
+       PERF_DECLARE( RecvGen );\r
+       PERF_DECLARE( RecvTcp );\r
+       PERF_DECLARE( RecvUdp );\r
+       PERF_DECLARE( RecvDhcp );\r
+       PERF_DECLARE( RecvArp );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       for( p_wc = p_done_wc_list; p_wc; p_wc = p_wc->p_next )\r
+       {\r
+               CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_RECV );\r
+               p_desc = (ipoib_recv_desc_t*)(uintn_t)p_wc->wr_id;\r
+               recv_cnt++;\r
+\r
+               if( p_wc->status != IB_WCS_SUCCESS )\r
+               {\r
+                       if( p_wc->status != IB_WCS_WR_FLUSHED_ERR )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Failed completion %s  (vendor specific %#x)\n",\r
+                                       p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
+                                       (int)p_wc->vendor_specific) );\r
+                               ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+                       }\r
+                       else\r
+                       {\r
+                               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
+                                       ("Flushed completion %s\n",\r
+                                       p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status )) );\r
+                               ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_DROPPED, 0, 0 );\r
+                       }\r
+                       cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                       /* Dereference the port object on behalf of the failed receive. */\r
+                       ipoib_port_deref( p_port, ref_failed_recv_wc );\r
+                       continue;\r
+               }\r
+\r
+               len = p_wc->length - sizeof(ib_grh_t);\r
+\r
+               if( len < sizeof(ipoib_hdr_t) )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Received ETH packet < min size\n") );\r
+                       ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+                       cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                       ipoib_port_deref( p_port, ref_recv_inv_len );\r
+                       continue;\r
+               }\r
+\r
+               if((len - sizeof(ipoib_hdr_t)) > p_port->p_adapter->params.payload_mtu)\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Received ETH packet len %d > payload MTU (%d)\n",\r
+                               (len - sizeof(ipoib_hdr_t)),\r
+                               p_port->p_adapter->params.payload_mtu) );\r
+                       ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+                       cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                       ipoib_port_deref( p_port, ref_recv_inv_len );\r
+                       continue;\r
+                       \r
+               }\r
+               /* Successful completion.  Get the receive information. */\r
+               p_desc->ndis_csum.Value = ( ( p_wc->recv.ud.recv_opt & IB_RECV_OPT_CSUM_MASK ) >> 8 );\r
+               cl_perf_start( GetRecvEndpts );\r
+               __recv_get_endpts( p_port, p_desc, p_wc, &p_src, &p_dst );\r
+               cl_perf_stop( &p_port->p_adapter->perf, GetRecvEndpts );\r
+\r
+#if IPOIB_INLINE_RECV\r
+               p_ipoib = &p_desc->buf.ib.pkt;\r
+               p_eth = &p_desc->buf.eth.pkt;\r
+#else  /* IPOIB_INLINE_RECV */\r
+               p_ipoib = &p_desc->p_buf->ib.pkt;\r
+               p_eth = &p_desc->p_buf->eth.pkt;\r
+#endif /*IPOIB_INLINE_RECV */\r
+\r
+               if( p_src )\r
+               {\r
+                       /* Don't report loopback traffic - we requested SW loopback. */\r
+                       if( !cl_memcmp( &p_port->p_adapter->params.conf_mac,\r
+                               &p_src->mac, sizeof(p_port->p_adapter->params.conf_mac) ) )\r
+                       {\r
+                               /*\r
+                                * "This is not the packet you're looking for" - don't update\r
+                                * receive statistics, the packet never happened.\r
+                                */\r
+                               cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                               /* Dereference the port object on behalf of the failed recv. */\r
+                               ipoib_port_deref( p_port, ref_recv_loopback );\r
+                               continue;\r
+                       }\r
+               }\r
+\r
+               switch( p_ipoib->hdr.type )\r
+               {\r
+               case ETH_PROT_TYPE_IP:\r
+                       if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Received IP packet < min size\n") );\r
+                               status = IB_INVALID_SETTING;\r
+                               break;\r
+                       }\r
+\r
+                       if( p_ipoib->type.ip.hdr.offset ||\r
+                               p_ipoib->type.ip.hdr.prot != IP_PROT_UDP )\r
+                       {\r
+                               /* Unfiltered.  Setup the ethernet header and report. */\r
+                               cl_perf_start( RecvTcp );\r
+                               status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
+                               cl_perf_stop( &p_port->p_adapter->perf, RecvTcp );\r
+                               break;\r
+                       }\r
+\r
+                       /* First packet of a UDP transfer. */\r
+                       if( len <\r
+                               (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Received UDP packet < min size\n") );\r
+                               status = IB_INVALID_SETTING;\r
+                               break;\r
+                       }\r
+\r
+                       /* Check if DHCP conversion is required. */\r
+                       if( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_SERVER &&\r
+                               p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) ||\r
+                               (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT &&\r
+                               p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_SERVER) )\r
+                       {\r
+                               if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) +\r
+                                       sizeof(udp_hdr_t) + DHCP_MIN_SIZE) )\r
+                               {\r
+                                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Received DHCP < min size\n") );\r
+                                       status = IB_INVALID_SETTING;\r
+                                       break;\r
+                               }\r
+                               if ((p_ipoib->type.ip.hdr.ver_hl & 0x0f) != 5 ) {\r
+                                       // If there are IP options in this message, we are in trouble in any case\r
+                                       status = IB_INVALID_SETTING;\r
+                                       break;                                  \r
+                               }\r
+                               /* UDP packet with BOOTP ports in src/dst port numbers. */\r
+                               cl_perf_start( RecvDhcp );\r
+                               status = __recv_dhcp( p_port, p_ipoib, p_eth, p_src, p_dst );\r
+                               cl_perf_stop( &p_port->p_adapter->perf, RecvDhcp );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Unfiltered.  Setup the ethernet header and report. */\r
+                               cl_perf_start( RecvUdp );\r
+                               status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
+                               cl_perf_stop( &p_port->p_adapter->perf, RecvUdp );\r
+                       }\r
+                       break;\r
+\r
+               case ETH_PROT_TYPE_ARP:\r
+                       if( len < (sizeof(ipoib_hdr_t) + sizeof(ipoib_arp_pkt_t)) )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Received ARP < min size\n") );\r
+                               status = IB_INVALID_SETTING;\r
+                               break;\r
+                       }\r
+                       cl_perf_start( RecvArp );\r
+                       status = __recv_arp( p_port, p_wc, p_ipoib, p_eth, &p_src, p_dst );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, RecvArp );\r
+                       len = sizeof(ipoib_hdr_t) + sizeof(arp_pkt_t);\r
+                       break;\r
+\r
+               default:\r
+                       /* Unfiltered.  Setup the ethernet header and report. */\r
+                       cl_perf_start( RecvGen );\r
+                       status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, RecvGen );\r
+               }\r
+\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       /* Update stats. */\r
+                       ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+                       cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                       /* Dereference the port object on behalf of the failed receive. */\r
+                       ipoib_port_deref( p_port, ref_recv_filter );\r
+               }\r
+               else\r
+               {\r
+                       ip_stat_sel_t               ip_stat;\r
+                       p_desc->len =\r
+                               len + sizeof(eth_hdr_t) - sizeof(ipoib_hdr_t);\r
+                       if( p_dst->h_mcast)\r
+                       {\r
+                               if( p_dst->dgid.multicast.raw_group_id[10] == 0xFF &&\r
+                                       p_dst->dgid.multicast.raw_group_id[11] == 0xFF &&\r
+                                       p_dst->dgid.multicast.raw_group_id[12] == 0xFF &&\r
+                                       p_dst->dgid.multicast.raw_group_id[13] == 0xFF )\r
+                               {\r
+                                       p_desc->type = PKT_TYPE_BCAST;\r
+                                       ip_stat = IP_STAT_BCAST_BYTES;\r
+                               }\r
+                               else\r
+                               {\r
+                                       p_desc->type = PKT_TYPE_MCAST;\r
+                                       ip_stat = IP_STAT_MCAST_BYTES;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               p_desc->type = PKT_TYPE_UCAST;\r
+                               ip_stat = IP_STAT_UCAST_BYTES;\r
+                               \r
+                       }\r
+                       cl_qlist_insert_tail( p_done_list, &p_desc->item.list_item );\r
+                       ipoib_inc_recv_stat( p_port->p_adapter, ip_stat, len, 1 );  \r
+               }\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return recv_cnt;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_gen(\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t* const            p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       if( !p_src || !p_dst )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Received packet with no matching endpoints.\n") );\r
+               return IB_NOT_DONE;\r
+       }\r
+\r
+       /*\r
+        * Fill in the ethernet header.  Note that doing so will overwrite\r
+        * the IPoIB header, so start by moving the information from the IPoIB\r
+        * header.\r
+        */\r
+       p_eth->hdr.type = p_ipoib->hdr.type;\r
+       p_eth->hdr.src = p_src->mac;\r
+       p_eth->hdr.dst = p_dst->mac;\r
+\r
+       if ( p_eth->hdr.dst.addr[0] == 1 && \r
+                p_eth->hdr.type == ETH_PROT_TYPE_IP &&\r
+                p_eth->hdr.dst.addr[2] == 0x5E)  \r
+       {\r
+               p_eth->hdr.dst.addr[1] = 0;\r
+               p_eth->hdr.dst.addr[3] = p_eth->hdr.dst.addr[3] & 0x7f;\r
+       }\r
+       if (p_dst->h_mcast)\r
+               p_dst->is_in_use = TRUE;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_dhcp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t* const            p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst )\r
+{\r
+       ib_api_status_t         status;\r
+       dhcp_pkt_t                      *p_dhcp;\r
+       uint8_t                         *p_option;\r
+       uint8_t                         *p_cid = NULL;\r
+       ib_gid_t                        gid;\r
+       uint8_t                         msg = 0;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       UNUSED_PARAM( p_port );\r
+\r
+       /* Create the ethernet header. */\r
+       status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__recv_gen returned %s.\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Fixup the payload. */\r
+       p_dhcp = &p_eth->type.ip.prot.udp.dhcp;\r
+       if( p_dhcp->op != DHCP_REQUEST && p_dhcp->op != DHCP_REPLY )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid DHCP op code.\n") );\r
+               return IB_INVALID_SETTING;\r
+       }\r
+\r
+       /*\r
+        * Find the client identifier option, making sure to skip\r
+        * the "magic cookie".\r
+        */\r
+       p_option = &p_dhcp->options[0];\r
+       if ( *(uint32_t *)p_option != DHCP_COOKIE )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("DHCP cookie corrupted.\n") );\r
+               return IB_INVALID_PARAMETER;\r
+       }\r
+\r
+       p_option = &p_dhcp->options[4];\r
+       while( *p_option != DHCP_OPT_END && p_option < &p_dhcp->options[312] )\r
+       {\r
+               switch( *p_option )\r
+               {\r
+               case DHCP_OPT_PAD:\r
+                       p_option++;\r
+                       break;\r
+\r
+               case DHCP_OPT_MSG:\r
+                       msg = p_option[2];\r
+                       p_option += 3;\r
+                       break;\r
+\r
+               case DHCP_OPT_CLIENT_ID:\r
+                       p_cid = p_option;\r
+                       /* Fall through. */\r
+\r
+               default:\r
+                       /*\r
+                        * All other options have a length byte following the option code.\r
+                        * Offset by the length to get to the next option.\r
+                        */\r
+                       p_option += (p_option[1] + 2);\r
+               }\r
+       }\r
+\r
+       switch( msg )\r
+       {\r
+       /* message from client */\r
+       case DHCPDISCOVER:\r
+       case DHCPREQUEST:\r
+       case DHCPDECLINE:\r
+       case DHCPRELEASE:\r
+       case DHCPINFORM:\r
+               if( !p_cid )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to find required Client-identifier option.\n") );\r
+                       return IB_INVALID_SETTING;\r
+               }\r
+               if( p_dhcp->htype != DHCP_HW_TYPE_IB )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Invalid hardware address type.\n") );\r
+                       return IB_INVALID_SETTING;\r
+               }\r
+               break;\r
+       /* message from DHCP server */\r
+       case DHCPOFFER:\r
+       case DHCPACK:\r
+       case DHCPNAK:\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalide message type.\n") );\r
+               return IB_INVALID_PARAMETER;\r
+       }\r
+       p_eth->type.ip.prot.udp.hdr.chksum = 0;\r
+       p_dhcp->htype = DHCP_HW_TYPE_ETH;\r
+       p_dhcp->hlen = HW_ADDR_LEN;\r
+\r
+       if( p_cid ) /* from client */\r
+       {\r
+               /* Validate that the length and type of the option is as required. */\r
+               if( p_cid[1] != 21 )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Client-identifier length not 21 as required.\n") );\r
+                       return IB_INVALID_SETTING;\r
+               }\r
+               if( p_cid[2] != DHCP_HW_TYPE_IB )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Client-identifier type is wrong.\n") );\r
+                       return IB_INVALID_SETTING;\r
+               }\r
+               /*\r
+                * Copy the GID value from the option so that we can make aligned\r
+                * accesses to the contents.\r
+                * Recover CID to standard type.\r
+                */\r
+               cl_memcpy( &gid, &p_cid[7], sizeof(ib_gid_t) );\r
+               p_cid[1] =  HW_ADDR_LEN +1;// CID length \r
+               p_cid[2] =  DHCP_HW_TYPE_ETH;// CID type \r
+               status = ipoib_mac_from_guid( gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, (mac_addr_t*)&p_cid[3] );\r
+               if (status == IB_INVALID_GUID_MASK)\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
+                               ("Invalid GUID mask received, rejecting it") );\r
+                       ipoib_create_log(p_port->p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+                       status = IB_SUCCESS;\r
+               }\r
+               p_cid[HW_ADDR_LEN + 3] = DHCP_OPT_END; //terminate tag\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return status;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_arp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_wc_t* const                          p_wc,\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t** const           pp_src,\r
+       IN                              ipoib_endpt_t* const            p_dst )\r
+{\r
+       ib_api_status_t                 status;\r
+       arp_pkt_t                               *p_arp;\r
+       const ipoib_arp_pkt_t   *p_ib_arp;\r
+       ib_gid_t                                gid;\r
+       mac_addr_t                              mac;\r
+       ipoib_hw_addr_t                 null_hw = {0};\r
+       uint8_t                                 cm_capable = 0;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       if( !p_dst )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Unknown destination endpoint\n") );\r
+               return IB_INVALID_SETTING;\r
+       }\r
+\r
+       p_ib_arp = &p_ipoib->type.arp;\r
+       p_arp = &p_eth->type.arp;\r
+\r
+       if( p_ib_arp->hw_type != ARP_HW_TYPE_IB )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ARP hardware type is not IB\n") );\r
+               return IB_INVALID_SETTING;\r
+       }\r
+\r
+       if( p_ib_arp->hw_size != sizeof(ipoib_hw_addr_t) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ARP hardware address size is not sizeof(ipoib_hw_addr_t)\n") );\r
+               return IB_INVALID_SETTING;\r
+       }\r
+\r
+       if( p_ib_arp->prot_type != ETH_PROT_TYPE_IP )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ARP protocal type not IP\n") );\r
+               return IB_INVALID_SETTING;\r
+       }\r
+\r
+       cm_capable = ipoib_addr_get_flags( &p_ib_arp->src_hw );\r
+\r
+       /*\r
+        * If we don't have a source, lookup the endpoint specified in the payload.\r
+        */\r
+       if( !*pp_src )\r
+               *pp_src = __endpt_mgr_get_by_gid( p_port, &p_ib_arp->src_hw.gid );\r
+\r
+       /*\r
+        * If the endpoint exists for the GID, make sure\r
+        * the dlid and qpn match the arp.\r
+        */\r
+       if( *pp_src )\r
+       {\r
+               if( cl_memcmp( &(*pp_src)->dgid, &p_ib_arp->src_hw.gid,\r
+                       sizeof(ib_gid_t) ) )\r
+               {\r
+                       /*\r
+                        * GIDs for the endpoint are different.  The ARP must\r
+                        * have been proxied.  Dereference it.\r
+                        */\r
+                       *pp_src = NULL;\r
+               }\r
+               else if( (*pp_src)->dlid &&\r
+                       (*pp_src)->dlid != p_wc->recv.ud.remote_lid )\r
+               {\r
+                       /* Out of date!  Destroy the endpoint and replace it. */\r
+                       __endpt_mgr_remove( p_port, *pp_src );\r
+                       *pp_src = NULL;\r
+               }\r
+               else if ( ! ((*pp_src)->dlid)) {\r
+                       /* Out of date!  Destroy the endpoint and replace it. */\r
+                       __endpt_mgr_remove( p_port, *pp_src );\r
+                       *pp_src = NULL;\r
+               }\r
+               else if( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) )\r
+               {\r
+                       if( (*pp_src)->qpn != ipoib_addr_get_qpn( &p_ib_arp->src_hw ) &&\r
+                                p_wc->recv.ud.remote_qp !=     ipoib_addr_get_qpn( &p_ib_arp->src_hw ) )\r
+                       {\r
+                               /* Out of date!  Destroy the endpoint and replace it. */\r
+                               __endpt_mgr_remove( p_port, *pp_src );\r
+                               *pp_src = NULL;\r
+                       }\r
+               }\r
+               else if( (*pp_src)->qpn != p_wc->recv.ud.remote_qp )\r
+               {\r
+                       /* Out of date!  Destroy the endpoint and replace it. */\r
+                       __endpt_mgr_remove( p_port, *pp_src );\r
+                       *pp_src = NULL;\r
+               }\r
+       }\r
+\r
+       /* Do we need to create an endpoint for this GID? */\r
+       if( !*pp_src )\r
+       {\r
+               /* Copy the src GID to allow aligned access */\r
+               cl_memcpy( &gid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) );\r
+               status = ipoib_mac_from_guid( gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
+               if (status == IB_INVALID_GUID_MASK)\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
+                               ("Invalid GUID mask received, rejecting it") );\r
+                       ipoib_create_log(p_port->p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+               }\r
+               else if( status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ipoib_mac_from_guid returned %s\n",\r
+                               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                       return status;\r
+               }\r
+               /*\r
+                * Create the endpoint.\r
+                */\r
+               *pp_src = ipoib_endpt_create( &p_ib_arp->src_hw.gid,\r
+                       p_wc->recv.ud.remote_lid, ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
+\r
+               if( !*pp_src )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ipoib_endpt_create failed\n") );\r
+                       return status;\r
+               }\r
+\r
+               cl_obj_lock( &p_port->obj );\r
+               status = __endpt_mgr_insert( p_port, mac, *pp_src );\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       cl_obj_unlock( &p_port->obj );\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("__endpt_mgr_insert return %s \n",\r
+                               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                       return status;\r
+               }\r
+\r
+               cl_obj_unlock( &p_port->obj );\r
+       }\r
+\r
+       (*pp_src)->cm_flag = cm_capable;\r
+\r
+       CL_ASSERT( !cl_memcmp(\r
+               &(*pp_src)->dgid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) ) );\r
+       CL_ASSERT( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) ||\r
+               (*pp_src)->qpn == ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
+#if 0\r
+       if( p_port->p_adapter->params.cm_enabled &&\r
+               p_ib_arp->op == ARP_OP_REQ &&\r
+               cm_capable == IPOIB_CM_FLAG_RC )\r
+       {\r
+               /* if we've got ARP request and RC flag is set, \r
+               save SID for connect REQ to be sent in ARP reply\r
+               when requestor's path get resolved */\r
+               if( endpt_cm_get_state( (*pp_src) ) == IPOIB_CM_DISCONNECTED )\r
+               {\r
+                       (*pp_src)->cm_flag = cm_capable;\r
+                       ipoib_addr_set_sid( \r
+                               &(*pp_src)->conn.service_id,\r
+                               ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
+               }\r
+       }\r
+#endif\r
+#if 0 //DBG\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       (" ARP %s from ENDPT[%p] state %d CM cap: %d QPN: %#x MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+                       ((p_ib_arp->op == ARP_OP_REQ )? "REQUEST" : "REPLY"),\r
+                       *pp_src, endpt_cm_get_state( *pp_src ), \r
+                       ((cm_capable == IPOIB_CM_FLAG_RC)? 1: 0),\r
+                       cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ),\r
+                       (*pp_src)->mac.addr[0], (*pp_src)->mac.addr[1],\r
+                       (*pp_src)->mac.addr[2], (*pp_src)->mac.addr[3],\r
+                       (*pp_src)->mac.addr[4], (*pp_src)->mac.addr[5] ));\r
+       }\r
+#endif\r
+\r
+       /* Now swizzle the data. */\r
+       p_arp->hw_type = ARP_HW_TYPE_ETH;\r
+       p_arp->hw_size = sizeof(mac_addr_t);\r
+       p_arp->src_hw = (*pp_src)->mac;\r
+       p_arp->src_ip = p_ib_arp->src_ip;\r
+\r
+       if( cl_memcmp( &p_ib_arp->dst_hw, &null_hw, sizeof(ipoib_hw_addr_t) ) )\r
+       {\r
+               if( cl_memcmp( &p_dst->dgid, &p_ib_arp->dst_hw.gid, sizeof(ib_gid_t) ) )\r
+               {\r
+                       /*\r
+                        * We received bcast ARP packet that means\r
+                        * remote port lets everyone know it was changed IP/MAC\r
+                        * or just activated\r
+                        */\r
+\r
+                       /* Guy: TODO: Check why this check fails in case of Voltaire IPR */\r
+\r
+                       if ( !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) &&\r
+                                !ib_gid_is_multicast( (const ib_gid_t*)&p_dst->dgid ) )\r
+                       {\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("ARP: is not ARP MCAST\n") );\r
+                               return IB_INVALID_SETTING;\r
+                       }\r
+\r
+                       p_arp->dst_hw = p_port->p_local_endpt->mac;\r
+                       p_dst->mac = p_port->p_local_endpt->mac;\r
+                       /*\r
+                        * we don't care what receiver ip addr is,\r
+                        * as long as OS' ARP table is global  ???\r
+                        */\r
+                       p_arp->dst_ip = (net32_t)0;\r
+               }\r
+               else /* we've got reply to our ARP request */\r
+               {\r
+                       p_arp->dst_hw = p_dst->mac;\r
+                       p_arp->dst_ip = p_ib_arp->dst_ip;\r
+                       CL_ASSERT( p_dst->qpn == ipoib_addr_get_qpn( &p_ib_arp->dst_hw ) );\r
+               }\r
+       }\r
+       else /* we got ARP reqeust */\r
+       {\r
+               cl_memclr( &p_arp->dst_hw, sizeof(mac_addr_t) );\r
+               p_arp->dst_ip = p_ib_arp->dst_ip;\r
+       }\r
+\r
+       /*\r
+        * Create the ethernet header.  Note that this is done last so that\r
+        * we have a chance to create a new endpoint.\r
+        */\r
+       status = __recv_gen( p_ipoib, p_eth, *pp_src, p_dst );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__recv_gen returned %s.\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_mgr_prepare_pkt(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t*      const   p_desc,\r
+               OUT                     NET_BUFFER_LIST** const         pp_net_buffer_list )\r
+{\r
+       NDIS_STATUS                                                     status;\r
+       uint32_t                                                        pkt_filter;\r
+       ip_stat_sel_t                                           type;\r
+       //NDIS60\r
+       NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO       chksum;\r
+       //NDIS_TCP_IP_CHECKSUM_PACKET_INFO      chksum;\r
+\r
+       PERF_DECLARE( GetNdisPkt );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       pkt_filter = p_port->p_adapter->packet_filter;\r
+       /* Check the packet filter. */\r
+       switch( p_desc->type )\r
+       {\r
+       default:\r
+       case PKT_TYPE_UCAST:\r
+               \r
+               if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ||\r
+                       pkt_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL ||\r
+                       pkt_filter & NDIS_PACKET_TYPE_SOURCE_ROUTING ||\r
+                       pkt_filter & NDIS_PACKET_TYPE_DIRECTED )\r
+               {\r
+                       /* OK to report. */\r
+                       type = IP_STAT_UCAST_BYTES;\r
+                       status = NDIS_STATUS_SUCCESS;\r
+                       IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
+                       ("Received UCAST PKT.\n"));\r
+               }\r
+               else\r
+               {\r
+                       type = IP_STAT_DROPPED;\r
+                       status = NDIS_STATUS_FAILURE;\r
+                       IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
+                       ("Received UCAST PKT with ERROR !!!!\n"));\r
+               }\r
+               break;\r
+       case PKT_TYPE_BCAST:\r
+               if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ||\r
+                       pkt_filter & NDIS_PACKET_TYPE_BROADCAST )\r
+               {\r
+                       /* OK to report. */\r
+                       type = IP_STAT_BCAST_BYTES;\r
+                       status = NDIS_STATUS_SUCCESS;\r
+                       IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
+                       ("Received BCAST PKT.\n"));\r
+               }\r
+               else\r
+               {\r
+                       type = IP_STAT_DROPPED;\r
+                       status = NDIS_STATUS_FAILURE;\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Received BCAST PKT with ERROR !!!!\n"));\r
+               }\r
+               break;\r
+       case PKT_TYPE_MCAST:\r
+               if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ||\r
+                       pkt_filter & NDIS_PACKET_TYPE_ALL_MULTICAST ||\r
+                       pkt_filter & NDIS_PACKET_TYPE_MULTICAST )\r
+               {\r
+                       /* OK to report. */\r
+                       type = IP_STAT_MCAST_BYTES;\r
+                       status = NDIS_STATUS_SUCCESS;\r
+                       IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
+                       ("Received UCAST PKT.\n"));\r
+               }\r
+               else\r
+               {\r
+                       type = IP_STAT_DROPPED;\r
+                       status = NDIS_STATUS_FAILURE;\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Received MCAST PKT with ERROR !!!!\n"));\r
+               }\r
+               break;\r
+       }\r
+\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               ipoib_inc_recv_stat( p_port->p_adapter, type, 0, 0 );\r
+               /* Return the receive descriptor to the pool. */\r
+               __buf_mgr_put_recv( p_port, p_desc, NULL );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_RECV,\r
+                       ("Packet filter doesn't match receive.  Dropping.\n") );\r
+               /*\r
+                * Return IB_NOT_DONE since the packet has been completed,\r
+                * but has not consumed an array entry.\r
+                */\r
+               return IB_NOT_DONE;\r
+       }\r
+\r
+       cl_perf_start( GetNdisPkt );\r
+       *pp_net_buffer_list = __buf_mgr_get_ndis_pkt( p_port, p_desc );\r
+       cl_perf_stop( &p_port->p_adapter->perf, GetNdisPkt );\r
+       if( !*pp_net_buffer_list )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__buf_mgr_get_ndis_pkt failed\n") );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       chksum.Value = 0;\r
+       switch( p_port->p_adapter->params.recv_chksum_offload )\r
+       {\r
+         default:\r
+               CL_ASSERT( FALSE );\r
+         case CSUM_DISABLED:\r
+               //NDIS60\r
+               //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) =\r
+               //(void*)(uintn_t)chksum.Value;\r
+               NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) = \r
+               (void*)(uintn_t)chksum.Value;\r
+               break;\r
+         case CSUM_ENABLED:\r
+               /* Get the checksums directly from packet information. */\r
+               /* In this case, no one of cheksum's cat get false value */\r
+               /* If hardware checksum failed or wasn't calculated, NDIS will recalculate it again */\r
+               //NDIS60\r
+               //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) = \r
+               NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) =\r
+                       (void*)(uintn_t)(p_desc->ndis_csum.Value);\r
+               break;\r
+         case CSUM_BYPASS:\r
+               /* Flag the checksums as having been calculated. */\r
+               chksum.Receive.TcpChecksumSucceeded = TRUE;\r
+               chksum.Receive.UdpChecksumSucceeded = TRUE;\r
+               chksum.Receive.IpChecksumSucceeded = TRUE;\r
+               //NDIS60\r
+               //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) =\r
+               NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) =\r
+               (void*)(uintn_t)chksum.Value;\r
+               break;\r
+       }\r
+       ipoib_inc_recv_stat( p_port->p_adapter, type, p_desc->len, 1 );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static uint32_t\r
+__recv_mgr_build_pkt_array(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              int32_t                                         shortage,\r
+               OUT                     cl_qlist_t* const                       p_done_list,\r
+               OUT                     int32_t* const                          p_discarded )\r
+{\r
+       cl_list_item_t                  *p_item;\r
+       ipoib_recv_desc_t               *p_desc;\r
+       uint32_t                                i = 0;\r
+       ib_api_status_t                 status;\r
+       PERF_DECLARE( PreparePkt );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       *p_discarded = 0;\r
+\r
+       /* Move any existing receives to the head to preserve ordering. */\r
+       cl_qlist_insert_list_head( p_done_list, &p_port->recv_mgr.done_list );\r
+       p_item = cl_qlist_remove_head( p_done_list );\r
+       while( p_item != cl_qlist_end( p_done_list ) )\r
+       {\r
+               p_desc = (ipoib_recv_desc_t*)p_item;\r
+\r
+               cl_perf_start( PreparePkt );\r
+               status = __recv_mgr_prepare_pkt( p_port, p_desc,\r
+                       &p_port->recv_mgr.recv_pkt_array[i] );\r
+               cl_perf_stop( &p_port->p_adapter->perf, PreparePkt );\r
+               if( status == IB_SUCCESS )\r
+               {\r
+                       CL_ASSERT( p_port->recv_mgr.recv_pkt_array[i] );\r
+                       if( shortage-- > 0 )\r
+                       {\r
+                               NET_BUFFER_LIST_STATUS(p_port->recv_mgr.recv_pkt_array[i])= NDIS_STATUS_RESOURCES;                                      \r
+                       }\r
+                       else\r
+                       {\r
+                               NET_BUFFER_LIST_STATUS(p_port->recv_mgr.recv_pkt_array[i])=  NDIS_STATUS_SUCCESS;\r
+                       }\r
+                       i++;\r
+               }\r
+               else if( status == IB_NOT_DONE )\r
+               {\r
+                       (*p_discarded)++;\r
+               }\r
+               else\r
+               {\r
+                       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+                               ("__recv_mgr_prepare_pkt returned %s\n",\r
+                               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                       /* Put all completed receives on the port's done list. */\r
+                       cl_qlist_insert_tail( &p_port->recv_mgr.done_list, p_item );\r
+                       cl_qlist_insert_list_tail( &p_port->recv_mgr.done_list, p_done_list );\r
+                       break;\r
+               }\r
+\r
+               p_item = cl_qlist_remove_head( p_done_list );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return i;\r
+}\r
+\r
+\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Send manager implementation.\r
+*\r
+******************************************************************************/\r
+static void\r
+__send_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+       p_port->send_mgr.depth = 0;\r
+       cl_qlist_init( &p_port->send_mgr.pending_list );\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+\r
+static void \r
+__pending_list_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       cl_list_item_t  *p_item;\r
+       NET_BUFFER_LIST         **pp_net_buffer_list, *p_head;\r
+       \r
+       p_head = NULL;\r
+       cl_spinlock_acquire( &p_port->send_lock );\r
+       /* Complete any pending packets. */\r
+       pp_net_buffer_list = &p_head;\r
+       for( p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list );\r
+               p_item != cl_qlist_end( &p_port->send_mgr.pending_list );\r
+               p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list ) )\r
+       {\r
+               *pp_net_buffer_list = IPOIB_PACKET_FROM_LIST_ITEM( p_item );\r
+               NET_BUFFER_LIST_STATUS(*pp_net_buffer_list) = NDIS_STATUS_RESET_IN_PROGRESS;\r
+               pp_net_buffer_list = &(NET_BUFFER_LIST_NEXT_NBL(*pp_net_buffer_list));\r
+       }\r
+       cl_spinlock_release( &p_port->send_lock );\r
+       if(p_head)\r
+               NdisMSendNetBufferListsComplete(\r
+            p_port->p_adapter->h_adapter,\r
+            p_head,\r
+            0);   \r
+}\r
+\r
+static void\r
+__send_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+       __pending_list_destroy(p_port);\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL* const                                      p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc )\r
+{\r
+       NDIS_STATUS             status;\r
+\r
+       PERF_DECLARE( FilterIp );\r
+       PERF_DECLARE( FilterArp );\r
+       PERF_DECLARE( SendGen );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       /*\r
+        * We already checked the ethernet header length, so we know it's safe\r
+        * to decrement the buf_len without underflowing.\r
+        */\r
+       buf_len -= sizeof(eth_hdr_t);\r
+\r
+       switch( p_eth_hdr->type )\r
+       {\r
+       case ETH_PROT_TYPE_IP:\r
+               cl_perf_start( FilterIp );\r
+               status = __send_mgr_filter_ip(\r
+                       p_port, p_eth_hdr, p_mdl, buf_len, p_sgl, p_desc);\r
+               cl_perf_stop( &p_port->p_adapter->perf, FilterIp );\r
+               break;\r
+\r
+       case ETH_PROT_TYPE_ARP:\r
+               cl_perf_start( FilterArp );\r
+               status = __send_mgr_filter_arp(\r
+                       p_port, p_eth_hdr, p_mdl, buf_len, p_desc );\r
+               p_desc->send_dir = SEND_UD_QP;\r
+               cl_perf_stop( &p_port->p_adapter->perf, FilterArp );\r
+               break;\r
+\r
+       default:\r
+               /*\r
+                * The IPoIB spec doesn't define how to send non IP or ARP packets.\r
+                * Just send the payload and hope for the best.\r
+                */\r
+\r
+               p_desc->send_dir = SEND_UD_QP;\r
+               cl_perf_start( SendGen );\r
+               status = __send_gen( p_port, p_desc, p_sgl, 0 );\r
+               cl_perf_stop( &p_port->p_adapter->perf, SendGen );\r
+               break;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return status;\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__send_copy(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc )\r
+{\r
+       NET_BUFFER_LIST                 *p_net_buffer_list;\r
+       NET_BUFFER                              *p_netbuffer;\r
+       MDL                                             *p_mdl;\r
+       UINT                                    tot_len = 0;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       UNREFERENCED_PARAMETER(p_port);\r
+       UNREFERENCED_PARAMETER(p_desc);\r
+\r
+       p_desc->p_buf = \r
+               NdisAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+       if( !p_desc->p_buf )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate buffer for packet copy.\n") );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+\r
+       p_mdl = NdisAllocateMdl(p_port->p_adapter->h_adapter,\r
+                                                       p_desc->p_buf,\r
+                                                       p_port->p_adapter->params.xfer_block_size );\r
+       if( !p_mdl )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate MDL\n") );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+\r
+       p_net_buffer_list = NdisAllocateNetBufferAndNetBufferList(\r
+                                               p_port->buf_mgr.h_send_buf_pool,\r
+                                               0,\r
+                                               0,\r
+                                               p_mdl,\r
+                                               0,\r
+                                               0);\r
+\r
+       if( !p_net_buffer_list )\r
+       {\r
+               NdisFreeMdl(p_mdl);\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+                       ("Failed to allocate NDIS_PACKET for copy.\n") );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+\r
+       for (p_netbuffer = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list); \r
+                p_netbuffer != NULL;\r
+                p_netbuffer = NET_BUFFER_NEXT_NB(p_netbuffer))\r
+       {\r
+               tot_len +=NET_BUFFER_DATA_LENGTH(p_netbuffer);\r
+       }\r
+\r
+       /* Setup the work request. */\r
+       p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr(\r
+               ((uint8_t*)p_desc->p_buf) + sizeof(eth_hdr_t) );\r
+       p_desc->send_wr[0].local_ds[1].length = tot_len - sizeof(eth_hdr_t);\r
+       p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey;\r
+       p_desc->send_wr[0].wr.num_ds = 2;\r
+       \r
+       /* Free our temp packet now that the data is copied. */\r
+       NdisFreeMdl(p_mdl);\r
+       NdisFreeNetBufferList(p_net_buffer_list);\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static inline NDIS_STATUS\r
+__send_mgr_get_eth_hdr(\r
+       IN                              PNET_BUFFER                                     p_net_buffer,\r
+               OUT                     MDL** const                                     pp_mdl,\r
+               OUT                     eth_hdr_t** const                       pp_eth_hdr,\r
+               OUT                     UINT*                                           p_mdl_len)\r
+{\r
+       PUCHAR  p_head = NULL;\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       *pp_mdl = NET_BUFFER_FIRST_MDL(p_net_buffer);\r
+\r
+       NdisQueryMdl(*pp_mdl,&p_head,p_mdl_len,NormalPagePriority);\r
+       if( ! p_head )\r
+       {\r
+               /* Failed to get first buffer. */\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisQueryMdl failed.\n") );\r
+               return NDIS_STATUS_FAILURE;\r
+       }\r
+\r
+       if( *p_mdl_len < sizeof(eth_hdr_t) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("First buffer in packet smaller than eth_hdr_t: %d.\n",\r
+                       *p_mdl_len) );\r
+               return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+       }\r
+\r
+       *pp_eth_hdr = (eth_hdr_t*)(p_head + NET_BUFFER_CURRENT_MDL_OFFSET(p_net_buffer));\r
+\r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+               ("Ethernet header:\n"\r
+               "\tsrc MAC: %02X-%02X-%02X-%02X-%02X-%02X\n"\r
+               "\tdst MAC: %02X-%02X-%02X-%02X-%02X-%02X\n"\r
+               "\tprotocol type: %04X\n",\r
+               (*pp_eth_hdr)->src.addr[0], (*pp_eth_hdr)->src.addr[1],\r
+               (*pp_eth_hdr)->src.addr[2], (*pp_eth_hdr)->src.addr[3],\r
+               (*pp_eth_hdr)->src.addr[4], (*pp_eth_hdr)->src.addr[5],\r
+               (*pp_eth_hdr)->dst.addr[0], (*pp_eth_hdr)->dst.addr[1],\r
+               (*pp_eth_hdr)->dst.addr[2], (*pp_eth_hdr)->dst.addr[3],\r
+               (*pp_eth_hdr)->dst.addr[4], (*pp_eth_hdr)->dst.addr[5],\r
+               cl_ntoh16( (*pp_eth_hdr)->type )) );\r
+\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+#if !IPOIB_USE_DMA\r
+/* Send using the MDL's page information rather than the SGL. */\r
+static ib_api_status_t\r
+__send_gen(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc )\r
+{\r
+       uint32_t                                i, j = 1;\r
+       ULONG                                   offset;\r
+       MDL                                             *p_mdl;\r
+       UINT                                    num_pages, tot_len;\r
+       ULONG                                   buf_len;\r
+       PPFN_NUMBER                             page_array;\r
+       boolean_t                               hdr_done = FALSE;\r
+       ib_api_status_t                 status;\r
+       PNET_BUFFER                             p_net_buf;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+       p_net_buf = NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list);\r
+       NdisQueryBuffer( p_net_buf, &num_pages, NULL, &p_mdl,\r
+               &tot_len );\r
+\r
+       if( !p_mdl )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("No buffers associated with packet.\n") );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       /* Remember that one of the DS entries is reserved for the IPoIB header. */\r
+       if( num_pages >= MAX_SEND_SGE )\r
+       {\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+                       ("Too many buffers to fit in WR ds_array.  Copying data.\n") );\r
+               status = __send_copy( p_port, p_desc );\r
+               IPOIB_EXIT( IPOIB_DBG_SEND );\r
+               return status;\r
+       }\r
+\r
+       CL_ASSERT( tot_len > sizeof(eth_hdr_t) );\r
+       CL_ASSERT( tot_len <= p_port->p_adapter->params.xfer_block_size );\r
+       /*\r
+        * Assume that the ethernet header is always fully contained\r
+        * in the first page of the first MDL.  This makes for much\r
+        * simpler code.\r
+        */\r
+       offset = MmGetMdlByteOffset( p_mdl ) + sizeof(eth_hdr_t);\r
+       CL_ASSERT( offset <= PAGE_SIZE );\r
+\r
+       while( tot_len )\r
+       {\r
+               buf_len = MmGetMdlByteCount( p_mdl );\r
+               page_array = MmGetMdlPfnArray( p_mdl );\r
+               CL_ASSERT( page_array );\r
+               i = 0;\r
+               if( !hdr_done )\r
+               {\r
+                       CL_ASSERT( buf_len >= sizeof(eth_hdr_t) );\r
+                       /* Skip the ethernet header. */\r
+                       buf_len -= sizeof(eth_hdr_t);\r
+                       CL_ASSERT( buf_len <= p_port->p_adapter->params.payload_mtu );\r
+                       if( buf_len )\r
+                       {\r
+                               /* The ethernet header is a subset of this MDL. */\r
+                               CL_ASSERT( i == 0 );\r
+                               if( offset < PAGE_SIZE )\r
+                               {\r
+                                       p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
+                                       p_desc->send_wr[0].local_ds[j].vaddr = (page_array[i] << PAGE_SHIFT);\r
+                                       /* Add the byte offset since we're on the 1st page. */\r
+                                       p_desc->send_wr[0].local_ds[j].vaddr += offset;\r
+                                       if( offset + buf_len > PAGE_SIZE )\r
+                                       {\r
+                                               p_desc->send_wr[0].local_ds[j].length = PAGE_SIZE - offset;\r
+                                               buf_len -= p_desc->send_wr[0].local_ds[j].length;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               p_desc->send_wr[0].local_ds[j].length = buf_len;\r
+                                               buf_len = 0;\r
+                                       }\r
+                                       /* This data segment is done.  Move to the next. */\r
+                                       j++;\r
+                               }\r
+                               /* This page is done.  Move to the next. */\r
+                               i++;\r
+                       }\r
+                       /* Done handling the ethernet header. */\r
+                       hdr_done = TRUE;\r
+               }\r
+\r
+               /* Finish this MDL */\r
+               while( buf_len )\r
+               {\r
+                       p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
+                       p_desc->send_wr[0].local_ds[j].vaddr = (page_array[i] << PAGE_SHIFT);\r
+                       /* Add the first page's offset if we're on the first page. */\r
+                       if( i == 0 )\r
+                               p_desc->send_wr[0].local_ds[j].vaddr += MmGetMdlByteOffset( p_mdl );\r
+\r
+                       if( i == 0 && (MmGetMdlByteOffset( p_mdl ) + buf_len) > PAGE_SIZE )\r
+                       {\r
+                               /* Buffers spans pages. */\r
+                               p_desc->send_wr[0].local_ds[j].length =\r
+                                       PAGE_SIZE - MmGetMdlByteOffset( p_mdl );\r
+                               buf_len -= p_desc->send_wr[0].local_ds[j].length;\r
+                               /* This page is done.  Move to the next. */\r
+                               i++;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Last page of the buffer. */\r
+                               p_desc->send_wr[0].local_ds[j].length = buf_len;\r
+                               buf_len = 0;\r
+                       }\r
+                       /* This data segment is done.  Move to the next. */\r
+                       j++;\r
+               }\r
+\r
+               tot_len -= MmGetMdlByteCount( p_mdl );\r
+               if( !tot_len )\r
+                       break;\r
+\r
+               NdisGetNextBuffer( p_mdl, &p_mdl );\r
+               if( !p_mdl )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get next buffer.\n") );\r
+                       return IB_ERROR;\r
+               }\r
+       }\r
+\r
+       /* Set the number of data segments. */\r
+       p_desc->send_wr[0].wr.num_ds = j;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+#else\r
+\r
+\r
+void \r
+ipoib_process_sg_list1(\r
+    IN  PDEVICE_OBJECT          pDO,\r
+    IN  PVOID                   pIrp,\r
+    IN  PSCATTER_GATHER_LIST    p_sgl,\r
+    IN  PVOID                   context\r
+    )\r
+{\r
+       int i;\r
+       char temp[200];\r
+       for (i = 0 ; i < 1;i++)\r
+               temp[i] = 5;\r
+}\r
+\r
+\r
+void \r
+ipoib_process_sg_list(\r
+    IN  PDEVICE_OBJECT          pDO,\r
+    IN  PVOID                   pIrp,\r
+    IN  PSCATTER_GATHER_LIST    p_sgl,\r
+    IN  PVOID                   context\r
+    )\r
+{      \r
+       NDIS_STATUS                             status;\r
+       ipoib_port_t                    *p_port;\r
+       MDL                                             *p_mdl;\r
+       eth_hdr_t                               *p_eth_hdr;\r
+       UINT                                    mdl_len;\r
+       static ipoib_send_desc_t                *p_desc = NULL;\r
+       ib_send_wr_t                    *p_wr_failed;\r
+       NET_BUFFER_LIST                 *p_net_buffer_list;\r
+       NET_BUFFER                              *p_netbuf;\r
+       boolean_t                               from_queue;\r
+       ib_api_status_t                 ib_status;\r
+       ULONG                                   complete_flags = 0;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       UNREFERENCED_PARAMETER(pDO);\r
+       UNREFERENCED_PARAMETER(pIrp);\r
+\r
+       PERF_DECLARE( SendCopy );\r
+       PERF_DECLARE( BuildSendDesc );\r
+       PERF_DECLARE( GetEthHdr );\r
+       PERF_DECLARE( QueuePacket );\r
+       PERF_DECLARE( SendMgrQueue );\r
+       PERF_DECLARE( PostSend );\r
+       PERF_DECLARE( ProcessFailedSends );\r
+       PERF_DECLARE( GetEndpt );\r
+\r
+\r
+       p_netbuf = (NET_BUFFER*)context;\r
+       p_net_buffer_list = (NET_BUFFER_LIST*)IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_netbuf);\r
+       p_port = (ipoib_port_t*)IPOIB_PORT_FROM_PACKET(p_net_buffer_list);\r
+       NDIS_SET_SEND_COMPLETE_FLAG(complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
+\r
+\r
+       cl_spinlock_acquire( &p_port->send_lock );\r
+       if (p_desc == NULL) {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_SEND, ("Allocating send_desc First Time\n") );\r
+               p_desc = ExAllocatePoolWithTag(NonPagedPool ,sizeof (ipoib_send_desc_t), 'XMXA');\r
+       }\r
+       ASSERT(p_desc);\r
+       p_desc->p_netbuf_list = p_net_buffer_list;\r
+       p_desc->p_endpt = NULL;\r
+       p_desc->p_buf = NULL;\r
+       p_desc->num_wrs = 1;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_SEND,\r
+                                               ("\n*******\nRECEIVED NB= %x with SG= %x\n********\n", p_netbuf, p_sgl) );\r
+       /* Get the ethernet header so we can find the endpoint. */\r
+       cl_perf_start( GetEthHdr );\r
+       status = __send_mgr_get_eth_hdr(\r
+               p_netbuf, &p_mdl, &p_eth_hdr, &mdl_len );\r
+       cl_perf_stop( &p_port->p_adapter->perf, GetEthHdr );\r
+\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               cl_perf_start( ProcessFailedSends );\r
+               /* fail  net buffer list */\r
+               __process_failed_send( p_port, p_desc, status, complete_flags);\r
+               cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+               goto send_end;\r
+       }\r
+       //from_queue = (boolean_t)(IPOIB_FROM_QUEUE(p_netbuf) == (void*)1);\r
+       from_queue = (boolean_t)(IPOIB_FROM_QUEUE(p_netbuf) != NULL);\r
+       if (from_queue)\r
+       {\r
+               cl_perf_start( GetEndpt );\r
+               status = __endpt_mgr_ref( p_port, p_eth_hdr->dst, &p_desc->p_endpt );\r
+               cl_perf_stop( &p_port->p_adapter->perf, GetEndpt );\r
+               if( status == NDIS_STATUS_PENDING )\r
+               {\r
+                       IPOIB_FROM_QUEUE(p_netbuf) = p_sgl;\r
+                       cl_qlist_insert_head( &p_port->send_mgr.pending_list,\r
+                               IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_netbuf_list ) );\r
+                       goto send_end;\r
+               }\r
+               else if( status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       ASSERT( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION );\r
+\r
+                       if( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) )\r
+                       {\r
+                               if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst,\r
+                                       IB_MC_REC_STATE_FULL_MEMBER) == IB_SUCCESS )\r
+                               {\r
+                                       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+                                               ("Multicast Mac - trying to join.\n") );\r
+                                       IPOIB_FROM_QUEUE(p_netbuf) = p_sgl;\r
+                                       cl_qlist_insert_head( &p_port->send_mgr.pending_list,\r
+                                               IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_netbuf_list ) );\r
+                                       goto send_end;\r
+                               }\r
+                       }\r
+                       /*\r
+                        * Complete the send as if we sent it - WHQL tests don't like the\r
+                        * sends to fail.\r
+                        */\r
+                       cl_perf_start( ProcessFailedSends );\r
+                       __process_failed_send( p_port, p_desc, NDIS_STATUS_SUCCESS,complete_flags );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+                       goto send_end;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               cl_perf_start( SendMgrQueue );\r
+               if ( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) && \r
+                        p_eth_hdr->type == ETH_PROT_TYPE_IP &&\r
+                        !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) ) \r
+               {\r
+                       ip_hdr_t                        *p_ip_hdr;\r
+                       uint8_t                         *p_tmp;\r
+                       MDL                                     *p_ip_hdr_mdl;\r
+                       UINT                            ip_hdr_mdl_len;\r
+\r
+                       if(mdl_len >= sizeof(ip_hdr_t) + sizeof(eth_hdr_t))\r
+                       {\r
+                               p_ip_hdr = (ip_hdr_t*)(p_eth_hdr + 1);\r
+                       }\r
+                       else\r
+                       {\r
+                               NdisGetNextMdl(p_mdl,&p_ip_hdr_mdl);\r
+                               // Extract the ip hdr \r
+                               if( !p_ip_hdr_mdl )\r
+                               {\r
+                                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Failed to get IP header buffer.\n") );\r
+                                       goto mc_end;\r
+                               }       \r
+                               NdisQueryMdl(p_ip_hdr_mdl,&p_tmp,&ip_hdr_mdl_len,NormalPagePriority);\r
+                               if( !p_tmp )\r
+                               {\r
+                                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Failed to get IP header.\n") );\r
+                                       goto mc_end;\r
+                               }                                       \r
+                               if( ip_hdr_mdl_len < sizeof(ip_hdr_t) )\r
+                               {\r
+                                       /* This buffer is done for.  Get the next buffer. */\r
+                                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Buffer too small for IP packet.\n") );\r
+                                       goto mc_end;\r
+                               }\r
+                               p_ip_hdr = (ip_hdr_t*)(p_tmp + NET_BUFFER_CURRENT_MDL_OFFSET(p_netbuf));\r
+                               p_eth_hdr->dst.addr[1] = ((unsigned char*)&p_ip_hdr->dst_ip)[0] & 0x0f;\r
+                               p_eth_hdr->dst.addr[3] = ((unsigned char*)&p_ip_hdr->dst_ip)[1];\r
+                       }\r
+               }\r
+mc_end:\r
+               status = __send_mgr_queue( p_port, p_eth_hdr, &p_desc->p_endpt );\r
+               cl_perf_stop( &p_port->p_adapter->perf, SendMgrQueue );\r
+               if( status == NDIS_STATUS_PENDING )\r
+               {\r
+                       /* Queue net buffer list. */\r
+                       cl_perf_start( QueuePacket );\r
+                       NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+                       IPOIB_FROM_QUEUE(p_netbuf) = p_sgl;\r
+                       cl_qlist_insert_tail( &p_port->send_mgr.pending_list,\r
+                                       IPOIB_LIST_ITEM_FROM_PACKET(p_net_buffer_list) );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, QueuePacket );\r
+                       goto send_end;\r
+               }\r
+               if( status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       ASSERT( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION );\r
+                       /*\r
+                        * Complete the send as if we sent it - WHQL tests don't like the\r
+                        * sends to fail.\r
+                        */\r
+                       cl_perf_start( ProcessFailedSends );\r
+                       __process_failed_send( p_port, p_desc, NDIS_STATUS_SUCCESS, complete_flags );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+                       goto send_end;\r
+               }\r
+       }\r
+       cl_perf_start( BuildSendDesc );\r
+       status = __build_send_desc( p_port, p_eth_hdr, p_mdl, mdl_len, p_sgl, p_desc );\r
+       cl_perf_stop( &p_port->p_adapter->perf, BuildSendDesc );\r
+\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               cl_perf_start( ProcessFailedSends );\r
+               __process_failed_send( p_port, p_desc, status, complete_flags );\r
+               cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+               goto send_end;\r
+       }\r
+\r
+       /* Post the WR. */\r
+       cl_perf_start( PostSend );\r
+       cl_msg_out("sending packet with wr-id =0x%x\n",&p_desc->send_wr[0].wr.wr_id );\r
+       ib_status = p_port->p_adapter->p_ifc->post_send( p_port->ib_mgr.h_qp, &p_desc->send_wr[0].wr, &p_wr_failed );\r
+       cl_perf_stop( &p_port->p_adapter->perf, PostSend );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_post_send returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+               cl_perf_start( ProcessFailedSends );\r
+               __process_failed_send( p_port, p_desc, NDIS_STATUS_FAILURE, complete_flags );\r
+               cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+               /* Flag the adapter as hung since posting is busted. */\r
+               p_port->p_adapter->hung = TRUE;\r
+       }\r
+       cl_atomic_inc( &p_port->send_mgr.depth );\r
+\r
+send_end:\r
+       if (status != NDIS_STATUS_SUCCESS) {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_SEND,\r
+                                               ("Free S/G List: 0x%x.\n", p_sgl) );\r
+               /*NdisMFreeNetBufferSGList(\r
+                       p_port->p_adapter->NdisMiniportDmaHandle,\r
+                       p_sgl,\r
+                       p_netbuf);*/\r
+               \r
+       }\r
+                       \r
+                       \r
+       cl_spinlock_release( &p_port->send_lock );\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+static NDIS_STATUS\r
+__send_gen(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN                              INT                                                     lso_data_index\r
+        )\r
+{\r
+       ib_api_status_t                 status;\r
+       uint32_t                                i, j = 1;\r
+       uint32_t                                offset = sizeof(eth_hdr_t);\r
+       PERF_DECLARE( SendCopy );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       if( !p_sgl )\r
+       {\r
+               ASSERT( p_sgl );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to get SGL from packet.\n") );\r
+               return NDIS_STATUS_FAILURE;\r
+       }\r
+\r
+       /* Remember that one of the DS entries is reserved for the IPoIB header. */\r
+       if( ( p_sgl->NumberOfElements >= MAX_SEND_SGE ||\r
+               p_sgl->Elements[0].Length < sizeof(eth_hdr_t)) )\r
+       {\r
+\r
+               IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+                       ("Too many buffers %d to fit in WR ds_array[%d] \\r
+                        Or buffer[0] length %d < Eth header. Copying data.\n",\r
+                       p_sgl->NumberOfElements, MAX_SEND_SGE,  p_sgl->Elements[0].Length ) );\r
+               status = NDIS_STATUS_RESOURCES;\r
+               if( !p_port->p_adapter->params.cm_enabled )\r
+               {\r
+                       cl_perf_start( SendCopy );\r
+                       status = __send_copy( p_port, p_desc );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, SendCopy );\r
+               }\r
+               IPOIB_EXIT( IPOIB_DBG_SEND );\r
+               return status;\r
+       }\r
+\r
+       /*\r
+        * Skip the ethernet header.  It is either the first element,\r
+        * or part of it.\r
+        */\r
+       i = 0;\r
+       if( lso_data_index )\r
+       { /* we have an LSO packet */\r
+               i = lso_data_index;\r
+               j = 0;\r
+       }\r
+       else while( offset )\r
+       {\r
+               if( p_sgl->Elements[i].Length <= offset )\r
+               {\r
+                       offset -= p_sgl->Elements[i++].Length;\r
+               }\r
+               else\r
+               {\r
+                       p_desc->send_wr[0].local_ds[j].vaddr =\r
+                               p_sgl->Elements[i].Address.QuadPart + offset;\r
+                       p_desc->send_wr[0].local_ds[j].length =\r
+                               p_sgl->Elements[i].Length - offset;\r
+                       p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
+                       i++;\r
+                       j++;\r
+                       break;\r
+               }\r
+       }\r
+       /* Now fill in the rest of the local data segments. */\r
+       while( i < p_sgl->NumberOfElements )\r
+       {\r
+               p_desc->send_wr[0].local_ds[j].vaddr = p_sgl->Elements[i].Address.QuadPart;\r
+               p_desc->send_wr[0].local_ds[j].length = p_sgl->Elements[i].Length;\r
+               p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
+               i++;\r
+               j++;\r
+       }\r
+\r
+       /* Set the number of data segments. */\r
+       p_desc->send_wr[0].wr.num_ds = j;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+#endif\r
+\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_ip(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc )\r
+{\r
+       NDIS_STATUS             status;\r
+       ip_hdr_t                *p_ip_hdr;\r
+       uint32_t                ip_packet_len;\r
+       size_t                  iph_size_in_bytes;\r
+       size_t                  iph_options_size;\r
+       \r
+       PERF_DECLARE( QueryIp );\r
+       PERF_DECLARE( SendTcp );\r
+       PERF_DECLARE( FilterUdp );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       if( !buf_len )\r
+       {\r
+               cl_perf_start( QueryIp );\r
+               NdisGetNextMdl ( p_mdl, &p_mdl );\r
+               if( !p_mdl )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get IP header buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+\r
+               NdisQueryMdl(p_mdl, &p_ip_hdr, &buf_len, NormalPagePriority);\r
+               if( !p_ip_hdr )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to query IP header buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               cl_perf_stop( &p_port->p_adapter->perf, QueryIp );\r
+       }\r
+       else\r
+       {\r
+               p_ip_hdr = (ip_hdr_t*)(p_eth_hdr + 1);\r
+       }\r
+       if( buf_len < sizeof(ip_hdr_t) )\r
+       {\r
+               /* This buffer is done for.  Get the next buffer. */\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Buffer too small for IP packet.\n") );\r
+               return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+       }\r
+\r
+       switch( p_ip_hdr->prot )\r
+       {\r
+       case IP_PROT_UDP:\r
+\r
+               cl_perf_start( FilterUdp );\r
+               status = __send_mgr_filter_udp(\r
+                       p_port, p_ip_hdr, p_mdl, (buf_len - sizeof(ip_hdr_t)), p_sgl, p_desc );\r
+               cl_perf_stop( &p_port->p_adapter->perf, FilterUdp );\r
+               if( status == NDIS_STATUS_PENDING )\r
+               {  /* not DHCP packet, keep going */\r
+                       if( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) )\r
+                               p_desc->send_dir = SEND_UD_QP;\r
+                       else\r
+                               p_desc->send_dir = SEND_RC_QP;\r
+                       break;\r
+               }\r
+               return status;\r
+       \r
+       case IP_PROT_TCP:\r
+               p_desc->send_dir = SEND_RC_QP;\r
+               break;\r
+       case IP_PROT_IGMP:\r
+               /*\r
+               In igmp packet I saw that iph arrive in 2 NDIS_BUFFERs:\r
+               1. iph\r
+               2. ip options\r
+                               So to get the IGMP packet we need to skip the ip options NDIS_BUFFER\r
+                       */\r
+                       iph_size_in_bytes = (p_ip_hdr->ver_hl & 0xf) * 4;\r
+                       iph_options_size = iph_size_in_bytes - buf_len;\r
+                       buf_len -= sizeof(ip_hdr_t);//without ipheader\r
+\r
+                       /*\r
+               Could be a case that arrived igmp packet not from type IGMPv2 ,\r
+               but IGMPv1 or IGMPv3.\r
+               We anyway pass it to __send_mgr_filter_igmp_v2().\r
+               */\r
+               status =\r
+                       __send_mgr_filter_igmp_v2( p_port, p_ip_hdr, iph_options_size, p_mdl, buf_len );\r
+               if( status != NDIS_STATUS_SUCCESS )\r
+                       return status;\r
+\r
+       case IP_PROT_ICMP:\r
+               p_desc->send_dir = SEND_UD_QP;\r
+       default:\r
+               break;\r
+       }\r
+       \r
+       if( !p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               p_desc->send_dir = SEND_UD_QP;\r
+               goto send_gen;\r
+       }\r
+       else if( endpt_cm_get_state( p_desc->p_endpt ) != IPOIB_CM_CONNECTED )\r
+       {\r
+               p_desc->send_dir = SEND_UD_QP;\r
+       }\r
+       if( p_desc->send_dir == SEND_UD_QP )\r
+       {\r
+               ip_packet_len = cl_ntoh16( p_ip_hdr->length );\r
+               if( ip_packet_len  > p_port->p_adapter->params.payload_mtu )\r
+               {\r
+                       //TODO: NDIS60\r
+                       #if 0\r
+                       status = __send_fragments( p_port, p_desc, (eth_hdr_t* const)p_eth_hdr,\r
+                                               (ip_hdr_t* const)p_ip_hdr, (uint32_t)buf_len, p_mdl );\r
+                       return status;\r
+                       #endif\r
+                       ASSERT(FALSE);\r
+               }\r
+       }\r
+\r
+send_gen:\r
+       cl_perf_start( SendTcp );\r
+       status = __send_gen( p_port, p_desc, p_sgl, 0 );\r
+       cl_perf_stop( &p_port->p_adapter->perf, SendTcp );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return status;\r
+}\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_igmp_v2(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ip_hdr_t* const                         p_ip_hdr,\r
+       IN                              size_t                                          iph_options_size,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len )\r
+{\r
+       igmp_v2_hdr_t           *p_igmp_v2_hdr = NULL;\r
+       NDIS_STATUS                     endpt_status;\r
+       ipoib_endpt_t*          p_endpt = NULL;\r
+       mac_addr_t                      fake_mcast_mac;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+                        ("buf_len = %d,iph_options_size = %d\n",(int)buf_len,(int)iph_options_size ) );\r
+\r
+       if( !buf_len )\r
+       {\r
+               // To get the IGMP packet we need to skip the ip options NDIS_BUFFER (if exists)\r
+               while ( iph_options_size )\r
+               {\r
+                       NdisGetNextMdl( p_mdl, &p_mdl );\r
+                       if( !p_mdl )\r
+                       {\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Failed to get IGMPv2 header buffer.\n") );\r
+                               return NDIS_STATUS_FAILURE;\r
+                       }\r
+                       NdisQueryMdl( p_mdl, &p_igmp_v2_hdr, &buf_len, NormalPagePriority );\r
+                       if( !p_igmp_v2_hdr )\r
+                       {\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Failed to query IGMPv2 header buffer.\n") );\r
+                               return NDIS_STATUS_FAILURE;\r
+                       }\r
+                       iph_options_size-=buf_len;\r
+               }\r
+        \r
+               NdisGetNextMdl( p_mdl, &p_mdl );\r
+               if( !p_mdl )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get IGMPv2 header buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               NdisQueryMdl( p_mdl, &p_igmp_v2_hdr, &buf_len, NormalPagePriority );\r
+               if( !p_igmp_v2_hdr )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to query IGMPv2 header buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               /* assuming ip header and options are in the same packet */\r
+               p_igmp_v2_hdr = GetIpPayloadPtr(p_ip_hdr);\r
+       }\r
+       /* Get the IGMP header length. */\r
+       if( buf_len < sizeof(igmp_v2_hdr_t) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Buffer not large enough for IGMPv2 packet.\n") );\r
+               return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+       }\r
+\r
+       // build fake mac from igmp packet group address\r
+       fake_mcast_mac.addr[0] = 1;\r
+       fake_mcast_mac.addr[1] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[0] & 0x0f;\r
+       fake_mcast_mac.addr[2] = 0x5E;\r
+       fake_mcast_mac.addr[3] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[1];\r
+       fake_mcast_mac.addr[4] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[2];\r
+       fake_mcast_mac.addr[5] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[3];\r
+\r
+       switch ( p_igmp_v2_hdr->type )\r
+       {\r
+       case IGMP_V2_MEMBERSHIP_REPORT:\r
+               /* \r
+                       This mean that some body open listener on this group \r
+                       Change type of mcast endpt to SEND_RECV endpt. So mcast garbage collector \r
+                       will not delete this mcast endpt.\r
+               */\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+                       ("Catched IGMP_V2_MEMBERSHIP_REPORT message\n") );\r
+               endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt );\r
+               if ( p_endpt )\r
+               {\r
+                       cl_obj_lock( &p_port->obj );\r
+                       p_endpt->is_mcast_listener = TRUE;\r
+                       cl_obj_unlock( &p_port->obj );\r
+            ipoib_endpt_deref( p_endpt );\r
+               }\r
+               break;\r
+\r
+       case IGMP_V2_LEAVE_GROUP:\r
+               /* \r
+                       This mean that somebody CLOSE listener on this group .\r
+                   Change type of mcast endpt to SEND_ONLY endpt. So mcast \r
+                       garbage collector will delete this mcast endpt next time.\r
+               */\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+                            ("Catched IGMP_V2_LEAVE_GROUP message\n") );\r
+               endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt );\r
+               if ( p_endpt )\r
+               {\r
+                       cl_obj_lock( &p_port->obj );\r
+                       p_endpt->is_mcast_listener = FALSE;\r
+                       p_endpt->is_in_use = FALSE;\r
+                       cl_obj_unlock( &p_port->obj );\r
+                       ipoib_endpt_deref( p_endpt );\r
+               }\r
+\r
+               __port_do_mcast_garbage(p_port);\r
+\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+                            ("Send Unknown IGMP message: 0x%x \n", p_igmp_v2_hdr->type ) );\r
+               break;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_udp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ip_hdr_t* const                         p_ip_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc )\r
+{\r
+       ib_api_status_t         status;\r
+       udp_hdr_t                       *p_udp_hdr;\r
+       PERF_DECLARE( QueryUdp );\r
+       PERF_DECLARE( SendUdp );\r
+       PERF_DECLARE( FilterDhcp );\r
+       //TODO NDIS60 remove this param\r
+       UNUSED_PARAM(p_sgl);\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       if( !buf_len )\r
+       {\r
+               cl_perf_start( QueryUdp );\r
+               NdisGetNextMdl( p_mdl, &p_mdl );\r
+               if( !p_mdl )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get UDP header buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               NdisQueryMdl( p_mdl, &p_udp_hdr, &buf_len, NormalPagePriority );\r
+               if( !p_udp_hdr )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to query UDP header buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               cl_perf_stop( &p_port->p_adapter->perf, QueryUdp );\r
+       }\r
+       else\r
+       {\r
+               p_udp_hdr = (udp_hdr_t*)GetIpPayloadPtr(p_ip_hdr);\r
+       }\r
+       /* Get the UDP header and check the destination port numbers. */\r
+       \r
+       if (p_ip_hdr->offset > 0) {\r
+               /* This is a fragmented part of UDP packet\r
+                * Only first packet will contain UDP header in such case\r
+                * So, return if offset > 0\r
+                */\r
+                return NDIS_STATUS_PENDING;\r
+       }\r
+                \r
+       if( buf_len < sizeof(udp_hdr_t) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Buffer not large enough for UDP packet.\n") );\r
+               return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+       }\r
+\r
+       if( (p_udp_hdr->src_port != DHCP_PORT_CLIENT ||\r
+               p_udp_hdr->dst_port != DHCP_PORT_SERVER) &&\r
+               (p_udp_hdr->src_port != DHCP_PORT_SERVER ||\r
+               p_udp_hdr->dst_port != DHCP_PORT_CLIENT) )\r
+       {\r
+               /* Not a DHCP packet. */\r
+               return NDIS_STATUS_PENDING;\r
+       }\r
+\r
+       buf_len -= sizeof(udp_hdr_t);\r
+\r
+       /* Allocate our scratch buffer. */\r
+       p_desc->p_buf = (send_buf_t*)\r
+               ExAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+       if( !p_desc->p_buf )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to query DHCP packet buffer.\n") );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+       /* Copy the IP and UDP headers. */\r
+       cl_memcpy( &p_desc->p_buf->ip.hdr, p_ip_hdr , sizeof(ip_hdr_t) );\r
+       cl_memcpy(\r
+               &p_desc->p_buf->ip.prot.udp.hdr, p_udp_hdr, sizeof(udp_hdr_t) );\r
+\r
+       cl_perf_start( FilterDhcp );\r
+       status = __send_mgr_filter_dhcp(\r
+               p_port, p_udp_hdr, p_mdl, buf_len, p_desc );\r
+       cl_perf_stop( &p_port->p_adapter->perf, FilterDhcp );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return status;\r
+}\r
+\r
+unsigned short ipchksum(unsigned short *ip, int len)\r
+{\r
+    unsigned long sum = 0;\r
+\r
+    len >>= 1;\r
+    while (len--) {\r
+        sum += *(ip++);\r
+        if (sum > 0xFFFF)\r
+            sum -= 0xFFFF;\r
+    }\r
+    return (unsigned short)((~sum) & 0x0000FFFF);\r
+}\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_dhcp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   udp_hdr_t* const                        p_udp_hdr,\r
+       IN                              NDIS_BUFFER*                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc )\r
+{\r
+       dhcp_pkt_t                      *p_dhcp;\r
+       dhcp_pkt_t                      *p_ib_dhcp;\r
+       uint8_t                         *p_option, *p_cid = NULL;\r
+       uint8_t                         msg = 0;\r
+       size_t                          len;\r
+       ib_gid_t                        gid;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       if( !buf_len )\r
+       {\r
+               NdisGetNextMdl( p_mdl, &p_mdl );\r
+               if( !p_mdl )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get DHCP buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               NdisQueryMdl( p_mdl, &p_dhcp, &buf_len, NormalPagePriority );\r
+               if( !p_dhcp )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to query DHCP buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               p_dhcp = (dhcp_pkt_t*)(p_udp_hdr + 1);\r
+       }\r
+\r
+       if( buf_len < DHCP_MIN_SIZE )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Buffer not large enough for DHCP packet.\n") );\r
+               return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+       }\r
+\r
+       p_ib_dhcp = &p_desc->p_buf->ip.prot.udp.dhcp;\r
+       cl_memcpy( p_ib_dhcp, p_dhcp, buf_len );\r
+\r
+       /* Now scan through the options looking for the client identifier. */\r
+       p_option = &p_ib_dhcp->options[4];\r
+       while( *p_option != DHCP_OPT_END && p_option < &p_ib_dhcp->options[312] )\r
+       {\r
+               switch( *p_option )\r
+               {\r
+               case DHCP_OPT_PAD:\r
+                       p_option++;\r
+                       break;\r
+\r
+               case DHCP_OPT_MSG:\r
+                       msg = p_option[2];\r
+                       p_option += 3;\r
+                       break;\r
+\r
+               case DHCP_OPT_CLIENT_ID:\r
+                       p_cid = p_option;\r
+                       /* Fall through. */\r
+\r
+               default:\r
+                       /*\r
+                        * All other options have a length byte following the option code.\r
+                        * Offset by the length to get to the next option.\r
+                        */\r
+                       p_option += (p_option[1] + 2);\r
+               }\r
+       }\r
+\r
+       switch( msg )\r
+       {\r
+       /* Client messages */\r
+       case DHCPDISCOVER:\r
+       case DHCPREQUEST:\r
+                       p_ib_dhcp->flags |= DHCP_FLAGS_BROADCAST;\r
+               /* Fall through */\r
+       case DHCPDECLINE:\r
+       case DHCPRELEASE:\r
+       case DHCPINFORM:\r
+               /* Fix up the client identifier option */\r
+               if( p_cid )\r
+               {\r
+                       /* do we need to replace it ?  len eq ETH MAC sz 'and' MAC is mine */\r
+                       if( p_cid[1] == HW_ADDR_LEN+1 && !cl_memcmp( &p_cid[3],\r
+                               &p_port->p_adapter->params.conf_mac.addr, HW_ADDR_LEN ) )\r
+                       {\r
+                               /* Make sure there's room to extend it.  23 is the size of\r
+                                * the CID option for IPoIB.\r
+                                */\r
+                               if( buf_len + 23 - p_cid[1] > sizeof(dhcp_pkt_t) )\r
+                               {\r
+                                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Can't convert CID to IPoIB format.\n") );\r
+                                       return NDIS_STATUS_RESOURCES;\r
+                               }\r
+                               /* Move the existing options down, and add a new CID option */\r
+                               len = p_option - ( p_cid + p_cid[1] + 2 );\r
+                               p_option = p_cid + p_cid[1] + 2;\r
+                               RtlMoveMemory( p_cid, p_option, len );\r
+                               \r
+                               p_cid += len;\r
+                               p_cid[0] = DHCP_OPT_CLIENT_ID;\r
+                               p_cid[1] = 21;\r
+                               p_cid[2] = DHCP_HW_TYPE_IB;\r
+                       }\r
+                       else\r
+                       {\r
+                               p_cid[2] = DHCP_HW_TYPE_IB;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /*\r
+                        * Make sure there's room to extend it.  23 is the size of\r
+                        * the CID option for IPoIB.\r
+                        */\r
+                       if( buf_len + 23 > sizeof(dhcp_pkt_t) )\r
+                       {\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Can't convert CID to IPoIB format.\n") );\r
+                               return NDIS_STATUS_RESOURCES;\r
+                       }\r
+\r
+                       p_cid = p_option;\r
+                       p_option = p_cid + 23;\r
+                       p_option[0] = DHCP_OPT_END;\r
+                       p_cid[0] = DHCP_OPT_CLIENT_ID;\r
+                       p_cid[1] = 21;\r
+                       p_cid[2] = DHCP_HW_TYPE_IB;\r
+               }\r
+\r
+               CL_ASSERT( p_cid[1] == 21 );\r
+               p_cid[23]= DHCP_OPT_END;\r
+               ib_gid_set_default( &gid, p_port->p_adapter->guids.port_guid.guid );\r
+               cl_memcpy( &p_cid[7], &gid, sizeof(ib_gid_t) );\r
+               cl_memcpy( &p_cid[3], &p_port->ib_mgr.qpn, sizeof(p_port->ib_mgr.qpn) );                \r
+               p_ib_dhcp->htype = DHCP_HW_TYPE_IB;\r
+\r
+               /* update lengths to include any change we made */\r
+               p_desc->p_buf->ip.hdr.length = cl_ntoh16( sizeof(ip_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t) );\r
+               p_desc->p_buf->ip.prot.udp.hdr.length = cl_ntoh16( sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t) );\r
+\r
+               /* update crc in ip header */\r
+               //if( !p_port->p_adapter->params.send_chksum_offload )\r
+               //{ //TODO ?\r
+               p_desc->p_buf->ip.hdr.chksum = 0;\r
+               p_desc->p_buf->ip.hdr.chksum = ipchksum((unsigned short*) &p_desc->p_buf->ip.hdr, sizeof(ip_hdr_t));\r
+               //} TODO ??\r
+               break;\r
+\r
+       /* Server messages. */\r
+       case DHCPOFFER:\r
+       case DHCPACK:\r
+       case DHCPNAK:\r
+               /* don't touch server messages */\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalide message type.\n") );\r
+               return NDIS_STATUS_INVALID_DATA;\r
+       }\r
+       /* no chksum for udp */\r
+       p_desc->p_buf->ip.prot.udp.hdr.chksum = 0;\r
+       p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( p_desc->p_buf );\r
+       p_desc->send_wr[0].local_ds[1].length = sizeof(ip_hdr_t) +      sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t);\r
+       p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey;\r
+       p_desc->send_wr[0].wr.num_ds = 2;\r
+       p_desc->send_dir = SEND_UD_QP;\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_arp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc )\r
+{\r
+       arp_pkt_t                       *p_arp;\r
+       ipoib_arp_pkt_t         *p_ib_arp;\r
+       NDIS_STATUS                     status;\r
+       mac_addr_t                      null_hw = {0};\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+       \r
+       if( !buf_len )\r
+       {\r
+               NdisGetNextMdl( p_mdl, &p_mdl );\r
+               if( !p_mdl )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get ARP buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               NdisQueryMdl( p_mdl, &p_arp, &buf_len, NormalPagePriority );\r
+               if( !p_arp )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get query ARP buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               p_arp = (arp_pkt_t*)(p_eth_hdr + 1);\r
+       }\r
+\r
+       /* Single buffer ARP packet. */\r
+       if( buf_len < sizeof(arp_pkt_t) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Buffer too short for ARP.\n") );\r
+               return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+       }\r
+\r
+       if( p_arp->prot_type != ETH_PROT_TYPE_IP )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Unsupported protocol type.\n") );\r
+               return NDIS_STATUS_INVALID_DATA;\r
+       }\r
+\r
+       /* Allocate our scratch buffer. */\r
+       p_desc->p_buf = (send_buf_t*)\r
+               NdisAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+       if( !p_desc->p_buf )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to query ARP packet buffer.\n") );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+       p_ib_arp = (ipoib_arp_pkt_t*)p_desc->p_buf;\r
+\r
+       /* Convert the ARP payload. */\r
+       p_ib_arp->hw_type = ARP_HW_TYPE_IB;\r
+       p_ib_arp->prot_type = p_arp->prot_type;\r
+       p_ib_arp->hw_size = sizeof(ipoib_hw_addr_t);\r
+       p_ib_arp->prot_size = p_arp->prot_size;\r
+       p_ib_arp->op = p_arp->op;\r
+       \r
+       ipoib_addr_set_qpn( &p_ib_arp->src_hw, p_port->ib_mgr.qpn );\r
+#if 0\r
+\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               ipoib_addr_set_flags( &p_ib_arp->src_hw, IPOIB_CM_FLAG_RC );\r
+       }\r
+#endif\r
+\r
+       ib_gid_set_default( &p_ib_arp->src_hw.gid,\r
+               p_port->p_adapter->guids.port_guid.guid );\r
+       p_ib_arp->src_ip = p_arp->src_ip;\r
+       if( cl_memcmp( &p_arp->dst_hw, &null_hw, sizeof(mac_addr_t) ) )\r
+       {\r
+               /* Get the endpoint referenced by the dst_hw address. */\r
+               net32_t qpn = 0;\r
+               status = __endpt_mgr_get_gid_qpn( p_port, p_arp->dst_hw,\r
+                       &p_ib_arp->dst_hw.gid, &qpn );\r
+               if( status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed lookup of destination HW address\n") );\r
+                       return status;\r
+               }\r
+               ipoib_addr_set_qpn( &p_ib_arp->dst_hw, qpn );\r
+#if 0\r
+               if( p_arp->op == ARP_OP_REP && \r
+                       p_port->p_adapter->params.cm_enabled && \r
+                       p_desc->p_endpt->cm_flag == IPOIB_CM_FLAG_RC )\r
+               {\r
+                       cm_state_t      cm_state;\r
+                       cm_state = \r
+                               ( cm_state_t )InterlockedCompareExchange( (volatile LONG *)&p_desc->p_endpt->conn.state,\r
+                                                               IPOIB_CM_CONNECT, IPOIB_CM_DISCONNECTED );\r
+                       switch( cm_state )\r
+                       {\r
+                       case IPOIB_CM_DISCONNECTED:\r
+                                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                                               ("ARP REPLY pending Endpt[%p] QPN %#x MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+                                               p_desc->p_endpt, \r
+                                               cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->dst_hw )),\r
+                                               p_desc->p_endpt->mac.addr[0], p_desc->p_endpt->mac.addr[1],\r
+                                               p_desc->p_endpt->mac.addr[2], p_desc->p_endpt->mac.addr[3],\r
+                                               p_desc->p_endpt->mac.addr[4], p_desc->p_endpt->mac.addr[5] ) );\r
+                                       ipoib_addr_set_sid( &p_desc->p_endpt->conn.service_id,\r
+                                                                               ipoib_addr_get_qpn( &p_ib_arp->dst_hw ) );\r
+\r
+                                       NdisFreeToNPagedLookasideList(\r
+                                               &p_port->buf_mgr.send_buf_list, p_desc->p_buf );\r
+                                       cl_qlist_insert_tail( &p_port->send_mgr.pending_list,\r
+                                                               IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_buf ) );\r
+                                       NdisInterlockedInsertTailList( &p_port->endpt_mgr.pending_conns, \r
+                                                                                               &p_desc->p_endpt->list_item, \r
+                                                                                               &p_port->endpt_mgr.conn_lock );\r
+                                       cl_event_signal( &p_port->endpt_mgr.event );\r
+                                       return NDIS_STATUS_PENDING;\r
+                       \r
+                       case IPOIB_CM_CONNECT:\r
+                               /* queue ARP REP packet until connected */\r
+                                       NdisFreeToNPagedLookasideList(\r
+                                       &p_port->buf_mgr.send_buf_list, p_desc->p_buf );\r
+                                       cl_qlist_insert_tail( &p_port->send_mgr.pending_list,\r
+                                                               IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_pkt ) );\r
+                                       return NDIS_STATUS_PENDING;\r
+                       default:\r
+                               break;\r
+                       }\r
+               }\r
+#endif\r
+       }\r
+       else\r
+       {\r
+               cl_memclr( &p_ib_arp->dst_hw, sizeof(ipoib_hw_addr_t) );\r
+       }\r
+       \r
+#if 0 //DBG\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+               (" ARP %s SEND to ENDPT[%p] State: %d flag: %#x, QPN: %#x MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+                       ( p_ib_arp->op == ARP_OP_REP ? "REP": "REQ"),                   p_desc->p_endpt, \r
+                       endpt_cm_get_state( p_desc->p_endpt ),\r
+                       p_desc->p_endpt->cm_flag, \r
+                       cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->dst_hw )),\r
+                       p_desc->p_endpt->mac.addr[0], p_desc->p_endpt->mac.addr[1],\r
+                       p_desc->p_endpt->mac.addr[2], p_desc->p_endpt->mac.addr[3],\r
+                       p_desc->p_endpt->mac.addr[4], p_desc->p_endpt->mac.addr[5] ));\r
+       }\r
+#endif\r
+\r
+       p_ib_arp->dst_ip = p_arp->dst_ip;\r
+\r
+       p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( p_ib_arp );\r
+       p_desc->send_wr[0].local_ds[1].length = sizeof(ipoib_arp_pkt_t);\r
+       p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey;\r
+       p_desc->send_wr[0].wr.num_ds = 2;\r
+       p_desc->send_wr[0].wr.p_next = NULL;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static inline NDIS_STATUS\r
+__send_mgr_queue(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              eth_hdr_t* const                        p_eth_hdr,\r
+               OUT                     ipoib_endpt_t** const           pp_endpt )\r
+{\r
+       NDIS_STATUS                     status;\r
+\r
+       PERF_DECLARE( GetEndpt );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       /* Check the send queue and pend the request if not empty. */\r
+       if( cl_qlist_count( &p_port->send_mgr.pending_list ) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+                       ("Pending list not empty.\n") );\r
+               return NDIS_STATUS_PENDING;\r
+       }\r
+\r
+       /* Check the send queue and pend the request if not empty. */\r
+       if( p_port->send_mgr.depth == p_port->p_adapter->params.sq_depth )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+                       ("No available WQEs.\n") );\r
+               return NDIS_STATUS_PENDING;\r
+       }\r
+\r
+       cl_perf_start( GetEndpt );\r
+       status = __endpt_mgr_ref( p_port, p_eth_hdr->dst, pp_endpt );\r
+       cl_perf_stop( &p_port->p_adapter->perf, GetEndpt );\r
+\r
+       if( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION &&\r
+               ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) )\r
+       {\r
+               if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst, \r
+                       IB_MC_REC_STATE_FULL_MEMBER) == IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+                               ("Multicast Mac - trying to join.\n") );\r
+                       return NDIS_STATUS_PENDING;\r
+               }\r
+       }\r
+       else if ( status == NDIS_STATUS_SUCCESS && \r
+                         ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) &&  \r
+                         !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) )\r
+       {\r
+               CL_ASSERT( (*pp_endpt) );\r
+               CL_ASSERT((*pp_endpt)->h_mcast != NULL);\r
+               (*pp_endpt)->is_in_use = TRUE;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return status;\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__build_send_desc(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL* const                                      p_mdl,\r
+       IN              const   size_t                                          mdl_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc )\r
+{\r
+       NDIS_STATUS                     status;\r
+       int32_t                         hdr_idx;\r
+       uint32_t                        mss;\r
+       //PVOID*                                pp_tmp;\r
+       PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO                      p_checksum_list_info;\r
+       PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO       p_lso_info;\r
+       PERF_DECLARE( SendMgrFilter );\r
+       \r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       /* Format the send descriptor. */\r
+       p_checksum_list_info = NET_BUFFER_LIST_INFO( p_desc->p_netbuf_list,TcpIpChecksumNetBufferListInfo);\r
+       //pp_tmp = &NET_BUFFER_LIST_INFO(p_desc->p_netbuf_list, TcpIpChecksumNetBufferListInfo);\r
+       //p_checksum_list_info =                (   ) ((PULONG)pp_tmp);\r
+       p_lso_info = NET_BUFFER_LIST_INFO( p_desc->p_netbuf_list, TcpLargeSendNetBufferListInfo );\r
+               \r
+       /* Format the send descriptor. */\r
+       hdr_idx = cl_atomic_inc( &p_port->hdr_idx );\r
+       hdr_idx &= (p_port->p_adapter->params.sq_depth - 1);\r
+       ASSERT( hdr_idx < p_port->p_adapter->params.sq_depth );\r
+       p_port->hdr[hdr_idx].type = p_eth_hdr->type;\r
+       p_port->hdr[hdr_idx].resv = 0;\r
+\r
+       p_desc->send_wr[0].local_ds[0].vaddr = cl_get_physaddr( &p_port->hdr[hdr_idx] );\r
+       p_desc->send_wr[0].local_ds[0].length = sizeof(ipoib_hdr_t);\r
+       p_desc->send_wr[0].local_ds[0].lkey = p_port->ib_mgr.lkey;\r
+       p_desc->send_wr[0].wr.send_opt = 0;\r
+\r
+       //TODO: first check params.lso, and thereafter calculate LSO\r
+       if( p_port->p_adapter->params.lso && \r
+               (mss = (p_lso_info->LsoV1Transmit.MSS | p_lso_info->LsoV2Transmit.MSS)) )\r
+       {\r
+               ASSERT( mss == (p_lso_info->LsoV1Transmit.MSS & p_lso_info->LsoV2Transmit.MSS));\r
+               ASSERT ( (mss & (1<<20)) == mss);\r
+               status = __build_lso_desc( p_port, p_desc, mss, p_sgl, hdr_idx, p_lso_info );\r
+               if( status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("__build_lso_desc returned 0x%08X.\n", status) );\r
+                       return status;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               uint32_t        i;\r
+               cl_perf_start( SendMgrFilter );\r
+               status = __send_mgr_filter(\r
+               p_port, p_eth_hdr, p_mdl, mdl_len,p_sgl, p_desc );\r
+               cl_perf_stop( &p_port->p_adapter->perf, SendMgrFilter );\r
+               if( status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("__send_mgr_filter returned 0x%08X.\n", status) );\r
+                       return status;\r
+               }\r
+\r
+               if( p_desc->send_dir == SEND_UD_QP )\r
+               {\r
+                       p_desc->send_qp = p_port->ib_mgr.h_qp; // UD QP\r
+                       for( i = 0; i < p_desc->num_wrs; i++ )\r
+                       {\r
+                               p_desc->send_wr[i].wr.dgrm.ud.remote_qp = p_desc->p_endpt->qpn;\r
+                               p_desc->send_wr[i].wr.dgrm.ud.remote_qkey = p_port->ib_mgr.bcast_rec.qkey;\r
+                               p_desc->send_wr[i].wr.dgrm.ud.h_av = p_desc->p_endpt->h_av;\r
+                               p_desc->send_wr[i].wr.dgrm.ud.pkey_index = p_port->pkey_index;\r
+                               p_desc->send_wr[i].wr.dgrm.ud.rsvd = NULL;\r
+                               p_desc->send_wr[i].wr.send_opt = 0;\r
+\r
+                               if( p_port->p_adapter->params.send_chksum_offload && \r
+                                       ( p_checksum_list_info->Transmit.IsIPv4  || \r
+                                       p_checksum_list_info->Transmit.IsIPv6  ))\r
+                               {\r
+                                       // Set transimition checksum offloading \r
+                                       if( p_checksum_list_info->Transmit.IpHeaderChecksum )\r
+                                       {\r
+                                               p_desc->send_wr[i].wr.send_opt |= IB_SEND_OPT_TX_IP_CSUM;\r
+                                       }\r
+                                       if( p_checksum_list_info->Transmit.TcpChecksum )\r
+                                       {\r
+                                               p_desc->send_wr[i].wr.send_opt |= IB_SEND_OPT_TX_TCP_UDP_CSUM;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               else // RC QP\r
+               {\r
+                       CL_ASSERT( p_desc->send_dir == SEND_RC_QP );\r
+                       p_desc->send_qp = p_desc->p_endpt->conn.h_work_qp;\r
+               }\r
+               for( i = 0; i < p_desc->num_wrs; i++ )\r
+               {\r
+                       p_desc->send_wr[i].wr.wr_type = WR_SEND;\r
+                       p_desc->send_wr[i].wr.wr_id = 0;\r
+                       p_desc->send_wr[i].wr.ds_array = &p_desc->send_wr[i].local_ds[0];\r
+                       if( i )\r
+                       {\r
+                               p_desc->send_wr[i-1].wr.p_next = &p_desc->send_wr[i].wr;\r
+                       }\r
+               }\r
+               //TODO p_net_buf or p_buf\r
+//             p_desc->send_wr[p_desc->num_wrs - 1].wr.wr_id = (uintn_t)NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list );\r
+//????         IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("WR_ID was set to NBL 0x%x \n",p_desc->p_netbuf_list ));\r
+               p_desc->send_wr[p_desc->num_wrs - 1].wr.wr_id = (uintn_t)p_desc->p_netbuf_list ;\r
+\r
+               p_desc->send_wr[p_desc->num_wrs - 1].wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
+               p_desc->send_wr[p_desc->num_wrs - 1].wr.p_next = NULL;\r
+       }\r
+\r
+       /* Store context in our reserved area of the packet. */\r
+       IPOIB_PORT_FROM_PACKET( p_desc->p_netbuf_list ) = p_port;\r
+       IPOIB_ENDPT_FROM_PACKET( p_desc->p_netbuf_list ) = p_desc->p_endpt;\r
+       IPOIB_SEND_FROM_NETBUFFER( NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list ))= p_desc->p_buf;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static NDIS_STATUS\r
+__build_lso_desc(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc,\r
+       IN                              ULONG                                           mss,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN                              int32_t                                         hdr_idx, \r
+       IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info)\r
+{\r
+       NDIS_STATUS                     status;\r
+       LsoData                                                         TheLsoData;\r
+       UINT                                                            IndexOfData = 0;\r
+       \r
+       PNET_BUFFER     FirstBuffer  = NET_BUFFER_LIST_FIRST_NB (p_desc->p_netbuf_list);\r
+       ULONG                   PacketLength = NET_BUFFER_DATA_LENGTH(FirstBuffer);\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+\r
+\r
+       memset(&TheLsoData, 0, sizeof TheLsoData );\r
+       status = GetLsoHeaderSize(\r
+               FirstBuffer, \r
+               &TheLsoData, \r
+               &IndexOfData,\r
+               &p_port->hdr[hdr_idx] );\r
+\r
+       if ((status != NDIS_STATUS_SUCCESS ) || \r
+               (TheLsoData.FullBuffers != TheLsoData.UsedBuffers)) \r
+       {\r
+               ASSERT(FALSE);\r
+\r
+               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("<-- Throwing this packet\n"));\r
+\r
+               if( status == NDIS_STATUS_SUCCESS )\r
+               {\r
+                       status = NDIS_STATUS_INVALID_PACKET;\r
+               }\r
+               return status;\r
+       }\r
+       ASSERT(TheLsoData.LsoHeaderSize> 0);\r
+       // Tell NDIS how much we will send.\r
+       //PktExt->NdisPacketInfo[TcpLargeSendPacketInfo] = UlongToPtr(PacketLength);\r
+       p_lso_info->LsoV1TransmitComplete.TcpPayload = PacketLength;\r
+\r
+       p_desc->send_wr[0].wr.dgrm.ud.mss = mss;\r
+       p_desc->send_wr[0].wr.dgrm.ud.header = TheLsoData.LsoBuffers[0].pData;\r
+       p_desc->send_wr[0].wr.dgrm.ud.hlen = TheLsoData.LsoHeaderSize ;//lso_header_size; \r
+       p_desc->send_wr[0].wr.dgrm.ud.remote_qp = p_desc->p_endpt->qpn;\r
+       p_desc->send_wr[0].wr.dgrm.ud.remote_qkey = p_port->ib_mgr.bcast_rec.qkey;\r
+       p_desc->send_wr[0].wr.dgrm.ud.h_av = p_desc->p_endpt->h_av;\r
+       p_desc->send_wr[0].wr.dgrm.ud.pkey_index = p_port->pkey_index;\r
+       p_desc->send_wr[0].wr.dgrm.ud.rsvd = NULL;\r
+\r
+       //TODO: Should be NBL or p_desc\r
+       p_desc->send_wr[0].wr.wr_id = (uintn_t)p_desc->p_netbuf_list;\r
+       p_desc->send_wr[0].wr.ds_array = p_desc->send_wr[0].local_ds;\r
+       p_desc->send_wr[0].wr.wr_type = WR_LSO;\r
+       p_desc->send_wr[0].wr.send_opt = \r
+               (IB_SEND_OPT_TX_IP_CSUM | IB_SEND_OPT_TX_TCP_UDP_CSUM) | IB_SEND_OPT_SIGNALED;\r
+       \r
+       p_desc->send_wr[0].wr.p_next = NULL;\r
+       p_desc->send_qp = p_port->ib_mgr.h_qp;\r
+       p_desc->send_dir = SEND_UD_QP;\r
+       status = __send_gen(p_port, p_desc, p_sgl, IndexOfData );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return status;\r
+}\r
+\r
+static inline void\r
+__process_failed_send(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc,\r
+       IN              const   NDIS_STATUS                                     status,\r
+       IN                              ULONG                                           compl_flags)\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       /* Complete the packet. */\r
+       NET_BUFFER_LIST_NEXT_NBL(p_desc->p_netbuf_list) = NULL;\r
+       NET_BUFFER_LIST_STATUS(p_desc->p_netbuf_list) = status;\r
+       NdisMSendNetBufferListsComplete( p_port->p_adapter->h_adapter,\r
+               p_desc->p_netbuf_list, compl_flags );\r
+       ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 );\r
+       /* Deref the endpoint. */\r
+       if( p_desc->p_endpt )\r
+               ipoib_endpt_deref( p_desc->p_endpt );\r
+\r
+       if( p_desc->p_buf )\r
+       {\r
+               NdisFreeToNPagedLookasideList(\r
+                       &p_port->buf_mgr.send_buf_list, p_desc->p_buf );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+// max number of physical fragmented buffers \r
+#define MAX_PHYS_BUF_FRAG_ELEMENTS      0x29\r
+#define MP_FRAG_ELEMENT SCATTER_GATHER_ELEMENT \r
+#define PMP_FRAG_ELEMENT PSCATTER_GATHER_ELEMENT \r
+\r
+\r
+typedef struct _MP_FRAG_LIST {\r
+    ULONG NumberOfElements;\r
+    ULONG_PTR Reserved;\r
+    SCATTER_GATHER_ELEMENT Elements[MAX_PHYS_BUF_FRAG_ELEMENTS];\r
+} MP_FRAG_LIST, *PMP_FRAG_LIST;\r
+\r
+\r
+void \r
+CreateFragList(\r
+    ULONG PhysBufCount,\r
+    PNET_BUFFER NetBuff,\r
+    ULONG PacketLength,\r
+    PMP_FRAG_LIST pFragList\r
+    )\r
+{\r
+//    ETH_ENTER(ETH_SND);\r
+\r
+    ULONG i = 0;\r
+       int j=0;\r
+\r
+    UINT  buf_len = NET_BUFFER_DATA_LENGTH(NetBuff);\r
+    PMDL pMdl = NET_BUFFER_CURRENT_MDL(NetBuff);\r
+\r
+    ULONG CurrentMdlDataOffset = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuff);\r
+    ASSERT(MmGetMdlByteCount(pMdl) >= CurrentMdlDataOffset);\r
+\r
+    \r
+    ASSERT(NetBuff != NULL);    \r
+    ASSERT(PhysBufCount <= MAX_PHYS_BUF_FRAG_ELEMENTS);\r
+    \r
+    ASSERT(buf_len > 0);\r
+    UNREFERENCED_PARAMETER(PacketLength);\r
+\r
+\r
+//    ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: NetBuff %p, Length =0x%x\n", NetBuff, buf_len);\r
+\r
+    while ( (pMdl != NULL) && (buf_len != 0) )\r
+    {\r
+        PPFN_NUMBER page_array = MmGetMdlPfnArray(pMdl);\r
+        int MdlBufCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(pMdl), MmGetMdlByteCount(pMdl));\r
+    \r
+        ULONG offset = MmGetMdlByteOffset(pMdl) + CurrentMdlDataOffset ;        \r
+        ULONG MdlBytesCount = MmGetMdlByteCount(pMdl) - CurrentMdlDataOffset;\r
+        CurrentMdlDataOffset = 0;\r
+        \r
+        if( MdlBytesCount == 0 )\r
+        {\r
+            pMdl = pMdl->Next;\r
+            continue;\r
+        }\r
+\r
+        ASSERT( (buf_len > 0) && (MdlBytesCount > 0) );\r
\r
+//        ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: pMdl=%p, MdlBytesCount=x%x, MdlBufCount=0x%x\n", pMdl, MdlBytesCount, MdlBufCount);\r
+\r
+        if (MdlBytesCount > 0)\r
+        {\r
+            if( buf_len > MdlBytesCount)\r
+            {\r
+                buf_len -= MdlBytesCount;    \r
+            }\r
+            else\r
+            {\r
+                MdlBytesCount = buf_len;\r
+                buf_len = 0;                \r
+            }                        \r
+            //\r
+            // In some cases the mdlcount is greater than needed and in the last page\r
+            // there is 0 bytes\r
+            //\r
+            for (j=0; ((j< MdlBufCount) && (MdlBytesCount > 0)); j++) \r
+            {\r
+                ASSERT(MdlBytesCount > 0);\r
+                if (j ==0 ) \r
+                {\r
+                    //\r
+                    // First page\r
+                    //\r
+                    ULONG64 ul64PageNum = page_array[j];\r
+                    pFragList->Elements[i].Address.QuadPart = (ul64PageNum << PAGE_SHIFT)+ offset;\r
+                    if( offset + MdlBytesCount > PAGE_SIZE )\r
+                    {\r
+                        //\r
+                        // the data slides behind the page boundry\r
+                        //\r
+                        ASSERT(PAGE_SIZE > offset);\r
+                        pFragList->Elements[i].Length = PAGE_SIZE - offset;\r
+                        MdlBytesCount -= pFragList->Elements[i].Length;\r
+                    }\r
+                    else\r
+                    {\r
+                        //\r
+                        // All the data is hold in one page\r
+                        //    \r
+                        pFragList->Elements[i].Length = MdlBytesCount;\r
+                        MdlBytesCount = 0;\r
+                    }\r
+\r
+//                    ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: j == 0, MdlBytesCount=x%x, i = %d, element.length=0x%x \n",  MdlBytesCount, i, pFragList->Elements[i].Length);                    \r
+                } \r
+                else \r
+                {\r
+                    if (page_array[j] == (page_array[j-1] + 1))\r
+                    {\r
+                        \r
+                        ULONG size = min(PAGE_SIZE, MdlBytesCount);\r
+                                               i -= 1;\r
+                        pFragList->Elements[i].Length += size;\r
+                        MdlBytesCount -= size;\r
+                    }\r
+                    else \r
+                    {\r
+                        //\r
+                        // Not first page. so the data always start at the begining of the page\r
+                        //\r
+                        ULONG64 ul64PageNum = page_array[j];\r
+                        pFragList->Elements[i].Address.QuadPart = (ul64PageNum << PAGE_SHIFT);\r
+                        pFragList->Elements[i].Length = min(PAGE_SIZE, MdlBytesCount);\r
+                        MdlBytesCount -= pFragList->Elements[i].Length;\r
+                    }\r
+\r
+//                    ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: j != 0, MdlBytesCount=x%x, i = %d, element.length=0x%x \n",  MdlBytesCount, i, pFragList->Elements[i].Length);                    \r
+                }                \r
+                i++;\r
+                ASSERT(i <= MAX_PHYS_BUF_FRAG_ELEMENTS);\r
+            }\r
+        }\r
+\r
+        pMdl = pMdl->Next;\r
+    }\r
+        \r
+    if (buf_len != 0)\r
+    {\r
+        //\r
+        // In some cases the size in MDL isn't equal to the buffer size. In such \r
+        // a case we need to add the rest of packet to last chunk\r
+        //\r
+        ASSERT(i > 0); // To prevent array underflow\r
+        pFragList->Elements[i-1].Length += buf_len;\r
+//        ETH_PRINT(TRACE_LEVEL_ERROR, ETH_SND, "CreateFragList: buf_len != 0, i = %d, element.length=0x%x \n",  i -1, pFragList->Elements[i-1].Length);                    \r
+    }\r
+\r
+    ASSERT(i <= PhysBufCount);\r
+    pFragList->NumberOfElements = i;\r
+\r
+#ifdef DBG\r
+{\r
+    ULONG size = 0;\r
+    for (i  = 0; i <  pFragList->NumberOfElements; ++i)\r
+    {\r
+        size += pFragList->Elements[i].Length;\r
+    }\r
+    ASSERT(size == PacketLength);\r
+}\r
+#endif\r
+\r
+//    ETH_EXIT(ETH_SND);\r
+}\r
+\r
+\r
+\r
+\r
+void\r
+ipoib_port_send(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+    IN  NET_BUFFER_LIST     *p_net_buffer_list,\r
+    IN  ULONG               send_flags)\r
+{\r
+       NDIS_STATUS                     status;\r
+       PNET_BUFFER                     p_netbuf;\r
+       UINT                            buf_cnt = 0;\r
+       //ipoib_send_desc_t     *p_desc;\r
+       ULONG                           send_complete_flags = 0;\r
+       KIRQL                           old_irql;\r
+       PVOID                           p_sgl;\r
+       \r
+       PERF_DECLARE( GetEthHdr );\r
+       PERF_DECLARE( BuildSendDesc );\r
+       PERF_DECLARE( QueuePacket );\r
+       PERF_DECLARE( SendMgrQueue );\r
+       PERF_DECLARE( PostSend );\r
+       PERF_DECLARE( ProcessFailedSends );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+       \r
+       if (NDIS_TEST_SEND_AT_DISPATCH_LEVEL(send_flags))\r
+       {\r
+               //TODO Tzachid: make an assert here to validate your IRQL\r
+               //ASSERT (KeGetCurrentIRQL() == DISPATCH_LEVEL);\r
+               NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
+       } else {\r
+               //ASSERT (KeGetCurrentIRQL() == PASSIVE_LEVEL);\r
+       }\r
+       \r
+       cl_obj_lock( &p_port->obj );\r
+       if( p_port->state != IB_QPS_RTS )\r
+       {\r
+               \r
+               \r
+               cl_obj_unlock( &p_port->obj );\r
+               \r
+               \r
+               NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_FAILURE;\r
+               NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+               ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 );\r
+                       \r
+               NdisMSendNetBufferListsComplete(\r
+                       p_port->p_adapter->h_adapter,\r
+                       p_net_buffer_list,\r
+                       send_complete_flags);  \r
+               \r
+               return;\r
+       }\r
+       cl_obj_unlock( &p_port->obj );\r
+       \r
+       //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+       //                      ("Processing netbuffer list: %x\n", p_net_buffer_list));\r
+       for (p_netbuf = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list);\r
+                p_netbuf != NULL; \r
+                p_netbuf = NET_BUFFER_NEXT_NB(p_netbuf))\r
+       {\r
+               IPOIB_PORT_FROM_PACKET(p_net_buffer_list) = p_port;\r
+               IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_netbuf)  = p_net_buffer_list;\r
+               IPOIB_FROM_QUEUE(p_netbuf) = NULL;\r
+               /*p_desc = &p_port->send_mgr.desc;\r
+               p_desc->p_buf = p_netbuf;\r
+               p_desc->p_endpt = NULL;\r
+               p_desc->p_buf = NULL;\r
+               p_desc->send_qp = NULL;\r
+               p_desc->num_wrs = 1;\r
+               p_desc->send_dir = 0;*/\r
+               \r
+               old_irql = KeGetCurrentIrql();\r
+               if (old_irql < DISPATCH_LEVEL) \r
+               {\r
+                       KeRaiseIrqlToDpcLevel();\r
+               }\r
+               ++buf_cnt;\r
+               //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+               //              ("[%d] Netbuf = %x\n",buf_cnt, p_netbuf) );\r
+               if (cl_is_item_in_qlist( &p_port->send_mgr.pending_list,\r
+                                               IPOIB_LIST_ITEM_FROM_PACKET( p_net_buffer_list ))) {\r
+                               p_sgl = IPOIB_FROM_QUEUE(p_netbuf);     \r
+                               //IPOIB_FROM_QUEUE(p_net_buffer) = (void*)1;\r
+                               ASSERT (p_sgl);                         \r
+                               //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               //              ("[%d] FROM_QUEUE Netbuf = %x, found SGL = %x\n",buf_cnt, p_netbuf, p_sgl) );\r
+                                status = NDIS_STATUS_SUCCESS;\r
+               } else {\r
+\r
+\r
+                       CHAR *pTemp = ExAllocatePoolWithTag(NonPagedPool , p_port->p_adapter->sg_list_size, 'abcd');\r
+                       CL_ASSERT(pTemp != NULL);\r
+                       status = NDIS_STATUS_SUCCESS;\r
+                       p_sgl = pTemp;\r
+                       CreateFragList(NdisQueryNetBufferPhysicalCount(p_netbuf), p_netbuf, NET_BUFFER_DATA_LENGTH(p_netbuf), p_sgl);\r
+                       IPOIB_FROM_QUEUE(p_netbuf) = NULL;\r
+                       /*IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("[%d] Allocation from scratch: Netbuf = %x, found SGL = %x, PhysBufCnt=%ld, NB LEN = %ld, sg_list_size=%ld\n",\r
+                                               buf_cnt, p_netbuf, p_sgl,NdisQueryNetBufferPhysicalCount(p_netbuf) ,\r
+                                               NET_BUFFER_DATA_LENGTH(p_netbuf),p_port->p_adapter->sg_list_size) );\r
+                                               */\r
+                       ipoib_process_sg_list(NULL, NULL, p_sgl, p_netbuf);\r
+                       status = NDIS_STATUS_SUCCESS;\r
+\r
+#if 0          \r
+                       status = NdisMAllocateNetBufferSGList(\r
+                                                                       p_port->p_adapter->NdisMiniportDmaHandle,\r
+                                                                       p_netbuf,\r
+                                                                       p_netbuf,\r
+                                                                       NDIS_SG_LIST_WRITE_TO_DEVICE,\r
+                                                                       NULL,\r
+                                                                       0);\r
+#endif\r
+               }\r
+               KeLowerIrql (old_irql);\r
+       \r
+               if( status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       /* fail net buffer list */\r
+                       NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+                       NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_RESOURCES;\r
+                       NdisMSendNetBufferListsComplete(\r
+                               p_port->p_adapter->h_adapter,\r
+                               p_net_buffer_list,\r
+                               send_complete_flags);   \r
+                               break;\r
+               }\r
+               ASSERT(buf_cnt);\r
+               IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(p_net_buffer_list) = (PVOID)(ULONG_PTR)buf_cnt;\r
+       }\r
+       \r
+               /* Post the WR. *\r
+               cl_perf_start( PostSend );\r
+               ib_status =     p_port->p_adapter->p_ifc->post_send( p_desc->send_qp, &p_desc->send_wr[0].wr, &p_wr_failed );\r
+               cl_perf_stop( &p_port->p_adapter->perf, PostSend );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ib_post_send returned %s\n", \r
+                               p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+                       cl_perf_start( ProcessFailedSends );\r
+                       __process_failed_send( p_port, p_desc, NDIS_STATUS_FAILURE );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+                       * Flag the adapter as hung since posting is busted. *\r
+                       p_port->p_adapter->hung = TRUE;\r
+                       continue;\r
+               }\r
+\r
+               cl_atomic_inc( &p_port->send_mgr.depth );\r
+       }\r
+       cl_spinlock_release( &p_port->send_lock );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );*/\r
+}\r
+\r
+\r
+void\r
+ipoib_port_resume(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN boolean_t                                                            b_pending )\r
+{\r
+       NDIS_STATUS                     status;\r
+       cl_list_item_t          *p_item;\r
+       NET_BUFFER                      *p_net_buffer;\r
+       NET_BUFFER_LIST         *p_net_buffer_list;\r
+       //ipoib_send_desc_t     *p_desc;\r
+       KIRQL                           old_irql;\r
+       UINT                            buf_cnt = 0;\r
+       NET_BUFFER_LIST         *p_prev_nbl = NULL;\r
+       PVOID                           p_sgl;\r
+       static PVOID            p_prev_sgl = NULL;\r
+       \r
+       PERF_DECLARE( GetEndpt );\r
+       PERF_DECLARE( BuildSendDesc );\r
+       PERF_DECLARE( ProcessFailedSends );\r
+       PERF_DECLARE( PostSend );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+       cl_obj_lock( &p_port->obj );\r
+       if( p_port->state != IB_QPS_RTS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+                       ("Invalid state - Aborting.\n") );\r
+               cl_obj_unlock( &p_port->obj );\r
+               return;\r
+       }\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+//TODO NDIS60\r
+////??????????????     cl_spinlock_acquire( &p_port->send_lock );\r
+\r
+       for( p_item = cl_qlist_head( &p_port->send_mgr.pending_list );\r
+               p_item != cl_qlist_end( &p_port->send_mgr.pending_list );\r
+               p_item = cl_qlist_head( &p_port->send_mgr.pending_list ) )\r
+       {\r
+               \r
+               \r
+               /* Check the send queue and pend the request if not empty. */\r
+               if( p_port->send_mgr.depth == p_port->p_adapter->params.sq_depth )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+                               ("No available WQEs.\n") );\r
+                       break;\r
+               }\r
+               \r
+               p_net_buffer_list = IPOIB_PACKET_FROM_LIST_ITEM(\r
+                       cl_qlist_remove_head( &p_port->send_mgr.pending_list ) );\r
+               if (p_prev_nbl == p_net_buffer_list) {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("TRYING TO PROCESS ONCE AGAIN, EXITING: %x\n", p_net_buffer_list));\r
+                       break; //TODO more sophisticated mechanism to avoid starvation\r
+               }\r
+               old_irql = KeGetCurrentIrql();\r
+               if (old_irql < DISPATCH_LEVEL) \r
+               {\r
+                       KeRaiseIrqlToDpcLevel();\r
+               }\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Processing netbuffer list from queue: %x\n", p_net_buffer_list));\r
+               \r
+               for( p_net_buffer = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list);\r
+                        p_net_buffer != NULL;\r
+                        p_net_buffer = NET_BUFFER_NEXT_NB(p_net_buffer), buf_cnt++)\r
+                               {\r
+\r
+                       \r
+                       p_sgl = IPOIB_FROM_QUEUE(p_net_buffer); \r
+                       //IPOIB_FROM_QUEUE(p_net_buffer) = (void*)1;\r
+                       ASSERT (p_sgl);\r
+                       IPOIB_PORT_FROM_PACKET(p_net_buffer_list) = p_port;\r
+                       IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_net_buffer)  = p_net_buffer_list;\r
+                       /*p_desc = &p_port->send_mgr.desc;\r
+                       p_desc->p_buf = p_net_buffer;\r
+                       p_desc->p_endpt = NULL;\r
+                       p_desc->p_buf = NULL;\r
+                       p_desc->send_qp = NULL;\r
+                       p_desc->num_wrs = 1;\r
+                       p_desc->send_dir = 0;*/\r
+\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("[%d] Netbuf = %x, p_sgl = %x\n",buf_cnt, p_net_buffer, p_sgl) );\r
+                       ASSERT(p_sgl);\r
+                       if (p_sgl != (void*) 1) {\r
+                               ipoib_process_sg_list(NULL, NULL, p_sgl, p_net_buffer);\r
+                               status = NDIS_STATUS_SUCCESS;\r
+                       }\r
+                       else {\r
+                               ASSERT(FALSE);\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Getting strange flow\n") );\r
+                               NdisMFreeNetBufferSGList(\r
+                                                                       p_port->p_adapter->NdisMiniportDmaHandle,\r
+                                                                       p_sgl,\r
+                                                                       p_net_buffer );\r
+                               status = NdisMAllocateNetBufferSGList(\r
+                                                                       p_port->p_adapter->NdisMiniportDmaHandle,\r
+                                                                       p_net_buffer,\r
+                                                                       p_net_buffer,\r
+                                                                       NDIS_SG_LIST_WRITE_TO_DEVICE,\r
+                                                                       NULL,\r
+                                                                       0 /*p_port->p_adapter->sg_list_size*/ );\r
+                       }\r
+                       p_prev_sgl = p_sgl;             \r
+                       if( status != NDIS_STATUS_SUCCESS )\r
+                       {\r
+                               /* fail net buffer list */\r
+                               NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+                               NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_RESOURCES;\r
+                               NdisMSendNetBufferListsComplete(\r
+                                       p_port->p_adapter->h_adapter,\r
+                                       p_net_buffer_list,\r
+                                       0);     \r
+                               break;\r
+                       }\r
+               }\r
+                        \r
+               KeLowerIrql (old_irql);\r
+               \r
+               \r
+               p_prev_nbl = p_net_buffer_list;\r
+               \r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+\r
+\r
+static void\r
+__send_cb(\r
+       IN              const   ib_cq_handle_t                          h_cq,\r
+       IN                              void                                            *cq_context )\r
+{\r
+       ipoib_port_t            *p_port;\r
+       ib_api_status_t         status;\r
+       ib_wc_t                         wc[MAX_SEND_WC], *p_wc, *p_free;\r
+       cl_qlist_t                      done_list;\r
+       NET_BUFFER_LIST         *p_nbl;\r
+       uint32_t                        length;\r
+       ipoib_endpt_t           *p_endpt;\r
+       send_buf_t                      *p_send_buf;\r
+       ip_stat_sel_t           type;\r
+       size_t                          i;\r
+       NET_BUFFER                      *p_netbuffer = NULL;\r
+\r
+       PERF_DECLARE( SendCompBundle );\r
+       PERF_DECLARE( SendCb );\r
+       PERF_DECLARE( PollSend );\r
+       PERF_DECLARE( SendComp );\r
+       PERF_DECLARE( FreeSendBuf );\r
+       PERF_DECLARE( RearmSend );\r
+       PERF_DECLARE( PortResume );\r
+//return;//???????????\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       cl_perf_clr( SendCompBundle );\r
+\r
+       cl_perf_start( SendCb );\r
+\r
+       UNUSED_PARAM( h_cq );\r
+\r
+       cl_qlist_init( &done_list );\r
+\r
+       p_port = (ipoib_port_t*)cq_context;\r
+\r
+       ipoib_port_ref( p_port, ref_send_cb );\r
+\r
+       for( i = 0; i < MAX_SEND_WC; i++ )\r
+               wc[i].p_next = &wc[i + 1];\r
+       wc[MAX_SEND_WC - 1].p_next = NULL;\r
+\r
+       do\r
+       {\r
+               p_free = wc;\r
+               cl_perf_start( PollSend );\r
+               status = p_port->p_adapter->p_ifc->poll_cq( p_port->ib_mgr.h_send_cq, &p_free, &p_wc );\r
+               cl_perf_stop( &p_port->p_adapter->perf, PollSend );\r
+               CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND );\r
+\r
+               while( p_wc )\r
+               {\r
+                       cl_perf_start( SendComp );\r
+                       CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_SEND );\r
+                       p_nbl = (NET_BUFFER_LIST*)(uintn_t)p_wc->wr_id;\r
+                       IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_SEND,\r
+                       ("[1]Successfull send completion for NBL=0x%x .\n", p_nbl ));\r
+                       CL_ASSERT( p_nbl );\r
+                       CL_ASSERT( IPOIB_PORT_FROM_PACKET( p_nbl ) == p_port );\r
+                       length = 0;\r
+                       p_endpt = IPOIB_ENDPT_FROM_PACKET( p_nbl );\r
+                       p_send_buf = IPOIB_SEND_FROM_NETBUFFER( NET_BUFFER_LIST_FIRST_NB (p_nbl ));\r
+                       \r
+                       switch( p_wc->status )\r
+                       {\r
+                       case IB_WCS_SUCCESS:\r
+                               if( p_endpt->h_mcast )\r
+                               {\r
+                                       if( p_endpt->dgid.multicast.raw_group_id[11] == 0xFF &&\r
+                                               p_endpt->dgid.multicast.raw_group_id[10] == 0xFF &&\r
+                                               p_endpt->dgid.multicast.raw_group_id[12] == 0xFF &&\r
+                                               p_endpt->dgid.multicast.raw_group_id[13] == 0xFF )\r
+                                       {\r
+                                               type = IP_STAT_BCAST_BYTES;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               type = IP_STAT_MCAST_BYTES;\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       type = IP_STAT_UCAST_BYTES;\r
+                               }\r
+                               for (p_netbuffer = NET_BUFFER_LIST_FIRST_NB(p_nbl);\r
+                                        p_netbuffer != NULL;\r
+                                        p_netbuffer = NET_BUFFER_NEXT_NB(p_netbuffer))\r
+                               {\r
+                                        length += NET_BUFFER_DATA_LENGTH(p_netbuffer);\r
+                               }                       \r
+                               ipoib_inc_send_stat( p_port->p_adapter, type, length );\r
+                                       IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_SEND,\r
+                                       ("Successfull send completion for NBL=0x%x .\n", p_nbl) );\r
+                               NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_SUCCESS;\r
+                               IPOIB_DEC_NET_BUFFER_LIST_REF_COUNT(p_nbl);\r
+                               if (IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(p_nbl) == 0)\r
+                                       NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter,\r
+                                                                                               p_nbl,\r
+                                                                                               0);\r
+                               break;\r
+\r
+                       case IB_WCS_WR_FLUSHED_ERR:\r
+                               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+                                       ("Flushed send completion.\n") );\r
+                                       ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 );\r
+                               NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_RESET_IN_PROGRESS;\r
+                               NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter,\r
+                                                                                               p_nbl,\r
+                                                                                               0);   \r
+                               break;\r
+\r
+                       default:\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Send failed with %s (vendor specific %#x)\n",\r
+                                       p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
+                                       (int)p_wc->vendor_specific) );\r
+                                       ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 );\r
+                               NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_FAILURE;\r
+                               NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter,\r
+                                                                                               p_nbl,\r
+                                                                                               0);  \r
+                               break;\r
+                       }\r
+                       cl_perf_stop( &p_port->p_adapter->perf, SendComp );\r
+                       /* Dereference the enpoint used for the transfer. */\r
+                       ipoib_endpt_deref( p_endpt );\r
+\r
+                       if( p_send_buf )\r
+                       {\r
+                               cl_perf_start( FreeSendBuf );\r
+                               NdisFreeToNPagedLookasideList( &p_port->buf_mgr.send_buf_list,\r
+                                       p_send_buf );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, FreeSendBuf );\r
+                       }\r
+\r
+                       cl_atomic_dec( &p_port->send_mgr.depth );\r
+\r
+                       p_wc = p_wc->p_next;\r
+                       cl_perf_inc( SendCompBundle );\r
+               }\r
+               /* If we didn't use up every WC, break out. */\r
+       } while( !p_free );\r
+\r
+       /* Rearm the CQ. */\r
+       cl_perf_start( RearmSend );\r
+       status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_send_cq, FALSE );\r
+       cl_perf_stop( &p_port->p_adapter->perf, RearmSend );\r
+       CL_ASSERT( status == IB_SUCCESS );\r
+\r
+       /* Resume any sends awaiting resources. */\r
+       cl_perf_start( PortResume );\r
+       ipoib_port_resume( p_port, TRUE );\r
+       cl_perf_stop( &p_port->p_adapter->perf, PortResume );\r
+       \r
+       ipoib_port_deref( p_port, ref_send_cb );\r
+\r
+       cl_perf_stop( &p_port->p_adapter->perf, SendCb );\r
+       cl_perf_update_ctr( &p_port->p_adapter->perf, SendCompBundle );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Endpoint manager implementation\r
+*\r
+******************************************************************************/\r
+static void\r
+__endpt_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       cl_qmap_init( &p_port->endpt_mgr.mac_endpts );\r
+       cl_qmap_init( &p_port->endpt_mgr.lid_endpts );\r
+       cl_fmap_init( &p_port->endpt_mgr.gid_endpts, __gid_cmp );\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+static void\r
+__endpt_cm_mgr_thread(\r
+IN             void*           p_context );\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+#if 0\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               cl_fmap_init( &p_port->endpt_mgr.conn_endpts, __gid_cmp );\r
+               \r
+               NdisInitializeListHead( &p_port->endpt_mgr.pending_conns );\r
+               NdisAllocateSpinLock( &p_port->endpt_mgr.conn_lock );\r
+               cl_event_init( &p_port->endpt_mgr.event, FALSE );\r
+       \r
+               NdisInitializeListHead( &p_port->endpt_mgr.remove_conns );\r
+               NdisAllocateSpinLock( &p_port->endpt_mgr.remove_lock );\r
+\r
+               cl_thread_init( &p_port->endpt_mgr.h_thread, \r
+                                               __endpt_cm_mgr_thread,\r
+                                               ( const void *)p_port, \r
+                                               "CmEndPtMgr" );\r
+       }\r
+#endif\r
+       UNUSED_PARAM(p_port);\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+static void\r
+__endpt_cm_mgr_thread(\r
+IN             void*           p_context )\r
+{\r
+       ib_api_status_t ib_status;\r
+       LIST_ENTRY              *p_item;\r
+       ipoib_endpt_t   *p_endpt;\r
+       ipoib_port_t    *p_port =( ipoib_port_t *)p_context;\r
+       \r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, \r
+               ("Starting Port [%d] Endpt CM thread \n", p_port->port_num ) );\r
+\r
+       while( !p_port->endpt_mgr.thread_is_done )\r
+       {\r
+               cl_event_wait_on( &p_port->endpt_mgr.event, EVENT_NO_TIMEOUT, FALSE );\r
+       \r
+               while( ( p_item = NdisInterlockedRemoveHeadList( \r
+                                                               &p_port->endpt_mgr.pending_conns,\r
+                                                               &p_port->endpt_mgr.conn_lock) ) != NULL )\r
+               {\r
+\r
+                       p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, list_item );\r
+                       if( p_port->endpt_mgr.thread_is_done )\r
+                       {\r
+                               endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED );\r
+                               continue;\r
+                       }\r
+\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                               ("Endpt[%p] CONNECT REQ to MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+                               p_endpt,\r
+                               p_endpt->mac.addr[0], p_endpt->mac.addr[1],\r
+                               p_endpt->mac.addr[2], p_endpt->mac.addr[3],\r
+                               p_endpt->mac.addr[4], p_endpt->mac.addr[5] ) );\r
+                       \r
+                       if( !p_endpt->conn.h_send_qp )\r
+                       {\r
+                               ib_status = endpt_cm_create_qp( p_endpt, &p_endpt->conn.h_send_qp );\r
+                               if( ib_status != IB_SUCCESS )\r
+                               {\r
+                                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Endpt [%p ] CM create QP failed status %#x\n", p_endpt, ib_status ) );\r
+                               }\r
+                               else\r
+                               {\r
+                                       ib_status = ipoib_endpt_connect( p_endpt );\r
+                                       if( ib_status != IB_SUCCESS && ib_status != IB_PENDING )\r
+                                       {\r
+                                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                                       ("Endpt [ %p ] conn REQ failed status %#x\n", p_endpt, ib_status ) );\r
+                                       }\r
+                               }\r
+                               if( ib_status != IB_SUCCESS && ib_status != IB_PENDING )\r
+                               {\r
+                                       endpt_cm_set_state( p_endpt, IPOIB_CM_DESTROY );\r
+                                       endpt_cm_flush_recv( p_port, p_endpt );\r
+                                       endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED );\r
+                               }\r
+                       }\r
+\r
+               }//while( p_item != NULL )\r
+\r
+               while( ( p_item = NdisInterlockedRemoveHeadList(\r
+                                                               &p_port->endpt_mgr.remove_conns,\r
+                                                               &p_port->endpt_mgr.remove_lock ) ) != NULL )\r
+               {\r
+                       p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, list_item );\r
+\r
+                       endpt_cm_set_state( p_endpt, IPOIB_CM_DESTROY );\r
+\r
+                       IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,\r
+                               ("\nDESTROYING Endpt[%p]  MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+                               p_endpt,\r
+                               p_endpt->mac.addr[0], p_endpt->mac.addr[1],\r
+                               p_endpt->mac.addr[2], p_endpt->mac.addr[3],\r
+                               p_endpt->mac.addr[4], p_endpt->mac.addr[5] ) );\r
+                       endpt_cm_flush_recv( p_port, p_endpt );\r
+                       endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED );\r
+                       cl_obj_destroy( &p_endpt->obj );\r
+               }\r
+       }\r
+\r
+       p_port->endpt_mgr.thread_is_done++;\r
+       NdisFreeSpinLock( &p_port->endpt_mgr.conn_lock );\r
+       \r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, \r
+               (" Port [%d] Endpt thread is done\n", p_port->port_num ) );\r
+}\r
+\r
+static void\r
+__endpt_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       CL_ASSERT( cl_is_qmap_empty( &p_port->endpt_mgr.mac_endpts ) );\r
+       CL_ASSERT( cl_is_qmap_empty( &p_port->endpt_mgr.lid_endpts ) );\r
+       CL_ASSERT( cl_is_fmap_empty( &p_port->endpt_mgr.gid_endpts ) );\r
+#if 0\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               CL_ASSERT( cl_is_fmap_empty( &p_port->endpt_mgr.conn_endpts ) );\r
+       }\r
+#endif\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__endpt_mgr_remove_all(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+       \r
+       cl_obj_lock( &p_port->obj );\r
+       /* Wait for all readers to complete. */\r
+       while( p_port->endpt_rdr )\r
+               ;\r
+       /*\r
+        * We don't need to initiate destruction - this is called only\r
+        * from the __port_destroying function, and destruction cascades\r
+        * to all child objects.  Just clear all the maps.\r
+        */\r
+       cl_qmap_remove_all( &p_port->endpt_mgr.mac_endpts );\r
+       cl_qmap_remove_all( &p_port->endpt_mgr.lid_endpts );\r
+       cl_fmap_remove_all( &p_port->endpt_mgr.gid_endpts );\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+static void\r
+__endpt_mgr_reset_all(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       cl_map_item_t                   *p_item;\r
+       cl_fmap_item_t                  *p_fmap_item;\r
+       ipoib_endpt_t                   *p_endpt;\r
+       cl_qlist_t                              mc_list;\r
+       cl_qlist_t                              conn_list;\r
+       uint32_t                                local_exist = 0;\r
+       NDIS_LINK_STATE                 link_state;\r
+       NDIS_STATUS_INDICATION  status_indication;\r
+\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       cl_qlist_init( &mc_list );\r
+       cl_qlist_init( &conn_list );\r
+//???  cl_obj_lock( &p_port->obj );\r
+       /* Wait for all readers to complete. */\r
+       while( p_port->endpt_rdr )\r
+               ;\r
+\r
+#if 0\r
+                       __endpt_mgr_remove_all(p_port);\r
+#else\r
+                       link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+                       link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+                       link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+                       link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+                       link_state.MediaDuplexState = MediaDuplexStateFull;\r
+                       link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+                       IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                                               p_port->p_adapter->h_adapter,\r
+                                                               NDIS_STATUS_LINK_STATE,\r
+                                                               (PVOID)&link_state,\r
+                                                               sizeof(link_state));\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate DISCONNECT!\n") );\r
+                       NdisMIndicateStatusEx(p_port->p_adapter->h_adapter,&status_indication);\r
+                       \r
+                       link_state.MediaConnectState = MediaConnectStateConnected;\r
+                       IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                                               p_port->p_adapter->h_adapter,\r
+                                                               NDIS_STATUS_LINK_STATE,\r
+                                                               (PVOID)&link_state,\r
+                                                               sizeof(link_state));\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate Connect\n") );\r
+                       NdisMIndicateStatusEx(p_port->p_adapter->h_adapter,&status_indication);\r
+\r
+               \r
+                               //      IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                                       //      ("Link DOWN!\n") );\r
+\r
+       if( p_port->p_local_endpt )\r
+       {\r
+               //TODO: CM RESTORE\r
+               //ipoib_port_cancel_listen( p_port, p_port->p_local_endpt );\r
+\r
+               cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+                       &p_port->p_local_endpt->gid_item );\r
+               cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+                       &p_port->p_local_endpt->mac_item );\r
+               cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+                       &p_port->p_local_endpt->lid_item );\r
+               \r
+               cl_qlist_insert_head(\r
+                       &mc_list, &p_port->p_local_endpt->mac_item.pool_item.list_item );\r
+               local_exist = 1;\r
+\r
+               p_port->p_local_endpt = NULL;\r
+       }\r
+\r
+       p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts );\r
+       while( p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+       {\r
+               p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+               p_item = cl_qmap_next( p_item );\r
+               if( p_endpt->h_mcast )\r
+               {\r
+                       /*\r
+                        * We destroy MC endpoints since they will get recreated\r
+                        * when the port comes back up and we rejoin the MC groups.\r
+                        */\r
+                       cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+                               &p_endpt->mac_item );\r
+                       cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+                               &p_endpt->gid_item );\r
+\r
+                       cl_qlist_insert_tail(\r
+                               &mc_list, &p_endpt->mac_item.pool_item.list_item );\r
+               }\r
+               /* destroy connected endpoints if any */\r
+               else if( p_port->p_adapter->params.cm_enabled &&\r
+                                endpt_cm_get_state( p_endpt ) != IPOIB_CM_DISCONNECTED )\r
+               {\r
+                       p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid );\r
+                       if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) )\r
+                       {\r
+                               cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, \r
+                                       &p_endpt->conn_item );\r
+                       }\r
+                       cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+                               &p_endpt->mac_item );\r
+                       cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+                               &p_endpt->gid_item );\r
+\r
+                       cl_qlist_insert_tail(\r
+                               &conn_list, &p_endpt->mac_item.pool_item.list_item );\r
+               }\r
+               if( p_endpt->h_av )\r
+               {\r
+                       /* Destroy the AV for all other endpoints. */\r
+                       p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av );\r
+                       p_endpt->h_av = NULL;\r
+               }\r
+               \r
+               if( p_endpt->dlid )\r
+               {\r
+                       cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+                               &p_endpt->lid_item );\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+                               ("<__endptr_mgr_reset_all: setting p_endpt->dlid to 0\n"));\r
+                       p_endpt->dlid = 0;\r
+               }\r
+               \r
+       }\r
+#endif\r
+//???  cl_obj_unlock( &p_port->obj );\r
+\r
+       //TODO CM\r
+       /*while( cl_qlist_count( &conn_list ) )\r
+       {\r
+               endpt_cm_destroy_conn( p_port,\r
+                       PARENT_STRUCT( cl_qlist_remove_head( &conn_list ),\r
+                       ipoib_endpt_t, mac_item.pool_item.list_item ) );\r
+       }*/\r
+\r
+       if(cl_qlist_count( &mc_list ) - local_exist)\r
+       {\r
+               p_port->mcast_cnt =  (uint32_t)cl_qlist_count( &mc_list ) - local_exist;\r
+       }\r
+       else\r
+       {\r
+               p_port->mcast_cnt = 0;\r
+               KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE );\r
+       }       \r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt - local_exist));\r
+\r
+       /* Destroy all multicast endpoints now that we have released the lock. */\r
+       while( cl_qlist_count( &mc_list ) )\r
+       {\r
+               cl_list_item_t  *p_item;\r
+               p_item = cl_qlist_remove_head( &mc_list );\r
+               p_endpt = PARENT_STRUCT(p_item, ipoib_endpt_t, mac_item.pool_item.list_item);\r
+               cl_obj_destroy( &p_endpt->obj);\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+/*\r
+ * Called when updating an endpoint entry in response to an ARP.\r
+ * Because receive processing is serialized, and holds a reference\r
+ * on the endpoint reader, we wait for all *other* readers to exit before\r
+ * removing the item.\r
+ */\r
+static void\r
+__endpt_mgr_remove(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+#if 0 //CM\r
+       cl_fmap_item_t* p_fmap_item;\r
+#endif \r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       /* This function must be called from the receive path */\r
+       CL_ASSERT(p_port->endpt_rdr > 0);\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+       /* Wait for all readers to complete. */    \r
+       while( p_port->endpt_rdr > 1 )\r
+               ;\r
+\r
+       /* Remove the endpoint from the maps so further requests don't find it. */\r
+       cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, &p_endpt->mac_item );\r
+       /*\r
+        * The enpoints are *ALWAYS* in both the MAC and GID maps.  They are only\r
+        * in the LID map if the GID has the same subnet prefix as us.\r
+        */\r
+       cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, &p_endpt->gid_item );\r
+#if 0\r
+\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid );\r
+               \r
+               if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) )\r
+               {\r
+                       cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, \r
+                               &p_endpt->conn_item );\r
+               }\r
+       }\r
+#endif \r
+       if( p_endpt->dlid )\r
+       {\r
+               cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+                       &p_endpt->lid_item );\r
+       }\r
+\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       //TODO CM\r
+       //endpt_cm_destroy_conn( p_port, p_endpt );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+NTSTATUS\r
+ipoib_mac_to_gid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ib_gid_t*                                       p_gid )\r
+{\r
+       ipoib_endpt_t*  p_endpt;\r
+       cl_map_item_t   *p_item;\r
+       uint64_t                key = 0;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+\r
+       p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
+       if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed endpoint lookup.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+       *p_gid = p_endpt->dgid;\r
+\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+NTSTATUS\r
+ipoib_mac_to_path(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ib_path_rec_t*                          p_path )\r
+{\r
+       ipoib_endpt_t*  p_endpt;\r
+       cl_map_item_t   *p_item;\r
+       uint64_t                key = 0;\r
+       uint8_t                 sl;\r
+       net32_t                 flow_lbl;\r
+       uint8_t                 hop_limit;\r
+       uint8_t                 pkt_life;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+\r
+       if( p_port->p_local_endpt == NULL )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("No local endpoint.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       if( mac.addr[0] == 0 && mac.addr[1] == 0 && mac.addr[2] == 0 &&\r
+               mac.addr[3] == 0 && mac.addr[4] == 0 && mac.addr[5] == 0 )\r
+       {\r
+               p_endpt = p_port->p_local_endpt;\r
+       }\r
+       else\r
+       {\r
+               p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
+               if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+               {\r
+                       cl_obj_unlock( &p_port->obj );\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed endpoint lookup.\n") );\r
+                       return STATUS_INVALID_PARAMETER;\r
+               }\r
+\r
+               p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+       }\r
+\r
+       p_path->resv0 = 0;\r
+       p_path->dgid = p_endpt->dgid;\r
+       p_path->sgid = p_port->p_local_endpt->dgid;\r
+       p_path->dlid = p_endpt->dlid;\r
+       p_path->slid = p_port->p_local_endpt->dlid;\r
+\r
+       ib_member_get_sl_flow_hop(\r
+               p_port->ib_mgr.bcast_rec.sl_flow_hop,\r
+               &sl,\r
+               &flow_lbl,\r
+               &hop_limit\r
+               );\r
+       if( p_path->slid == p_path->dlid )\r
+               pkt_life = 0;\r
+       else\r
+               pkt_life = p_port->ib_mgr.bcast_rec.pkt_life;\r
+\r
+       ib_path_rec_init_local(\r
+               p_path,\r
+               &p_endpt->dgid,\r
+               &p_port->p_local_endpt->dgid,\r
+               p_endpt->dlid,\r
+               p_port->p_local_endpt->dlid,\r
+               1,\r
+               p_port->ib_mgr.bcast_rec.pkey,\r
+               sl,\r
+               IB_PATH_SELECTOR_EXACTLY, p_port->ib_mgr.bcast_rec.mtu,\r
+               IB_PATH_SELECTOR_EXACTLY, p_port->ib_mgr.bcast_rec.rate,\r
+               IB_PATH_SELECTOR_EXACTLY, pkt_life,\r
+               0 );\r
+\r
+       /* Set global routing information. */\r
+       ib_path_rec_set_hop_flow_raw( p_path, hop_limit, flow_lbl, FALSE );\r
+       p_path->tclass = p_port->ib_mgr.bcast_rec.tclass;\r
\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static inline NDIS_STATUS\r
+__endpt_mgr_ref(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ipoib_endpt_t** const           pp_endpt )\r
+{\r
+       NDIS_STATUS             status;\r
+       cl_map_item_t   *p_item;\r
+       uint64_t                key;\r
+\r
+       PERF_DECLARE( EndptQueue );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       if( !cl_memcmp( &mac, &p_port->p_adapter->params.conf_mac, sizeof(mac) ) )\r
+       {\r
+               /* Discard loopback traffic. */\r
+               IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_ENDPT,\r
+                       ("Discarding loopback traffic\n") );\r
+               IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+               return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;\r
+       }\r
+\r
+       key = 0;\r
+       cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ENDPT,\r
+               ("Look for :\t  MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+               mac.addr[0], mac.addr[1], mac.addr[2],\r
+               mac.addr[3], mac.addr[4], mac.addr[5]) );\r
+\r
+       p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
+       if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+                       ("Failed endpoint lookup.\n") );\r
+               return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;\r
+       }\r
+\r
+       *pp_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+       ipoib_endpt_ref( *pp_endpt );\r
+\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       cl_perf_start( EndptQueue );\r
+       status = ipoib_endpt_queue( *pp_endpt );\r
+       cl_perf_stop( &p_port->p_adapter->perf, EndptQueue );\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+               *pp_endpt = NULL;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return status;\r
+}\r
+\r
+\r
+static inline NDIS_STATUS\r
+__endpt_mgr_get_gid_qpn(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ib_gid_t* const                         p_gid,\r
+               OUT                     UNALIGNED net32_t* const        p_qpn )\r
+{\r
+       UNALIGNED\r
+       cl_map_item_t   *p_item;\r
+       ipoib_endpt_t   *p_endpt;\r
+       uint64_t                key;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+\r
+       key = 0;\r
+       cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+       p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
+       if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+                       ("Failed endpoint lookup.\n") );\r
+               return NDIS_STATUS_FAILURE;\r
+       }\r
+\r
+       p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+\r
+       *p_gid = p_endpt->dgid;\r
+       *p_qpn = p_endpt->qpn;\r
+\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static inline ipoib_endpt_t*\r
+__endpt_mgr_get_by_gid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ib_gid_t* const                         p_gid )\r
+{\r
+       cl_fmap_item_t  *p_item;\r
+       ipoib_endpt_t   *p_endpt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       p_item = cl_fmap_get( &p_port->endpt_mgr.gid_endpts, p_gid );\r
+       if( p_item == cl_fmap_end( &p_port->endpt_mgr.gid_endpts ) )\r
+               p_endpt = NULL;\r
+       else\r
+               p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, gid_item );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return p_endpt;\r
+}\r
+\r
+\r
+static ipoib_endpt_t*\r
+__endpt_mgr_get_by_lid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   net16_t                                         lid )\r
+{\r
+       cl_map_item_t   *p_item;\r
+       ipoib_endpt_t   *p_endpt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       p_item = cl_qmap_get( &p_port->endpt_mgr.lid_endpts, lid );\r
+       if( p_item == cl_qmap_end( &p_port->endpt_mgr.lid_endpts ) )\r
+               p_endpt = NULL;\r
+       else\r
+               p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, lid_item );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return p_endpt;\r
+}\r
+\r
+\r
+inline ib_api_status_t\r
+__endpt_mgr_insert_locked(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       ib_api_status_t status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+               ("insert  :\t  MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+               mac.addr[0], mac.addr[1], mac.addr[2],\r
+               mac.addr[3], mac.addr[4], mac.addr[5]) );\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+       while( p_port->endpt_rdr )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               cl_obj_lock( &p_port->obj );\r
+       }\r
+       /* __endpt_mgr_insert expects *one* reference to be held when being called. */\r
+       cl_atomic_inc( &p_port->endpt_rdr );\r
+       status= __endpt_mgr_insert( p_port, mac, p_endpt );\r
+       cl_atomic_dec( &p_port->endpt_rdr );\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       return status;\r
+}\r
+\r
+\r
+inline ib_api_status_t\r
+__endpt_mgr_insert(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       uint64_t                key;\r
+       cl_status_t             cl_status;\r
+       cl_map_item_t   *p_qitem;\r
+       cl_fmap_item_t  *p_fitem;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       /* Wait for all accesses to the map to complete. */\r
+       while( p_port->endpt_rdr > 1 )\r
+               ;\r
+\r
+       /* Link the endpoint to the port. */\r
+       cl_status = cl_obj_insert_rel_parent_locked(\r
+               &p_endpt->rel, &p_port->obj, &p_endpt->obj );\r
+\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               cl_obj_destroy( &p_endpt->obj );\r
+               return IB_INVALID_STATE;\r
+       }\r
+\r
+#if DBG\r
+       cl_atomic_inc( &p_port->ref[ref_endpt_track] );\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
+               ("ref  type %d ref_cnt %d\n", ref_endpt_track, p_port->obj.ref_cnt) );\r
+#endif\r
+\r
+       p_endpt->mac = mac;\r
+       key = 0;\r
+       cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+       p_qitem = cl_qmap_insert(\r
+               &p_port->endpt_mgr.mac_endpts, key, &p_endpt->mac_item );\r
+       CL_ASSERT( p_qitem == &p_endpt->mac_item );\r
+       p_fitem = cl_fmap_insert(\r
+               &p_port->endpt_mgr.gid_endpts, &p_endpt->dgid, &p_endpt->gid_item );\r
+       CL_ASSERT( p_fitem == &p_endpt->gid_item );\r
+       if( p_endpt->dlid )\r
+       {\r
+               p_qitem = cl_qmap_insert(\r
+                       &p_port->endpt_mgr.lid_endpts, p_endpt->dlid, &p_endpt->lid_item );\r
+               CL_ASSERT( p_qitem == &p_endpt->lid_item );\r
+               if (p_qitem != &p_endpt->lid_item) {\r
+                       // Since we failed to insert into the list, make sure it is not removed\r
+                       p_endpt->dlid =0;\r
+               }\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_add_bcast(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_mcast_rec_t                          *p_mcast_rec )\r
+{\r
+       ib_api_status_t status;\r
+       ipoib_endpt_t   *p_endpt;\r
+       mac_addr_t              bcast_mac;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /*\r
+        * Cache the broadcast group properties for creating future mcast groups.\r
+        */\r
+       p_port->ib_mgr.bcast_rec = *p_mcast_rec->p_member_rec;\r
+\r
+       /* Allocate the broadcast endpoint. */\r
+       p_endpt = ipoib_endpt_create( &p_mcast_rec->p_member_rec->mgid,\r
+               0 , CL_HTON32(0x00FFFFFF) );\r
+       if( !p_endpt )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_endpt_create failed.\n") );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+       /* set reference to transport to be used while is not attached to the port */\r
+       p_endpt->is_mcast_listener = TRUE;\r
+       p_endpt->p_ifc = p_port->p_adapter->p_ifc;\r
+       status = ipoib_endpt_set_mcast( p_endpt, p_port->ib_mgr.h_pd,\r
+               p_port->port_num, p_mcast_rec );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               cl_obj_destroy( &p_endpt->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_create_mcast_endpt returned %s\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Add the broadcast endpoint to the endpoint map. */\r
+       cl_memset( &bcast_mac, 0xFF, sizeof(bcast_mac) );\r
+       status = __endpt_mgr_insert_locked( p_port, bcast_mac, p_endpt );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+void\r
+ipoib_port_remove_endpt(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac )\r
+{\r
+       cl_map_item_t   *p_item;\r
+       //TODO CM\r
+//     cl_fmap_item_t  *p_fmap_item;\r
+       ipoib_endpt_t   *p_endpt;\r
+       uint64_t                key;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       key = 0;\r
+       cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+\r
+       /* Remove the endpoint from the maps so further requests don't find it. */\r
+       cl_obj_lock( &p_port->obj );\r
+       /* Wait for all readers to finish */\r
+       while( p_port->endpt_rdr )\r
+               ;\r
+       p_item = cl_qmap_remove( &p_port->endpt_mgr.mac_endpts, key );\r
+       /*\r
+        * Dereference the endpoint.  If the ref count goes to zero, it\r
+        * will get freed.\r
+        */\r
+       if( p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+       {\r
+               p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+               /*\r
+                * The enpoints are *ALWAYS* in both the MAC and GID maps.  They are only\r
+                * in the LID map if the GID has the same subnet prefix as us.\r
+                */\r
+               cl_fmap_remove_item(\r
+                       &p_port->endpt_mgr.gid_endpts, &p_endpt->gid_item );\r
+#if 0\r
+               if( p_port->p_adapter->params.cm_enabled )\r
+               {\r
+                       p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid );\r
+               \r
+                       if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) )\r
+                       {\r
+                               cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, \r
+                                       &p_endpt->conn_item );\r
+                       }\r
+               }\r
+#endif\r
+\r
+               if( p_endpt->dlid )\r
+               {\r
+                       cl_qmap_remove_item(\r
+                               &p_port->endpt_mgr.lid_endpts, &p_endpt->lid_item );\r
+               }\r
+\r
+               cl_obj_unlock( &p_port->obj );\r
+               //TODO CM\r
+               //endpt_cm_destroy_conn( p_port, p_endpt );\r
+\r
+#if DBG\r
+               cl_atomic_dec( &p_port->ref[ref_endpt_track] );\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+                       ("ref type %d ref_cnt %d\n", ref_endpt_track, p_port->obj.ref_cnt) );\r
+#endif\r
+\r
+       }\r
+       else\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+/*\r
+ * The sequence for port up is as follows:\r
+ *     1. The port goes active.  This allows the adapter to send SA queries\r
+ *     and join the broadcast group (and other groups).\r
+ *\r
+ *     2. The adapter sends an SA query for the broadcast group.\r
+ *\r
+ *     3. Upon completion of the query, the adapter joins the broadcast group.\r
+ */\r
+\r
+\r
+/*\r
+ * Query the SA for the broadcast group.\r
+ */\r
+void\r
+ipoib_port_up(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ib_pnp_port_rec_t* const        p_pnp_rec )\r
+{\r
+       ib_port_info_t          *p_port_info;\r
+       ib_mad_t                        *mad_in         = NULL;\r
+       ib_mad_t                        *mad_out = NULL;\r
+       ib_api_status_t         status  = IB_INSUFFICIENT_MEMORY;\r
+       static int                      cnt     = 0;\r
+       \r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
+                       ("[%d] Entering port_up.\n", ++cnt) ); \r
+       \r
+       cl_obj_lock( &p_port->obj );\r
+       if ( p_port->state == IB_QPS_INIT ) \r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               status = IB_SUCCESS;\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("p_port->state = %d - Aborting.\n", p_port->state) );        \r
+               goto up_done;\r
+       }\r
+       else if ( p_port->state == IB_QPS_RTS )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               cl_obj_lock( &p_port->p_adapter->obj );\r
+               if( p_port->p_adapter->state == IB_PNP_PORT_INIT )\r
+               {\r
+                       p_port->p_adapter->state = IB_PNP_PORT_ACTIVE;\r
+               }\r
+               cl_obj_unlock( &p_port->p_adapter->obj );\r
+               status = IB_SUCCESS;\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Port init is done. p_port->state = %d.\n", p_port->state ) );\r
+               goto up_done;\r
+       }\r
+       p_port->state = IB_QPS_INIT;\r
+       cl_obj_unlock( &p_port->obj );  \r
+\r
+\r
+       /* Wait for all work requests to get flushed. */\r
+       while( p_port->recv_mgr.depth || p_port->send_mgr.depth )\r
+               cl_thread_suspend( 0 );\r
+\r
+       KeResetEvent( &p_port->sa_event );\r
+\r
+       mad_out = (ib_mad_t*)cl_zalloc(256);\r
+       if(! mad_out)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("failed to allocate mad mad_out\n")); \r
+               goto up_done;\r
+       }\r
+       mad_in = (ib_mad_t*)cl_zalloc(256);\r
+       if(! mad_in)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("failed to allocate mad mad_in\n")); \r
+               goto up_done;\r
+       }\r
+\r
+       mad_in->attr_id = IB_MAD_ATTR_PORT_INFO;\r
+       mad_in->method = IB_MAD_METHOD_GET;\r
+       mad_in->base_ver = 1;\r
+       mad_in->class_ver =1;\r
+       mad_in->mgmt_class = IB_MCLASS_SUBN_LID;\r
+       \r
+       status = p_port->p_adapter->p_ifc->local_mad(\r
+               p_port->ib_mgr.h_ca ,p_port->port_num ,mad_in ,mad_out);\r
+\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               ipoib_set_inactive( p_port->p_adapter );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_local_mad returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               goto up_done;\r
+       }\r
+\r
+       p_port_info = (ib_port_info_t*)(((ib_smp_t*)mad_out)->data);\r
+       p_port->base_lid = p_pnp_rec->p_port_attr->lid;\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Received port info: link width = %d.\n",\r
+                       p_port_info->link_width_active) );\r
+       p_port->ib_mgr.rate =\r
+               ib_port_info_compute_rate( p_port_info );\r
+       \r
+       ipoib_set_rate( p_port->p_adapter,\r
+               p_port_info->link_width_active,\r
+       ib_port_info_get_link_speed_active( p_port_info ) );\r
+\r
+       status = __port_get_bcast( p_port );\r
+       if (status != IB_SUCCESS)\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+               (" __port_get_bcast returned %s\n",p_port->p_adapter->p_ifc->get_err_str( status )));\r
+\r
+up_done:\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               if( status != IB_CANCELED )\r
+               {\r
+                       ipoib_set_inactive( p_port->p_adapter );\r
+                       __endpt_mgr_reset_all( p_port );\r
+               }\r
+               ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+               p_port->state = IB_QPS_ERROR;\r
+               KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+       }\r
+\r
+       if(mad_out)\r
+               cl_free(mad_out);\r
+       if(mad_in)\r
+               cl_free(mad_in);\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_add_local(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_port_info_t* const           p_port_info )\r
+{\r
+       ib_api_status_t                 status;\r
+       ib_gid_t                                gid;\r
+       ipoib_endpt_t                   *p_endpt;\r
+       ib_av_attr_t                    av_attr;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       ib_gid_set_default( &gid, p_port->p_adapter->guids.port_guid.guid );\r
+       p_endpt = ipoib_endpt_create(\r
+               &gid, p_port_info->base_lid, p_port->ib_mgr.qpn );\r
+       if( !p_endpt )\r
+       {\r
+               p_port->p_adapter->hung = TRUE;\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to create local endpt\n") );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
+       av_attr.port_num = p_port->port_num;\r
+       av_attr.sl = 0;\r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+               (" av_attr.dlid = p_port_info->base_lid = %d\n", cl_ntoh16( p_port_info->base_lid ) ));\r
+       av_attr.dlid = p_port_info->base_lid;\r
+       av_attr.static_rate = p_port->ib_mgr.rate;\r
+       av_attr.path_bits = 0;\r
+       status = p_port->p_adapter->p_ifc->create_av(\r
+               p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               cl_obj_destroy( &p_endpt->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_av for local endpoint returned %s\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* __endpt_mgr_insert expects *one* reference to be held. */\r
+       cl_atomic_inc( &p_port->endpt_rdr );\r
+       status = __endpt_mgr_insert( p_port, p_port->p_adapter->params.conf_mac, p_endpt );\r
+       cl_atomic_dec( &p_port->endpt_rdr );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__endpt_mgr_insert for local endpoint returned %s\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       p_port->p_local_endpt = p_endpt;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+\r
+\r
+static ib_api_status_t\r
+__port_get_bcast(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_query_req_t          query;\r
+       ib_user_query_t         info;\r
+       ib_member_rec_t         member_rec;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       info.method = IB_MAD_METHOD_GETTABLE;\r
+       info.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;\r
+       info.attr_size = sizeof(ib_member_rec_t);\r
+       info.comp_mask = IB_MCR_COMPMASK_MGID;\r
+       info.p_attr = &member_rec;\r
+\r
+       /* Query requires only the MGID. */\r
+       cl_memclr( &member_rec, sizeof(ib_member_rec_t) );\r
+       member_rec.mgid = bcast_mgid_template;\r
+\r
+    member_rec.mgid.raw[4] = (uint8_t) (p_port->p_adapter->guids.port_guid.pkey >> 8) ;\r
+       member_rec.mgid.raw[5] = (uint8_t) p_port->p_adapter->guids.port_guid.pkey;\r
+       member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey);\r
+       cl_memclr( &query, sizeof(ib_query_req_t) );\r
+       query.query_type = IB_QUERY_USER_DEFINED;\r
+       query.p_query_input = &info;\r
+       query.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+       query.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
+       query.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
+       query.query_context = p_port;\r
+       query.pfn_query_cb = __bcast_get_cb;\r
+\r
+       /* reference the object for the multicast query. */\r
+       ipoib_port_ref( p_port, ref_get_bcast );\r
+\r
+       status = p_port->p_adapter->p_ifc->query(\r
+               p_port->p_adapter->h_al, &query, &p_port->ib_mgr.h_query );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               ipoib_port_deref( p_port, ref_get_bcast );\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_query returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+       }\r
+       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_query returned SUCCESS\n"));\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+/* Callback for the MCMemberRecord Get query for the IPv4 broadcast group. */\r
+static void\r
+__bcast_get_cb(\r
+       IN                              ib_query_rec_t                          *p_query_rec )\r
+{\r
+       ipoib_port_t            *p_port;\r
+       ib_member_rec_t         *p_mc_req;\r
+       ib_api_status_t         status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_port = (ipoib_port_t*)p_query_rec->query_context;\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+       p_port->ib_mgr.h_query = NULL;\r
+\r
+       CL_ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+       if( p_port->state != IB_QPS_INIT )\r
+       {\r
+               status = IB_CANCELED;\r
+               goto done;\r
+       }\r
+       \r
+       status = p_query_rec->status;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+               ("status of request %s\n", \r
+               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+\r
+       switch( status )\r
+       {\r
+       case IB_SUCCESS:\r
+               if( p_query_rec->result_cnt )\r
+               {\r
+                       p_mc_req = (ib_member_rec_t*)\r
+                               ib_get_query_result( p_query_rec->p_result_mad, 0 );\r
+\r
+                       /* Join the broadcast group. */\r
+                       status = __port_join_bcast( p_port, p_mc_req );\r
+                       break;\r
+               }\r
+               /* Fall through. */\r
+\r
+       case IB_REMOTE_ERROR:\r
+               /* SA failed the query.  Broadcast group doesn't exist, create it. */\r
+               status = __port_create_bcast( p_port );\r
+               break;\r
+\r
+       case IB_CANCELED:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Instance destroying - Aborting.\n") );\r
+               break;\r
+\r
+       default:\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_BCAST_GET, 1, p_query_rec->status );\r
+       }\r
+done:\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               if( status != IB_CANCELED )\r
+               {\r
+                       ipoib_set_inactive( p_port->p_adapter );\r
+                       __endpt_mgr_reset_all( p_port );\r
+               }\r
+               p_port->state = IB_QPS_ERROR;\r
+               KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+       }\r
+\r
+       /* Return the response MAD to AL. */\r
+       if( p_query_rec->p_result_mad )\r
+               p_port->p_adapter->p_ifc->put_mad( p_query_rec->p_result_mad );\r
+\r
+       /* Release the reference taken when issuing the member record query. */\r
+       ipoib_port_deref( p_port, ref_bcast_get_cb );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__port_join_bcast(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_member_rec_t* const          p_member_rec )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_mcast_req_t          mcast_req;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /* Check that the rate is realizable for our port. */\r
+       if( p_port->ib_mgr.rate < (p_member_rec->rate & 0x3F) &&\r
+               (g_ipoib.bypass_check_bcast_rate == 0))\r
+       {\r
+               /*\r
+                * The MC group rate is higher than our port's rate.  Log an error\r
+                * and stop.  A port transition will drive the retry.\r
+                */\r
+               IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,\r
+                       ("Unrealizable join due to rate mismatch.\n") );\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_BCAST_RATE, 2,\r
+                       (uint32_t)(p_member_rec->rate & 0x3F),\r
+                       (uint32_t)p_port->ib_mgr.rate );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       /* Join the broadcast group. */\r
+       cl_memclr( &mcast_req, sizeof(mcast_req) );\r
+       /* Copy the results of the Get to use as parameters. */\r
+       mcast_req.member_rec = *p_member_rec;\r
+       /* We specify our port GID for the join operation. */\r
+       mcast_req.member_rec.port_gid.unicast.prefix = IB_DEFAULT_SUBNET_PREFIX;\r
+       mcast_req.member_rec.port_gid.unicast.interface_id =\r
+               p_port->p_adapter->guids.port_guid.guid;\r
+\r
+       mcast_req.mcast_context = p_port;\r
+       mcast_req.pfn_mcast_cb = __bcast_cb;\r
+       mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
+       mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
+       mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+       mcast_req.pkey_index = p_port->pkey_index;\r
+\r
+       if( ib_member_get_state( mcast_req.member_rec.scope_state ) !=\r
+               IB_MC_REC_STATE_FULL_MEMBER )\r
+       {\r
+               IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,\r
+                       ("Incorrect MC member rec join state in query response.\n") );\r
+               ib_member_set_state( &mcast_req.member_rec.scope_state,\r
+                       IB_MC_REC_STATE_FULL_MEMBER );\r
+       }\r
+\r
+       /* reference the object for the multicast join request. */\r
+       ipoib_port_ref( p_port, ref_join_bcast );\r
+\r
+       status = p_port->p_adapter->p_ifc->join_mcast(\r
+               p_port->ib_mgr.h_qp, &mcast_req );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               ipoib_port_deref( p_port, ref_bcast_join_failed );\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_join_mcast returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__port_create_bcast(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_mcast_req_t          mcast_req;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /* Join the broadcast group. */\r
+       cl_memclr( &mcast_req, sizeof(mcast_req) );\r
+       mcast_req.create = TRUE;\r
+       /*\r
+        * Create requires pkey, qkey, SL, flow label, traffic class, joing state\r
+        * and port GID.\r
+        *\r
+        * We specify the MGID since we don't want the SA to generate it for us.\r
+        */\r
+       mcast_req.member_rec.mgid = bcast_mgid_template;\r
+       mcast_req.member_rec.mgid.raw[4] = (uint8_t) (p_port->p_adapter->guids.port_guid.pkey >> 8); \r
+       mcast_req.member_rec.mgid.raw[5] = (uint8_t) p_port->p_adapter->guids.port_guid.pkey;\r
+       ib_gid_set_default( &mcast_req.member_rec.port_gid,\r
+               p_port->p_adapter->guids.port_guid.guid );\r
+       /*\r
+        * IPOIB spec requires that the QKEY have the MSb set so that the QKEY\r
+        * from the QP is used rather than the QKEY in the send WR.\r
+        */\r
+       mcast_req.member_rec.qkey =\r
+               (uint32_t)(uintn_t)p_port | IB_QP_PRIVILEGED_Q_KEY;\r
+       mcast_req.member_rec.mtu =\r
+               (IB_PATH_SELECTOR_EXACTLY << 6) | IB_MTU_LEN_2048;\r
+\r
+       mcast_req.member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey);\r
+\r
+       mcast_req.member_rec.sl_flow_hop = ib_member_set_sl_flow_hop( 0, 0, 0 );\r
+       mcast_req.member_rec.scope_state =\r
+               ib_member_set_scope_state( 2, IB_MC_REC_STATE_FULL_MEMBER );\r
+\r
+       mcast_req.mcast_context = p_port;\r
+       mcast_req.pfn_mcast_cb = __bcast_cb;\r
+       mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
+       mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
+       mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+       mcast_req.pkey_index = p_port->pkey_index;\r
+\r
+       /* reference the object for the multicast join request. */\r
+       ipoib_port_ref( p_port, ref_join_bcast );\r
+\r
+       status = p_port->p_adapter->p_ifc->join_mcast( p_port->ib_mgr.h_qp, &mcast_req );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               ipoib_port_deref( p_port, ref_bcast_create_failed );\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_join_mcast returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+void\r
+ipoib_port_down(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_qp_mod_t                     qp_mod;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /*\r
+        * Mark our state.  This causes all callbacks to abort.\r
+        * Note that we hold the receive lock so that we synchronize\r
+        * with reposting.  We must take the receive lock before the\r
+        * object lock since that is the order taken when reposting.\r
+        */\r
+       cl_spinlock_acquire( &p_port->recv_lock );\r
+       cl_obj_lock( &p_port->obj );\r
+       p_port->state = IB_QPS_ERROR;\r
+\r
+       NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+               EVENT_IPOIB_PORT_DOWN, 0 );\r
+\r
+       if( p_port->ib_mgr.h_query )\r
+       {\r
+               p_port->p_adapter->p_ifc->cancel_query(\r
+                       p_port->p_adapter->h_al, p_port->ib_mgr.h_query );\r
+               p_port->ib_mgr.h_query = NULL;\r
+       }\r
+       cl_obj_unlock( &p_port->obj );\r
+       cl_spinlock_release( &p_port->recv_lock );\r
+\r
+       KeWaitForSingleObject(\r
+               &p_port->sa_event, Executive, KernelMode, FALSE, NULL );\r
+\r
+       /* garbage collector timer is not needed when link is down */\r
+       KeCancelTimer(&p_port->gc_timer);\r
+       KeFlushQueuedDpcs();\r
+\r
+       /*\r
+        * Put the QP in the error state.  This removes the need to\r
+        * synchronize with send/receive callbacks.\r
+        */\r
+       CL_ASSERT( p_port->ib_mgr.h_qp );\r
+       cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
+       qp_mod.req_state = IB_QPS_ERROR;\r
+       status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_modify_qp to error state returned %s.\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               p_port->p_adapter->hung = TRUE;\r
+               return;\r
+       }\r
+\r
+       KeResetEvent(&p_port->leave_mcast_event);\r
+\r
+       /* Reset all endpoints so we don't flush our ARP cache. */\r
+       __endpt_mgr_reset_all( p_port );\r
+\r
+       KeWaitForSingleObject(\r
+               &p_port->leave_mcast_event, Executive, KernelMode, FALSE, NULL );\r
+\r
+       __pending_list_destroy(p_port);\r
+       \r
+       cl_obj_lock( &p_port->p_adapter->obj );\r
+       ipoib_dereg_addrs( p_port->p_adapter );\r
+       cl_obj_unlock( &p_port->p_adapter->obj );\r
+       \r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__bcast_cb(\r
+       IN                              ib_mcast_rec_t                          *p_mcast_rec )\r
+{\r
+       ipoib_port_t    *p_port;\r
+       ib_api_status_t status;\r
+       LARGE_INTEGER   gc_due_time;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_port = (ipoib_port_t*)p_mcast_rec->mcast_context;\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+\r
+       ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+       if( p_port->state != IB_QPS_INIT )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               if( p_mcast_rec->status == IB_SUCCESS )\r
+               {\r
+                       ipoib_port_ref(p_port, ref_leave_mcast);\r
+                       p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+               }\r
+               KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+               ipoib_port_deref( p_port, ref_bcast_inv_state );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Invalid state - Aborting.\n") );\r
+               return;\r
+       }\r
+       status = p_mcast_rec->status;\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Multicast join for broadcast group returned %s.\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( p_mcast_rec->status )) );\r
+               if( status == IB_REMOTE_ERROR )\r
+               {\r
+                       /*\r
+                        * Either:\r
+                        *      - the join failed because the group no longer exists\r
+                        *      - the create failed because the group already exists\r
+                        *\r
+                        * Kick off a new Get query to the SA to restart the join process\r
+                        * from the top.  Note that as an optimization, it would be\r
+                        * possible to distinguish between the join and the create.\r
+                        * If the join fails, try the create.  If the create fails, start\r
+                        * over with the Get.\r
+                        */\r
+                       /* TODO: Assert is a place holder.  Can we ever get here if the\r
+                       state isn't IB_PNP_PORT_ADD or PORT_DOWN or PORT_INIT? */\r
+                       CL_ASSERT( p_port->p_adapter->state == IB_PNP_PORT_ADD ||\r
+                               p_port->p_adapter->state == IB_PNP_PORT_DOWN ||\r
+                               p_port->p_adapter->state == IB_PNP_PORT_INIT );\r
+                       if(++p_port->bc_join_retry_cnt < p_port->p_adapter->params.bc_join_retry)\r
+                       {\r
+                               status = __port_get_bcast( p_port );\r
+                       }\r
+                       else\r
+                       {\r
+                               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                                       EVENT_IPOIB_BCAST_JOIN, 1, p_mcast_rec->status );\r
+                               p_port->bc_join_retry_cnt = 0;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                               EVENT_IPOIB_BCAST_JOIN, 1, p_mcast_rec->status );\r
+               }\r
+\r
+               cl_obj_unlock( &p_port->obj );\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       ipoib_set_inactive( p_port->p_adapter );\r
+                       __endpt_mgr_reset_all( p_port );\r
+                       ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+                       p_port->state = IB_QPS_ERROR;\r
+                       KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+               }\r
+               ipoib_port_deref( p_port, ref_bcast_req_failed );\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return;\r
+       }\r
+       p_port->bc_join_retry_cnt = 0;\r
+\r
+       while( p_port->endpt_rdr )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               cl_obj_lock( &p_port->obj );\r
+       }\r
+\r
+       if( !p_port->p_local_endpt )\r
+       {\r
+               ib_port_info_t  port_info;\r
+               cl_memclr(&port_info, sizeof(port_info));\r
+               port_info.base_lid = p_port->base_lid;\r
+               status = __endpt_mgr_add_local( p_port, &port_info );\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("__endpt_mgr_add_local returned %s\n",\r
+                               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                       cl_obj_unlock( &p_port->obj );\r
+                       goto err;\r
+               }\r
+       }\r
+\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       status = __endpt_mgr_add_bcast( p_port, p_mcast_rec );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__endpt_mgr_add_bcast returned %s\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               ipoib_port_ref(p_port, ref_leave_mcast);\r
+               status = p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+               CL_ASSERT( status == IB_SUCCESS );\r
+               goto err;\r
+       }\r
+\r
+       /* Get the QP ready for action. */\r
+       status = __ib_mgr_activate( p_port );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__ib_mgr_activate returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+\r
+err:\r
+               /* Flag the adapter as hung. */\r
+               p_port->p_adapter->hung = TRUE;\r
+               ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+               p_port->state = IB_QPS_ERROR;        \r
+               KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+               ipoib_port_deref( p_port, ref_bcast_error );\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return;\r
+       }\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+       /* Only change the state if we're still in INIT. */\r
+       ASSERT( p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+       if (p_port->state == IB_QPS_INIT) {\r
+               p_port->state = IB_QPS_RTS;\r
+       }\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       /* Prepost receives. */\r
+       cl_spinlock_acquire( &p_port->recv_lock );\r
+       __recv_mgr_repost( p_port );\r
+       cl_spinlock_release( &p_port->recv_lock );\r
+\r
+       /* Notify the adapter that we now have an active connection. */\r
+       status = ipoib_set_active( p_port->p_adapter );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               ib_qp_mod_t                     qp_mod;\r
+               ipoib_set_inactive( p_port->p_adapter );\r
+               KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("ipoib_set_active returned %s.\n",p_port->p_adapter->p_ifc->get_err_str( status )));\r
+               cl_spinlock_acquire( &p_port->recv_lock );\r
+               cl_obj_lock( &p_port->obj );\r
+               p_port->state = IB_QPS_ERROR;\r
+               if( p_port->ib_mgr.h_query )\r
+               {\r
+                       p_port->p_adapter->p_ifc->cancel_query(\r
+                               p_port->p_adapter->h_al, p_port->ib_mgr.h_query );\r
+                       p_port->ib_mgr.h_query = NULL;\r
+               }\r
+               cl_obj_unlock( &p_port->obj );\r
+               cl_spinlock_release( &p_port->recv_lock );\r
+\r
+               CL_ASSERT( p_port->ib_mgr.h_qp );\r
+               cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
+               qp_mod.req_state = IB_QPS_ERROR;\r
+               status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod );\r
+               __endpt_mgr_reset_all( p_port );\r
+\r
+               ipoib_port_deref( p_port, ref_join_bcast );\r
+               return;\r
+       }\r
+#if 0 //CM\r
+       if( p_port->p_adapter->params.cm_enabled &&\r
+               !p_port->p_local_endpt->conn.h_cm_listen )\r
+       {\r
+               if( ipoib_port_listen( p_port ) != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Port CM Listen failed\n" ) );\r
+                       /*keep going with UD only */\r
+                       p_port->p_adapter->params.cm_enabled = FALSE;\r
+\r
+                       NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                               EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de3 );\r
+               }\r
+       }\r
+#endif\r
+       /* garbage collector timer is needed when link is active */\r
+       gc_due_time.QuadPart = -(int64_t)(((uint64_t)p_port->p_adapter->params.mc_leave_rescan * 2000000) * 10);\r
+       KeSetTimerEx(&p_port->gc_timer,gc_due_time,\r
+                           (LONG)p_port->p_adapter->params.mc_leave_rescan*1000,&p_port->gc_dpc);\r
+\r
+       KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+       ipoib_port_deref( p_port, ref_join_bcast );\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__qp_event(\r
+       IN                              ib_async_event_rec_t            *p_event_rec )\r
+{\r
+       UNUSED_PARAM( p_event_rec );\r
+       CL_ASSERT( p_event_rec->context );\r
+       ((ipoib_port_t*)p_event_rec->context)->p_adapter->hung = TRUE;\r
+}\r
+\r
+\r
+static void\r
+__cq_event(\r
+       IN                              ib_async_event_rec_t            *p_event_rec )\r
+{\r
+       UNUSED_PARAM( p_event_rec );\r
+       CL_ASSERT( p_event_rec->context );\r
+       ((ipoib_port_t*)p_event_rec->context)->p_adapter->hung = TRUE;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__ib_mgr_activate(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t status;\r
+       ib_dgrm_info_t  dgrm_info;\r
+       ib_qp_mod_t             qp_mod;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       /*\r
+        * Move the QP to RESET.  This allows us to reclaim any\r
+        * unflushed receives.\r
+        */\r
+       cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
+       qp_mod.req_state = IB_QPS_RESET;\r
+       status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_modify_qp returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Move the QP to RTS. */\r
+       dgrm_info.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+       dgrm_info.qkey = p_port->ib_mgr.bcast_rec.qkey;\r
+       dgrm_info.pkey_index = p_port->pkey_index;\r
+       status = p_port->p_adapter->p_ifc->init_dgrm_svc( p_port->ib_mgr.h_qp, &dgrm_info );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_init_dgrm_svc returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Rearm the CQs. */\r
+       status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_recv_cq, FALSE );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_rearm_cq for recv returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+       status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_send_cq, FALSE );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_rearm_cq for send returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+/* Transition to a passive level thread. */\r
+ib_api_status_t\r
+ipoib_port_join_mcast(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                              mac,\r
+       IN              const   uint8_t                                 state)\r
+{\r
+       ib_api_status_t         status;\r
+       ib_mcast_req_t          mcast_req;\r
+       ipoib_endpt_t           *p_endpt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+       switch( __endpt_mgr_ref( p_port, mac, &p_endpt ) )\r
+       {\r
+       case NDIS_STATUS_NO_ROUTE_TO_DESTINATION:\r
+               break;\r
+\r
+       case NDIS_STATUS_SUCCESS:\r
+               ipoib_endpt_deref( p_endpt );\r
+               /* Fall through */\r
+\r
+       case NDIS_STATUS_PENDING:\r
+               return IB_SUCCESS;\r
+       }\r
+\r
+       /*\r
+        * Issue the mcast request, using the parameters of the broadcast group.\r
+        * This allows us to do a create request that should always succeed since\r
+        * the required parameters are known.\r
+        */\r
+       cl_memclr( &mcast_req, sizeof(mcast_req) );\r
+       mcast_req.create = TRUE;\r
+\r
+       /* Copy the settings from the broadcast group. */\r
+       mcast_req.member_rec = p_port->ib_mgr.bcast_rec;\r
+       /* Clear fields that aren't specified in the join */\r
+       mcast_req.member_rec.mlid = 0;\r
+       ib_member_set_state( &mcast_req.member_rec.scope_state,state);\r
+\r
+       if( (mac.addr[0] == 1) && (mac.addr[2] == 0x5E ))\r
+       {\r
+               /*\r
+                * Update the address portion of the MGID with the 28 lower bits of the\r
+                * IP address.  Since we're given a MAC address, we are using \r
+                * 24 lower bits of that network-byte-ordered value (assuming MSb\r
+                * is zero) and 4 lsb bits of the first byte of IP address.\r
+                */\r
+               mcast_req.member_rec.mgid.raw[12] = mac.addr[1];\r
+               mcast_req.member_rec.mgid.raw[13] = mac.addr[3];\r
+               mcast_req.member_rec.mgid.raw[14] = mac.addr[4];\r
+               mcast_req.member_rec.mgid.raw[15] = mac.addr[5];\r
+       }\r
+       else\r
+       {\r
+               /* Handle non IP mutlicast MAC addresses. */\r
+               /* Update the signature to use the lower 2 bytes of the OpenIB OUI. */\r
+               mcast_req.member_rec.mgid.raw[2] = 0x14;\r
+               mcast_req.member_rec.mgid.raw[3] = 0x05;\r
+               /* Now copy the MAC address into the last 6 bytes of the GID. */\r
+               cl_memcpy( &mcast_req.member_rec.mgid.raw[10], mac.addr, 6 );\r
+       }\r
+\r
+       mcast_req.mcast_context = p_port;\r
+       mcast_req.pfn_mcast_cb = __mcast_cb;\r
+       mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
+       mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
+       mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+       mcast_req.pkey_index = p_port->pkey_index;\r
+       mcast_req.member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey);\r
+       /*\r
+        * Create the endpoint and insert it in the port.  Since we don't wait for\r
+        * the mcast SA operations to complete before returning from the multicast\r
+        * list set OID asynchronously, it is possible for the mcast entry to be\r
+        * cleared before the SA interaction completes.  In this case, when the\r
+        * mcast callback is invoked, it would not find the corresponding endpoint\r
+        * and would be undone.\r
+        */\r
+       p_endpt = ipoib_endpt_create(\r
+               &mcast_req.member_rec.mgid, 0, CL_HTON32(0x00FFFFFF) );\r
+       if( !p_endpt )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_endpt_create failed.\n") );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       status = __endpt_mgr_insert_locked( p_port, mac, p_endpt );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__endpt_mgr_insert_locked returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* reference the object for the multicast join request. */\r
+       ipoib_port_ref( p_port, ref_join_mcast );\r
+\r
+       status = p_port->p_adapter->p_ifc->join_mcast( p_port->ib_mgr.h_qp, &mcast_req );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               ipoib_port_deref( p_port, ref_mcast_join_failed );\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_join_mcast returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+       return status;\r
+}\r
+\r
+\r
+static void\r
+__mcast_cb(\r
+       IN                              ib_mcast_rec_t                          *p_mcast_rec )\r
+{\r
+       ib_api_status_t         status;\r
+       ipoib_port_t            *p_port;\r
+       cl_fmap_item_t          *p_item;\r
+       ipoib_endpt_t           *p_endpt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+       p_port = (ipoib_port_t*)p_mcast_rec->mcast_context;\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+       while( p_port->endpt_rdr )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               cl_obj_lock( &p_port->obj );\r
+       }\r
+       if( p_port->state != IB_QPS_RTS )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               if( p_mcast_rec->status == IB_SUCCESS )\r
+\r
+               {\r
+                       ipoib_port_ref(p_port, ref_leave_mcast);\r
+                       p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+               }\r
+               ipoib_port_deref( p_port, ref_mcast_inv_state );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Invalid state - Aborting.\n") );\r
+               return;\r
+       }\r
+\r
+       if( p_mcast_rec->status != IB_SUCCESS )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Multicast join request failed with status %s.\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( p_mcast_rec->status )) );\r
+               /* Flag the adapter as hung. */\r
+               p_port->p_adapter->hung =TRUE;\r
+               ipoib_port_deref( p_port, ref_mcast_req_failed );\r
+               IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+               return;\r
+       }\r
+\r
+       p_item = cl_fmap_get(\r
+               &p_port->endpt_mgr.gid_endpts, &p_mcast_rec->p_member_rec->mgid );\r
+       if( p_item == cl_fmap_end( &p_port->endpt_mgr.gid_endpts ) )\r
+       {\r
+               /*\r
+                * The endpoint must have been flushed while the join request\r
+                * was outstanding.  Just leave the group and return.  This\r
+                * is not an error.\r
+                */\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
+                       ("Failed to find endpoint for update.\n") );\r
+\r
+               ipoib_port_ref(p_port, ref_leave_mcast);\r
+               p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+               ipoib_port_deref( p_port, ref_mcast_no_endpt );\r
+               IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+               return;\r
+       }\r
+\r
+       p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, gid_item );\r
+       p_endpt->p_ifc = p_port->p_adapter->p_ifc;\r
+\r
+       /* Setup the endpoint for use. */\r
+       status = ipoib_endpt_set_mcast(\r
+               p_endpt, p_port->ib_mgr.h_pd, p_port->port_num, p_mcast_rec );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_MCAST,\r
+                       ("ipoib_endpt_set_mcast returned %s.\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               /* Flag the adapter as hung. */\r
+               p_port->p_adapter->hung = TRUE;\r
+               ipoib_port_deref( p_port, ref_mcast_av_failed );\r
+               IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+               return;\r
+       }\r
+\r
+       /*\r
+        * The endpoint is already in the GID and MAC maps.\r
+        * mast endpoint are not used in the LID map.\r
+        */\r
+       CL_ASSERT(p_endpt->dlid == 0);\r
+       /* set flag that endpoint is use */\r
+       p_endpt->is_in_use = TRUE;\r
+       cl_obj_unlock( &p_port->obj );\r
+       \r
+       /* Try to send all pending sends. */\r
+       ipoib_port_resume( p_port , FALSE);\r
+\r
+       ipoib_port_deref( p_port, ref_join_mcast );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+\r
+void\r
+ipoib_leave_mcast_cb(\r
+       IN                              void                            *context )\r
+{\r
+       ipoib_port_t            *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+       p_port = (ipoib_port_t*)context;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_MCAST,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt));\r
+       \r
+       ipoib_port_deref( p_port, ref_leave_mcast);\r
+       cl_atomic_dec( &p_port->mcast_cnt);\r
+       \r
+       if(0 == p_port->mcast_cnt)\r
+       {\r
+               KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE );\r
+       }\r
+       \r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+                       ("Leave mcast callback deref ipoib_port \n") );\r
+       \r
+       IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+\r
+\r
+void\r
+__leave_error_mcast_cb(\r
+       IN                              void                            *context )\r
+{\r
+       ipoib_port_t            *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+       p_port = (ipoib_port_t*)context;\r
+\r
+       ipoib_port_deref( p_port, ref_leave_mcast);\r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+                       ("Leave mcast callback deref ipoib_port \n") );\r
+       \r
+       IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+/*++\r
+Routine Description:\r
+    The routine process the packet and returns LSO information\r
+    \r
+Arguments:\r
+    pNetBuffer - a pointer to the first net buffer object of the packet\r
+    TcpHeaderOffset - offset to the begining of the TCP header in the packet\r
+    pLsoData - pointer to LsoData object in which the routine returns the LSO information\r
+    pHeaderSize - pointer to ULONG object in which the header size is returned\r
+    IndexOfData - \r
+             \r
+Return Value:\r
+     NDIS_STATUS   \r
+\r
+NOTE:\r
+    called at DISPATCH level\r
+--*/\r
+\r
+NDIS_STATUS GetLsoHeaderSize(\r
+       IN              PNET_BUFFER             pNetBuffer,\r
+       IN              LsoData                 *pLsoData,\r
+       OUT     UINT                    *IndexOfData,\r
+       IN              ipoib_hdr_t *ipoib_hdr\r
+       )\r
+{\r
+       UINT            CurrLength;\r
+       PUCHAR          pSrc;\r
+       PUCHAR          pCopiedData = pLsoData->coppied_data;\r
+       ip_hdr_t        UNALIGNED  *IpHdr;\r
+       tcp_hdr_t       UNALIGNED *TcpHdr;\r
+       uint16_t        TcpHeaderLen;\r
+       uint16_t        IpHeaderLen;\r
+       uint16_t        IpOffset;\r
+       INT                     FullBuffers = 0;\r
+       PMDL            pMDL;\r
+       NDIS_STATUS     status = NDIS_STATUS_INVALID_PACKET;\r
+       \r
+       \r
+#define IP_OFFSET 14;\r
+       //\r
+       // This Flag indicates the way we gets the headers\r
+       // RegularFlow = we get the headers (ETH+IP+TCP) in the same Buffer \r
+       // in sequence.\r
+       //\r
+       boolean_t                       IsRegularFlow = TRUE;\r
+\r
+       const uint16_t          ETH_OFFSET = IP_OFFSET; \r
+       \r
+       pLsoData->LsoHeaderSize = 0;\r
+       IpOffset = IP_OFFSET; //(uint16_t)pPort->EncapsulationFormat.EncapsulationHeaderSize;\r
+       *IndexOfData = 0;\r
+\r
+       pMDL = NET_BUFFER_CURRENT_MDL(pNetBuffer);\r
+       NdisQueryMdl(pMDL, &pSrc, &CurrLength, NormalPagePriority);\r
+       //NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority );\r
+       if (pSrc == NULL) {\r
+               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error processing packets\n"));\r
+               return status;\r
+       }\r
+       // We start by looking for the ethernet and the IP\r
+       if (CurrLength < ETH_OFFSET) {\r
+               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+               return status;\r
+       }\r
+       //pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + ETH_OFFSET;\r
+       if (CurrLength == ETH_OFFSET) {        \r
+               ASSERT(FALSE);\r
+               IsRegularFlow = FALSE;        \r
+               memcpy(pCopiedData, pSrc, ETH_OFFSET);\r
+               pCopiedData += ETH_OFFSET;        \r
+               FullBuffers++;\r
+               // First buffer was only ethernet\r
+               pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer);\r
+        NdisQueryMdl(NET_BUFFER_CURRENT_MDL(pNetBuffer), &pSrc, &CurrLength, NormalPagePriority);\r
+               if (pSrc == NULL) {\r
+                       IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+                       return status;\r
+           }\r
+       } else {\r
+               // This is ETH + IP together (at least)\r
+               pLsoData->LsoBuffers[0].pData = pSrc + (ETH_OFFSET - sizeof (ipoib_hdr_t));\r
+               memcpy (pLsoData->LsoBuffers[0].pData, ipoib_hdr, sizeof (ipoib_hdr_t));\r
+               CurrLength -= ETH_OFFSET;\r
+               pSrc = pSrc + ETH_OFFSET;\r
+               pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + sizeof (ipoib_hdr_t);\r
+       }\r
+       // we should now be having at least the size of ethernet data\r
+       if (CurrLength < sizeof (ip_hdr_t)) {\r
+               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+               return status;\r
+       }\r
+       IpHdr = (ip_hdr_t UNALIGNED*)pSrc;\r
+       IpHeaderLen = (uint16_t)IP_HEADER_LENGTH(IpHdr);\r
+       ASSERT(IpHdr->prot == IP_PROT_TCP);\r
+       if (CurrLength < IpHeaderLen) {\r
+               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error processing packets\n"));\r
+               return status;\r
+       }\r
+       pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + IpHeaderLen;\r
+       // We now start to find where the TCP header starts\r
+       if (CurrLength == IpHeaderLen) {\r
+               ASSERT(FALSE);\r
+               // two options : \r
+               // if(IsRegularFlow = FALSE) ==> ETH and IP seperated in two buffers\r
+               // if(IsRegularFlow = TRUE ) ==> ETH and IP in the same buffer \r
+               // TCP will start at next buffer\r
+               if(IsRegularFlow){\r
+                       memcpy(pCopiedData, pSrc-ETH_OFFSET ,ETH_OFFSET+IpHeaderLen);\r
+                       pCopiedData += (ETH_OFFSET + IpHeaderLen);\r
+               } else {\r
+                       memcpy(pCopiedData, pSrc,IpHeaderLen);\r
+                       pCopiedData += IpHeaderLen;\r
+               }\r
+\r
+               FullBuffers++;\r
+               IsRegularFlow = FALSE;\r
+               //NdisGetNextBuffer( CurrBuffer, &CurrBuffer);\r
+               //NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority );\r
+               pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer);\r
+               NdisQueryMdl(NET_BUFFER_CURRENT_MDL(pNetBuffer), &pSrc, &CurrLength, NormalPagePriority);\r
+               if (pSrc == NULL) {\r
+                       IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+                       return status;\r
+               }\r
+       } else {\r
+               // if(IsRegularFlow = TRUE ) ==> the ETH and IP and TCP in the same buffer       \r
+               // if(IsRegularFlow = FLASE ) ==> ETH in one buffer , IP+TCP together in the same buffer\r
+               if (IsRegularFlow) {            \r
+                       pLsoData->LsoBuffers[0].Len += IpHeaderLen;\r
+               } else {            \r
+                       memcpy(pCopiedData, pSrc, IpHeaderLen);\r
+                       pCopiedData += IpHeaderLen;\r
+               }\r
+\r
+               CurrLength -= IpHeaderLen;\r
+               pSrc = pSrc + IpHeaderLen;\r
+       }\r
+       if (CurrLength < sizeof (tcp_hdr_t)) {\r
+               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+               return status;\r
+       }\r
+       // We have finaly found the TCP header\r
+       TcpHdr = (tcp_hdr_t UNALIGNED *)pSrc;\r
+       TcpHeaderLen = TCP_HEADER_LENGTH(TcpHdr);\r
+\r
+       //ASSERT(TcpHeaderLen == 20);\r
+       \r
+       if (CurrLength < TcpHeaderLen) {\r
+               //IPOIB_PRINT(TRACE_LEVEL_VERBOSE, ETH, ("Error porcessing packets\n"));\r
+               return status;\r
+       }\r
+       pLsoData->LsoHeaderSize =  pLsoData->LsoHeaderSize + TcpHeaderLen;\r
+       if(IsRegularFlow){\r
+               pLsoData->LsoBuffers[0].Len += TcpHeaderLen;\r
+       }\r
+       else{\r
+               memcpy(pCopiedData, pSrc, TcpHeaderLen);\r
+               pCopiedData += TcpHeaderLen;\r
+       }\r
+       if (CurrLength == TcpHeaderLen) {\r
+               FullBuffers++;\r
+               pLsoData->UsedBuffers = FullBuffers;\r
+               *IndexOfData = FullBuffers ;\r
+       } else {\r
+               pLsoData->UsedBuffers = FullBuffers + 1;\r
+               *IndexOfData = FullBuffers - 1;\r
+       }\r
+       pLsoData->FullBuffers = FullBuffers; \r
+       if (!IsRegularFlow){\r
+               pLsoData->LsoBuffers[0].pData = pLsoData->coppied_data;\r
+               pLsoData->LsoBuffers[0].Len = ETH_OFFSET + IpHeaderLen + TcpHeaderLen;\r
+               ASSERT(pLsoData->LsoBuffers[0].Len <= LSO_MAX_HEADER);\r
+       }\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static void __port_do_mcast_garbage(ipoib_port_t* const        p_port)\r
+{\r
+    const mac_addr_t DEFAULT_MCAST_GROUP = {0x01, 0x00, 0x5E, 0x00, 0x00, 0x01};\r
+       /* Do garbage collecting... */\r
+\r
+       cl_map_item_t   *p_item;\r
+       ipoib_endpt_t   *p_endpt;\r
+       cl_qlist_t              destroy_mc_list;\r
+       uint8_t                 cnt;\r
+       const static GC_MAX_LEAVE_NUM = 80;\r
+\r
+       cl_qlist_init( &destroy_mc_list );\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+       /* Wait for all readers to finish */\r
+       while( p_port->endpt_rdr )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               cl_obj_lock( &p_port->obj );\r
+       }\r
+       cnt = 0;\r
+       p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts );\r
+       while( (p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts )) && (cnt < GC_MAX_LEAVE_NUM))\r
+       {\r
+               p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+               p_item = cl_qmap_next( p_item );\r
+\r
+               /* Check if the current endpoint is not a multicast listener */\r
+\r
+               if( p_endpt->h_mcast && \r
+                       (!p_endpt->is_mcast_listener) &&\r
+                       ( cl_memcmp( &p_endpt->mac, &DEFAULT_MCAST_GROUP, sizeof(mac_addr_t) ) &&\r
+                        (!p_endpt->is_in_use) ))\r
+               {\r
+                       cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+                               &p_endpt->mac_item );\r
+                       cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+                               &p_endpt->gid_item );\r
+\r
+                       if( p_endpt->dlid )\r
+                       {\r
+                               cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+                                       &p_endpt->lid_item );\r
+                               p_endpt->dlid = 0;\r
+                       }\r
+\r
+                       cl_qlist_insert_tail(\r
+                               &destroy_mc_list, &p_endpt->mac_item.pool_item.list_item );\r
+                       cnt++;\r
+               }\r
+               else\r
+                       p_endpt->is_in_use = FALSE;\r
+       }\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       /* Destroy all multicast endpoints now that we have released the lock. */\r
+       while( cl_qlist_count( &destroy_mc_list ) )\r
+       {\r
+               p_endpt = PARENT_STRUCT( cl_qlist_remove_head( &destroy_mc_list ),\r
+                                                                ipoib_endpt_t, mac_item.pool_item.list_item );\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+                       ("mcast garbage collector: destroying endpoint %02x:%02x:%02x:%02x:%02x:%02x \n", \r
+                                p_endpt->mac.addr[0],\r
+                                p_endpt->mac.addr[1],\r
+                                p_endpt->mac.addr[2],\r
+                                p_endpt->mac.addr[3],\r
+                                p_endpt->mac.addr[4],\r
+                                p_endpt->mac.addr[5]) );\r
+               cl_obj_destroy( &p_endpt->obj );\r
+       }\r
+}\r
+\r
+static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2)\r
+{\r
+       ipoib_port_t *p_port = context;\r
+\r
+       UNREFERENCED_PARAMETER(p_gc_dpc);\r
+       UNREFERENCED_PARAMETER(s_arg1);\r
+       UNREFERENCED_PARAMETER(s_arg2);\r
+\r
+       __port_do_mcast_garbage(p_port);\r
+}\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_get_by_gid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ib_gid_t* const                         p_gid )\r
+{\r
+       return __endpt_mgr_get_by_gid( p_port, p_gid );\r
+}\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_get_by_lid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   net16_t                                         lid )\r
+{\r
+       return __endpt_mgr_get_by_lid( p_port, lid );\r
+}\r
+\r
+ib_api_status_t\r
+ipoib_recv_dhcp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t* const            p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst )\r
+{\r
+       return __recv_dhcp(\r
+               p_port, p_ipoib, p_eth, p_src,p_dst );\r
+}\r
+\r
+\r
+void\r
+ipoib_port_cancel_xmit(\r
+       IN                              ipoib_port_t* const             p_port,\r
+       IN                              PVOID                                    cancel_id )\r
+{\r
+       cl_list_item_t          *p_item;\r
+       PNET_BUFFER_LIST                p_nbl;\r
+       PVOID                   nbl_id;\r
+       cl_qlist_t              cancel_list;\r
+       ULONG                   send_complete_flags = 0;\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       cl_qlist_init( &cancel_list );\r
+\r
+       cl_spinlock_acquire( &p_port->send_lock );\r
+\r
+       for( p_item = cl_qlist_head( &p_port->send_mgr.pending_list );\r
+               p_item != cl_qlist_end( &p_port->send_mgr.pending_list );\r
+               p_item = cl_qlist_next( p_item ) )\r
+       {\r
+               p_nbl = IPOIB_PACKET_FROM_LIST_ITEM( p_item );\r
+               nbl_id = NDIS_GET_NET_BUFFER_LIST_CANCEL_ID( p_nbl );\r
+               if( nbl_id == cancel_id )\r
+               {\r
+                       cl_qlist_remove_item( &p_port->send_mgr.pending_list, p_item );\r
+                       NET_BUFFER_LIST_STATUS( p_nbl) = NDIS_STATUS_REQUEST_ABORTED ;\r
+                       cl_qlist_insert_tail( &cancel_list, IPOIB_LIST_ITEM_FROM_PACKET( p_nbl ) );\r
+               }\r
+       }\r
+       cl_spinlock_release( &p_port->send_lock );\r
+\r
+       if( cl_qlist_count( &cancel_list ) )\r
+       {\r
+               while( ( p_item = cl_qlist_remove_head( &cancel_list )) \r
+                                                               != cl_qlist_end( &cancel_list ))\r
+               {\r
+                       p_nbl = IPOIB_PACKET_FROM_LIST_ITEM( p_item );\r
+                       NET_BUFFER_LIST_STATUS( p_nbl) = NDIS_STATUS_SEND_ABORTED;\r
+                       send_complete_flags = 0;\r
+                       if (NDIS_CURRENT_IRQL() == DISPATCH_LEVEL)\r
+                       {\r
+                               NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
+                       }\r
+                       NdisMSendNetBufferListsComplete( p_port->p_adapter->h_adapter,\r
+                               p_nbl, send_complete_flags );\r
+               }\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+/* \r
+*  Put all fragments into separate WR and chain together.\r
+*  The last WR will be set to generate CQ Event.\r
+*  lookaside buffer is used for ipoib and ip headers attached to each WR.\r
+*  Buffer will be released on last WR send completion.\r
+*/\r
+#if 0\r
+static NDIS_STATUS\r
+__send_fragments(\r
+IN             ipoib_port_t* const                     p_port,\r
+IN             ipoib_send_desc_t* const        p_desc,\r
+IN             eth_hdr_t* const                        p_eth_hdr,\r
+IN             ip_hdr_t* const                         p_ip_hdr,\r
+IN             uint32_t                                        buf_len,\r
+IN             NDIS_BUFFER*                            p_ndis_buf )\r
+{\r
+       uint32_t        ds_idx = 1;\r
+       uint32_t        wr_idx = 0;\r
+       uint32_t        sgl_idx = 2; //skip eth hdr, ip hdr\r
+       uint32_t        options_len = 0;\r
+       uint8_t*        p_options = NULL;\r
+       uint8_t*        p_buf;\r
+       uint32_t        frag_offset = 0;\r
+       uint32_t        next_sge;\r
+       uint32_t        wr_size = 0;\r
+       uint32_t        ip_hdr_len = IP_HEADER_LENGTH( p_ip_hdr );\r
+       uint32_t        total_ip_len = cl_ntoh16( p_ip_hdr->length );\r
+\r
+       SCATTER_GATHER_LIST             *p_sgl;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       if( IP_DONT_FRAGMENT(p_ip_hdr) )\r
+                       return NDIS_STATUS_INVALID_PACKET;\r
+       \r
+       p_sgl = NDIS_PER_PACKET_INFO_FROM_PACKET( p_desc->p_pkt, ScatterGatherListPacketInfo );\r
+       if( !p_sgl )\r
+       {\r
+               ASSERT( p_sgl );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to get SGL from packet.\n") );\r
+               return NDIS_STATUS_FAILURE;\r
+       }\r
+       if( ( p_sgl->NumberOfElements > MAX_SEND_SGE ||\r
+               p_sgl->Elements[0].Length < sizeof(eth_hdr_t)) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Too many SG Elements in packet.\n") );\r
+               return NDIS_STATUS_FAILURE;\r
+       }\r
+       p_buf = (uint8_t *)\r
+               ExAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+       if( !p_buf )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate lookaside buffer.\n") );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+       p_desc->p_buf = (send_buf_t*)p_buf;\r
+\r
+       if( buf_len < ip_hdr_len )\r
+       {       /* ip options in a separate buffer */\r
+               CL_ASSERT( buf_len == sizeof( ip_hdr_t ) );\r
+               NdisGetNextBuffer( p_ndis_buf, &p_ndis_buf );\r
+               if( !p_ndis_buf )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get IP options buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               NdisQueryBufferSafe( p_ndis_buf, &p_options, &options_len, NormalPagePriority );\r
+               if( !p_options )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to query IP options buffer address.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               cl_memcpy( p_buf, p_ip_hdr, sizeof( ip_hdr_t ) );\r
+               if( p_options && options_len )\r
+               { \r
+                       __copy_ip_options( &p_buf[sizeof(ip_hdr_t)], \r
+                                                               p_options, options_len, TRUE );\r
+               }\r
+               wr_size = buf_len + options_len;\r
+               sgl_idx++;\r
+       }\r
+       else\r
+       {       /*options probably in the same buffer */\r
+               cl_memcpy( p_buf, p_ip_hdr, buf_len );\r
+               options_len = ip_hdr_len - sizeof( ip_hdr_t );\r
+               if( options_len )\r
+               {\r
+                       p_options = p_buf + sizeof( ip_hdr_t );\r
+               }\r
+               frag_offset += ( buf_len - ip_hdr_len );\r
+               wr_size = buf_len;\r
+       }\r
+\r
+       p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf );\r
+       p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+       p_desc->send_wr[wr_idx].local_ds[ds_idx].length = wr_size;\r
+       \r
+       /* count how much data can be put into the first WR beside IP header.\r
+        * other protocols headers possibly supplied in subsequent buffers.\r
+        */\r
+       for( sgl_idx; sgl_idx < p_sgl->NumberOfElements; sgl_idx++ )\r
+       {\r
+               next_sge = p_sgl->Elements[sgl_idx].Length;\r
+\r
+               /* add sgl if it can fit into the same WR \r
+               * Note: so far not going to split large SGE between WRs,\r
+               * so first fragment could be a smaller size.\r
+               */\r
+               if( next_sge <= ( p_port->p_adapter->params.payload_mtu - wr_size ) )\r
+               {\r
+                       ++ds_idx;\r
+                       wr_size += next_sge;\r
+                       frag_offset += next_sge;\r
+                       p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = \r
+                                                                       p_sgl->Elements[sgl_idx].Address.QuadPart;\r
+                       p_desc->send_wr[wr_idx].local_ds[ds_idx].length = next_sge;\r
+                       p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+               }\r
+               else\r
+               {\r
+                       /* fix ip hdr for the first fragment and move on */\r
+                       __update_fragment_ip_hdr( (ip_hdr_t* const)p_buf,\r
+                               (uint16_t)wr_size, IP_FRAGMENT_OFFSET(p_ip_hdr), TRUE );\r
+\r
+                       p_desc->send_wr[wr_idx].wr.num_ds = ds_idx + 1;\r
+                       p_buf += ip_hdr_len;\r
+                       p_buf += (( buf_len > ip_hdr_len ) ? ( buf_len - ip_hdr_len ): 0);\r
+                       frag_offset += ( (IP_FRAGMENT_OFFSET(p_ip_hdr)) << 3 );\r
+                       ++wr_idx;\r
+                       ds_idx = 0;\r
+                       break;\r
+               }\r
+       }\r
+       total_ip_len -= wr_size;\r
+       wr_size = 0;\r
+\r
+       for( sgl_idx, wr_idx; sgl_idx < p_sgl->NumberOfElements; sgl_idx++ )\r
+       {\r
+               uint32_t        seg_len;\r
+               uint64_t        next_sgl_addr;\r
+               \r
+               if( wr_idx >= ( MAX_WRS_PER_MSG - 1 ) )\r
+                       return NDIS_STATUS_RESOURCES;\r
+               \r
+               next_sge = p_sgl->Elements[sgl_idx].Length;\r
+               next_sgl_addr = p_sgl->Elements[sgl_idx].Address.QuadPart;\r
+\r
+               while( next_sge )\r
+               {\r
+                       if( ds_idx == 0 )\r
+                       {       /* new ipoib + ip header */\r
+                               ((ipoib_hdr_t*)p_buf)->type = p_eth_hdr->type;\r
+                               ((ipoib_hdr_t*)p_buf)->resv = 0;\r
+                               p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf );\r
+                               p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+                               p_desc->send_wr[wr_idx].local_ds[ds_idx].length = sizeof( ipoib_hdr_t );\r
+                               p_buf += sizeof( ipoib_hdr_t );\r
+                               ++ds_idx;\r
+\r
+                               cl_memcpy( p_buf, p_ip_hdr, sizeof( ip_hdr_t ) );\r
+                               if( p_options && options_len )\r
+                               {\r
+                                       /* copy ip options if needed */\r
+                                       __copy_ip_options( &p_buf[sizeof(ip_hdr_t)], \r
+                                                               p_options, options_len, FALSE );\r
+                               }\r
+                               wr_size = ip_hdr_len;\r
+                       }\r
+                       if( ds_idx == 1 )\r
+                       {\r
+                               p_desc->send_wr[wr_idx].local_ds[ds_idx].length = ip_hdr_len;\r
+                               p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf );\r
+                               p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+                               ++ds_idx;\r
+                       }\r
+\r
+                       seg_len = ( next_sge > ( p_port->p_adapter->params.payload_mtu - wr_size ) )?\r
+                               ( p_port->p_adapter->params.payload_mtu - wr_size ) : next_sge;\r
+\r
+                       p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = next_sgl_addr;\r
+                       p_desc->send_wr[wr_idx].local_ds[ds_idx].length = seg_len;\r
+                       p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+                       ++ds_idx;\r
+                       \r
+                       wr_size += seg_len;\r
+                       total_ip_len -= seg_len;\r
+\r
+                       if( wr_size >= p_port->p_adapter->params.payload_mtu || total_ip_len == 0 )\r
+                       {       /* fix ip hdr for that fragment */\r
+                               __update_fragment_ip_hdr( (ip_hdr_t* const)p_buf, (uint16_t)wr_size,\r
+                                       ((uint16_t)(frag_offset >> 3 )), \r
+                                       (BOOLEAN)(( total_ip_len > 0 ) || IP_MORE_FRAGMENTS( p_ip_hdr)) );\r
+                               p_desc->send_wr[wr_idx].wr.num_ds = ds_idx;\r
+                               if( total_ip_len > 0 )\r
+                               {\r
+                                       ++wr_idx;\r
+                                       frag_offset += (wr_size - ip_hdr_len);\r
+                                       wr_size = 0;\r
+                                       ds_idx = 0;\r
+                                       p_buf += ip_hdr_len;\r
+                               }\r
+                       }\r
+                       next_sge -= seg_len;\r
+                       if( next_sge > 0 )\r
+                       {\r
+                               next_sgl_addr += seg_len;\r
+                       }\r
+               }\r
+       }\r
+       p_desc->num_wrs += wr_idx;\r
+       \r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+#endif\r
+\r
+static void\r
+__update_fragment_ip_hdr(\r
+IN             ip_hdr_t* const         p_ip_hdr,\r
+IN             uint16_t                        fragment_size, \r
+IN             uint16_t                        fragment_offset, \r
+IN             BOOLEAN                         more_fragments )\r
+{\r
+       uint16_t*       p_hdr = (uint16_t*)p_ip_hdr;\r
+       p_ip_hdr->length = cl_hton16( fragment_size ); // bytes\r
+       p_ip_hdr->offset = cl_hton16( fragment_offset ); // 8-byte units\r
+       if( more_fragments )\r
+       {\r
+               IP_SET_MORE_FRAGMENTS( p_ip_hdr );\r
+       }\r
+       else\r
+       {\r
+               IP_SET_LAST_FRAGMENT( p_ip_hdr );\r
+       }\r
+       p_ip_hdr->chksum = 0;\r
+       p_ip_hdr->chksum = ipchksum( p_hdr, IP_HEADER_LENGTH(p_ip_hdr) );\r
+}\r
+\r
+static void\r
+__copy_ip_options(\r
+IN             uint8_t*        p_buf,\r
+IN             uint8_t*        p_options,\r
+IN             uint32_t        options_len,\r
+IN             BOOLEAN         copy_all )\r
+{\r
+       uint32_t        option_length;\r
+       uint32_t        total_length = 0;\r
+       uint32_t        copied_length = 0;\r
+       uint8_t*        p_src = p_options;\r
+       uint8_t*        p_dst = p_buf;\r
+\r
+       if( p_options == NULL || options_len == 0 )\r
+               return;\r
+       if( copy_all )\r
+       {\r
+               cl_memcpy( p_dst, p_src, options_len );\r
+               return;\r
+       }\r
+       do\r
+       {\r
+               if( ( *p_src ) == 0 ) // end of options list\r
+               {\r
+                       total_length++;\r
+                       break;\r
+               }\r
+               if( ( *p_src ) == 0x1 ) // no op\r
+               {\r
+                       p_src++;\r
+                       total_length++;\r
+                       continue;\r
+               }\r
+               /*from RFC791: \r
+               * This option may be used between options, for example, to align\r
+        * the beginning of a subsequent option on a 32 bit boundary.\r
+               */\r
+               if( copied_length && (copied_length % 4) )\r
+               {\r
+                       uint32_t align = 4 - (copied_length % 4);\r
+                       cl_memset( p_dst, 0x1, (size_t)align );\r
+                       p_dst += align;\r
+                       copied_length += align;\r
+               }\r
+               option_length = *(p_src + 1);\r
+\r
+               if( *p_src & 0x80 )\r
+               {\r
+                       cl_memcpy( p_dst, p_src, option_length );\r
+                       p_dst += option_length;\r
+                       copied_length += option_length;\r
+               }\r
+               total_length += option_length;\r
+               p_src += option_length;\r
+\r
+       }while( total_length < options_len );\r
+\r
+       CL_ASSERT( total_length == options_len );\r
+       CL_ASSERT( copied_length <= 40 );\r
+\r
+       /* padding the rest */\r
+       if( options_len > copied_length )\r
+       {\r
+               cl_memclr( p_dst, ( options_len - copied_length ) );\r
+       }\r
+       return;\r
+}\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_port.h b/trunk/ulp/ipoib/kernel6/ipoib_port.h
new file mode 100644 (file)
index 0000000..602389b
--- /dev/null
@@ -0,0 +1,827 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_port.h 4226 2009-04-06 06:01:03Z xalex $\r
+ */\r
+\r
+\r
+\r
+#ifndef _IPOIB_PORT_H_\r
+#define _IPOIB_PORT_H_\r
+\r
+\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_obj.h>\r
+#include <complib/cl_qmap.h>\r
+#include <complib/cl_fleximap.h>\r
+#include <ip_packet.h>\r
+#include "ipoib_xfr_mgr.h"\r
+#include "ipoib_endpoint.h"\r
+\r
+\r
+/*\r
+ * Define to place receive buffer inline in receive descriptor.\r
+ */\r
+#define IPOIB_INLINE_RECV      1\r
+\r
+/* \r
+ *  Invalid pkey index\r
+ */\r
+#define PKEY_INVALID_INDEX     0xFFFF\r
+\r
+/*\r
+ * Define to control how transfers are done.  When defined as 1, causes\r
+ * packets to be sent using NDIS DMA facilities (getting the SGL from the\r
+ * packet).  When defined as 0, uses the NDIS_BUFFER structures as MDLs\r
+ * to get the physical page mappings of the buffers.\r
+ */\r
+#define IPOIB_USE_DMA  1\r
+\r
+\r
+#define IPOIB_PORT_FROM_PACKET( P )    \\r
+       (((ipoib_port_t**)NET_BUFFER_LIST_MINIPORT_RESERVED(P))[0])\r
+#define IPOIB_ENDPT_FROM_PACKET( P )   \\r
+       (((ipoib_endpt_t**)NET_BUFFER_LIST_MINIPORT_RESERVED(P))[1])\r
+#define IPOIB_RECV_FROM_PACKET( P )    \\r
+       (((ipoib_recv_desc_t**)NET_BUFFER_LIST_MINIPORT_RESERVED(P))[1])\r
+       \r
+//TODO to be renamed: IPOIB_NBL_FROM_LIST_ITEM\r
+#define IPOIB_PACKET_FROM_LIST_ITEM( I ) \\r
+       (PARENT_STRUCT( I, NET_BUFFER_LIST, MiniportReserved ))\r
+#define IPOIB_LIST_ITEM_FROM_PACKET( P ) \\r
+       ((cl_list_item_t*)NET_BUFFER_LIST_MINIPORT_RESERVED(P))\r
+\r
+#define IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER( P )      \\r
+       (((NET_BUFFER_LIST**)NET_BUFFER_MINIPORT_RESERVED(P))[0])\r
+#define IPOIB_FROM_QUEUE( P )  \\r
+       (((void**)NET_BUFFER_MINIPORT_RESERVED(P))[1])\r
+#define IPOIB_SEND_FROM_NETBUFFER( P ) \\r
+       (((send_buf_t**)NET_BUFFER_MINIPORT_RESERVED(P))[2])\r
+\r
+\r
+#define IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(_NetBufferList)    ((_NetBufferList->FirstNetBuffer)->MiniportReserved[3])\r
+#define IPOIB_DEC_NET_BUFFER_LIST_REF_COUNT(_NetBufferList)    (*(PULONG)&(_NetBufferList->FirstNetBuffer)->MiniportReserved[3])--\r
+\r
+\r
+typedef struct _ipoib_ib_mgr\r
+{\r
+       ib_ca_handle_t                  h_ca;\r
+       ib_pd_handle_t                  h_pd;\r
+       ib_cq_handle_t                  h_recv_cq;\r
+       ib_cq_handle_t                  h_send_cq;\r
+       ib_qp_handle_t                  h_qp;\r
+       ib_query_handle_t               h_query;\r
+       ib_srq_handle_t                 h_srq;\r
+       net32_t                                 qpn;\r
+\r
+       ib_mr_handle_t                  h_mr;\r
+       net32_t                                 lkey;\r
+\r
+       uint8_t                                 rate;\r
+       ib_member_rec_t                 bcast_rec;\r
+\r
+}      ipoib_ib_mgr_t;\r
+/*\r
+* FIELDS\r
+*      h_ca\r
+*              CA handle for all IB resources.\r
+*\r
+*      h_pd\r
+*              PD handle for all IB resources.\r
+*\r
+*      h_recv_cq\r
+*              Recv CQ handle.\r
+*\r
+*      h_send_cq\r
+*              Send CQ handle.\r
+*\r
+*      h_qp\r
+*              QP handle for data transfers.\r
+*\r
+*      h_query\r
+*              Query handle for cancelling SA queries.\r
+*\r
+*      h_mr\r
+*              Registration handle for all of physical memory.  Used for\r
+*              send/receive buffers to simplify growing the receive pool.\r
+*\r
+*      lkey\r
+*              LKey for the memory region.\r
+*\r
+*      bcast_rec\r
+*              Cached information about the broadcast group, used to specify\r
+*              parameters used to join other multicast groups.\r
+*********/\r
+\r
+\r
+#include <complib/cl_packon.h>\r
+/****s* IPoIB Driver/ipoib_hdr_t\r
+* NAME\r
+*      ipoib_hdr_t\r
+*\r
+* DESCRIPTION\r
+*      IPoIB packet header.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ipoib_hdr\r
+{\r
+       net16_t                 type;\r
+       net16_t                 resv;\r
+\r
+}      PACK_SUFFIX ipoib_hdr_t;\r
+/*\r
+* FIELDS\r
+*      type\r
+*              Protocol type.\r
+*\r
+*      resv\r
+*              Reserved portion of IPoIB header.\r
+*********/\r
+\r
+typedef struct _ipoib_arp_pkt\r
+{\r
+       net16_t                 hw_type;\r
+       net16_t                 prot_type;\r
+       uint8_t                 hw_size;\r
+       uint8_t                 prot_size;\r
+       net16_t                 op;\r
+       ipoib_hw_addr_t src_hw;\r
+       net32_t                 src_ip;\r
+       ipoib_hw_addr_t dst_hw;\r
+       net32_t                 dst_ip;\r
+\r
+}      PACK_SUFFIX ipoib_arp_pkt_t;\r
+\r
+\r
+/****s* IPoIB Driver/ipoib_pkt_t\r
+* NAME\r
+*      ipoib_pkt_t\r
+*\r
+* DESCRIPTION\r
+*      Represents an IPoIB packet with no GRH.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ipoib_pkt\r
+{\r
+       ipoib_hdr_t             hdr;\r
+       union _payload\r
+       {\r
+               uint8_t                 data[MAX_UD_PAYLOAD_MTU];\r
+               ipoib_arp_pkt_t arp;\r
+               ip_pkt_t                ip;\r
+\r
+       }       PACK_SUFFIX type;\r
+\r
+}      PACK_SUFFIX ipoib_pkt_t;\r
+/*\r
+* FIELDS\r
+*      hdr\r
+*              IPoIB header.\r
+*\r
+*      type\r
+*              Union for different types of payloads.\r
+*\r
+*      type.data\r
+*              raw packet.\r
+*\r
+*      type.ib_arp\r
+*              IPoIB ARP packet.\r
+*\r
+*      type.arp\r
+*              Ethernet ARP packet.\r
+*\r
+*      type.ip\r
+*              IP packet.\r
+*********/\r
+\r
+\r
+/****s* IPoIB Driver/recv_buf_t\r
+* NAME\r
+*      recv_buf_t\r
+*\r
+* DESCRIPTION\r
+*      Represents a receive buffer, including the ethernet header\r
+*      used to indicate the receive to the OS.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef union _recv_buf\r
+{\r
+       struct _recv_buf_type_eth\r
+       {\r
+               uint8_t                 pad[sizeof(ib_grh_t) +\r
+                                                       sizeof(ipoib_hdr_t) -\r
+                                                       sizeof(eth_hdr_t)];\r
+               eth_pkt_t               pkt;    /* data starts at sizeof(grh)+sizeof(eth_hdr) */\r
+\r
+       }       PACK_SUFFIX eth;\r
+\r
+       struct _recv_buf_type_ib\r
+       {\r
+               ib_grh_t                grh;    /* Must be same offset as lcl_rt.ib.pkt */\r
+               ipoib_pkt_t             pkt;    /* data starts at 10+grh+4 */\r
+\r
+       }       PACK_SUFFIX ib;\r
+\r
+}      PACK_SUFFIX recv_buf_t;\r
+/*\r
+* FIELDS\r
+*      eth.pkt\r
+*              Ethernet packet, used to indicate the receive to the OS.\r
+*\r
+*      ib.grh\r
+*              GRH for a globally routed received packet.\r
+*\r
+*      ib.pkt\r
+*              IPOIB packet representing a globally routed received packet.\r
+*\r
+* NOTES\r
+*      When posting the work request, the address of ib.grh is used.\r
+*\r
+*      TODO: Do we need a pad to offset the header so that the data ends up\r
+*      aligned on a pointer boundary?\r
+*********/\r
+\r
+/****s* IPoIB Driver/send_buf_t\r
+* NAME\r
+*      send_buf_t\r
+*\r
+* DESCRIPTION\r
+*      Represents a send buffer, used to convert packets to IPoIB format.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef union _send_buf\r
+{\r
+       uint8_t                 data[MAX_UD_PAYLOAD_MTU];\r
+       ipoib_arp_pkt_t arp;\r
+       ip_pkt_t                ip;\r
+\r
+}      PACK_SUFFIX send_buf_t;\r
+/*\r
+* FIELDS\r
+*      data\r
+*              IP/ARP packet.\r
+*\r
+* NOTES\r
+*      TODO: Do we need a pad to offset the header so that the data ends up\r
+*      aligned on a pointer boundary?\r
+*********/\r
+#include <complib/cl_packoff.h>\r
+\r
+\r
+typedef struct _ipoib_buf_mgr\r
+{\r
+       cl_qpool_t                      recv_pool;\r
+\r
+       NDIS_HANDLE                     h_packet_pool;\r
+       NDIS_HANDLE                     h_buffer_pool;\r
+\r
+       NPAGED_LOOKASIDE_LIST   send_buf_list;\r
+       NDIS_HANDLE                     h_send_pkt_pool;\r
+       NDIS_HANDLE                     h_send_buf_pool;\r
+\r
+}      ipoib_buf_mgr_t;\r
+/*\r
+* FIELDS\r
+*      recv_pool\r
+*              Pool of ipoib_recv_desc_t structures.\r
+*\r
+*      h_packet_pool\r
+*              NDIS packet pool, used to indicate receives to NDIS.\r
+*\r
+*      h_buffer_pool\r
+*              NDIS buffer pool, used to indicate receives to NDIS.\r
+*\r
+*      send_buf_list\r
+*              Lookaside list for dynamically allocating send buffers for send\r
+*              that require copies (ARP, DHCP, and any with more physical pages\r
+*              than can fit in the local data segments).\r
+*********/\r
+\r
+\r
+typedef enum _ipoib_pkt_type\r
+{\r
+       PKT_TYPE_UCAST,\r
+       PKT_TYPE_BCAST,\r
+       PKT_TYPE_MCAST,\r
+       PKT_TYPE_CM_UCAST\r
+\r
+}      ipoib_pkt_type_t;\r
+\r
+typedef struct _ipoib_cm_desc\r
+{\r
+       cl_pool_item_t                          item;   /* Must be first. */\r
+       uint32_t                                        len;\r
+       ipoib_pkt_type_t                        type;\r
+       ib_recv_wr_t                            wr;\r
+       ib_local_ds_t                           local_ds[2];\r
+       cl_list_item_t                          list_item;\r
+       uint8_t*                                        p_alloc_buf;\r
+       uint8_t*                                        p_buf;\r
+       uint32_t                                        alloc_buf_size;\r
+       uint32_t                                        buf_size;\r
+       net32_t                                         lkey;\r
+       ib_mr_handle_t                          h_mr;\r
+       NDIS_TCP_IP_CHECKSUM_PACKET_INFO        ndis_csum;\r
+\r
+}      ipoib_cm_desc_t;\r
+\r
+typedef struct _ipoib_recv_desc\r
+{\r
+       cl_pool_item_t          item;   /* Must be first. */\r
+       uint32_t                        len;\r
+       ipoib_pkt_type_t        type;\r
+       ib_recv_wr_t            wr;\r
+       ib_local_ds_t           local_ds[2];\r
+       NDIS_TCP_IP_CHECKSUM_PACKET_INFO        ndis_csum;\r
+#if IPOIB_INLINE_RECV\r
+       recv_buf_t                      buf;\r
+#else\r
+       recv_buf_t                      *p_buf;\r
+#endif\r
+\r
+}      ipoib_recv_desc_t;\r
+/*\r
+* FIELDS\r
+*      item\r
+*              Pool item for storing descriptors in a pool.\r
+*\r
+*      len\r
+*              Length to indicate to NDIS.  This is different than the length of the\r
+*              received data as some data is IPoIB specific and filtered out.\r
+*\r
+*      type\r
+*              Type of packet, used in filtering received packets against the packet\r
+*              filter.  Also used to update stats.\r
+*\r
+*      wr\r
+*              Receive work request.\r
+*\r
+*      local_ds\r
+*              Local data segments.  The second segment is only used if a buffer\r
+*              spans physical pages.\r
+*\r
+*      buf\r
+*              Buffer for the receive.\r
+*\r
+* NOTES\r
+*      The pool item is always first to allow casting form a cl_pool_item_t or\r
+*      cl_list_item_t to the descriptor.\r
+*********/\r
+typedef struct __ipoib_send_wr\r
+{\r
+       ib_send_wr_t            wr;\r
+       ib_local_ds_t           local_ds[MAX_SEND_SGE]; /* Must be last. */\r
+} ipoib_send_wr_t;\r
+\r
+typedef enum __send_dir\r
+{\r
+       SEND_UD_QP = 1,\r
+       SEND_RC_QP = 2\r
+} send_dir_t;\r
+\r
+typedef struct _ipoib_send_desc\r
+{\r
+       PNET_BUFFER_LIST    p_netbuf_list;\r
+       ipoib_endpt_t           *p_endpt;\r
+       send_buf_t                      *p_buf;\r
+       ib_qp_handle_t          send_qp;\r
+       send_dir_t                      send_dir;\r
+       uint32_t                        num_wrs;\r
+       ipoib_send_wr_t         send_wr[MAX_WRS_PER_MSG];\r
+\r
+}      ipoib_send_desc_t;\r
+/*\r
+* FIELDS\r
+*      p_pkt\r
+*              Pointer to the NDIS_PACKET associated with the send operation.\r
+*\r
+*      p_endpt\r
+*              Endpoint for this send.\r
+*\r
+*      p_buf\r
+*              Buffer for the send, if allocated.\r
+*\r
+*      wr\r
+*              Send work request.\r
+*\r
+*      pkt_hdr\r
+*              IPoIB packet header, pointed to by the first local datasegment.\r
+*\r
+*      local_ds\r
+*              Local data segment array.  Placed last to allow allocating beyond the\r
+*              end of the descriptor for additional datasegments.\r
+*\r
+* NOTES\r
+*      The pool item is always first to allow casting form a cl_pool_item_t or\r
+*      cl_list_item_t to the descriptor.\r
+*********/\r
+\r
+\r
+typedef struct _ipoib_recv_mgr\r
+{\r
+       int32_t                 depth;\r
+\r
+       NET_BUFFER_LIST         **recv_pkt_array;\r
+\r
+       cl_qlist_t              done_list;\r
+\r
+}      ipoib_recv_mgr_t;\r
+/*\r
+* FIELDS\r
+*      depth\r
+*              Current number of WRs posted.\r
+*\r
+*      p_head\r
+*              Pointer to work completion in descriptor at the head of the QP.\r
+*\r
+*      p_tail\r
+*              Pointer to the work completion in the descriptor at the tail of the QP.\r
+*\r
+*      recv_pkt_array\r
+*              Array of pointers to NDIS_PACKET used to indicate receives.\r
+*\r
+*      done_list\r
+*              List of receive descriptors that need to be indicated to NDIS.\r
+*********/\r
+\r
+\r
+typedef struct _ipoib_send_mgr\r
+{\r
+       atomic32_t              depth;\r
+       cl_qlist_t              pending_list;\r
+       ipoib_send_desc_t desc;\r
+\r
+}      ipoib_send_mgr_t;\r
+/*\r
+* FIELDS\r
+*      depth\r
+*              Current number of WRs posted, used to queue pending requests.\r
+*\r
+*      pending_list\r
+*              List of NDIS_PACKET structures that are awaiting available WRs to send.\r
+*********/\r
+\r
+\r
+typedef struct _ipoib_endpt_mgr\r
+{\r
+       cl_qmap_t                               mac_endpts;\r
+       cl_fmap_t                               gid_endpts;\r
+       cl_qmap_t                               lid_endpts;\r
+       cl_fmap_t                               conn_endpts;\r
+       LIST_ENTRY                      pending_conns;\r
+       LIST_ENTRY                              remove_conns;\r
+       NDIS_SPIN_LOCK                  conn_lock;\r
+       NDIS_SPIN_LOCK                  remove_lock;\r
+       cl_thread_t                             h_thread;\r
+       cl_event_t                              event;\r
+       uint32_t                                thread_is_done;\r
+}      ipoib_endpt_mgr_t;\r
+/*\r
+* FIELDS\r
+*      mac_endpts\r
+*              Map of enpoints, keyed by MAC address.\r
+*\r
+*      gid_endpts\r
+*              Map of enpoints, keyed by GID.\r
+*\r
+*      lid_endpts\r
+*              Map of enpoints, keyed by LID.  Only enpoints on the same subnet\r
+*              are inserted in the LID map.\r
+*\r
+*      conn_endpts\r
+*              Map of connected endpts, keyed by remote gid.\r
+*********/\r
+\r
+\r
+typedef struct _ipoib_port\r
+{\r
+       cl_obj_t                                obj;\r
+       cl_obj_rel_t                    rel;\r
+\r
+       ib_qp_state_t                   state;\r
+\r
+       cl_spinlock_t                   recv_lock;\r
+       cl_spinlock_t                   send_lock;\r
+\r
+       struct _ipoib_adapter   *p_adapter;\r
+       uint8_t                                 port_num;\r
+\r
+       KEVENT                                  sa_event;\r
+\r
+       atomic32_t                              mcast_cnt;\r
+       KEVENT                                  leave_mcast_event;\r
+       \r
+       ipoib_ib_mgr_t                  ib_mgr;\r
+\r
+       ipoib_buf_mgr_t                 buf_mgr;\r
+\r
+       ipoib_recv_mgr_t                recv_mgr;\r
+       ipoib_send_mgr_t                send_mgr;\r
+\r
+       KDPC                                    recv_dpc;\r
+\r
+       ipoib_endpt_mgr_t               endpt_mgr;\r
+\r
+       endpt_buf_mgr_t                 cm_buf_mgr;\r
+       endpt_recv_mgr_t                cm_recv_mgr;\r
+\r
+       ipoib_endpt_t                   *p_local_endpt;\r
+       ib_ca_attr_t                    *p_ca_attrs;\r
+#if DBG\r
+       atomic32_t                              ref[ref_array_size];\r
+#endif\r
+\r
+       atomic32_t                              endpt_rdr;\r
+\r
+       atomic32_t                              hdr_idx;\r
+       uint16_t                                pkey_index;\r
+       KDPC                                    gc_dpc;\r
+       KTIMER                                  gc_timer;\r
+       uint32_t                                bc_join_retry_cnt;\r
+       ib_net16_t                              base_lid;\r
+       ipoib_hdr_t                             hdr[1]; /* Must be last! */\r
+\r
+}      ipoib_port_t;\r
+/*\r
+* FIELDS\r
+*      obj\r
+*              Complib object for reference counting, relationships,\r
+*              and destruction synchronization.\r
+*\r
+*      rel\r
+*              Relationship to associate the port with the adapter.\r
+*\r
+*      state\r
+*              State of the port object.  Tracks QP state fairly closely.\r
+*\r
+*      recv_lock\r
+*              Spinlock to protect receive operations.\r
+*\r
+*      send_lock\r
+*              Spinlock to protect send operations.\r
+*\r
+*      p_adapter\r
+*              Parent adapter.  Used to get AL handle.\r
+*\r
+*      port_num\r
+*              Port number of this adapter.\r
+*\r
+*      ib_mgr\r
+*              IB resource manager.\r
+*\r
+*      recv_mgr\r
+*              Receive manager.\r
+*\r
+*      send_mgr\r
+*              Send manager.\r
+*\r
+*      endpt_mgr\r
+*              Endpoint manager.\r
+*********/\r
+typedef struct _sgl_context\r
+{\r
+       MDL                                     *p_mdl;\r
+       NET_BUFFER_LIST         *p_netbuffer_list;\r
+       ipoib_port_t            *p_port;\r
+}sgl_context_t;\r
+\r
+ib_api_status_t\r
+ipoib_create_port(\r
+       IN                              struct _ipoib_adapter* const    p_adapter,\r
+       IN                              ib_pnp_port_rec_t* const        p_pnp_rec,\r
+               OUT                     ipoib_port_t** const            pp_port );\r
+\r
+void\r
+ipoib_port_destroy(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+void\r
+ipoib_port_up(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ib_pnp_port_rec_t* const        p_pnp_rec );\r
+\r
+void\r
+ipoib_port_down(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+ib_api_status_t\r
+ipoib_port_join_mcast(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                              mac,\r
+       IN              const   uint8_t                                 state );\r
+\r
+\r
+void\r
+ipoib_leave_mcast_cb(\r
+       IN                              void                            *context );\r
+\r
+\r
+void\r
+ipoib_port_remove_endpt(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac );\r
+\r
+void\r
+ipoib_port_send(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              NET_BUFFER_LIST                         *net_buffer_list,\r
+       IN                              ULONG                                           send_flags );\r
+\r
+void\r
+ipoib_return_net_buffer_list(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              PNET_BUFFER_LIST                        p_netbuffer_lists,\r
+       IN                              ULONG                                           return_flags);\r
+\r
+void\r
+ipoib_port_resume(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN boolean_t                                                            b_pending );\r
+\r
+NTSTATUS\r
+ipoib_mac_to_gid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ib_gid_t*                                       p_gid );\r
+\r
+NTSTATUS\r
+ipoib_mac_to_path(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ib_path_rec_t*                          p_path );\r
+\r
+void \r
+ipoib_process_sg_list(\r
+    IN  PDEVICE_OBJECT          pDO,\r
+    IN  PVOID                   pIrp,\r
+    IN  PSCATTER_GATHER_LIST    pSGList,\r
+    IN  PVOID                   Context);\r
+    \r
+inline void ipoib_port_ref(\r
+       IN                              ipoib_port_t *                          p_port, \r
+       IN                              int                                             type);\r
+\r
+inline void ipoib_port_deref(\r
+       IN                              ipoib_port_t *                          p_port,\r
+       IN                              int                                             type);\r
+\r
+#if 0\r
+// This function is only used to monitor send failures\r
+static inline VOID NdisMSendCompleteX(\r
+       IN NDIS_HANDLE  MiniportAdapterHandle,\r
+       IN PNDIS_PACKET  Packet,\r
+       IN NDIS_STATUS  Status\r
+       ) {\r
+       if (Status != NDIS_STATUS_SUCCESS) {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Sending status other than Success to NDIS\n"));\r
+       }\r
+       NdisMSendComplete(MiniportAdapterHandle,Packet,Status);\r
+}\r
+#else\r
+//#define NdisMSendCompleteX NdisMSendComplete\r
+#endif\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_get_by_gid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ib_gid_t* const                         p_gid );\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_get_by_lid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   net16_t                                         lid );\r
+\r
+ib_api_status_t\r
+ipoib_port_srq_init(\r
+       IN              ipoib_port_t* const             p_port );\r
+\r
+void\r
+ipoib_port_srq_destroy( \r
+       IN              ipoib_port_t* const             p_port );\r
+\r
+#if 0 //CM\r
+ib_api_status_t\r
+ipoib_port_listen(\r
+        IN             ipoib_port_t* const             p_port );\r
+\r
+ib_api_status_t\r
+ipoib_port_cancel_listen(\r
+       IN              ipoib_port_t*   const   p_port,\r
+       IN              ipoib_endpt_t* const    p_endpt ) {\r
+       UNUSED_PARAM(p_port);\r
+       UNUSED_PARAM(p_endpt);\r
+       return IB_SUCCESS;\r
+}\r
+#endif \r
+\r
+ib_api_status_t\r
+endpt_cm_buf_mgr_init(\r
+       IN              ipoib_port_t* const                     p_port );\r
+\r
+void\r
+endpt_cm_buf_mgr_destroy(\r
+       IN              ipoib_port_t* const             p_port );\r
+\r
+void\r
+endpt_cm_buf_mgr_reset(\r
+       IN              ipoib_port_t* const             p_port );\r
+\r
+void\r
+endpt_cm_buf_mgr_put_recv(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr,\r
+       IN              ipoib_cm_desc_t* const          p_desc );\r
+\r
+void\r
+endpt_cm_buf_mgr_put_recv_list(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr,\r
+       IN              cl_qlist_t* const                       p_list );\r
+\r
+uint32_t\r
+endpt_cm_recv_mgr_build_pkt_array(\r
+       IN              ipoib_port_t* const                     p_port,\r
+       IN              ipoib_endpt_t* const            p_endpt,\r
+       IN              cl_qlist_t* const                       p_done_list,\r
+       IN OUT  uint32_t*                                       p_bytes_recv );\r
+\r
+ib_api_status_t\r
+endpt_cm_post_recv(\r
+       IN              ipoib_port_t* const                     p_port );\r
+\r
+/*void\r
+endpt_cm_destroy_conn(\r
+       IN              ipoib_port_t* const                     p_port,\r
+       IN              ipoib_endpt_t* const            p_endpt );\r
+*/\r
+void\r
+endpt_cm_disconnect(\r
+       IN              ipoib_port_t*   const           p_port,\r
+       IN              ipoib_endpt_t*  const           p_endpt );\r
+void\r
+endpt_cm_flush_recv(\r
+       IN                              ipoib_port_t* const             p_port,\r
+       IN                              ipoib_endpt_t* const    p_endpt );\r
+\r
+ib_api_status_t\r
+ipoib_recv_dhcp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t* const            p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst );\r
+\r
+void\r
+ipoib_port_cancel_xmit(\r
+       IN                              ipoib_port_t* const             p_port,\r
+       IN                              PVOID                                    cancel_id );\r
+\r
+static inline uint32_t\r
+__port_attr_to_mtu_size(uint32_t value)\r
+{\r
+       switch (value) \r
+       {\r
+       default:\r
+       case IB_MTU_LEN_2048:\r
+               return 2048;\r
+       case IB_MTU_LEN_4096:\r
+               return 4096;\r
+       case IB_MTU_LEN_1024:\r
+               return 1024;\r
+       case IB_MTU_LEN_512:\r
+               return  512;\r
+       case IB_MTU_LEN_256:\r
+               return  256;\r
+       }\r
+}\r
+#endif /* _IPOIB_PORT_H_ */\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_xfr_mgr.c b/trunk/ulp/ipoib/kernel6/ipoib_xfr_mgr.c
new file mode 100644 (file)
index 0000000..ce0650f
--- /dev/null
@@ -0,0 +1,74 @@
+/*\r
+ * Copyright (c) 2008 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: ipoib_xfr_mgr.c 3459 2008-11-12 16:48:21Z tzachid $\r
+ */\r
+\r
+\r
+#include "ipoib_xfr_mgr.h"\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_xfr_mgr.tmh"\r
+#endif\r
+\r
+\r
+const ipoib_guid2mac_translation_t guid2mac_table[] = {\r
+       {0x30, 0x48, 0xE7},\r
+       {0x05, 0xAD, 0xE7},\r
+       {0x18, 0x8B, 0xE7},\r
+       {0x1A, 0x4B, 0xE7},\r
+       {0x17, 0x08, 0xE7},\r
+       {0x1E, 0x0B, 0xE7},\r
+\r
+       {0x03, 0xBA, 0xE7},\r
+       {0x05, 0xAD, 0xE7},\r
+       {0x0D, 0x9D, 0xE7},\r
+       {0x11, 0x0A, 0xE7},\r
+       {0x11, 0x85, 0xE7},\r
+       {0x12, 0x79, 0xE7},\r
+       {0x13, 0x21, 0xE7},\r
+       {0x14, 0x38, 0xE7},\r
+       {0x16, 0x35, 0xE7},\r
+       {0x17, 0x08, 0xE7},\r
+       {0x17, 0xA4, 0xE7},\r
+       {0x18, 0x8B, 0xE7},\r
+       {0x18, 0xFE, 0xE7},\r
+       {0x19, 0xBB, 0xE7},\r
+       {0x1A, 0x4B, 0xE7},\r
+       {0x1B, 0x78, 0xE7},\r
+       {0x1E, 0x0B, 0xE7},\r
+       {0x22, 0x64, 0xE7},\r
+       {0x23, 0x7D, 0xE7},\r
+       {0x30, 0x48, 0xE7},\r
+       {0x80, 0x5F, 0xE7},\r
+\r
+       {0x00, 0x00, 0x00},\r
+};\r
+\r
diff --git a/trunk/ulp/ipoib/kernel6/ipoib_xfr_mgr.h b/trunk/ulp/ipoib/kernel6/ipoib_xfr_mgr.h
new file mode 100644 (file)
index 0000000..9e38b60
--- /dev/null
@@ -0,0 +1,513 @@
+/*\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: ipoib_xfr_mgr.h 3719 2009-01-07 12:31:52Z reuven $\r
+ */\r
+\r
+\r
+#ifndef _IPOIB_XFR_MGR_H_\r
+#define _IPOIB_XFR_MGR_H_\r
+\r
+\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_types.h>\r
+#include <complib/cl_qpool.h>\r
+#include <complib/cl_spinlock.h>\r
+#include <complib/cl_qlist.h>\r
+#include <complib/cl_qpool.h>\r
+#include <complib/cl_list.h>\r
+\r
+\r
+#include "ipoib_driver.h"\r
+#include "ip_stats.h"\r
+#include <ip_packet.h>\r
+\r
+\r
+#include <complib/cl_packon.h>\r
+/****s* IPoIB Driver/ipoib_hw_addr_t\r
+* NAME\r
+*   ipoib_hw_addr_t\r
+*\r
+* DESCRIPTION\r
+*   The ipoib_hw_addr_t structure defines an IPoIB compatible hardware\r
+*   address.  Values in this structure are stored in network order.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ipoib_hw_addr\r
+{\r
+       uint32_t        flags_qpn;\r
+       ib_gid_t        gid;\r
+\r
+}      PACK_SUFFIX ipoib_hw_addr_t;\r
+/*\r
+* FIELDS\r
+*      flags_qpn\r
+*              Flags and queue pair number.  Use ipoib_addr_get_flags,\r
+*              ipoib_addr_set_flags, ipoib_addr_set_qpn, and ipoib_addr_get_qpn\r
+*              to manipulate the contents.\r
+*\r
+*      gid\r
+*              IB GID value.\r
+*\r
+* SEE ALSO\r
+*      IPoIB, ipoib_addr_get_flags, ipoib_addr_set_flags, ipoib_addr_set_qpn,\r
+*      ipoib_addr_get_qpn\r
+*********/\r
+#include <complib/cl_packoff.h>\r
+\r
+/****s* IPoIB Driver/ipoib_guid2mac_translation_t\r
+* NAME\r
+*   ipoib_guid2mac_translation_t\r
+*\r
+* DESCRIPTION\r
+*   The ipoib_guid2mac_translation_t structure defines a GUID to MAC translation.\r
+*   The structure holds map between known OUI to an appropriate GUID mask.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ipoib_guid2mac_translation_\r
+{\r
+       uint8_t second_byte;\r
+       uint8_t third_byte;\r
+       uint8_t guid_mask;\r
+       \r
+}      ipoib_guid2mac_translation_t;\r
+/*\r
+* FIELDS\r
+*      second_byte\r
+*              second byte of OUI (located in lower three bytes of GUID).\r
+*\r
+*      third_byte\r
+*              third byte of OUI (located in lower three bytes of GUID).\r
+*\r
+*      guid_mask\r
+*              GUID mask that will be used to generate MAC from the GUID.      \r
+*\r
+* SEE ALSO\r
+*      IPoIB, ipoib_mac_from_guid_mask\r
+*********/\r
+\r
+extern const ipoib_guid2mac_translation_t guid2mac_table[];\r
+\r
+#ifdef __cplusplus\r
+extern "C"\r
+{\r
+#endif\r
+\r
+\r
+/*\r
+ * Address accessors\r
+ */\r
+\r
+static inline uint8_t\r
+ipoib_addr_get_flags(\r
+       IN              const   ipoib_hw_addr_t* const          p_addr )\r
+{\r
+       return (uint8_t)( p_addr->flags_qpn & 0x000000ff);\r
+}\r
+\r
+static inline void\r
+ipoib_addr_set_flags(\r
+       IN                              ipoib_hw_addr_t* const          p_addr,\r
+       IN              const   uint8_t                                         flags )\r
+{\r
+       p_addr->flags_qpn &= ( 0xFFFFFF00 );\r
+       p_addr->flags_qpn |= ( flags );\r
+}\r
+\r
+static inline net32_t\r
+ipoib_addr_get_qpn(\r
+       IN              const   ipoib_hw_addr_t* const          p_addr )\r
+{\r
+       return( ( p_addr->flags_qpn ) & 0xffffff00 );\r
+}\r
+\r
+static inline void\r
+ipoib_addr_set_qpn(\r
+       IN                              ipoib_hw_addr_t* const          p_addr,\r
+       IN              const   net32_t                                         qpn )\r
+{\r
+       p_addr->flags_qpn &= ( 0x000000FF );\r
+       p_addr->flags_qpn |= qpn ;\r
+}\r
+\r
+static inline void\r
+ipoib_addr_set_sid(\r
+       IN      net64_t* const          p_sid,\r
+       IN      const   net32_t         qpn )\r
+{\r
+       *p_sid = qpn;\r
+       *p_sid <<= 32;\r
+       *p_sid |= IPOIB_CM_FLAG_SVCID;\r
+}\r
+\r
+/****f* IPOIB/ipoib_mac_from_sst_guid\r
+* NAME\r
+*      ipoib_mac_from_sst_guid\r
+*\r
+* DESCRIPTION\r
+*      Generates an ethernet MAC address given a SilverStorm port GUID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_api_status_t\r
+ipoib_mac_from_sst_guid(\r
+       IN              const   net64_t                                         port_guid,\r
+               OUT                     mac_addr_t* const                       p_mac_addr )\r
+{\r
+       const uint8_t   *p_guid = (const uint8_t*)&port_guid;\r
+       uint32_t                low24;\r
+\r
+       /* Port guid is in network byte order.  OUI is in lower 3 bytes. */\r
+       ASSERT( p_guid[0] == 0x00 && p_guid[1] == 0x06 && p_guid[2] == 0x6a );\r
+\r
+       /*\r
+        * We end up using only the lower 23-bits of the GUID.  Trap that\r
+        * the 24th (bit 23) through 27th (bit 26) bit aren't set.\r
+        */\r
+       if( port_guid & CL_HTON64( 0x0000000007800000 ) )\r
+               return IB_INVALID_GUID;\r
+\r
+       low24 = 0x00FFF000 -\r
+               ((((uint32_t)cl_ntoh64( port_guid ) & 0x00FFFFFF) - 0x101) * 2);\r
+       low24 -= p_guid[3]; /* minus port number */\r
+\r
+       p_mac_addr->addr[0] = p_guid[0];\r
+       p_mac_addr->addr[1] = p_guid[1];\r
+       p_mac_addr->addr[2] = p_guid[2];\r
+       p_mac_addr->addr[3] = (uint8_t)(low24 >> 16);\r
+       p_mac_addr->addr[4] = (uint8_t)(low24 >> 8);\r
+       p_mac_addr->addr[5] = (uint8_t)low24;\r
+       \r
+       return IB_SUCCESS;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      port_guid\r
+*              The port GUID, in network byte order, for which to generate a\r
+*              MAC address.\r
+*\r
+*      p_mac_addr\r
+*              Pointer to a mac address in which to store the results.\r
+*\r
+* RETURN VALUES\r
+*      IB_SUCCESS\r
+*              The MAC address was successfully converted.\r
+*\r
+*      IB_INVALID_GUID\r
+*              The port GUID provided was not a known GUID format.\r
+*\r
+* NOTES\r
+*      The algorithm to convert portGuid to MAC address is as per DN0074, and\r
+*      assumes a 2 port HCA.\r
+*\r
+* SEE ALSO\r
+*      IPOIB\r
+*********/\r
+\r
+\r
+/****f* IPOIB/ipoib_mac_from_mlx_guid\r
+* NAME\r
+*      ipoib_mac_from_mlx_guid\r
+*\r
+* DESCRIPTION\r
+*      Generates an ethernet MAC address given a Mellanox port GUID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_api_status_t\r
+ipoib_mac_from_mlx_guid(\r
+       IN              const   net64_t                                         port_guid,\r
+               OUT                     mac_addr_t* const                       p_mac_addr )\r
+{\r
+       const uint8_t   *p_guid = (const uint8_t*)&port_guid;\r
+       uint32_t                low24;\r
+       net16_t                 guid_middle;\r
+\r
+       /* Port guid is in network byte order.  OUI is in lower 3 bytes. */\r
+       ASSERT( p_guid[0] == 0x00 && p_guid[1] == 0x02 && p_guid[2] == 0xc9 );\r
+\r
+       guid_middle = (net16_t)((port_guid & CL_HTON64( 0x000000ffff000000 )) >>24);\r
+\r
+       if (guid_middle == 2) {\r
+                       p_mac_addr->addr[0] = 0;\r
+       } else if (guid_middle == 3) {\r
+                       p_mac_addr->addr[0] = 2;\r
+       } else {\r
+               return IB_INVALID_GUID;\r
+       }\r
+       low24 = ((uint32_t)cl_ntoh64( port_guid ) & 0x00FFFFFF);\r
+\r
+       p_mac_addr->addr[1] = p_guid[1];\r
+       p_mac_addr->addr[2] = p_guid[2];\r
+       p_mac_addr->addr[3] = (uint8_t)(low24 >> 16);\r
+       p_mac_addr->addr[4] = (uint8_t)(low24 >> 8);\r
+       p_mac_addr->addr[5] = (uint8_t)low24;\r
+       \r
+       return IB_SUCCESS;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      port_guid\r
+*              The port GUID, in network byte order, for which to generate a\r
+*              MAC address.\r
+*\r
+*      p_mac_addr\r
+*              Pointer to a mac address in which to store the results.\r
+*\r
+* RETURN VALUES\r
+*      IB_SUCCESS\r
+*              The MAC address was successfully converted.\r
+*\r
+*      IB_INVALID_GUID\r
+*              The port GUID provided was not a known GUID format.\r
+*\r
+*********/\r
+\r
+\r
+/****f* IPOIB/ipoib_mac_from_voltaire_guid\r
+* NAME\r
+*      ipoib_mac_from_voltaire_guid\r
+*\r
+* DESCRIPTION\r
+*      Generates an ethernet MAC address given a Voltaire port GUID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_api_status_t\r
+ipoib_mac_from_voltaire_guid(\r
+       IN              const   net64_t                                         port_guid,\r
+               OUT                     mac_addr_t* const                       p_mac_addr )\r
+{\r
+       const uint8_t   *p_guid = (const uint8_t*)&port_guid;\r
+\r
+       /* Port guid is in network byte order.  OUI is in lower 3 bytes. */\r
+       ASSERT( p_guid[0] == 0x00 && p_guid[1] == 0x08 && p_guid[2] == 0xf1 );\r
+\r
+       p_mac_addr->addr[0] = p_guid[0];\r
+       p_mac_addr->addr[1] = p_guid[1];\r
+       p_mac_addr->addr[2] = p_guid[2];\r
+       p_mac_addr->addr[3] = p_guid[4] ^ p_guid[6];\r
+       p_mac_addr->addr[4] = p_guid[5] ^ p_guid[7];\r
+       p_mac_addr->addr[5] = p_guid[5] + p_guid[6] + p_guid[7];\r
+\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+/****f* IPOIB/ipoib_mac_from_guid_mask\r
+* NAME\r
+*      ipoib_mac_from_guid_mask\r
+*\r
+* DESCRIPTION\r
+*      Generates an ethernet MAC address given general port GUID and a bitwise mask\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_api_status_t\r
+ipoib_mac_from_guid_mask(\r
+       IN              const   uint8_t                                         *p_guid,\r
+       IN                              uint32_t                                        guid_mask,\r
+               OUT                     mac_addr_t* const                       p_mac_addr )\r
+{\r
+       static const mac_addr_size =  HW_ADDR_LEN;\r
+       uint8_t i;\r
+       int digit_counter = 0;\r
+\r
+       // All non-zero bits of guid_mask indicates the number of an appropriate\r
+       // byte in port_guid, that will be used in MAC address construction\r
+       for (i = 7; guid_mask; guid_mask >>= 1, --i )\r
+       {\r
+               if( guid_mask & 1 )\r
+               {\r
+                       ++digit_counter;\r
+                       if( digit_counter > mac_addr_size )\r
+                       {\r
+                               //to avoid negative index\r
+                               return IB_INVALID_GUID_MASK;\r
+                       }\r
+                       p_mac_addr->addr[mac_addr_size - digit_counter] = p_guid [i];\r
+               }\r
+       }\r
+\r
+       // check for the mask validity: it should have 6 non-zero bits\r
+       if( digit_counter != mac_addr_size )\r
+               return IB_INVALID_GUID_MASK;\r
+\r
+       return IB_SUCCESS;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      port_guid\r
+*              The port GUID, in network byte order, for which to generate a\r
+*              MAC address.\r
+*\r
+*      guid_mask\r
+*              Each BIT in the mask indicates whether to include the appropriate BYTE\r
+*              to the MAC address. Bit 0 corresponds to the less significant BYTE , i.e.\r
+*              highest index in the MAC array\r
+*\r
+*      p_mac_addr\r
+*              Pointer to a mac address in which to store the results.\r
+*\r
+* RETURN VALUES\r
+*      IB_SUCCESS\r
+*              The MAC address was successfully converted.\r
+*\r
+*      IB_INVALID_GUID\r
+*              The port GUID provided was not a known GUID format.\r
+*\r
+* SEE ALSO\r
+*      IPOIB\r
+*********/\r
+\r
+\r
+/****f* IPOIB/ipoib_mac_from_guid\r
+* NAME\r
+*      ipoib_mac_from_guid\r
+*\r
+* DESCRIPTION\r
+*      Generates an ethernet MAC address given a port GUID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_api_status_t\r
+ipoib_mac_from_guid(\r
+       IN              const   net64_t                                         port_guid,\r
+       IN                              uint32_t                                        guid_mask,\r
+               OUT                     mac_addr_t* const                       p_mac_addr\r
+               )\r
+{\r
+       ib_api_status_t status = IB_INVALID_GUID;\r
+       const uint8_t   *p_guid = (const uint8_t*)&port_guid;\r
+       uint32_t                laa, idx = 0;\r
+\r
+       /* Port guid is in network byte order.  OUI is in lower 3 bytes. */\r
+       if( p_guid[0] == 0 )\r
+       {\r
+               if( p_guid[1] == 0x02 && p_guid[2] == 0xc9 )\r
+               {\r
+                       status = ipoib_mac_from_mlx_guid( port_guid, p_mac_addr );\r
+               }\r
+               else if( p_guid[1] == 0x08 && p_guid[2] == 0xf1 )\r
+               {\r
+                       status = ipoib_mac_from_voltaire_guid( port_guid, p_mac_addr );\r
+               }\r
+               else if( p_guid[1] == 0x06 && p_guid[2] == 0x6a )\r
+               {\r
+                       status = ipoib_mac_from_sst_guid( port_guid, p_mac_addr );\r
+               }\r
+               else\r
+               {\r
+                       while( guid2mac_table[idx].second_byte != 0x00 ||\r
+                                  guid2mac_table[idx].third_byte != 0x00 )\r
+                       {\r
+                               if( p_guid[1] == guid2mac_table[idx].second_byte &&\r
+                                       p_guid[2] == guid2mac_table[idx].third_byte )\r
+                               {\r
+                                       status = ipoib_mac_from_guid_mask(p_guid, guid2mac_table[idx].guid_mask,\r
+                                                                                                               p_mac_addr);\r
+                                       break;\r
+                               }\r
+                               ++idx;\r
+                       }\r
+               }\r
+\r
+               if( status == IB_SUCCESS )\r
+                       return status;\r
+       }\r
+\r
+       if( guid_mask )\r
+               return ipoib_mac_from_guid_mask( p_guid, guid_mask, p_mac_addr );\r
+\r
+       /* Value of zero is reserved. */\r
+       laa = cl_atomic_inc( &g_ipoib.laa_idx );\r
+\r
+       if( !laa )\r
+               return IB_INVALID_GUID;\r
+\r
+       p_mac_addr->addr[0] = 2; /* LAA bit */\r
+       p_mac_addr->addr[1] = 0;\r
+       p_mac_addr->addr[2] = (uint8_t)(laa >> 24);\r
+       p_mac_addr->addr[3] = (uint8_t)(laa >> 16);\r
+       p_mac_addr->addr[4] = (uint8_t)(laa >> 8);\r
+       p_mac_addr->addr[5] = (uint8_t)laa;\r
+       \r
+       return IB_SUCCESS;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      port_guid\r
+*              The port GUID, in network byte order, for which to generate a\r
+*              MAC address.\r
+*\r
+*      p_mac_addr\r
+*              Pointer to a mac address in which to store the results.\r
+*\r
+* RETURN VALUES\r
+*      IB_SUCCESS\r
+*              The MAC address was successfully converted.\r
+*\r
+*      IB_INVALID_GUID\r
+*              The port GUID provided was not a known GUID format.\r
+*\r
+* NOTES\r
+*      Creates a locally administered address using a global incrementing counter.\r
+*\r
+* SEE ALSO\r
+*      IPOIB\r
+*********/\r
+\r
+\r
+/****f* IPOIB/ipoib_is_voltaire_router_gid\r
+* NAME\r
+*      ipoib_is_voltaire_router_gid\r
+*\r
+* DESCRIPTION\r
+*      Checks whether the GID belongs to Voltaire IP router\r
+*\r
+* SYNOPSIS\r
+*/\r
+boolean_t\r
+static inline\r
+ipoib_is_voltaire_router_gid(\r
+       IN              const   ib_gid_t                                        *p_gid )\r
+{\r
+       static const uint8_t VOLTAIRE_GUID_PREFIX[] = {0, 0x08, 0xf1, 0, 0x1};\r
+\r
+       return !cl_memcmp( &p_gid->unicast.interface_id, VOLTAIRE_GUID_PREFIX,\r
+               sizeof(VOLTAIRE_GUID_PREFIX) );\r
+}\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* _IPOIB_XFR_MGR_H_ */\r
diff --git a/trunk/ulp/ipoib/kernel6/makefile b/trunk/ulp/ipoib/kernel6/makefile
new file mode 100644 (file)
index 0000000..bffacaa
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the OpenIB Windows project.\r
+#\r
+\r
+!INCLUDE ..\..\..\inc\openib.def\r
diff --git a/trunk/ulp/ipoib/kernel6/makefile.inc b/trunk/ulp/ipoib/kernel6/makefile.inc
new file mode 100644 (file)
index 0000000..4f29f50
--- /dev/null
@@ -0,0 +1,17 @@
+\r
+# Transform .inx file to .inf file adding date + major,min & svn.version stamp\r
+# Output .inf file is copied to the $(INF_TARGET) folder (commonly where .sys file resides).\r
+\r
+_LNG=$(LANGUAGE)\r
+\r
+!IF !DEFINED(_INX)\r
+_INX=.\r
+!ENDIF\r
+\r
+STAMP=stampinf -a $(_BUILDARCH)\r
+\r
+!INCLUDE mod_ver.def\r
+\r
+$(INF_TARGET) : $(_INX)\$(INF_NAME).inx\r
+    copy $(_INX)\$(@B).inx $@\r
+    $(STAMP) -f $@ -d * -v $(IB_MAJORVERSION).$(IB_MINORVERSION).$(IB_BUILDVERSION).$(OPENIB_REV)\r
diff --git a/trunk/ulp/ipoib/kernel6/netipoib-xp32.inf b/trunk/ulp/ipoib/kernel6/netipoib-xp32.inf
new file mode 100644 (file)
index 0000000..fd29521
--- /dev/null
@@ -0,0 +1,280 @@
+; OpenFabrics Alliance Internet Protocol over InfiniBand Adapter\r
+; Copyright 2005 SilverStorm Technologies all Rights Reserved.\r
+; Copyright 2006 Mellanox Technologies all Rights Reserved.\r
+\r
+[Version]\r
+Signature   = "$Windows NT$"\r
+Class       = Net\r
+ClassGUID   = {4d36e972-e325-11ce-bfc1-08002be10318}\r
+Provider    = %MTL%\r
+DriverVer=10/10/2008,2.0.0000.1630\r
+CatalogFile=ipoib.cat\r
+\r
+[Manufacturer]\r
+%MTL%       = MTL,ntx86,ntamd64,ntia64\r
+\r
+[ControlFlags]\r
+ExcludeFromSelect = IBA\IPoIB\r
+\r
+[MTL]\r
+; empty since we don't support W9x/Me\r
+\r
+[MTL.ntx86]\r
+%IpoibDesc%      = Ipoib.DDInstall,    IBA\IPoIB   ; Internet Protocol over InfiniBand Adapter\r
+%IpoibDescP%     = Ipoib.DDInstall,    IBA\IPoIBP  ; Internet Protocol over InfiniBand Adapter with partition key\r
+\r
+[MTL.ntamd64]\r
+%IpoibDesc%      = Ipoib.DDInstall,    IBA\IPoIB   ; Internet Protocol over InfiniBand Adapter\r
+%IpoibDescP%     = Ipoib.DDInstall,    IBA\IPoIBP  ; Internet Protocol over InfiniBand Adapter with partition key\r
+\r
+[MTL.ntia64]\r
+%IpoibDesc%      = Ipoib.DDInstall,    IBA\IPoIB   ; Internet Protocol over InfiniBand Adapter\r
+%IpoibDescP%     = Ipoib.DDInstall,    IBA\IPoIBP  ; Internet Protocol over InfiniBand Adapter with partition key\r
+\r
+[Ipoib.DDInstall.ntx86]\r
+Characteristics = 0x81 ; NCF_HAS_UI | NCF_VIRTUAL\r
+AddReg          = IpoibAddReg\r
+CopyFiles       = IpoibCopyFiles\r
+CopyFiles       = NdCopyFiles\r
+\r
+[Ipoib.DDInstall.ntamd64]\r
+Characteristics = 0x81 ; NCF_HAS_UI | NCF_VIRTUAL\r
+AddReg          = IpoibAddReg\r
+CopyFiles       = IpoibCopyFiles\r
+CopyFiles       = NdCopyFiles\r
+CopyFiles       = WOW64CopyFiles\r
+\r
+[Ipoib.DDInstall.ntia64]\r
+Characteristics = 0x81 ; NCF_HAS_UI | NCF_VIRTUAL\r
+AddReg          = IpoibAddReg\r
+CopyFiles       = IpoibCopyFiles\r
+CopyFiles       = NdCopyFiles\r
+CopyFiles       = WOW64CopyFiles\r
+\r
+[Ipoib.DDInstall.ntx86.Services]\r
+AddService = ipoib, 2, IpoibService, IpoibEventLog\r
+\r
+[Ipoib.DDInstall.ntamd64.Services]\r
+AddService = ipoib, 2, IpoibService, IpoibEventLog\r
+\r
+[Ipoib.DDInstall.ntia64.Services]\r
+AddService = ipoib, 2, IpoibService, IpoibEventLog\r
+\r
+[IpoibAddReg]\r
+HKR, ,RDMACapable, %REG_DWORD%, 1\r
+HKR, Ndi,                       Service,    0, "ipoib"\r
+HKR, Ndi\Interfaces,            UpperRange, 0, "ndis5"\r
+HKR, Ndi\Interfaces,            LowerRange, 0, "ethernet"\r
+\r
+HKR, Ndi\Params\RqDepth,               ParamDesc,      0, %RQ_DEPTH_STR%\r
+HKR, Ndi\Params\RqDepth,               Type,           0, "dword"\r
+HKR, Ndi\Params\RqDepth,               Default,        0, "512"\r
+HKR, Ndi\Params\RqDepth,               Optional,       0, "0"\r
+HKR, Ndi\Params\RqDepth,               Min,            0, "128"\r
+HKR, Ndi\Params\RqDepth,               Max,            0, "1024"\r
+HKR, Ndi\Params\RqDepth,               Step,           0, "128"\r
+\r
+HKR, Ndi\Params\RqLowWatermark,        ParamDesc,      0, %RQ_WATERMARK_STR%\r
+HKR, Ndi\Params\RqLowWatermark,        Type,           0, "dword"\r
+HKR, Ndi\Params\RqLowWatermark,        Default,        0, "4"\r
+HKR, Ndi\Params\RqLowWatermark,        Optional,       0, "0"\r
+HKR, Ndi\Params\RqLowWatermark,        Min,            0, "2"\r
+HKR, Ndi\Params\RqLowWatermark,        Max,            0, "8"\r
+HKR, Ndi\Params\RqLowWatermark,        Step,           0, "1"\r
+\r
+HKR, Ndi\Params\SqDepth,               ParamDesc,      0, %SQ_DEPTH_STR%\r
+HKR, Ndi\Params\SqDepth,               Type,           0, "dword"\r
+HKR, Ndi\Params\SqDepth,               Default,        0, "512"\r
+HKR, Ndi\Params\SqDepth,               Optional,       0, "0"\r
+HKR, Ndi\Params\SqDepth,               Min,            0, "128"\r
+HKR, Ndi\Params\SqDepth,               Max,            0, "1024"\r
+HKR, Ndi\Params\SqDepth,               Step,           0, "128"\r
+\r
+HKR, Ndi\Params\SendChksum,            ParamDesc,      0, %SQ_CSUM_STR%\r
+HKR, Ndi\Params\SendChksum,            Type,           0, "enum"\r
+HKR, Ndi\Params\SendChksum,            Default,        0, "1"\r
+HKR, Ndi\Params\SendChksum,            Optional,       0, "0"\r
+HKR, Ndi\Params\SendChksum\enum,       "0",    0, %DISABLED_STR%\r
+HKR, Ndi\Params\SendChksum\enum,       "1",    0, %ENABLED_IF_STR%\r
+HKR, Ndi\Params\SendChksum\enum,       "2",    0, %BYPASS_STR%\r
+\r
+HKR, Ndi\Params\RecvChksum,            ParamDesc,      0, %RQ_CSUM_STR%\r
+HKR, Ndi\Params\RecvChksum,            Type,           0, "enum"\r
+HKR, Ndi\Params\RecvChksum,            Default,        0, "1"\r
+HKR, Ndi\Params\RecvChksum,            Optional,       0, "0"\r
+HKR, Ndi\Params\RecvChksum\enum,       "0",    0, %DISABLED_STR%\r
+HKR, Ndi\Params\RecvChksum\enum,       "1",    0, %ENABLED_IF_STR%\r
+HKR, Ndi\Params\RecvChksum\enum,       "2",    0, %BYPASS_STR%\r
+\r
+HKR, Ndi\Params\lso,           ParamDesc,      0, %LSO_STR%\r
+HKR, Ndi\Params\lso,           Type,           0, "enum"\r
+HKR, Ndi\Params\lso,           Default,        0, "0"\r
+HKR, Ndi\Params\lso,           Optional,       0, "0"\r
+HKR, Ndi\Params\lso\enum,      "0",    0, %DISABLED_STR%\r
+HKR, Ndi\Params\lso\enum,      "1",    0, %ENABLED_STR%\r
+\r
+\r
+HKR, Ndi\Params\SaTimeout,             ParamDesc,      0, %SA_QUERY_TO_STR%\r
+HKR, Ndi\Params\SaTimeout,             Type,           0, "dword"\r
+HKR, Ndi\Params\SaTimeout,             Default,        0, "1000"\r
+HKR, Ndi\Params\SaTimeout,             Optional,       0, "0"\r
+HKR, Ndi\Params\SaTimeout,             Min,            0, "500"\r
+HKR, Ndi\Params\SaTimeout,             Step,           0, "250"\r
+\r
+HKR, Ndi\Params\SaRetries,             ParamDesc,      0, %SA_QUERY_RETRY_STR%\r
+HKR, Ndi\Params\SaRetries,             Type,           0, "dword"\r
+HKR, Ndi\Params\SaRetries,             Default,        0, "10"\r
+HKR, Ndi\Params\SaRetries,             Optional,       0, "0"\r
+HKR, Ndi\Params\SaRetries,             Min,            0, "1"\r
+\r
+HKR, Ndi\Params\RecvRatio,             ParamDesc,      0, %RECV_RATIO_STR%\r
+HKR, Ndi\Params\RecvRatio,             Type,           0, "dword"\r
+HKR, Ndi\Params\RecvRatio,             Default,        0, "1"\r
+HKR, Ndi\Params\RecvRatio,             Optional,       0, "0"\r
+HKR, Ndi\Params\RecvRatio,             Min,            0, "1"\r
+HKR, Ndi\Params\RecvRatio,             Max,            0, "10"\r
+\r
+HKR, Ndi\Params\PayloadMtu,            ParamDesc,      0, %MTU_STR%\r
+HKR, Ndi\Params\PayloadMtu,            Type,           0, "dword"\r
+HKR, Ndi\Params\PayloadMtu,            Default,        0, "2044"\r
+HKR, Ndi\Params\PayloadMtu,            Min,            0, "512"\r
+HKR, Ndi\Params\PayloadMtu,            Max,            0, "4092"\r
+\r
+HKR, Ndi\Params\MCLeaveRescan,         ParamDesc,      0, %MC_RESCAN_STR%\r
+HKR, Ndi\Params\MCLeaveRescan,         Type,           0, "dword"\r
+HKR, Ndi\Params\MCLeaveRescan,         Default,        0, "260"\r
+HKR, Ndi\Params\MCLeaveRescan,         Optional,       0, "0"\r
+HKR, Ndi\Params\MCLeaveRescan,         Min,            0, "1"\r
+HKR, Ndi\Params\MCLeaveRescan,         Max,            0, "3600"\r
+\r
+HKR, Ndi\Params\GUIDMask,              ParamDesc,      0, %GUID_MASK_STR%\r
+HKR, Ndi\Params\GUIDMask,              Type,           0, "dword"\r
+HKR, Ndi\Params\GUIDMask,              Default,        0, "0"\r
+HKR, Ndi\Params\GUIDMask,              Optional,       0, "0"\r
+HKR, Ndi\Params\GUIDMask,              Min,            0, "0"\r
+HKR, Ndi\Params\GUIDMask,              Max,            0, "252"\r
+\r
+HKR, Ndi\Params\BCJoinRetry,           ParamDesc,      0, %BC_JOIN_RETRY_STR%\r
+HKR, Ndi\Params\BCJoinRetry,           Type,           0, "dword"\r
+HKR, Ndi\Params\BCJoinRetry,           Default,        0, "50"\r
+HKR, Ndi\Params\BCJoinRetry,           Optional,       0, "0"\r
+HKR, Ndi\Params\BCJoinRetry,           Min,            0, "0"\r
+HKR, Ndi\Params\BCJoinRetry,           Max,            0, "1000"\r
+\r
+HKR, Ndi\Params\CmEnabled,             ParamDesc,      0, %CONNECTED_MODE_STR%\r
+HKR, Ndi\Params\CmEnabled,             Type,           0, "enum"\r
+HKR, Ndi\Params\CmEnabled,             Default,        0, "1"\r
+HKR, Ndi\Params\CmEnabled,             Optional,       0, "0"\r
+HKR, Ndi\Params\CmEnabled\enum,        "0",    0,      %DISABLED_STR%\r
+HKR, Ndi\Params\CmEnabled\enum,        "1",    0,      %ENABLED_STR%\r
+\r
+HKR, Ndi\Params\CmPayloadMtu,          ParamDesc,      0, %CONNECTED_MODE_MTU_STR%\r
+HKR, Ndi\Params\CmPayloadMtu,          Type,           0, "dword"\r
+HKR, Ndi\Params\CmPayloadMtu,          Default,        0, "65520"\r
+HKR, Ndi\Params\CmPayloadMtu,          Min,            0, "512"\r
+HKR, Ndi\Params\CmPayloadMtu,          Max,            0, "65520"\r
+\r
+[IpoibService]\r
+DisplayName     = %IpoibServiceDispName%\r
+ServiceType     = 1 ;%SERVICE_KERNEL_DRIVER%\r
+StartType       = 3 ;%SERVICE_DEMAND_START%\r
+ErrorControl    = 1 ;%SERVICE_ERROR_NORMAL%\r
+ServiceBinary   = %12%\ipoib.sys\r
+LoadOrderGroup  = NDIS\r
+AddReg          = Ipoib.ParamsReg\r
+\r
+[Ipoib.ParamsReg]\r
+HKR,"Parameters","DebugLevel",%REG_DWORD_NO_CLOBBER%,0x00000002\r
+HKR,"Parameters","DebugFlags",%REG_DWORD_NO_CLOBBER%,0x00000fff\r
+HKR,"Parameters","bypass_check_bcast_rate",%REG_DWORD_NO_CLOBBER%,0x00000000\r
+\r
+[IpoibEventLog]\r
+AddReg = IpoibAddEventLogReg\r
+\r
+[IpoibAddEventLogReg]\r
+HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\netevent.dll;%%SystemRoot%%\System32\drivers\ipoib.sys"\r
+HKR, , TypesSupported,   0x00010001, 7\r
+\r
+\r
+[IpoibCopyFiles]\r
+ipoib.sys,,,2\r
+\r
+[NdCopyFiles]\r
+ibndprov.dll,,,0x00000002\r
+ndinstall.exe,,,0x00000002\r
+\r
+[WOW64CopyFiles]\r
+ibwsd.dll,ibwsd32.dll,,0x00000002\r
+ibndprov.dll,ibndprov32.dll,,0x00000002\r
+\r
+[SourceDisksNames.x86]\r
+1 = %IcsDisk1%,,,""\r
+\r
+[SourceDisksNames.amd64]\r
+1 = %IcsDisk1%,,,""\r
+\r
+[SourceDisksNames.ia64]\r
+1 = %IcsDisk1%,,,""\r
+\r
+[SourceDisksFiles.x86]\r
+ipoib.sys = 1\r
+ibndprov.dll = 1\r
+ndinstall.exe = 1\r
+\r
+[SourceDisksFiles.amd64]\r
+ipoib.sys = 1\r
+ibwsd.dll = 1\r
+ibwsd32.dll = 1\r
+ibndprov.dll = 1\r
+ibndprov32.dll = 1\r
+ndinstall.exe = 1\r
+\r
+[SourceDisksFiles.ia64]\r
+ipoib.sys = 1\r
+ibwsd.dll = 1\r
+ibwsd32.dll = 1\r
+ibndprov.dll = 1\r
+ibndprov32.dll = 1\r
+ndinstall.exe = 1\r
+\r
+[DestinationDirs]\r
+IpoibCopyFiles    = %DIRID_DRIVERS%\r
+WsdCopyFiles      = %DIRID_SYSTEM%\r
+NdCopyFiles       = %DIRID_SYSTEM%\r
+WOW64CopyFiles    = %DIRID_SYSTEM_X86%\r
+DefaultDestDir    = %DIRID_SYSTEM%\r
+\r
+[Strings]\r
+OPENIB               = "OpenFabrics Alliance"\r
+MTL                     = "Mellanox Technologies Ltd."\r
+IpoibDesc            = "Mellanox IPoIB Adapter"\r
+IpoibDescP           = "Mellanox IPoIB Adapter Partition"\r
+IpoibServiceDispName = "IPoIB"\r
+IcsDisk1             = "Mellanox IPoIB Disk #1"\r
+DIRID_SYSTEM         = 11\r
+DIRID_DRIVERS        = 12\r
+DIRID_SYSTEM_X86     = 16425\r
+REG_DWORD            = 0x00010001\r
+REG_DWORD_NO_CLOBBER = 0x00010003\r
+\r
+RQ_DEPTH_STR           = "Receive Queue depth"\r
+RQ_WATERMARK_STR       = "Receive Queue Low Watermark"\r
+SQ_DEPTH_STR           = "Send Queue Depth"\r
+SQ_CSUM_STR            = "Send Checksum Offload"\r
+RQ_CSUM_STR            = "Recv Checksum Offload"\r
+LSO_STR                        = "Large Send Offload"\r
+SA_QUERY_TO_STR                = "SA Query Timeout (ms)"\r
+SA_QUERY_RETRY_STR     = "SA Query Retry Count"\r
+RECV_RATIO_STR         = "Receive Pool Ratio"\r
+MTU_STR                        = "Payload Mtu size"\r
+MC_RESCAN_STR          = "MC leave rescan (sec)"\r
+GUID_MASK_STR          = "GUID bitwise mask"\r
+BC_JOIN_RETRY_STR   = "Number of retries connecting to bc"\r
+\r
+ENABLED_IF_STR         = "Enabled (if supported by HW)"\r
+ENABLED_STR            = "Enabled"\r
+DISABLED_STR           = "Disabled"\r
+BYPASS_STR             = "Bypass"\r
+CONNECTED_MODE_STR     = "Connected mode"\r
+CONNECTED_MODE_MTU_STR = "Connected Mode Payload Mtu size"\r
+\r
diff --git a/trunk/ulp/ipoib/kernel6/netipoib.inx b/trunk/ulp/ipoib/kernel6/netipoib.inx
new file mode 100644 (file)
index 0000000..ca3126b
--- /dev/null
@@ -0,0 +1,295 @@
+; OpenFabrics Alliance Internet Protocol over InfiniBand Adapter\r
+; Copyright 2005 SilverStorm Technologies all Rights Reserved.\r
+; Copyright 2006 Mellanox Technologies all Rights Reserved.\r
+\r
+[Version]\r
+Signature   = "$Windows NT$"\r
+Class       = Net\r
+ClassGUID   = {4d36e972-e325-11ce-bfc1-08002be10318}\r
+Provider    = %MTL%\r
+DriverVer=06/11/2008,1.0.0000.1207\r
+CatalogFile=ipoib.cat\r
+\r
+[Manufacturer]\r
+%MTL%       = MTL,ntx86,ntamd64,ntia64\r
+\r
+[ControlFlags]\r
+ExcludeFromSelect = IBA\IPoIB\r
+\r
+[MTL]\r
+; empty since we don't support W9x/Me\r
+\r
+[MTL.ntx86]\r
+%IpoibDesc%      = Ipoib.DDInstall,    IBA\IPoIB   ; Internet Protocol over InfiniBand Adapter\r
+%IpoibDescP%     = Ipoib.DDInstall,    IBA\IPoIBP  ; Internet Protocol over InfiniBand Adapter with partition key\r
+\r
+[MTL.ntamd64]\r
+%IpoibDesc%      = Ipoib.DDInstall,    IBA\IPoIB   ; Internet Protocol over InfiniBand Adapter\r
+%IpoibDescP%     = Ipoib.DDInstall,    IBA\IPoIBP  ; Internet Protocol over InfiniBand Adapter with partition key\r
+\r
+[MTL.ntia64]\r
+%IpoibDesc%      = Ipoib.DDInstall,    IBA\IPoIB   ; Internet Protocol over InfiniBand Adapter\r
+%IpoibDescP%     = Ipoib.DDInstall,    IBA\IPoIBP  ; Internet Protocol over InfiniBand Adapter with partition key\r
+\r
+[Ipoib.DDInstall.ntx86]\r
+Characteristics = 0x81 ; NCF_HAS_UI | NCF_VIRTUAL\r
+AddReg          = IpoibAddReg\r
+CopyFiles       = IpoibCopyFiles\r
+CopyFiles       = WsdCopyFiles\r
+CopyFiles       = NdCopyFiles\r
+*IfType         = 6            ; IF_TYPE_ETHERNET_CSMACD \r
+*MediaType      = 0            ; NdisMedium802_3\r
+*PhysicalMediaType = 14                ; NdisPhysicalMedium802_3\r
+\r
+[Ipoib.DDInstall.ntamd64]\r
+Characteristics = 0x81 ; NCF_HAS_UI | NCF_VIRTUAL\r
+AddReg          = IpoibAddReg\r
+CopyFiles       = IpoibCopyFiles\r
+CopyFiles       = WsdCopyFiles\r
+CopyFiles       = NdCopyFiles\r
+CopyFiles       = WOW64CopyFiles\r
+*IfType         = 6            ; IF_TYPE_ETHERNET_CSMACD \r
+*MediaType      = 0            ; NdisMedium802_3\r
+*PhysicalMediaType = 14                ; NdisPhysicalMedium802_3\r
+\r
+[Ipoib.DDInstall.ntia64]\r
+Characteristics = 0x81 ; NCF_HAS_UI | NCF_VIRTUAL\r
+AddReg          = IpoibAddReg\r
+CopyFiles       = IpoibCopyFiles\r
+CopyFiles       = WsdCopyFiles\r
+CopyFiles       = NdCopyFiles\r
+CopyFiles       = WOW64CopyFiles\r
+*IfType         = 6            ; IF_TYPE_ETHERNET_CSMACD \r
+*MediaType      = 0            ; NdisMedium802_3\r
+*PhysicalMediaType = 14                ; NdisPhysicalMedium802_3\r
+\r
+[Ipoib.DDInstall.ntx86.Services]\r
+AddService = ipoib, 2, IpoibService, IpoibEventLog\r
+\r
+[Ipoib.DDInstall.ntamd64.Services]\r
+AddService = ipoib, 2, IpoibService, IpoibEventLog\r
+\r
+[Ipoib.DDInstall.ntia64.Services]\r
+AddService = ipoib, 2, IpoibService, IpoibEventLog\r
+\r
+[IpoibAddReg]\r
+HKR, ,RDMACapable, %REG_DWORD%, 1\r
+HKR, Ndi,                       Service,    0, "ipoib"\r
+HKR, Ndi\Interfaces,            UpperRange, 0, "ndis5"\r
+HKR, Ndi\Interfaces,            LowerRange, 0, "ethernet"\r
+\r
+HKR, Ndi\Params\RqDepth,               ParamDesc,      0, %RQ_DEPTH_STR%\r
+HKR, Ndi\Params\RqDepth,               Type,           0, "dword"\r
+HKR, Ndi\Params\RqDepth,               Default,        0, "512"\r
+HKR, Ndi\Params\RqDepth,               Optional,       0, "0"\r
+HKR, Ndi\Params\RqDepth,               Min,            0, "128"\r
+HKR, Ndi\Params\RqDepth,               Max,            0, "1024"\r
+HKR, Ndi\Params\RqDepth,               Step,           0, "128"\r
+\r
+HKR, Ndi\Params\RqLowWatermark,        ParamDesc,      0, %RQ_WATERMARK_STR%\r
+HKR, Ndi\Params\RqLowWatermark,        Type,           0, "dword"\r
+HKR, Ndi\Params\RqLowWatermark,        Default,        0, "4"\r
+HKR, Ndi\Params\RqLowWatermark,        Optional,       0, "0"\r
+HKR, Ndi\Params\RqLowWatermark,        Min,            0, "2"\r
+HKR, Ndi\Params\RqLowWatermark,        Max,            0, "8"\r
+HKR, Ndi\Params\RqLowWatermark,        Step,           0, "1"\r
+\r
+HKR, Ndi\Params\SqDepth,               ParamDesc,      0, %SQ_DEPTH_STR%\r
+HKR, Ndi\Params\SqDepth,               Type,           0, "dword"\r
+HKR, Ndi\Params\SqDepth,               Default,        0, "512"\r
+HKR, Ndi\Params\SqDepth,               Optional,       0, "0"\r
+HKR, Ndi\Params\SqDepth,               Min,            0, "128"\r
+HKR, Ndi\Params\SqDepth,               Max,            0, "1024"\r
+HKR, Ndi\Params\SqDepth,               Step,           0, "128"\r
+\r
+HKR, Ndi\Params\SendChksum,            ParamDesc,      0, %SQ_CSUM_STR%\r
+HKR, Ndi\Params\SendChksum,            Type,           0, "enum"\r
+HKR, Ndi\Params\SendChksum,            Default,        0, "1"\r
+HKR, Ndi\Params\SendChksum,            Optional,       0, "0"\r
+HKR, Ndi\Params\SendChksum\enum,       "0",    0, %DISABLED_STR%\r
+HKR, Ndi\Params\SendChksum\enum,       "1",    0, %ENABLED_IF_STR%\r
+HKR, Ndi\Params\SendChksum\enum,       "2",    0, %BYPASS_STR%\r
+\r
+HKR, Ndi\Params\RecvChksum,            ParamDesc,      0, %RQ_CSUM_STR%\r
+HKR, Ndi\Params\RecvChksum,            Type,           0, "enum"\r
+HKR, Ndi\Params\RecvChksum,            Default,        0, "1"\r
+HKR, Ndi\Params\RecvChksum,            Optional,       0, "0"\r
+HKR, Ndi\Params\RecvChksum\enum,       "0",    0, %DISABLED_STR%\r
+HKR, Ndi\Params\RecvChksum\enum,       "1",    0, %ENABLED_IF_STR%\r
+HKR, Ndi\Params\RecvChksum\enum,       "2",    0, %BYPASS_STR%\r
+\r
+HKR, Ndi\Params\lso,           ParamDesc,      0, %LSO_STR%\r
+HKR, Ndi\Params\lso,           Type,           0, "enum"\r
+HKR, Ndi\Params\lso,           Default,        0, "0"\r
+HKR, Ndi\Params\lso,           Optional,       0, "0"\r
+HKR, Ndi\Params\lso\enum,      "0",    0, %DISABLED_STR%\r
+HKR, Ndi\Params\lso\enum,      "1",    0, %ENABLED_STR%\r
+\r
+\r
+HKR, Ndi\Params\SaTimeout,             ParamDesc,      0, %SA_QUERY_TO_STR%\r
+HKR, Ndi\Params\SaTimeout,             Type,           0, "dword"\r
+HKR, Ndi\Params\SaTimeout,             Default,        0, "1000"\r
+HKR, Ndi\Params\SaTimeout,             Optional,       0, "0"\r
+HKR, Ndi\Params\SaTimeout,             Min,            0, "500"\r
+HKR, Ndi\Params\SaTimeout,             Step,           0, "250"\r
+\r
+HKR, Ndi\Params\SaRetries,             ParamDesc,      0, %SA_QUERY_RETRY_STR%\r
+HKR, Ndi\Params\SaRetries,             Type,           0, "dword"\r
+HKR, Ndi\Params\SaRetries,             Default,        0, "10"\r
+HKR, Ndi\Params\SaRetries,             Optional,       0, "0"\r
+HKR, Ndi\Params\SaRetries,             Min,            0, "1"\r
+\r
+HKR, Ndi\Params\RecvRatio,             ParamDesc,      0, %RECV_RATIO_STR%\r
+HKR, Ndi\Params\RecvRatio,             Type,           0, "dword"\r
+HKR, Ndi\Params\RecvRatio,             Default,        0, "1"\r
+HKR, Ndi\Params\RecvRatio,             Optional,       0, "0"\r
+HKR, Ndi\Params\RecvRatio,             Min,            0, "1"\r
+HKR, Ndi\Params\RecvRatio,             Max,            0, "10"\r
+\r
+HKR, Ndi\Params\PayloadMtu,            ParamDesc,      0, %MTU_STR%\r
+HKR, Ndi\Params\PayloadMtu,            Type,           0, "dword"\r
+HKR, Ndi\Params\PayloadMtu,            Default,        0, "2044"\r
+HKR, Ndi\Params\PayloadMtu,            Min,            0, "512"\r
+HKR, Ndi\Params\PayloadMtu,            Max,            0, "4092"\r
+\r
+HKR, Ndi\Params\MCLeaveRescan,         ParamDesc,      0, %MC_RESCAN_STR%\r
+HKR, Ndi\Params\MCLeaveRescan,         Type,           0, "dword"\r
+HKR, Ndi\Params\MCLeaveRescan,         Default,        0, "260"\r
+HKR, Ndi\Params\MCLeaveRescan,         Optional,       0, "0"\r
+HKR, Ndi\Params\MCLeaveRescan,         Min,            0, "1"\r
+HKR, Ndi\Params\MCLeaveRescan,         Max,            0, "3600"\r
+\r
+HKR, Ndi\Params\GUIDMask,              ParamDesc,      0, %GUID_MASK_STR%\r
+HKR, Ndi\Params\GUIDMask,              Type,           0, "dword"\r
+HKR, Ndi\Params\GUIDMask,              Default,        0, "0"\r
+HKR, Ndi\Params\GUIDMask,              Optional,       0, "0"\r
+HKR, Ndi\Params\GUIDMask,              Min,            0, "0"\r
+HKR, Ndi\Params\GUIDMask,              Max,            0, "252"\r
+\r
+HKR, Ndi\Params\BCJoinRetry,           ParamDesc,      0, %BC_JOIN_RETRY_STR%\r
+HKR, Ndi\Params\BCJoinRetry,           Type,           0, "dword"\r
+HKR, Ndi\Params\BCJoinRetry,           Default,        0, "50"\r
+HKR, Ndi\Params\BCJoinRetry,           Optional,       0, "0"\r
+HKR, Ndi\Params\BCJoinRetry,           Min,            0, "0"\r
+HKR, Ndi\Params\BCJoinRetry,           Max,            0, "1000"\r
+\r
+HKR, Ndi\Params\CmEnabled,             ParamDesc,      0, %CONNECTED_MODE_STR%\r
+HKR, Ndi\Params\CmEnabled,             Type,           0, "enum"\r
+HKR, Ndi\Params\CmEnabled,             Default,        0, "0"\r
+HKR, Ndi\Params\CmEnabled,             Optional,       0, "0"\r
+HKR, Ndi\Params\CmEnabled\enum,        "0",    0,      %DISABLED_STR%\r
+HKR, Ndi\Params\CmEnabled\enum,        "1",    0,      %ENABLED_STR%\r
+\r
+HKR, Ndi\Params\CmPayloadMtu,          ParamDesc,      0, %CONNECTED_MODE_MTU_STR%\r
+HKR, Ndi\Params\CmPayloadMtu,          Type,           0, "dword"\r
+HKR, Ndi\Params\CmPayloadMtu,          Default,        0, "65520"\r
+HKR, Ndi\Params\CmPayloadMtu,          Min,            0, "512"\r
+HKR, Ndi\Params\CmPayloadMtu,          Max,            0, "65520"\r
+\r
+[IpoibService]\r
+DisplayName     = %IpoibServiceDispName%\r
+ServiceType     = 1 ;%SERVICE_KERNEL_DRIVER%\r
+StartType       = 3 ;%SERVICE_DEMAND_START%\r
+ErrorControl    = 1 ;%SERVICE_ERROR_NORMAL%\r
+ServiceBinary   = %12%\ipoib.sys\r
+LoadOrderGroup  = NDIS\r
+AddReg          = Ipoib.ParamsReg\r
+\r
+[Ipoib.ParamsReg]\r
+HKR,"Parameters","DebugLevel",%REG_DWORD_NO_CLOBBER%,0x00000002\r
+HKR,"Parameters","DebugFlags",%REG_DWORD_NO_CLOBBER%,0x00000fff\r
+HKR,"Parameters","bypass_check_bcast_rate",%REG_DWORD_NO_CLOBBER%,0x00000000\r
+\r
+[IpoibEventLog]\r
+AddReg = IpoibAddEventLogReg\r
+\r
+[IpoibAddEventLogReg]\r
+HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\netevent.dll;%%SystemRoot%%\System32\drivers\ipoib.sys"\r
+HKR, , TypesSupported,   0x00010001, 7\r
+\r
+\r
+[IpoibCopyFiles]\r
+ipoib.sys,,,2\r
+\r
+[WsdCopyFiles]\r
+ibwsd.dll,,,0x00000002\r
+\r
+[NdCopyFiles]\r
+ibndprov.dll,,,0x00000002\r
+ndinstall.exe,,,0x00000002\r
+\r
+[WOW64CopyFiles]\r
+ibwsd.dll,ibwsd32.dll,,0x00000002\r
+ibndprov.dll,ibndprov32.dll,,0x00000002\r
+\r
+[SourceDisksNames.x86]\r
+1 = %IcsDisk1%,,,""\r
+\r
+[SourceDisksNames.amd64]\r
+1 = %IcsDisk1%,,,""\r
+\r
+[SourceDisksNames.ia64]\r
+1 = %IcsDisk1%,,,""\r
+\r
+[SourceDisksFiles.x86]\r
+ipoib.sys = 1\r
+ibwsd.dll = 1\r
+ibndprov.dll = 1\r
+ndinstall.exe = 1\r
+\r
+[SourceDisksFiles.amd64]\r
+ipoib.sys = 1\r
+ibwsd.dll = 1\r
+ibwsd32.dll = 1\r
+ibndprov.dll = 1\r
+ibndprov32.dll = 1\r
+ndinstall.exe = 1\r
+\r
+[SourceDisksFiles.ia64]\r
+ipoib.sys = 1\r
+ibwsd.dll = 1\r
+ibwsd32.dll = 1\r
+ibndprov.dll = 1\r
+ibndprov32.dll = 1\r
+ndinstall.exe = 1\r
+\r
+[DestinationDirs]\r
+IpoibCopyFiles    = %DIRID_DRIVERS%\r
+WsdCopyFiles      = %DIRID_SYSTEM%\r
+NdCopyFiles       = %DIRID_SYSTEM%\r
+WOW64CopyFiles    = %DIRID_SYSTEM_X86%\r
+DefaultDestDir    = %DIRID_SYSTEM%\r
+\r
+[Strings]\r
+OPENIB               = "OpenFabrics Alliance"\r
+MTL                     = "Mellanox Technologies Ltd."\r
+IpoibDesc            = "Mellanox IPoIB Adapter"\r
+IpoibDescP           = "Mellanox IPoIB Adapter Partition"\r
+IpoibServiceDispName = "IPoIB"\r
+IcsDisk1             = "Mellanox IPoIB Disk #1"\r
+DIRID_SYSTEM         = 11\r
+DIRID_DRIVERS        = 12\r
+DIRID_SYSTEM_X86     = 16425\r
+REG_DWORD            = 0x00010001\r
+REG_DWORD_NO_CLOBBER = 0x00010003\r
+\r
+RQ_DEPTH_STR           = "Receive Queue depth"\r
+RQ_WATERMARK_STR       = "Receive Queue Low Watermark"\r
+SQ_DEPTH_STR           = "Send Queue Depth"\r
+SQ_CSUM_STR            = "Send Checksum Offload"\r
+RQ_CSUM_STR            = "Recv Checksum Offload"\r
+LSO_STR                        = "Large Send Offload"\r
+SA_QUERY_TO_STR                = "SA Query Timeout (ms)"\r
+SA_QUERY_RETRY_STR     = "SA Query Retry Count"\r
+RECV_RATIO_STR         = "Receive Pool Ratio"\r
+MTU_STR                        = "Payload Mtu size"\r
+MC_RESCAN_STR          = "MC leave rescan (sec)"\r
+GUID_MASK_STR          = "GUID bitwise mask"\r
+BC_JOIN_RETRY_STR   = "Number of retries connecting to bc"\r
+\r
+ENABLED_IF_STR         = "Enabled (if supported by HW)"\r
+ENABLED_STR            = "Enabled"\r
+DISABLED_STR           = "Disabled"\r
+BYPASS_STR             = "Bypass"\r
+CONNECTED_MODE_STR     = "Connected mode"\r
+CONNECTED_MODE_MTU_STR = "Connected Mode Payload Mtu size"
\ No newline at end of file
diff --git a/trunk/ulp/ipoib/kernel6/offload.h b/trunk/ulp/ipoib/kernel6/offload.h
new file mode 100644 (file)
index 0000000..de696c6
--- /dev/null
@@ -0,0 +1,47 @@
+/*++\r
\r
+Copyright (c) 2005-2008 Mellanox Technologies. All rights reserved.\r
+\r
+Module Name:\r
+    offload.h\r
+\r
+Abstract:\r
+    Task offloading header file\r
+\r
+Revision History:\r
+\r
+Notes:\r
+\r
+--*/\r
+\r
+//\r
+//  Define the maximum size of large TCP packets the driver can offload.\r
+//  This sample driver uses shared memory to map the large packets, \r
+//  LARGE_SEND_OFFLOAD_SIZE is useless in this case, so we just define \r
+//  it as NIC_MAX_PACKET_SIZE. But shipping drivers should define\r
+//  LARGE_SEND_OFFLOAD_SIZE if they support LSO, and use it as \r
+//  MaximumPhysicalMapping  when they call NdisMInitializeScatterGatherDma \r
+//  if they use ScatterGather method. If the drivers don't support\r
+//  LSO, then MaximumPhysicalMapping is NIC_MAX_PACKET_SIZE.\r
+//\r
+\r
+#define LSO_MAX_HEADER 136\r
+#define LARGE_SEND_OFFLOAD_SIZE 60000 \r
+\r
+// This struct is being used in order to pass data about the GSO buffers if they\r
+// are present\r
+typedef struct LsoBuffer_ {\r
+    PUCHAR pData;\r
+    UINT Len;\r
+} LsoBuffer;\r
+\r
+typedef struct LsoData_ {\r
+    LsoBuffer LsoBuffers[1];\r
+    UINT UsedBuffers;\r
+    UINT FullBuffers;\r
+    UINT LsoHeaderSize;\r
+    UINT IndexOfData;\r
+    UCHAR coppied_data[LSO_MAX_HEADER];\r
+} LsoData;\r
+\r
+\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/dirs b/trunk/ulp/ipoib_NDIS6_CM/dirs
new file mode 100644 (file)
index 0000000..ed41dcf
--- /dev/null
@@ -0,0 +1,2 @@
+DIRS=\\r
+       kernel\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/ip_stats.h b/trunk/ulp/ipoib_NDIS6_CM/ip_stats.h
new file mode 100644 (file)
index 0000000..2f93e41
--- /dev/null
@@ -0,0 +1,150 @@
+/*\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: ip_stats.h 1611 2006-08-20 14:48:55Z sleybo $\r
+ */\r
+\r
+\r
+#ifndef _IP_STATS_H_\r
+#define _IP_STATS_H_\r
+\r
+\r
+#include <complib/cl_types.h>\r
+\r
+\r
+/****s* IB Network Drivers/ip_data_stats_t\r
+* NAME\r
+*      ip_data_stats_t\r
+*\r
+* DESCRIPTION\r
+*      Defines data transfer statistic information for an IP device.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ip_data_stats\r
+{\r
+       uint64_t                bytes;\r
+       uint64_t                frames;\r
+\r
+}      ip_data_stats_t;\r
+/*\r
+* FIELDS\r
+*      bytes\r
+*              Total number of bytes transfered.\r
+*\r
+*      frames\r
+*              Total number of frames transfered.\r
+*\r
+* SEE ALSO\r
+*      IPoIB, INIC, ip_comp_stats_t, ip_stats_t\r
+*********/\r
+\r
+\r
+/****s* IB Network Drivers/ip_comp_stats_t\r
+* NAME\r
+*      ip_comp_stats_t\r
+*\r
+* DESCRIPTION\r
+*      Defines transfer completion statistic information for an IP device.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ip_comp_stats\r
+{\r
+       uint64_t                success;\r
+       uint64_t                error;\r
+       uint64_t                dropped;\r
+\r
+}      ip_comp_stats_t;\r
+/*\r
+* FIELDS\r
+*      success\r
+*              Total number of requests transfered successfully.\r
+*\r
+*      error\r
+*              Total number of requests that failed being transfered.\r
+*\r
+*      dropped\r
+*              Total number of requests that were dropped.\r
+*\r
+* SEE ALSO\r
+*      IPoIB, INIC, ip_data_stats_t, ip_stats_t\r
+*********/\r
+\r
+\r
+/****s* IB Network Drivers/ip_stats_t\r
+* NAME\r
+*      ip_stats_t\r
+*\r
+* DESCRIPTION\r
+*      Defines statistic information for an IP device.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ip_stats\r
+{\r
+       ip_comp_stats_t         comp;\r
+       ip_data_stats_t         ucast;\r
+       ip_data_stats_t         bcast;\r
+       ip_data_stats_t         mcast;\r
+\r
+}      ip_stats_t;\r
+/*\r
+* FIELDS\r
+*      comp\r
+*              Request completion statistics.\r
+*\r
+*      ucast\r
+*              Data statistics for unicast packets\r
+*\r
+*      bcast\r
+*              Data statistics for broadcast packets\r
+*\r
+*      mcast\r
+*              Data statistics for multicast packets\r
+*\r
+* SEE ALSO\r
+*      IPoIB, INIC, ip_data_stats_t, ip_comp_stats_t\r
+*********/\r
+\r
+\r
+typedef enum _ip_stat_sel\r
+{\r
+       IP_STAT_SUCCESS,\r
+       IP_STAT_ERROR,\r
+       IP_STAT_DROPPED,\r
+       IP_STAT_UCAST_BYTES,\r
+       IP_STAT_UCAST_FRAMES,\r
+       IP_STAT_BCAST_BYTES,\r
+       IP_STAT_BCAST_FRAMES,\r
+       IP_STAT_MCAST_BYTES,\r
+       IP_STAT_MCAST_FRAMES\r
+\r
+}      ip_stat_sel_t;\r
+\r
+#endif /* _IP_STATS_H_ */\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/SOURCES b/trunk/ulp/ipoib_NDIS6_CM/kernel/SOURCES
new file mode 100644 (file)
index 0000000..a528904
--- /dev/null
@@ -0,0 +1,59 @@
+TARGETNAME=ipoib\r
+TARGETPATH=..\..\..\bin\kernel\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE=DRIVER\r
+\r
+!if $(_NT_TOOLS_VERSION) != 0x700\r
+# WDK build only - transform .inx --> .inf adding date & version stamp.\r
+# see .\makefile.inc\r
+INF_NAME=netipoib\r
+INF_TARGET=..\..\..\bin\kernel\$(O)\$(INF_NAME).inf\r
+NTTARGETFILES=$(INF_TARGET)\r
+!endif\r
+\r
+!if $(FREEBUILD)\r
+ENABLE_EVENT_TRACING=1\r
+!else\r
+#ENABLE_EVENT_TRACING=1\r
+!endif\r
+\r
+\r
+SOURCES=       ipoib_log.mc \\r
+               ipoib.rc \\r
+               ipoib_driver.c \\r
+               ipoib_adapter.c \\r
+               ipoib_endpoint.c \\r
+               ipoib_port.c \\r
+               ipoib_ibat.c \\r
+#              ipoib_cm.c      \\r
+               ipoib_xfr_mgr.c\r
+\r
+INCLUDES=..;..\..\..\inc;..\..\..\inc\kernel;\r
+\r
+C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER -DNDIS_WDM=1 \\r
+       -DDEPRECATE_DDK_FUNCTIONS -DNDIS60_MINIPORT=1 -DNEED_CL_OBJ -DBINARY_COMPATIBLE=0 -DVER_FILEREV=42\r
+\r
+TARGETLIBS= \\r
+       $(TARGETPATH)\*\complib.lib \\r
+       $(DDK_LIB_PATH)\ndis.lib \\r
+       $(DDK_LIB_PATH)\ntstrsafe.lib \\r
+       $(DDK_LIB_PATH)\strsafe.lib\r
+\r
+!if !defined(DDK_TARGET_OS) || "$(DDK_TARGET_OS)"=="Win2K"\r
+#\r
+# The driver is built in the Win2K build environment\r
+# - use the library version of safe strings \r
+#\r
+#TARGETLIBS= $(TARGETLIBS) $(DDK_LIB_PATH)\ntstrsafe.lib\r
+!endif\r
+\r
+!IFDEF ENABLE_EVENT_TRACING\r
+\r
+C_DEFINES = $(C_DEFINES) -DEVENT_TRACING\r
+\r
+RUN_WPP = $(SOURCES) -km -ext: .c .h .C .H \\r
+       -scan:ipoib_debug.h \\r
+       -func:IPOIB_PRINT(LEVEL,FLAGS,(MSG,...)) \\r
+       -func:IPOIB_PRINT_EXIT(LEVEL,FLAGS,(MSG,...))\r
+!ENDIF\r
+\r
+MSC_WARNING_LEVEL= /W4\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib.cdf b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib.cdf
new file mode 100644 (file)
index 0000000..eb21da9
--- /dev/null
@@ -0,0 +1,13 @@
+[CatalogHeader]\r
+Name=ipoib.cat\r
+PublicVersion=0x0000001\r
+EncodingType=0x00010001\r
+CATATTR1=0x10010001:OSAttr:2:6.0\r
+[CatalogFiles]\r
+<hash>netipoib.inf=netipoib.inf\r
+<hash>ipoib.sys=ipoib.sys\r
+<hash>ibwsd.dll=ibwsd.dll\r
+<hash>ibwsd32.dll=ibwsd32.dll\r
+<hash>ibndprov.dll=ibndprov.dll\r
+<hash>ibndprov32.dll=ibndprov32.dll\r
+<hash>ndinstall.exe=ndinstall.exe\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib.rc b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib.rc
new file mode 100644 (file)
index 0000000..330f19e
--- /dev/null
@@ -0,0 +1,48 @@
+/*\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: ipoib.rc 1611 2006-08-20 14:48:55Z sleybo $\r
+ */\r
+\r
+\r
+#include <oib_ver.h>\r
+\r
+#define VER_FILETYPE                           VFT_DRV\r
+#define VER_FILESUBTYPE                                VFT2_UNKNOWN\r
+\r
+#ifdef _DEBUG_\r
+#define VER_FILEDESCRIPTION_STR                "IP over InfiniBand NDIS Miniport (Debug)"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR                "IP over InfiniBand NDIS Miniport"\r
+#endif\r
+\r
+#define VER_INTERNALNAME_STR           "ipoib.sys"\r
+#define VER_ORIGINALFILENAME_STR       "ipoib.sys"\r
+\r
+#include <common.ver>\r
+#include "ipoib_log.rc"\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib32.cdf b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib32.cdf
new file mode 100644 (file)
index 0000000..50225ba
--- /dev/null
@@ -0,0 +1,11 @@
+[CatalogHeader]\r
+Name=ipoib.cat\r
+PublicVersion=0x0000001\r
+EncodingType=0x00010001\r
+CATATTR1=0x10010001:OSAttr:2:6.0\r
+[CatalogFiles]\r
+<hash>netipoib.inf=netipoib.inf\r
+<hash>ipoib.sys=ipoib.sys\r
+<hash>ibwsd.dll=ibwsd.dll\r
+<hash>ibndprov.dll=ibndprov.dll\r
+<hash>ndinstall.exe=ndinstall.exe\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.c b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.c
new file mode 100644 (file)
index 0000000..9274709
--- /dev/null
@@ -0,0 +1,1642 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_adapter.c 4506 2009-06-23 14:40:54Z xalex $\r
+ */\r
+\r
+\r
+\r
+#include "ipoib_adapter.h"\r
+#include "ipoib_port.h"\r
+#include "ipoib_driver.h"\r
+#include "ipoib_debug.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_adapter.tmh"\r
+#endif\r
+\r
+\r
+#define ITEM_POOL_START                16\r
+#define ITEM_POOL_GROW         16\r
+\r
+\r
+/* IB Link speeds in 100bps */\r
+#define ONE_X_IN_100BPS                25000000\r
+#define FOUR_X_IN_100BPS       100000000\r
+#define TWELVE_X_IN_100BPS     300000000\r
+\r
+\r
+/* Declarations */\r
+static void\r
+adapter_construct(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+\r
+static ib_api_status_t\r
+adapter_init(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+\r
+static void\r
+__adapter_destroying(\r
+       IN                              cl_obj_t* const                         p_obj );\r
+\r
+\r
+static void\r
+__adapter_free(\r
+       IN                              cl_obj_t* const                         p_obj );\r
+\r
+\r
+static ib_api_status_t\r
+__ipoib_pnp_reg(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              ib_pnp_class_t                          flags );\r
+\r
+\r
+static void\r
+__ipoib_pnp_dereg(\r
+       IN                              void*                                           context );\r
+\r
+\r
+static void\r
+__ipoib_adapter_reset(\r
+       IN                              void*   context);\r
+\r
+\r
+static ib_api_status_t\r
+__ipoib_pnp_cb(\r
+       IN                              ib_pnp_rec_t                            *p_pnp_rec );\r
+\r
+\r
+void\r
+ipoib_join_mcast(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+\r
+/* Leaves all mcast groups when port goes down. */\r
+static void\r
+ipoib_clear_mcast(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+NDIS_STATUS\r
+ipoib_get_adapter_guids(\r
+       IN                              NDIS_HANDLE* const                      h_adapter,\r
+       IN      OUT                     ipoib_adapter_t                         *p_adapter );\r
+\r
+NDIS_STATUS\r
+ipoib_get_adapter_params(\r
+       IN                              NDIS_HANDLE* const                      wrapper_config_context,\r
+       IN      OUT                     ipoib_adapter_t                         *p_adapter,\r
+       OUT                             PUCHAR                                          *p_mac,\r
+       OUT                             UINT                                            *p_len);\r
+\r
+\r
+/* Implementation */\r
+ib_api_status_t\r
+ipoib_create_adapter(\r
+       IN                              NDIS_HANDLE                                     wrapper_config_context,\r
+       IN                              void* const                                     h_adapter,\r
+               OUT                     ipoib_adapter_t** const         pp_adapter )\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       ib_api_status_t         status;\r
+       cl_status_t                     cl_status;\r
+       PUCHAR                          mac;\r
+       UINT                            len;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_adapter = cl_zalloc( sizeof(ipoib_adapter_t) );\r
+       if( !p_adapter )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate ipoib_adapter_t (%d bytes)",\r
+                       sizeof(ipoib_adapter_t)) );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       adapter_construct( p_adapter );\r
+\r
+       p_adapter->h_adapter = h_adapter;\r
+\r
+       p_adapter->p_ifc = cl_zalloc( sizeof(ib_al_ifc_t) );\r
+       if( !p_adapter->p_ifc )\r
+       {\r
+               __adapter_free( &p_adapter->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_create_adapter failed to alloc ipoib_ifc_t %d bytes\n",\r
+                       sizeof(ib_al_ifc_t)) );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       /* Get the CA and port GUID from the bus driver. */\r
+       status = ipoib_get_adapter_guids( h_adapter,  p_adapter );\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+ASSERT(FALSE);\r
+//return NDIS_STATUS_SUCCESS;\r
+               __adapter_free( &p_adapter->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_get_adapter_guids returned 0x%.8X.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Port %016I64x (CA %016I64x port %d) initializing\n",\r
+                       p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid,\r
+                       p_adapter->guids.port_num) );\r
+\r
+       cl_status = cl_obj_init( &p_adapter->obj, CL_DESTROY_SYNC,\r
+               __adapter_destroying, NULL, __adapter_free );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               __adapter_free( &p_adapter->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_obj_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       /* Read configuration parameters. */\r
+       status = ipoib_get_adapter_params( wrapper_config_context,\r
+               p_adapter , &mac, &len);\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               cl_obj_destroy( &p_adapter->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_get_adapter_params returned 0x%.8x.\n", status) );\r
+               return status;\r
+       }\r
+               \r
+       status = adapter_init( p_adapter );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               cl_obj_destroy( &p_adapter->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("adapter_init returned %s.\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, p_adapter->mac.addr );\r
+       /* If there is a NetworkAddress override in registry, use it */\r
+       if( (status == NDIS_STATUS_SUCCESS) && (len == HW_ADDR_LEN) )\r
+       {\r
+               if( ETH_IS_MULTICAST(mac) || ETH_IS_BROADCAST(mac) ||\r
+                       !ETH_IS_LOCALLY_ADMINISTERED(mac) )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
+                               ("Overriding NetworkAddress is invalid - "\r
+                               "%02x-%02x-%02x-%02x-%02x-%02x\n",\r
+                               mac[0], mac[1], mac[2],\r
+                               mac[3], mac[4], mac[5]) );\r
+               }\r
+               else\r
+       {\r
+                       ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, mac );\r
+               }\r
+       }\r
+\r
+       *pp_adapter = p_adapter;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ipoib_start_adapter(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       ib_api_status_t status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       status = __ipoib_pnp_reg( p_adapter,\r
+               IB_PNP_FLAG_REG_SYNC | IB_PNP_FLAG_REG_COMPLETE );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+void\r
+ipoib_destroy_adapter(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_adapter );\r
+\r
+       /*\r
+        * Flag the adapter as being removed.  We use the IB_PNP_PORT_REMOVE state\r
+        * for this purpose.  Note that we protect this state change with both the\r
+        * mutex and the lock.  The mutex provides synchronization as a whole\r
+        * between destruction and AL callbacks (PnP, Query, Destruction).\r
+        * The lock provides protection\r
+        */\r
+       KeWaitForMutexObject(\r
+               &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
+       cl_obj_lock( &p_adapter->obj );\r
+       p_adapter->state = IB_PNP_PORT_REMOVE;\r
+\r
+       /*\r
+        * Clear the pointer to the port object since the object destruction\r
+        * will cascade to child objects.  This prevents potential duplicate\r
+        * destruction (or worse, stale pointer usage).\r
+        */\r
+       p_adapter->p_port = NULL;\r
+\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       KeReleaseMutex( &p_adapter->mutex, FALSE );\r
+\r
+       cl_obj_destroy( &p_adapter->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+adapter_construct(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       cl_obj_construct( &p_adapter->obj, IPOIB_OBJ_INSTANCE );\r
+       cl_spinlock_construct( &p_adapter->send_stat_lock );\r
+       cl_spinlock_construct( &p_adapter->recv_stat_lock );\r
+       cl_qpool_construct( &p_adapter->item_pool );\r
+       KeInitializeMutex( &p_adapter->mutex, 0 );\r
+\r
+       cl_thread_construct(&p_adapter->destroy_thread);\r
+       \r
+       cl_vector_construct( &p_adapter->ip_vector );\r
+\r
+       cl_perf_construct( &p_adapter->perf );\r
+\r
+       p_adapter->state = IB_PNP_PORT_ADD;\r
+       p_adapter->port_rate = FOUR_X_IN_100BPS;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+adapter_init(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       cl_status_t                     cl_status;\r
+       ib_api_status_t         status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       cl_status = cl_perf_init( &p_adapter->perf, MaxPerf );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_perf_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       cl_status = cl_spinlock_init( &p_adapter->send_stat_lock );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_spinlock_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       cl_status = cl_spinlock_init( &p_adapter->recv_stat_lock );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_spinlock_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       cl_status = cl_qpool_init( &p_adapter->item_pool, ITEM_POOL_START, 0,\r
+               ITEM_POOL_GROW, sizeof(cl_pool_obj_t), NULL, NULL, NULL );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_qpool_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+\r
+       /* We manually manage the size and capacity of the vector. */\r
+       cl_status = cl_vector_init( &p_adapter->ip_vector, 0,\r
+               0, sizeof(net_address_item_t), NULL, NULL, p_adapter );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_vector_init for ip_vector returned %#x\n",\r
+                       cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       /* Validate the port GUID and generate the MAC address. */\r
+       status =\r
+               ipoib_mac_from_guid( p_adapter->guids.port_guid.guid, p_adapter->params.guid_mask, &p_adapter->mac);\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               if( status == IB_INVALID_GUID_MASK )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
+                               ("Invalid GUID mask received, rejecting it") );\r
+                       ipoib_create_log(p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+               }\r
+\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_mac_from_guid returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Open AL. */\r
+       status = p_adapter->p_ifc->open_al( &p_adapter->h_al );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_open_al returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__ipoib_pnp_reg(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              ib_pnp_class_t                          flags )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_pnp_req_t            pnp_req;\r
+       \r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( !p_adapter->h_pnp );\r
+       CL_ASSERT( !p_adapter->registering );\r
+\r
+       p_adapter->registering = TRUE;\r
+       \r
+       /* Register for PNP events. */\r
+       cl_memclr( &pnp_req, sizeof(pnp_req) );\r
+       pnp_req.pnp_class = IB_PNP_PORT | flags;\r
+       /*\r
+        * Context is the cl_obj of the adapter to allow passing cl_obj_deref\r
+        * to ib_dereg_pnp.\r
+        */\r
+       pnp_req.pnp_context = &p_adapter->obj;\r
+       pnp_req.pfn_pnp_cb = __ipoib_pnp_cb;\r
+       status = p_adapter->p_ifc->reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               ASSERT(FALSE);\r
+               p_adapter->registering = FALSE;\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_reg_pnp returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+       /*\r
+        * Reference the adapter on behalf of the PNP registration.\r
+        * This allows the destruction to block until the PNP deregistration\r
+        * completes.\r
+        */\r
+       cl_obj_ref( &p_adapter->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+static void\r
+__adapter_destroying(\r
+       IN                              cl_obj_t* const                         p_obj )\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );\r
+\r
+       /*\r
+        * The adapter's object will be dereferenced when the deregistration\r
+        * completes.  No need to lock here since all PnP related API calls\r
+        * are driven by NDIS (via the Init/Reset/Destroy paths).\r
+        */\r
+       if( p_adapter->h_pnp )\r
+       {\r
+               p_adapter->p_ifc->dereg_pnp( p_adapter->h_pnp, cl_obj_deref );\r
+               p_adapter->h_pnp = NULL;\r
+       }\r
+\r
+       if( p_adapter->packet_filter )\r
+       {\r
+               KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+               cl_obj_lock( &p_adapter->obj );\r
+\r
+               ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
+               cl_qlist_remove_item( &g_ipoib.adapter_list, &p_adapter->entry );\r
+\r
+               p_adapter->packet_filter = 0;\r
+\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               KeReleaseInStackQueuedSpinLock( &hdl );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__adapter_free(\r
+       IN                              cl_obj_t* const                         p_obj )\r
+{\r
+       ipoib_adapter_t *p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_adapter = PARENT_STRUCT( p_obj, ipoib_adapter_t, obj );\r
+\r
+       if( p_adapter->p_ifc )\r
+       {\r
+               if( p_adapter->h_al )\r
+                       p_adapter->p_ifc->close_al( p_adapter->h_al );\r
+\r
+               cl_free( p_adapter->p_ifc );\r
+               p_adapter->p_ifc = NULL;\r
+       }\r
+\r
+       cl_vector_destroy( &p_adapter->ip_vector );\r
+       cl_qpool_destroy( &p_adapter->item_pool );\r
+       cl_spinlock_destroy( &p_adapter->recv_stat_lock );\r
+       cl_spinlock_destroy( &p_adapter->send_stat_lock );\r
+       cl_obj_deinit( p_obj );\r
+\r
+       cl_perf_destroy( &p_adapter->perf, TRUE );\r
+\r
+       cl_free( p_adapter );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+ipoib_query_pkey_index(ipoib_adapter_t *p_adapter)\r
+{\r
+       ib_api_status_t                 status;\r
+       ib_ca_attr_t                *ca_attr;\r
+       uint32_t                            ca_size;\r
+       uint16_t index = 0;\r
+\r
+       /* Query the CA for Pkey table */\r
+       status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, NULL, &ca_size);\r
+       if(status != IB_INSUFFICIENT_MEMORY)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("ib_query_ca failed\n"));\r
+               return status;\r
+       }\r
+\r
+       ca_attr = (ib_ca_attr_t*)cl_zalloc(ca_size);\r
+       if      (!ca_attr)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("cl_zalloc can't allocate %d\n",ca_size));\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       status = p_adapter->p_ifc->query_ca(p_adapter->p_port->ib_mgr.h_ca, ca_attr,&ca_size);  \r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("ib_query_ca returned %s\n", \r
+                                                p_adapter->p_ifc->get_err_str( status )) );\r
+               goto pkey_end;\r
+       }\r
+       CL_ASSERT(ca_attr->p_port_attr[p_adapter->p_port->port_num -1].p_pkey_table[0] == IB_DEFAULT_PKEY);\r
+       for(index = 0; index < ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys; index++)\r
+       {\r
+               if(cl_hton16(p_adapter->guids.port_guid.pkey) == ca_attr->p_port_attr[p_adapter->p_port->port_num -1].p_pkey_table[index])\r
+                       break;\r
+       }\r
+       if(index >= ca_attr->p_port_attr[p_adapter->p_port->port_num -1].num_pkeys)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Pkey table is invalid, index not found\n"));\r
+               NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
+                       EVENT_IPOIB_PARTITION_ERR, 1, p_adapter->guids.port_guid.pkey );\r
+               status = IB_NOT_FOUND;\r
+               p_adapter->p_port->pkey_index = PKEY_INVALID_INDEX;\r
+               goto pkey_end;\r
+       }\r
+\r
+       p_adapter->p_port->pkey_index = index;\r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_IB,\r
+                                       ("for PKEY = 0x%04X got index = %d\n",p_adapter->guids.port_guid.pkey,index));\r
+\r
+pkey_end:\r
+       if(ca_attr)\r
+               cl_free(ca_attr);\r
+       return status;\r
+}\r
+\r
+static ib_api_status_t\r
+__ipoib_pnp_cb(\r
+       IN                              ib_pnp_rec_t                            *p_pnp_rec )\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       ipoib_port_t            *p_port;\r
+       ib_pnp_event_t          old_state;\r
+       ib_pnp_port_rec_t       *p_port_rec;\r
+       ib_api_status_t         status = IB_SUCCESS;\r
+       NDIS_LINK_STATE         link_state;\r
+       NDIS_STATUS_INDICATION  status_indication;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_PNP );\r
+\r
+       CL_ASSERT( p_pnp_rec );\r
+       NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
+       p_adapter =\r
+               PARENT_STRUCT( p_pnp_rec->pnp_context, ipoib_adapter_t, obj );\r
+\r
+       CL_ASSERT( p_adapter );\r
+\r
+       /* Synchronize with destruction */\r
+       KeWaitForMutexObject(\r
+               &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
+       cl_obj_lock( &p_adapter->obj );\r
+       old_state = p_adapter->state;\r
+       cl_obj_unlock( &p_adapter->obj );\r
+       if( old_state == IB_PNP_PORT_REMOVE )\r
+       {\r
+               KeReleaseMutex( &p_adapter->mutex, FALSE );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP,\r
+                       ("Aborting - Adapter destroying.\n") );\r
+               return IB_NOT_DONE;\r
+       }\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP,\r
+               ("p_pnp_rec->pnp_event = 0x%x (%s)\n",\r
+               p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
+\r
+       p_port_rec = (ib_pnp_port_rec_t*)p_pnp_rec;\r
+\r
+       switch( p_pnp_rec->pnp_event )\r
+       {\r
+       case IB_PNP_PORT_ADD:\r
+               CL_ASSERT( !p_pnp_rec->context );\r
+               /* Only process our port GUID. */\r
+               if( p_pnp_rec->guid != p_adapter->guids.port_guid.guid )\r
+               {\r
+                       status = IB_NOT_DONE;\r
+                       break;\r
+               }\r
+\r
+               /* Don't process if we're destroying. */\r
+               if( p_adapter->obj.state == CL_DESTROYING )\r
+               {\r
+                       status = IB_NOT_DONE;\r
+                       break;\r
+               }\r
+\r
+               CL_ASSERT( !p_adapter->p_port );\r
+               /* Allocate all IB resources. */\r
+               cl_obj_lock( &p_adapter->obj );\r
+               p_adapter->state = IB_PNP_PORT_ADD;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               status = ipoib_create_port( p_adapter, p_port_rec, &p_port );\r
+               cl_obj_lock( &p_adapter->obj );\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       p_adapter->state = old_state;\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       p_adapter->hung = TRUE;\r
+                       break;\r
+               }\r
+\r
+               p_pnp_rec->context = p_port;\r
+\r
+               p_adapter->p_port = p_port;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               break;\r
+\r
+       case IB_PNP_PORT_REMOVE:\r
+               /* Release all IB resources. */\r
+               CL_ASSERT( p_pnp_rec->context );\r
+\r
+               cl_obj_lock( &p_adapter->obj );\r
+               p_adapter->state = IB_PNP_PORT_REMOVE;\r
+               p_port = p_adapter->p_port;\r
+               p_adapter->p_port = NULL;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               ipoib_port_destroy( p_port );\r
+               p_pnp_rec->context = NULL;\r
+               status = IB_SUCCESS;\r
+               break;\r
+\r
+       case IB_PNP_PORT_ACTIVE:\r
+               /* Join multicast groups and put QP in RTS. */\r
+               CL_ASSERT( p_pnp_rec->context );\r
+\r
+               cl_obj_lock( &p_adapter->obj );\r
+               p_adapter->state = IB_PNP_PORT_INIT;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               ipoib_port_up( p_adapter->p_port, p_port_rec );\r
+\r
+               status = IB_SUCCESS;\r
+               break;\r
+\r
+       case IB_PNP_PORT_ARMED:\r
+               status = IB_SUCCESS;\r
+               break;\r
+\r
+       case IB_PNP_PORT_INIT:\r
+               /*\r
+                * Init could happen if the SM brings the port down\r
+                * without changing the physical link.\r
+                */\r
+       case IB_PNP_PORT_DOWN:\r
+               CL_ASSERT( p_pnp_rec->context );\r
+\r
+               cl_obj_lock( &p_adapter->obj );\r
+               old_state = p_adapter->state;\r
+               p_adapter->state = IB_PNP_PORT_DOWN;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               status = IB_SUCCESS;\r
+\r
+               if( !p_adapter->registering && old_state != IB_PNP_PORT_DOWN )\r
+               {\r
+                       link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+                       link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+                       link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+                       link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+                       //link_state.MediaConnectState = MediaConnectStateConnected;\r
+                       link_state.MediaDuplexState = MediaDuplexStateFull;\r
+                       link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+                       IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                   p_adapter->h_adapter,\r
+                                   NDIS_STATUS_LINK_STATE,\r
+                                   (PVOID)&link_state,\r
+                                   sizeof(link_state));\r
+\r
+                       NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                               ("Link DOWN!\n") );\r
+\r
+                       ipoib_port_down( p_adapter->p_port );\r
+               }\r
+               break;\r
+\r
+       case IB_PNP_REG_COMPLETE:\r
+               if( p_adapter->registering )\r
+               {\r
+                       p_adapter->registering = FALSE;\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       old_state = p_adapter->state;\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+\r
+                       if( old_state == IB_PNP_PORT_DOWN )\r
+                       {\r
+                               /* If we were initializing, we might have pended some OIDs. */\r
+                               ipoib_resume_oids( p_adapter );\r
+\r
+                               link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+                               link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+                               link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+                               link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+                               //link_state.MediaConnectState = MediaConnectStateConnected;\r
+                               link_state.MediaDuplexState = MediaDuplexStateFull;\r
+                               link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+                               IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                                                          p_adapter->h_adapter,\r
+                                                                          NDIS_STATUS_LINK_STATE,\r
+                                                                          (PVOID)&link_state,\r
+                                                                          sizeof(link_state));\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
+                       ("Indicate DISCONNECT\n") );\r
+                               NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);                 \r
+                       }\r
+               }\r
+\r
+               if( p_adapter->reset && p_adapter->state != IB_PNP_PORT_INIT )\r
+               {\r
+                       p_adapter->reset = FALSE;\r
+                       NdisMResetComplete(\r
+                               p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
+               }\r
+               status = IB_SUCCESS;\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("IPOIB: Received unhandled PnP event 0x%x (%s)\n",\r
+                       p_pnp_rec->pnp_event, ib_get_pnp_event_str( p_pnp_rec->pnp_event )) );\r
+               /* Fall through. */\r
+\r
+               status = IB_SUCCESS;\r
+\r
+               /* We ignore events below if the link is not active. */\r
+               if( p_port_rec->p_port_attr->link_state != IB_LINK_ACTIVE )\r
+                       break;\r
+\r
+               case IB_PNP_PKEY_CHANGE:\r
+                       if(p_pnp_rec->pnp_event == IB_PNP_PKEY_CHANGE && \r
+                          p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
+                       {\r
+                               status = ipoib_query_pkey_index(p_adapter);\r
+                               if(status != IB_SUCCESS)\r
+                               {\r
+                                  cl_obj_lock( &p_adapter->obj );\r
+                                  p_adapter->state = IB_PNP_PORT_INIT;\r
+                                  cl_obj_unlock( &p_adapter->obj );\r
+                               }\r
+                       }\r
+\r
+               case IB_PNP_SM_CHANGE:\r
+               case IB_PNP_GID_CHANGE:\r
+               case IB_PNP_LID_CHANGE:\r
+\r
+               cl_obj_lock( &p_adapter->obj );\r
+               old_state = p_adapter->state;\r
+               switch( old_state )\r
+               {\r
+               case IB_PNP_PORT_DOWN:\r
+                       p_adapter->state = IB_PNP_PORT_INIT;\r
+                       break;\r
+\r
+               default:\r
+                       p_adapter->state = IB_PNP_PORT_DOWN;\r
+               }\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               \r
+               if( p_adapter->registering )\r
+                       break;\r
+\r
+               switch( old_state )\r
+               {\r
+               case IB_PNP_PORT_ACTIVE:\r
+               case IB_PNP_PORT_INIT:\r
+                       link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+                       link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+                       link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+                       link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+                       //link_state.MediaConnectState = MediaConnectStateConnected;\r
+                       link_state.MediaDuplexState = MediaDuplexStateFull;\r
+                       link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+                       IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                                                  p_adapter->h_adapter,\r
+                                                                  NDIS_STATUS_LINK_STATE,\r
+                                                                  (PVOID)&link_state,\r
+                                                                  sizeof(link_state));\r
+\r
+                       NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);         \r
+\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                               ("Link DOWN!\n") );\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
+                       ("Indicate DISCONNECT\n") );\r
+\r
+                       ipoib_port_down( p_adapter->p_port );\r
+                       /* Fall through. */\r
+\r
+               case IB_PNP_PORT_DOWN:\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       p_adapter->state = IB_PNP_PORT_INIT;\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       ipoib_port_up( p_adapter->p_port, (ib_pnp_port_rec_t*)p_pnp_rec );\r
+               }\r
+               break;\r
+       }\r
+\r
+       KeReleaseMutex( &p_adapter->mutex, FALSE );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_PNP );\r
+       return status;\r
+}\r
+\r
+\r
+/* Joins/leaves mcast groups based on currently programmed mcast MACs. */\r
+void\r
+ipoib_refresh_mcast(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              mac_addr_t* const                       p_mac_array,\r
+       IN              const   uint8_t                                         num_macs )\r
+{\r
+       uint8_t                         i, j;\r
+       ipoib_port_t            *p_port = NULL;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+       cl_obj_lock( &p_adapter->obj );\r
+       if( p_adapter->state == IB_PNP_PORT_ACTIVE )\r
+       {\r
+               p_port = p_adapter->p_port;\r
+               ipoib_port_ref( p_port, ref_refresh_mcast );\r
+       }\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       if( p_port )\r
+       {\r
+               /* Purge old entries. */\r
+               for( i = 0; i < p_adapter->mcast_array_size; i++ )\r
+               {\r
+                       for( j = 0; j < num_macs; j++ )\r
+                       {\r
+                               if( !cl_memcmp( &p_adapter->mcast_array[i], &p_mac_array[j],\r
+                                       sizeof(mac_addr_t) ) )\r
+                               {\r
+                                       break;\r
+                               }\r
+                       }\r
+                       if( j != num_macs )\r
+                               continue;\r
+\r
+                       ipoib_port_remove_endpt( p_port, p_adapter->mcast_array[i] );\r
+               }\r
+\r
+               /* Add new entries */\r
+               for( i = 0; i < num_macs; i++ )\r
+               {\r
+                       for( j = 0; j < p_adapter->mcast_array_size; j++ )\r
+                       {\r
+                               if( !cl_memcmp( &p_adapter->mcast_array[j], &p_mac_array[i],\r
+                                       sizeof(mac_addr_t) ) )\r
+                               {\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       if( j != p_adapter->mcast_array_size )\r
+                               continue;\r
+                       if ( ( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e &&\r
+                                  p_mac_array[i].addr[3] == 0 && p_mac_array[i].addr[4] == 0 && p_mac_array[i].addr[5] == 1 ) ||\r
+                                 !( p_mac_array[i].addr[0] == 1 && p_mac_array[i].addr[1] == 0 && p_mac_array[i].addr[2] == 0x5e )\r
+                               )\r
+                       {\r
+                               ipoib_port_join_mcast( p_port, p_mac_array[i], IB_MC_REC_STATE_FULL_MEMBER );\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* Copy the MAC array. */\r
+       NdisMoveMemory( p_adapter->mcast_array, p_mac_array,\r
+               num_macs * sizeof(mac_addr_t) );\r
+       p_adapter->mcast_array_size = num_macs;\r
+\r
+       if( p_port )\r
+               ipoib_port_deref( p_port, ref_refresh_mcast );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ipoib_reset_adapter(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_pnp_handle_t         h_pnp;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       if( p_adapter->reset )\r
+               return IB_INVALID_STATE;\r
+\r
+       p_adapter->hung = FALSE;\r
+       p_adapter->reset = TRUE;\r
+\r
+       if( p_adapter->h_pnp )\r
+       {\r
+               h_pnp = p_adapter->h_pnp;\r
+               p_adapter->h_pnp  = NULL;\r
+               status = p_adapter->p_ifc->dereg_pnp( h_pnp, __ipoib_pnp_dereg );\r
+               if( status == IB_SUCCESS )\r
+                       status = IB_NOT_DONE;\r
+       }\r
+       else\r
+       {\r
+               status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );\r
+               if( status == IB_SUCCESS )\r
+                       p_adapter->hung = FALSE;\r
+       }\r
+       if (status == IB_NOT_DONE) {\r
+               p_adapter->reset = TRUE;\r
+       }\r
+       else {\r
+               p_adapter->reset = FALSE;\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+static void\r
+__ipoib_pnp_dereg(\r
+       IN                              void*                                           context )\r
+{\r
+       ipoib_adapter_t*        p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_adapter = PARENT_STRUCT( context, ipoib_adapter_t, obj );\r
+\r
+       cl_thread_init(&p_adapter->destroy_thread, __ipoib_adapter_reset, (void*)p_adapter, "destroy_thread");\r
+       \r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+}\r
+\r
+static void\r
+__ipoib_adapter_reset(\r
+       IN                              void*   context)\r
+{\r
+\r
+       ipoib_adapter_t *p_adapter;\r
+       ipoib_port_t            *p_port;\r
+       ib_api_status_t         status;\r
+       ib_pnp_event_t          state;\r
+       \r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Got RESET\n") );\r
+//     return;\r
+       p_adapter = (ipoib_adapter_t*)context;\r
+       \r
+       /* Synchronize with destruction */\r
+       KeWaitForMutexObject(\r
+               &p_adapter->mutex, Executive, KernelMode, FALSE, NULL );\r
+\r
+       cl_obj_lock( &p_adapter->obj );\r
+\r
+       CL_ASSERT( !p_adapter->h_pnp );\r
+\r
+       if( p_adapter->state != IB_PNP_PORT_REMOVE )\r
+               p_adapter->state = IB_PNP_PORT_ADD;\r
+\r
+       state = p_adapter->state;\r
+\r
+       /* Destroy the current port instance if it still exists. */\r
+       p_port = p_adapter->p_port;\r
+       p_adapter->p_port = NULL;\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       if( p_port )\r
+               ipoib_port_destroy( p_port );\r
+       ASSERT(p_adapter->reset == TRUE);\r
+       if( state != IB_PNP_PORT_REMOVE )\r
+       {\r
+               status = __ipoib_pnp_reg( p_adapter, IB_PNP_FLAG_REG_COMPLETE );\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       p_adapter->reset = FALSE;\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("__ipoib_pnp_reg returned %s\n",\r
+                               p_adapter->p_ifc->get_err_str( status )) );\r
+                       NdisMResetComplete( \r
+                               p_adapter->h_adapter, NDIS_STATUS_HARD_ERRORS, TRUE );\r
+               }\r
+       }\r
+       else\r
+       {\r
+               p_adapter->reset = FALSE;\r
+               NdisMResetComplete(\r
+                       p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
+               status = IB_SUCCESS;\r
+       }\r
+\r
+       /* Dereference the adapter since the previous registration is now gone. */\r
+       cl_obj_deref( &p_adapter->obj );\r
+\r
+       KeReleaseMutex( &p_adapter->mutex, FALSE );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+void\r
+ipoib_set_rate(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   uint8_t                                         link_width, \r
+       IN              const   uint8_t                                         link_speed )\r
+{\r
+       uint32_t        rate;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /* Set the link speed based on the IB link speed (1x vs 4x, etc). */\r
+       switch( link_speed )\r
+       {\r
+       case IB_LINK_SPEED_ACTIVE_2_5:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Link speed is 2.5Gs\n") );\r
+               rate = IB_LINK_SPEED_ACTIVE_2_5;\r
+               break;\r
+\r
+       case IB_LINK_SPEED_ACTIVE_5:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Link speed is 5G\n") );\r
+               rate = IB_LINK_SPEED_ACTIVE_5;\r
+               break;\r
+\r
+       case IB_LINK_SPEED_ACTIVE_10:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Link speed is 10G\n") );\r
+               rate = IB_LINK_SPEED_ACTIVE_10;\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid link speed %d.\n", link_speed) );\r
+               rate = 0;\r
+       }\r
+\r
+       switch( link_width )\r
+       {\r
+       case IB_LINK_WIDTH_ACTIVE_1X:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Link width is 1X\n") );\r
+               rate *= ONE_X_IN_100BPS;\r
+               break;\r
+\r
+       case IB_LINK_WIDTH_ACTIVE_4X:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Link width is 4X\n") );\r
+               rate *= FOUR_X_IN_100BPS;\r
+               break;\r
+\r
+       case IB_LINK_WIDTH_ACTIVE_12X:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Link width is 12X\n") );\r
+               rate *= TWELVE_X_IN_100BPS;\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid link rate (%d).\n", link_width) );\r
+               rate = 0;\r
+       }\r
+\r
+       p_adapter->port_rate = rate;\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ipoib_set_active(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       ib_pnp_event_t  old_state;\r
+       uint8_t                 i;\r
+       ib_api_status_t status = IB_SUCCESS;\r
+       NDIS_LINK_STATE         link_state;\r
+       NDIS_STATUS_INDICATION  status_indication;\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
+       cl_obj_lock( &p_adapter->obj );\r
+       old_state = p_adapter->state;\r
+\r
+       /* Change the state to indicate that we are now connected and live. */\r
+       if( old_state == IB_PNP_PORT_INIT )\r
+               p_adapter->state = IB_PNP_PORT_ACTIVE;\r
+\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       /*\r
+        * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
+        * complete it now.\r
+        */\r
+       switch( old_state )\r
+       {\r
+       case IB_PNP_PORT_ADD:\r
+               ipoib_reg_addrs( p_adapter );\r
+               /* Fall through. */\r
+\r
+       case IB_PNP_PORT_REMOVE:\r
+               ipoib_resume_oids( p_adapter );\r
+               break;\r
+\r
+       default:\r
+               if (p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
+               {\r
+                       status = ipoib_query_pkey_index(p_adapter);\r
+                       if( IB_SUCCESS != status)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+               /* Join all programmed multicast groups. */\r
+               for( i = 0; i < p_adapter->mcast_array_size; i++ )\r
+               {\r
+                       ipoib_port_join_mcast(\r
+                               p_adapter->p_port, p_adapter->mcast_array[i] ,IB_MC_REC_STATE_FULL_MEMBER);\r
+               }\r
+\r
+               /* Register all existing addresses. */\r
+               ipoib_reg_addrs( p_adapter );\r
+\r
+               ipoib_resume_oids( p_adapter );\r
+\r
+               /*\r
+                * Now that we're in the broadcast group, notify that\r
+                * we have a link.\r
+                */\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Link UP!\n") );\r
+               NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
+                       EVENT_IPOIB_PORT_UP + (p_adapter->port_rate/ONE_X_IN_100BPS),\r
+                       1, p_adapter->port_rate );\r
+\r
+               if( !p_adapter->reset )\r
+               {\r
+                       link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+                       link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+                       link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+                       link_state.MediaConnectState = MediaConnectStateConnected;\r
+                       link_state.MediaDuplexState = MediaDuplexStateFull;\r
+                       link_state.XmitLinkSpeed = \r
+                       link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+                       link_state.PauseFunctions = NdisPauseFunctionsSendAndReceive;\r
+                       IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                                                  p_adapter->h_adapter,\r
+                                                                  NDIS_STATUS_LINK_STATE,\r
+                                                                  (PVOID)&link_state,\r
+                                                                  sizeof(link_state));\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("***************Indicate connect!\n") );\r
+                       NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
+               }\r
+       }\r
+\r
+       if( p_adapter->reset )\r
+       {\r
+               ASSERT(FALSE);\r
+               p_adapter->reset = FALSE;\r
+               NdisMResetComplete(\r
+                       p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return  status;\r
+}\r
+\r
+/*\r
+ * If something goes wrong after the port goes active, e.g.\r
+ *     - PortInfo query failure\r
+ *     - MC Join timeout\r
+ *     - etc\r
+ * Mark the port state as down, resume any pended OIDS, etc.\r
+ */\r
+void\r
+ipoib_set_inactive(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       ib_pnp_event_t  old_state;\r
+       NDIS_LINK_STATE         link_state;\r
+       NDIS_STATUS_INDICATION  status_indication;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       NdisZeroMemory(&link_state, sizeof(NDIS_LINK_STATE));\r
+       cl_obj_lock( &p_adapter->obj );\r
+       old_state = p_adapter->state;\r
+       if( old_state != IB_PNP_PORT_REMOVE )\r
+               p_adapter->state = IB_PNP_PORT_DOWN;\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       /*\r
+        * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
+        * complete it now.\r
+        */\r
+       if( old_state == IB_PNP_PORT_INIT )\r
+       {\r
+               link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+               link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+               link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+               link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+               //link_state.MediaConnectState = MediaConnectStateConnected;\r
+               \r
+               link_state.MediaDuplexState = MediaDuplexStateFull;\r
+               link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+               IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                                          p_adapter->h_adapter,\r
+                                                          NDIS_STATUS_LINK_STATE,\r
+                                                          (PVOID)&link_state,\r
+                                                          sizeof(link_state));\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate Disconnect!\n") );\r
+               NdisMIndicateStatusEx(p_adapter->h_adapter,&status_indication);\r
+\r
+               ipoib_resume_oids( p_adapter );\r
+       }\r
+\r
+       if( p_adapter->reset )\r
+       {\r
+               p_adapter->reset = FALSE;\r
+               NdisMResetComplete(\r
+                       p_adapter->h_adapter, NDIS_STATUS_SUCCESS, TRUE );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+NDIS_STATUS\r
+ipoib_get_gen_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       OUT             pending_oid_t* const            p_oid_info)\r
+{\r
+       PNDIS_STATISTICS_INFO StatisticsInfo;\r
+       IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+       if (p_oid_info->buf_len < sizeof(StatisticsInfo))\r
+       {\r
+               *p_oid_info->p_bytes_needed = sizeof(NDIS_STATISTICS_INFO);\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+       }\r
+\r
+       StatisticsInfo = (PNDIS_STATISTICS_INFO)p_oid_info->p_buf;\r
+    StatisticsInfo->Header.Revision = NDIS_OBJECT_REVISION_1;\r
+    StatisticsInfo->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+    StatisticsInfo->Header.Size = sizeof(NDIS_STATISTICS_INFO);\r
+    /*StatisticsInfo->SupportedStatistics = NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS          |\r
+                                          NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR             |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV   |\r
+                                          NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV  |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV  |\r
+                                          NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV             | \r
+                                          NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV   |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV       |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV        |\r
+\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS                     |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR            |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT  | \r
+                                          NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT                        |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT       |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT      |\r
+                                                                                 NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT; */\r
+                                                                                 \r
+                                                                                 \r
+       StatisticsInfo->SupportedStatistics =  NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV |\r
+                                                                                       //The data in the ifHCInUcastPkts member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV |\r
+                                                                                       //The data in the ifHCInMulticastPkts member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV |\r
+                                                                                       //The data in the ifHCInBroadcastPkts member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV |\r
+                                                                                       //The data in the ifHCInOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS |\r
+                                                                                       //The data in the ifInDiscards member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR |\r
+                                                                                       //The data in the ifInErrors member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT |\r
+                                                                                       //The data in the ifHCOutUcastPkts member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |\r
+                                                                                       //The data in the ifHCOutMulticastPkts member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |\r
+                                                                                       //The data in the ifHCOutBroadcastPkts member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT |\r
+                                                                                       //The data in the ifHCOutOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR |\r
+                                                                                       //The data in the ifOutErrors member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS |\r
+                                                                                       //The data in the ifOutDiscards member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV |\r
+                                                                                       //The data in the ifHCInUcastOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV |\r
+                                                                                       //The data in the ifHCInMulticastOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV |\r
+                                                                                       //The data in the ifHCInBroadcastOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT |\r
+                                                                                       //The data in the ifHCOutUcastOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT |\r
+                                                                                       //The data in the ifHCOutMulticastOctets member is valid. \r
+                                                                                       NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT ;\r
+                                                                                       //The data in the ifHCOutBroadcastOctets member is valid\r
+\r
+    cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
+    StatisticsInfo->ifInDiscards = p_adapter->recv_stats.comp.dropped +\r
+                                   p_adapter->recv_stats.comp.error;            \r
+    StatisticsInfo->ifInErrors = p_adapter->recv_stats.comp.error;\r
+    StatisticsInfo->ifHCInOctets = p_adapter->recv_stats.ucast.bytes + \r
+                                                                  p_adapter->recv_stats.bcast.bytes + \r
+                                                                  p_adapter->recv_stats.mcast.bytes;       \r
+    StatisticsInfo->ifHCInUcastPkts       = p_adapter->recv_stats.ucast.frames;\r
+    StatisticsInfo->ifHCInMulticastPkts   = p_adapter->recv_stats.mcast.frames;  \r
+    StatisticsInfo->ifHCInBroadcastPkts   = p_adapter->recv_stats.bcast.frames;  \r
+       StatisticsInfo->ifHCInMulticastOctets = p_adapter->recv_stats.mcast.bytes;\r
+       StatisticsInfo->ifHCInBroadcastOctets = p_adapter->recv_stats.bcast.bytes;\r
+       StatisticsInfo->ifHCInUcastOctets     = p_adapter->recv_stats.ucast.bytes;\r
+       cl_spinlock_release( &p_adapter->recv_stat_lock );\r
+\r
+    cl_spinlock_acquire( &p_adapter->send_stat_lock ); \r
+    StatisticsInfo->ifHCOutOctets = p_adapter->send_stats.ucast.bytes + \r
+                                                                       p_adapter->send_stats.mcast.bytes + \r
+                                                                       p_adapter->send_stats.bcast.bytes;        \r
+    StatisticsInfo->ifHCOutUcastPkts       = p_adapter->send_stats.ucast.frames;     \r
+    StatisticsInfo->ifHCOutMulticastPkts   = p_adapter->send_stats.mcast.frames; \r
+    StatisticsInfo->ifHCOutBroadcastPkts   = p_adapter->send_stats.bcast.frames; \r
+    StatisticsInfo->ifOutErrors            = p_adapter->send_stats.comp.error;                                      \r
+    StatisticsInfo->ifOutDiscards          = p_adapter->send_stats.comp.dropped;\r
+       StatisticsInfo->ifHCOutUcastOctets     = p_adapter->send_stats.ucast.bytes;\r
+       StatisticsInfo->ifHCOutMulticastOctets = p_adapter->send_stats.mcast.bytes;\r
+       StatisticsInfo->ifHCOutBroadcastOctets = p_adapter->send_stats.bcast.bytes;\r
+    cl_spinlock_release( &p_adapter->send_stat_lock );\r
+\r
+       *p_oid_info->p_bytes_used = sizeof(NDIS_STATISTICS_INFO);\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+NDIS_STATUS\r
+ipoib_get_recv_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN                              pending_oid_t* const            p_oid_info )\r
+{\r
+       uint64_t        stat;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+       CL_ASSERT( p_adapter );\r
+\r
+       cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
+       switch( stat_sel )\r
+       {\r
+       case IP_STAT_SUCCESS:\r
+               stat = p_adapter->recv_stats.comp.success;\r
+               break;\r
+\r
+       case IP_STAT_ERROR:\r
+               stat = p_adapter->recv_stats.comp.error;\r
+               break;\r
+\r
+       case IP_STAT_DROPPED:\r
+               stat = p_adapter->recv_stats.comp.dropped;\r
+               break;\r
+\r
+       case IP_STAT_UCAST_BYTES:\r
+               stat = p_adapter->recv_stats.ucast.bytes;\r
+               break;\r
+\r
+       case IP_STAT_UCAST_FRAMES:\r
+               stat = p_adapter->recv_stats.ucast.frames;\r
+               break;\r
+\r
+       case IP_STAT_BCAST_BYTES:\r
+               stat = p_adapter->recv_stats.bcast.bytes;\r
+               break;\r
+\r
+       case IP_STAT_BCAST_FRAMES:\r
+               stat = p_adapter->recv_stats.bcast.frames;\r
+               break;\r
+\r
+       case IP_STAT_MCAST_BYTES:\r
+               stat = p_adapter->recv_stats.mcast.bytes;\r
+               break;\r
+\r
+       case IP_STAT_MCAST_FRAMES:\r
+               stat = p_adapter->recv_stats.mcast.frames;\r
+               break;\r
+\r
+       default:\r
+               stat = 0;\r
+       }\r
+       cl_spinlock_release( &p_adapter->recv_stat_lock );\r
+\r
+       *p_oid_info->p_bytes_needed = sizeof(uint64_t);\r
+\r
+       if( p_oid_info->buf_len >= sizeof(uint64_t) )\r
+       {\r
+               *((uint64_t*)p_oid_info->p_buf) = stat;\r
+               *p_oid_info->p_bytes_used = sizeof(uint64_t);\r
+       }\r
+       else if( p_oid_info->buf_len >= sizeof(uint32_t) )\r
+       {\r
+               *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;\r
+               *p_oid_info->p_bytes_used = sizeof(uint32_t);\r
+       }\r
+       else\r
+       {\r
+               *p_oid_info->p_bytes_used = 0;\r
+               IPOIB_EXIT( IPOIB_DBG_STAT );\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_STAT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+ipoib_inc_recv_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN              const   size_t                                          bytes OPTIONAL,\r
+       IN              const   size_t                                          packets OPTIONAL )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+       cl_spinlock_acquire( &p_adapter->recv_stat_lock );\r
+       switch( stat_sel )\r
+       {\r
+       case IP_STAT_ERROR:\r
+               p_adapter->recv_stats.comp.error++;\r
+               break;\r
+\r
+       case IP_STAT_DROPPED:\r
+               p_adapter->recv_stats.comp.dropped++;\r
+               break;\r
+\r
+       case IP_STAT_UCAST_BYTES:\r
+       case IP_STAT_UCAST_FRAMES:\r
+               p_adapter->recv_stats.comp.success++;\r
+               p_adapter->recv_stats.ucast.frames += packets;\r
+               p_adapter->recv_stats.ucast.bytes += bytes;\r
+               break;\r
+\r
+       case IP_STAT_BCAST_BYTES:\r
+       case IP_STAT_BCAST_FRAMES:\r
+               p_adapter->recv_stats.comp.success++;\r
+               p_adapter->recv_stats.bcast.frames += packets;\r
+               p_adapter->recv_stats.bcast.bytes += bytes;\r
+               break;\r
+\r
+       case IP_STAT_MCAST_BYTES:\r
+       case IP_STAT_MCAST_FRAMES:\r
+               p_adapter->recv_stats.comp.success++;\r
+               p_adapter->recv_stats.mcast.frames += packets;\r
+               p_adapter->recv_stats.mcast.bytes += bytes;\r
+               break;\r
+\r
+       default:\r
+               break;\r
+       }\r
+       cl_spinlock_release( &p_adapter->recv_stat_lock );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_STAT );\r
+}\r
+\r
+NDIS_STATUS\r
+ipoib_get_send_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN                              pending_oid_t* const            p_oid_info )\r
+{\r
+       uint64_t        stat;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+       CL_ASSERT( p_adapter );\r
+\r
+       cl_spinlock_acquire( &p_adapter->send_stat_lock );\r
+       switch( stat_sel )\r
+       {\r
+       case IP_STAT_SUCCESS:\r
+               stat = p_adapter->send_stats.comp.success;\r
+               break;\r
+\r
+       case IP_STAT_ERROR:\r
+               stat = p_adapter->send_stats.comp.error;\r
+               break;\r
+\r
+       case IP_STAT_DROPPED:\r
+               stat = p_adapter->send_stats.comp.dropped;\r
+               break;\r
+\r
+       case IP_STAT_UCAST_BYTES:\r
+               stat = p_adapter->send_stats.ucast.bytes;\r
+               break;\r
+\r
+       case IP_STAT_UCAST_FRAMES:\r
+               stat = p_adapter->send_stats.ucast.frames;\r
+               break;\r
+\r
+       case IP_STAT_BCAST_BYTES:\r
+               stat = p_adapter->send_stats.bcast.bytes;\r
+               break;\r
+\r
+       case IP_STAT_BCAST_FRAMES:\r
+               stat = p_adapter->send_stats.bcast.frames;\r
+               break;\r
+\r
+       case IP_STAT_MCAST_BYTES:\r
+               stat = p_adapter->send_stats.mcast.bytes;\r
+               break;\r
+\r
+       case IP_STAT_MCAST_FRAMES:\r
+               stat = p_adapter->send_stats.mcast.frames;\r
+               break;\r
+\r
+       default:\r
+               stat = 0;\r
+       }\r
+       cl_spinlock_release( &p_adapter->send_stat_lock );\r
+\r
+       *p_oid_info->p_bytes_needed = sizeof(uint64_t);\r
+\r
+       if( p_oid_info->buf_len >= sizeof(uint64_t) )\r
+       {\r
+               *((uint64_t*)p_oid_info->p_buf) = stat;\r
+               *p_oid_info->p_bytes_used = sizeof(uint64_t);\r
+       }\r
+       else if( p_oid_info->buf_len >= sizeof(uint32_t) )\r
+       {\r
+               *((uint32_t*)p_oid_info->p_buf) = (uint32_t)stat;\r
+               *p_oid_info->p_bytes_used = sizeof(uint32_t);\r
+       }\r
+       else\r
+       {\r
+               *p_oid_info->p_bytes_used = 0;\r
+               IPOIB_EXIT( IPOIB_DBG_STAT );\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_STAT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+ipoib_inc_send_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN              const   size_t                                          bytes OPTIONAL )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_STAT );\r
+\r
+       cl_spinlock_acquire( &p_adapter->send_stat_lock );\r
+       switch( stat_sel )\r
+       {\r
+       case IP_STAT_ERROR:\r
+               p_adapter->send_stats.comp.error++;\r
+               break;\r
+\r
+       case IP_STAT_DROPPED:\r
+               p_adapter->send_stats.comp.dropped++;\r
+               break;\r
+\r
+       case IP_STAT_UCAST_BYTES:\r
+       case IP_STAT_UCAST_FRAMES:\r
+               p_adapter->send_stats.comp.success++;\r
+               p_adapter->send_stats.ucast.frames++;\r
+               p_adapter->send_stats.ucast.bytes += bytes;\r
+               break;\r
+\r
+       case IP_STAT_BCAST_BYTES:\r
+       case IP_STAT_BCAST_FRAMES:\r
+               p_adapter->send_stats.comp.success++;\r
+               p_adapter->send_stats.bcast.frames++;\r
+               p_adapter->send_stats.bcast.bytes += bytes;\r
+               break;\r
+\r
+       case IP_STAT_MCAST_BYTES:\r
+       case IP_STAT_MCAST_FRAMES:\r
+               p_adapter->send_stats.comp.success++;\r
+               p_adapter->send_stats.mcast.frames++;\r
+               p_adapter->send_stats.mcast.bytes += bytes;\r
+               break;\r
+\r
+       default:\r
+               break;\r
+       }\r
+       cl_spinlock_release( &p_adapter->send_stat_lock );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_STAT );\r
+}\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.h b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_adapter.h
new file mode 100644 (file)
index 0000000..2254f39
--- /dev/null
@@ -0,0 +1,483 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_adapter.h 4494 2009-06-22 14:31:08Z xalex $\r
+ */\r
+\r
+\r
+#ifndef _IPOIB_ADAPTER_H_\r
+#define _IPOIB_ADAPTER_H_\r
+\r
+#include <iba/ipoib_ifc.h>\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_obj.h>\r
+#include <complib/cl_spinlock.h>\r
+#include <complib/cl_mutex.h>\r
+#include <complib/cl_qpool.h>\r
+#include <complib/cl_atomic.h>\r
+#include <complib/cl_perf.h>\r
+#include <complib/cl_vector.h>\r
+#include <ip_packet.h>\r
+#include "ip_stats.h"\r
+\r
+\r
+/*\r
+ * Definitions\r
+ */\r
+#define MAX_MCAST                              32\r
+\r
+#define IPV4_ADDR_SIZE                 4\r
+\r
+#define PORT_NUM_INDEX_IN_GUID 3 /* 0 based index into big endian GUID to get port number */\r
+\r
+/*\r
+ * Macros\r
+ */\r
+typedef enum \r
+{\r
+       CSUM_DISABLED = 0, \r
+       CSUM_ENABLED, \r
+       CSUM_BYPASS\r
+} csum_flag_t;\r
+\r
+typedef enum _ipoib_state\r
+{\r
+    IPOIB_PAUSED,\r
+    IPOIB_PAUSING,\r
+    IPOIB_RUNNING\r
+} ipoib_state_t;\r
+\r
+typedef struct _ipoib_params\r
+{\r
+       int32_t         rq_depth;\r
+       int32_t         rq_low_watermark;\r
+       int32_t         sq_depth;\r
+       csum_flag_t     send_chksum_offload;\r
+       csum_flag_t     recv_chksum_offload;\r
+       uint32_t        sa_timeout;\r
+       uint32_t        sa_retry_cnt;\r
+       uint32_t        recv_pool_ratio;\r
+       uint32_t        payload_mtu;\r
+       boolean_t       lso;\r
+       uint32_t        xfer_block_size;\r
+       mac_addr_t      conf_mac;\r
+       uint32_t        mc_leave_rescan;\r
+       uint32_t        guid_mask;\r
+       uint32_t        bc_join_retry;\r
+       boolean_t       cm_enabled;\r
+       uint32_t        cm_payload_mtu;\r
+       uint32_t        cm_xfer_block_size;\r
+}      ipoib_params_t;\r
+/*\r
+* FIELDS\r
+*      rq_depth\r
+*              Number of receive WQEs to allocate.\r
+*\r
+*      rq_low_watermark\r
+*              Receives are indicated with NDIS_STATUS_RESOURCES when the number of\r
+*              receives posted to the RQ falls bellow this value.\r
+*\r
+*      sq_depth\r
+*              Number of send WQEs to allocate.\r
+*\r
+*      send_chksum_offload\r
+*      recv_chksum_offload\r
+*              Flags to indicate whether to offload send/recv checksums.\r
+*              0 - No hardware cheksum\r
+*              1 - Try to offload if the device support it\r
+*              2 - Always report success (checksum bypass)\r
+*\r
+*      wsdp_enabled\r
+*              Flag to indicate whether WSDP is enabled for an adapter adapter.\r
+*\r
+*      static_lid\r
+*              LID to assign to the port if that port is down (not init) and has none.\r
+*              This feature allows a LID to be assigned, alowing locally targetted\r
+*              traffic to occur even on ports that are not plugged in.\r
+*\r
+*      sa_timeout\r
+*              Time, in milliseconds, to wait for a response before retransmitting an\r
+*              SA query request.\r
+*\r
+*      sa_retry_cnt\r
+*              Number of times to retry an SA query request.\r
+*\r
+*      recv_pool_ratio\r
+*              Initial ratio of receive pool size to receive queue depth.\r
+*\r
+*      grow_thresh\r
+*              Threshold at which to grow the receive pool.  Valid values start are\r
+*              powers of 2, excluding 1.  When zero, grows only when the pool is\r
+*              exhausted.  Other values indicate fractional values\r
+*              (i.e. 2 indicates 1/2, 4 indicates 1/4, etc.)\r
+*\r
+*      payload_mtu\r
+               The maximum available size of IPoIB transfer unit.\r
+               \r
+               If using UD mode:\r
+*              It should be decremented by size of IPoIB header (==4B)\r
+*              For example, if the HCA support 4K MTU, \r
+*              upper threshold for payload mtu is 4092B and not 4096B\r
+\r
+               If using CM mode:\r
+               MTU will be not limited by 4K threshold.\r
+               UD QP still may be used for different protocols (like ARP).\r
+               For these situations the threshold for the UD QP will take the default value\r
+               \r
+*\r
+*      lso\r
+*      It indicates if there's a support for hardware large/giant send offload\r
+*              \r
+*********/\r
+\r
+\r
+typedef struct _pending_oid\r
+{\r
+       NDIS_OID                        oid;\r
+       PVOID                           p_buf;\r
+       ULONG                           buf_len;\r
+       PULONG                          p_bytes_used;\r
+       PULONG                          p_bytes_needed;\r
+       PNDIS_OID_REQUEST       p_pending_oid;\r
+}      pending_oid_t;\r
+\r
+\r
+typedef struct _ipoib_adapter\r
+{\r
+       cl_obj_t                                obj;\r
+       NDIS_HANDLE                             h_adapter;\r
+       ipoib_ifc_data_t                guids;\r
+\r
+       cl_list_item_t                  entry;\r
+\r
+       ib_al_handle_t                  h_al;\r
+       ib_pnp_handle_t                 h_pnp;\r
+\r
+       ib_pnp_event_t                  state;\r
+       boolean_t                               hung;\r
+       boolean_t                               reset;\r
+       boolean_t                               registering;\r
+\r
+       boolean_t                               pending_query;\r
+       pending_oid_t                   query_oid;\r
+       boolean_t                               pending_set;\r
+       pending_oid_t                   set_oid;\r
+\r
+       struct _ipoib_port              *p_port;\r
+\r
+       uint32_t                                port_rate;\r
+\r
+       ipoib_params_t                  params;\r
+       cl_spinlock_t                   recv_stat_lock;\r
+       ip_stats_t                              recv_stats;\r
+       cl_spinlock_t                   send_stat_lock;\r
+       ip_stats_t                              send_stats;\r
+\r
+       boolean_t                               is_primary;\r
+       struct _ipoib_adapter   *p_primary;\r
+\r
+       uint32_t                                packet_filter;\r
+\r
+       mac_addr_t                              mac;\r
+       mac_addr_t                              mcast_array[MAX_MCAST];\r
+       uint8_t                                 mcast_array_size;\r
+\r
+       cl_qpool_t                              item_pool;\r
+\r
+       KMUTEX                                  mutex;\r
+\r
+       cl_thread_t                             destroy_thread;\r
+       cl_vector_t                             ip_vector;\r
+\r
+       cl_perf_t                               perf;\r
+    NDIS_HANDLE                        NdisMiniportDmaHandle;\r
+       ipoib_state_t                   ipoib_state;\r
+       ib_al_ifc_t                             *p_ifc;\r
+\r
+       ULONG                                   sg_list_size;\r
+\r
+}      ipoib_adapter_t;\r
+/*\r
+* FIELDS\r
+*      obj\r
+*              Complib object for reference counting and destruction synchronization.\r
+*\r
+*      h_adapter\r
+*              NDIS adapter handle.\r
+*\r
+*      guids\r
+*              CA and port GUIDs returned by the bus driver.\r
+*\r
+*      entry\r
+*              List item for storing all adapters in a list for address translation.\r
+*              We add adapters when their packet filter is set to a non-zero value,\r
+*              and remove them when their packet filter is cleared.  This is needed\r
+*              since user-mode removal events are generated after the packet filter\r
+*              is cleared, but before the adapter is destroyed.\r
+*\r
+*      h_al\r
+*              AL handle for all IB resources.\r
+*\r
+*      h_pnp\r
+*              PNP registration handle for port events.\r
+*\r
+*      state\r
+*              State of the adapter.  IB_PNP_PORT_ADD indicates that the adapter\r
+*              is ready to transfer data.\r
+*\r
+*      hung\r
+*              Boolean flag used to return whether we are hung or not.\r
+*\r
+*      p_port\r
+*              Pointer to an ipoib_port_t representing all resources for moving data\r
+*              on the IB fabric.\r
+*\r
+*      rate\r
+*              Rate, in 100bps increments, of the link.\r
+*\r
+*      params\r
+*              Configuration parameters.\r
+*\r
+*      pending_query\r
+*              Indicates that an query OID request is being processed asynchronously.\r
+*\r
+*      query_oid\r
+*              Information about the pended query OID request.\r
+*              Valid only if pending_query is TRUE.\r
+*\r
+*      pending_set\r
+*              Indicates that an set OID request is being processed asynchronously.\r
+*\r
+*      set_oid\r
+*              Information about the pended set OID request.\r
+*              Valid only if pending_set is TRUE.\r
+*\r
+*      recv_lock\r
+*              Spinlock protecting receive processing.\r
+*\r
+*      recv_stats\r
+*              Receive statistics.\r
+*\r
+*      send_lock\r
+*              Spinlock protecting send processing.\r
+*\r
+*      send_stats\r
+*              Send statistics.\r
+*\r
+*      is_primary\r
+*              Boolean flag to indicate if an adapter is the primary adapter\r
+*              of a bundle.\r
+*\r
+*      p_primary\r
+*              Pointer to the primary adapter for a bundle.\r
+*\r
+*      packet_filter\r
+*              Packet filter set by NDIS.\r
+*\r
+*      mac_addr\r
+*              Ethernet MAC address reported to NDIS.\r
+*\r
+*      mcast_array\r
+*              List of multicast MAC addresses programmed by NDIS.\r
+*\r
+*      mcast_array_size\r
+*              Number of entries in the multicat MAC address array;\r
+*\r
+*      item_pool\r
+*              Pool of cl_pool_obj_t structures to use for queueing pending\r
+*              packets for transmission.\r
+*\r
+*      mutex\r
+*              Mutex to synchronized PnP callbacks with destruction.\r
+*\r
+*      ip_vector\r
+*              Vector of assigned IP addresses.\r
+*\r
+*      p_ifc\r
+*              Pointer to transport interface.\r
+*\r
+*********/\r
+\r
+\r
+typedef struct _ats_reg\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       ib_reg_svc_handle_t     h_reg_svc;\r
+\r
+}      ats_reg_t;\r
+/*\r
+* FIELDS\r
+*      p_adapter\r
+*              Pointer to the adapter to which this address is assigned.\r
+*\r
+*      h_reg_svc\r
+*              Service registration handle.\r
+*********/\r
+\r
+\r
+typedef struct _net_address_item\r
+{\r
+       ats_reg_t                       *p_reg;\r
+       union _net_address_item_address\r
+       {\r
+               ULONG                   as_ulong;\r
+               UCHAR                   as_bytes[IPV4_ADDR_SIZE];\r
+       }       address;\r
+\r
+}      net_address_item_t;\r
+/*\r
+* FIELDS\r
+*      p_reg\r
+*              Pointer to the ATS registration assigned to this address.\r
+*\r
+*      address\r
+*              Union representing the IP address as an unsigned long or as\r
+*              an array of bytes.\r
+*\r
+*      as_ulong\r
+*              The IP address represented as an unsigned long.  Windows stores\r
+*              IPs this way.\r
+*\r
+*      as_bytes\r
+*              The IP address represented as an array of bytes.\r
+*********/\r
+\r
+\r
+ib_api_status_t\r
+ipoib_create_adapter(\r
+       IN              NDIS_HANDLE                     wrapper_config_context,\r
+       IN              void* const                     h_adapter,\r
+       OUT             ipoib_adapter_t**  const        pp_adapter );\r
+\r
+\r
+ib_api_status_t\r
+ipoib_start_adapter(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+\r
+void\r
+ipoib_destroy_adapter(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+\r
+/* Joins/leaves mcast groups based on currently programmed mcast MACs. */\r
+void\r
+ipoib_refresh_mcast(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              mac_addr_t* const                       p_mac_array,\r
+       IN              const   uint8_t                                         num_macs );\r
+/*\r
+* PARAMETERS\r
+*      p_adapter\r
+*              Instance whose multicast MAC address list to modify.\r
+*\r
+*      p_mac_array\r
+*              Array of multicast MAC addresses assigned to the adapter.\r
+*\r
+*      num_macs\r
+*              Number of MAC addresses in the array.\r
+*********/\r
+NDIS_STATUS\r
+ipoib_get_gen_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       OUT             pending_oid_t* const            p_oid_info );\r
+\r
+NDIS_STATUS\r
+ipoib_get_recv_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN                              pending_oid_t* const            p_oid_info );\r
+\r
+\r
+void\r
+ipoib_inc_recv_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN              const   size_t                                          bytes OPTIONAL,\r
+       IN              const   size_t                                          packets OPTIONAL );\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_get_send_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN                              pending_oid_t* const            p_oid_info );\r
+\r
+\r
+void\r
+ipoib_inc_send_stat(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   ip_stat_sel_t                           stat_sel,\r
+       IN              const   size_t                                          bytes OPTIONAL );\r
+\r
+\r
+void\r
+ipoib_set_rate(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN              const   uint8_t                                         link_width,\r
+       IN              const   uint8_t                                         link_speed );\r
+\r
+\r
+ib_api_status_t\r
+ipoib_set_active(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+void\r
+ipoib_set_inactive(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+ib_api_status_t\r
+ipoib_reset_adapter(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+void\r
+ipoib_reg_addrs(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+void\r
+ipoib_dereg_addrs(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+#define IPOIB_INIT_NDIS_STATUS_INDICATION(_pStatusIndication, _M, _St, _Buf, _BufSize)        \\r
+    {                                                                                      \\r
+        NdisZeroMemory(_pStatusIndication, sizeof(NDIS_STATUS_INDICATION));                \\r
+        (_pStatusIndication)->Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;            \\r
+        (_pStatusIndication)->Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;         \\r
+        (_pStatusIndication)->Header.Size = sizeof(NDIS_STATUS_INDICATION);                \\r
+        (_pStatusIndication)->SourceHandle = _M;                                           \\r
+        (_pStatusIndication)->StatusCode = _St;                                            \\r
+        (_pStatusIndication)->StatusBuffer = _Buf;                                         \\r
+        (_pStatusIndication)->StatusBufferSize = _BufSize;                                 \\r
+    }\r
+\r
+//TODO rename to 4\r
+#define IPOIB_MEDIA_MAX_SPEED  40000000000\r
+\r
+#endif /* _IPOIB_ADAPTER_H_ */\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_debug.h b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_debug.h
new file mode 100644 (file)
index 0000000..69ec3c5
--- /dev/null
@@ -0,0 +1,303 @@
+/*\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: ipoib_debug.h 3719 2009-01-07 12:31:52Z reuven $\r
+ */\r
+\r
+\r
+#ifndef _IPOIB_DEBUG_H_\r
+#define _IPOIB_DEBUG_H_\r
+\r
+#if defined __MODULE__\r
+#undef __MODULE__\r
+#endif\r
+\r
+#define __MODULE__     "[IPoIB]"\r
+\r
+#include <complib/cl_debug.h>\r
+\r
+\r
+/* Object types for passing into complib. */\r
+#define IPOIB_OBJ_INSTANCE             1\r
+#define IPOIB_OBJ_PORT                 2\r
+#define IPOIB_OBJ_ENDPOINT             3\r
+\r
+\r
+extern uint32_t                g_ipoib_dbg_level;\r
+extern uint32_t                g_ipoib_dbg_flags;\r
+\r
+\r
+#if defined(EVENT_TRACING)\r
+//\r
+// Software Tracing Definitions\r
+//\r
+#define WPP_CONTROL_GUIDS \\r
+       WPP_DEFINE_CONTROL_GUID( \\r
+               IPOIBCtlGuid,(3F9BC73D, EB03, 453a, B27B, 20F9A664211A), \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_ERROR) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_INIT) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_PNP) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_SEND) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_RECV) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_ENDPT) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_IB) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_BUF) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_MCAST) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_ALLOC) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_OID) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_IOCTL) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_STAT) \\r
+       WPP_DEFINE_BIT(IPOIB_DBG_OBJ))\r
+\r
+\r
+\r
+#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \\r
+       (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level  >= lvl)\r
+#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags)\r
+#define WPP_FLAG_ENABLED(flags) \\r
+       (WPP_LEVEL_ENABLED(flags) && \\r
+       WPP_CONTROL(WPP_BIT_ ## flags).Level  >= TRACE_LEVEL_VERBOSE)\r
+#define WPP_FLAG_LOGGER(flags) WPP_LEVEL_LOGGER(flags)\r
+\r
+// begin_wpp config\r
+// IPOIB_ENTER(FLAG);\r
+// IPOIB_EXIT(FLAG);\r
+// USEPREFIX(IPOIB_PRINT, "%!STDPREFIX! [IPoIB] :%!FUNC!() :");\r
+// USEPREFIX(IPOIB_PRINT_EXIT, "%!STDPREFIX! [IPoIB] :%!FUNC!() :");\r
+// USESUFFIX(IPOIB_PRINT_EXIT, "[IpoIB] :%!FUNC!():]");\r
+// USESUFFIX(IPOIB_ENTER, " [IPoIB] :%!FUNC!():[");\r
+// USESUFFIX(IPOIB_EXIT, " [IPoIB] :%!FUNC!():]");\r
+// end_wpp\r
+\r
+#else\r
+\r
+#include <evntrace.h>\r
+\r
+\r
+/*\r
+ * Debug macros\r
+ */\r
+#define IPOIB_DBG_ERR  (1 << 0)\r
+#define IPOIB_DBG_INIT (1 << 1)\r
+#define IPOIB_DBG_PNP  (1 << 2)\r
+#define IPOIB_DBG_SEND (1 << 3)\r
+#define IPOIB_DBG_RECV (1 << 4)\r
+#define IPOIB_DBG_ENDPT        (1 << 5)\r
+#define IPOIB_DBG_IB   (1 << 6)\r
+#define IPOIB_DBG_BUF  (1 << 7)\r
+#define IPOIB_DBG_MCAST        (1 << 8)\r
+#define IPOIB_DBG_ALLOC        (1 << 9)\r
+#define IPOIB_DBG_OID  (1 << 10)\r
+#define IPOIB_DBG_IOCTL        (1 << 11)\r
+#define IPOIB_DBG_STAT (1 << 12)\r
+#define IPOIB_DBG_OBJ  (1 << 13)\r
+\r
+#define IPOIB_DBG_ERROR        (CL_DBG_ERROR | IPOIB_DBG_ERR)\r
+#define IPOIB_DBG_ALL  CL_DBG_ALL\r
+\r
+\r
+#if DBG\r
+\r
+// assignment of _level_ is need to to overcome warning C4127\r
+#define IPOIB_PRINT(_level_,_flag_,_msg_) \\r
+       { \\r
+               __pragma(warning(suppress:6326)) \\r
+               if( g_ipoib_dbg_level >= (_level_) ) \\r
+                       CL_TRACE( _flag_, g_ipoib_dbg_flags, _msg_ ); \\r
+       }\r
+\r
+#define IPOIB_PRINT_EXIT(_level_,_flag_,_msg_) \\r
+       { \\r
+               __pragma(warning(suppress:6326)) \\r
+               if( g_ipoib_dbg_level >= (_level_) ) \\r
+                       CL_TRACE( _flag_, g_ipoib_dbg_flags, _msg_ );\\r
+               IPOIB_EXIT(_flag_);\\r
+       }\r
+\r
+#define IPOIB_ENTER(_flag_) \\r
+       { \\r
+               __pragma(warning(suppress:6326)) \\r
+               if( g_ipoib_dbg_level >= TRACE_LEVEL_VERBOSE ) \\r
+                       CL_ENTER( _flag_, g_ipoib_dbg_flags ); \\r
+       }\r
+\r
+#define IPOIB_EXIT(_flag_)\\r
+       { \\r
+               __pragma(warning(suppress:6326)) \\r
+               if( g_ipoib_dbg_level >= TRACE_LEVEL_VERBOSE ) \\r
+                       CL_EXIT( _flag_, g_ipoib_dbg_flags ); \\r
+       }\r
+\r
+#define IPOIB_TRACE_BYTES( lvl, ptr, len )                                                                     \\r
+       {                                                                                                                                               \\r
+               __pragma(warning(suppress:6326))                                                                        \\r
+               if( g_ipoib_dbg_level >= (_level_) &&                                                           \\r
+                       (g_ipoib_dbg_flags & (_flag_)) )                                                                \\r
+               {                                                                                                                                       \\r
+                       size_t _loop_;                                                                                                  \\r
+                       for( _loop_ = 0; _loop_ < (len); ++_loop_ )                                             \\r
+                       {                                                                                                                               \\r
+                               cl_dbg_out( "0x%.2X ", ((uint8_t*)(ptr))[_loop_] );                     \\r
+                               if( (_loop_ + 1)% 16 == 0 )                                                                     \\r
+                                       cl_dbg_out("\n");                                                                                       \\r
+                               else if( (_loop_ % 4 + 1) == 0 )                                                        \\r
+                                       cl_dbg_out("  ");                                                                                       \\r
+                       }                                                                                                                               \\r
+                       cl_dbg_out("\n");                                                                                                       \\r
+               }                                                                                                                                       \\r
+       }\r
+\r
+#else\r
+\r
+#define IPOIB_PRINT(lvl, flags, msg)\r
+\r
+#define IPOIB_PRINT_EXIT(_level_,_flag_,_msg_)\r
+\r
+#define IPOIB_ENTER(_flag_)\r
+\r
+#define IPOIB_EXIT(_flag_)\r
+\r
+#define IPOIB_TRACE_BYTES( lvl, ptr, len )\r
+\r
+#endif\r
+\r
+#endif //EVENT_TRACING\r
+\r
+\r
+enum ipoib_perf_counters\r
+{\r
+       SendBundle,\r
+       SendPackets,\r
+               PortSend,\r
+                       GetEthHdr,\r
+                       SendMgrQueue,\r
+                               GetEndpt,\r
+                                       EndptQueue,\r
+                       QueuePacket,\r
+                       BuildSendDesc,\r
+                               SendMgrFilter,\r
+                                       FilterIp,\r
+                                               QueryIp,\r
+                                               SendTcp,\r
+                                               FilterUdp,\r
+                                                       QueryUdp,\r
+                                                       SendUdp,\r
+                                                       FilterDhcp,\r
+                                       FilterArp,\r
+                                       SendGen,\r
+                                               SendCopy,\r
+                       PostSend,\r
+                       ProcessFailedSends,\r
+       SendCompBundle,\r
+       SendCb,\r
+               PollSend,\r
+               SendComp,\r
+               FreeSendBuf,\r
+               RearmSend,\r
+               PortResume,\r
+       RecvCompBundle,\r
+       RecvCb,\r
+               PollRecv,\r
+               FilterRecv,\r
+                       GetRecvEndpts,\r
+                               GetEndptByGid,\r
+                               GetEndptByLid,\r
+                               EndptInsert,\r
+                       RecvTcp,\r
+                       RecvUdp,\r
+                       RecvDhcp,\r
+                       RecvArp,\r
+                       RecvGen,\r
+       BuildPktArray,\r
+               PreparePkt,\r
+                       GetNdisPkt,\r
+       RecvNdisIndicate,\r
+       PutRecvList,\r
+       RepostRecv,\r
+               GetRecv,\r
+               PostRecv,\r
+       RearmRecv,\r
+               ReturnPacket,\r
+               ReturnPutRecv,\r
+               ReturnRepostRecv,\r
+               ReturnPreparePkt,\r
+               ReturnNdisIndicate,\r
+\r
+       /* Must be last! */\r
+       MaxPerf\r
+\r
+};\r
+\r
+\r
+enum ref_cnt_buckets\r
+{\r
+       ref_init = 0,\r
+       ref_refresh_mcast,      /* only used in refresh_mcast */\r
+       ref_send_packets,       /* only in send_packets */\r
+       ref_get_recv,\r
+       ref_repost,             /* only in __recv_mgr_repost */\r
+       ref_recv_cb,    /* only in __recv_cb */\r
+       ref_send_cb,    /* only in __send_cb */\r
+       ref_port_up,\r
+       ref_get_bcast,\r
+       ref_bcast,              /* join and create, used as base only */\r
+       ref_join_mcast,\r
+       ref_leave_mcast,\r
+       ref_endpt_track,        /* used when endpt is in port's child list. */\r
+\r
+       ref_array_size, /* Used to size the array of ref buckets. */\r
+       ref_mask = 100, /* Used to differentiate derefs. */\r
+\r
+       ref_failed_recv_wc = 100 + ref_get_recv,\r
+       ref_recv_inv_len = 200 + ref_get_recv,\r
+       ref_recv_loopback = 300 + ref_get_recv,\r
+       ref_recv_filter = 400 + ref_get_recv,\r
+\r
+       ref_bcast_get_cb = 100 + ref_get_bcast,\r
+\r
+       ref_join_bcast = 100 + ref_bcast,\r
+       ref_create_bcast = 200 + ref_bcast,\r
+       ref_bcast_inv_state = 300 + ref_bcast,\r
+       ref_bcast_req_failed = 400 + ref_bcast,\r
+       ref_bcast_error = 500 + ref_bcast,\r
+       ref_bcast_join_failed = 600 + ref_bcast,\r
+       ref_bcast_create_failed = 700 + ref_bcast,\r
+\r
+       ref_mcast_inv_state = 100 + ref_join_mcast,\r
+       ref_mcast_req_failed = 200 + ref_join_mcast,\r
+       ref_mcast_no_endpt = 300 + ref_join_mcast,\r
+       ref_mcast_av_failed = 400 + ref_join_mcast,\r
+       ref_mcast_join_failed = 500 + ref_join_mcast,\r
+\r
+       ref_port_info_cb = 100 + ref_port_up\r
+\r
+};\r
+\r
+\r
+#endif /* _IPOIB_DEBUG_H_ */\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.c b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.c
new file mode 100644 (file)
index 0000000..0bc3ebd
--- /dev/null
@@ -0,0 +1,4708 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_driver.c 4506 2009-06-23 14:40:54Z xalex $\r
+ */\r
+\r
+#include "limits.h"\r
+#include "ipoib_driver.h"\r
+#include "ipoib_debug.h"\r
+\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_driver.tmh"\r
+#endif\r
+\r
+#include "ipoib_port.h"\r
+#include "ipoib_ibat.h"\r
+#include <complib/cl_bus_ifc.h>\r
+#include <complib/cl_init.h>\r
+#include <initguid.h>\r
+#include <iba/ipoib_ifc.h>\r
+#include "ntstrsafe.h"\r
+#include "strsafe.h"\r
+#include <offload.h>\r
+\r
+\r
+\r
+#define MAJOR_DRIVER_VERSION 2\r
+#define MINOR_DRIVER_VERSION 1\r
+#if defined(NDIS60_MINIPORT)\r
+#define MAJOR_NDIS_VERSION 6\r
+#define MINOR_NDIS_VERSION 0\r
+\r
+#else\r
+#error NDIS Version not defined, try defining NDIS60_MINIPORT\r
+#endif\r
+\r
+PDRIVER_OBJECT                         g_p_drv_obj;\r
+\r
+\r
+#if 0\r
+static const NDIS_OID SUPPORTED_OIDS[] =\r
+{\r
+       OID_GEN_SUPPORTED_LIST,\r
+       OID_GEN_HARDWARE_STATUS,\r
+       OID_GEN_MEDIA_SUPPORTED,\r
+       OID_GEN_MEDIA_IN_USE,\r
+       OID_GEN_MAXIMUM_LOOKAHEAD,\r
+       OID_GEN_MAXIMUM_FRAME_SIZE,\r
+       OID_GEN_LINK_SPEED,\r
+       OID_GEN_TRANSMIT_BUFFER_SPACE,\r
+       OID_GEN_RECEIVE_BUFFER_SPACE,\r
+       OID_GEN_TRANSMIT_BLOCK_SIZE,\r
+       OID_GEN_RECEIVE_BLOCK_SIZE,\r
+       OID_GEN_VENDOR_ID,\r
+       OID_GEN_VENDOR_DESCRIPTION,\r
+       OID_GEN_CURRENT_PACKET_FILTER,\r
+       OID_GEN_CURRENT_LOOKAHEAD,\r
+       OID_GEN_DRIVER_VERSION,\r
+       OID_GEN_MAXIMUM_TOTAL_SIZE,\r
+       OID_GEN_PROTOCOL_OPTIONS,\r
+       OID_GEN_MAC_OPTIONS,\r
+       OID_GEN_MEDIA_CONNECT_STATUS,\r
+       OID_GEN_MAXIMUM_SEND_PACKETS,\r
+       OID_GEN_NETWORK_LAYER_ADDRESSES,\r
+       OID_GEN_VENDOR_DRIVER_VERSION,\r
+       OID_GEN_PHYSICAL_MEDIUM,\r
+       OID_GEN_XMIT_OK,\r
+       OID_GEN_RCV_OK,\r
+       OID_GEN_XMIT_ERROR,\r
+       OID_GEN_RCV_ERROR,\r
+       OID_GEN_RCV_NO_BUFFER,\r
+       OID_GEN_DIRECTED_BYTES_XMIT,\r
+       OID_GEN_DIRECTED_FRAMES_XMIT,\r
+       OID_GEN_MULTICAST_BYTES_XMIT,\r
+       OID_GEN_MULTICAST_FRAMES_XMIT,\r
+       OID_GEN_BROADCAST_BYTES_XMIT,\r
+       OID_GEN_BROADCAST_FRAMES_XMIT,\r
+       OID_GEN_DIRECTED_BYTES_RCV,\r
+       OID_GEN_DIRECTED_FRAMES_RCV,\r
+       OID_GEN_MULTICAST_BYTES_RCV,\r
+       OID_GEN_MULTICAST_FRAMES_RCV,\r
+       OID_GEN_BROADCAST_BYTES_RCV,\r
+       OID_GEN_BROADCAST_FRAMES_RCV,\r
+       OID_802_3_PERMANENT_ADDRESS,\r
+       OID_802_3_CURRENT_ADDRESS,\r
+       OID_802_3_MULTICAST_LIST,\r
+       OID_802_3_MAXIMUM_LIST_SIZE,\r
+       OID_802_3_MAC_OPTIONS,\r
+       OID_802_3_RCV_ERROR_ALIGNMENT,\r
+       OID_802_3_XMIT_ONE_COLLISION,\r
+       OID_802_3_XMIT_MORE_COLLISIONS,\r
+       OID_TCP_TASK_OFFLOAD\r
+};\r
+#endif\r
+\r
+NDIS_OID NICSupportedOidsTest[] =\r
+{\r
+    OID_GEN_SUPPORTED_LIST,\r
+    OID_GEN_HARDWARE_STATUS,\r
+    OID_GEN_MEDIA_SUPPORTED,\r
+    OID_GEN_MEDIA_IN_USE,\r
+    OID_GEN_MAXIMUM_LOOKAHEAD,\r
+    OID_GEN_MAXIMUM_FRAME_SIZE,\r
+    OID_GEN_TRANSMIT_BUFFER_SPACE,\r
+    OID_GEN_RECEIVE_BUFFER_SPACE,\r
+    OID_GEN_TRANSMIT_BLOCK_SIZE,\r
+    OID_GEN_RECEIVE_BLOCK_SIZE,\r
+    OID_GEN_VENDOR_ID,\r
+    OID_GEN_VENDOR_DESCRIPTION,\r
+    OID_GEN_VENDOR_DRIVER_VERSION,\r
+    OID_GEN_CURRENT_PACKET_FILTER,\r
+    OID_GEN_CURRENT_LOOKAHEAD,\r
+    OID_GEN_DRIVER_VERSION,\r
+    OID_GEN_MAXIMUM_TOTAL_SIZE,\r
+    OID_GEN_MAC_OPTIONS,\r
+    OID_GEN_MAXIMUM_SEND_PACKETS,\r
+    OID_GEN_XMIT_OK,\r
+    OID_GEN_RCV_OK,\r
+    OID_GEN_XMIT_ERROR,\r
+    OID_GEN_RCV_ERROR,\r
+    OID_GEN_RCV_NO_BUFFER,\r
+    OID_GEN_RCV_CRC_ERROR,\r
+    OID_GEN_TRANSMIT_QUEUE_LENGTH,\r
+    OID_802_3_PERMANENT_ADDRESS,\r
+    OID_802_3_CURRENT_ADDRESS,\r
+    OID_802_3_MULTICAST_LIST,\r
+    OID_802_3_MAXIMUM_LIST_SIZE,\r
+    OID_802_3_RCV_ERROR_ALIGNMENT,\r
+    OID_802_3_XMIT_ONE_COLLISION,\r
+    OID_802_3_XMIT_MORE_COLLISIONS,\r
+    OID_802_3_XMIT_DEFERRED,\r
+    OID_802_3_XMIT_MAX_COLLISIONS,\r
+    OID_802_3_RCV_OVERRUN,\r
+    OID_802_3_XMIT_UNDERRUN,\r
+    OID_802_3_XMIT_HEARTBEAT_FAILURE,\r
+    OID_802_3_XMIT_TIMES_CRS_LOST,\r
+    OID_802_3_XMIT_LATE_COLLISIONS,\r
+\r
+#if !BUILD_W2K\r
+    OID_GEN_PHYSICAL_MEDIUM,\r
+#endif\r
+\r
+    OID_TCP_TASK_OFFLOAD,\r
+    \r
+/* powermanagement */\r
+\r
+    OID_PNP_CAPABILITIES,\r
+    OID_PNP_SET_POWER,\r
+    OID_PNP_QUERY_POWER,\r
+    OID_PNP_ADD_WAKE_UP_PATTERN,\r
+    OID_PNP_REMOVE_WAKE_UP_PATTERN,\r
+    OID_PNP_ENABLE_WAKE_UP,\r
+\r
+\r
+/* custom oid WMI support */\r
+//    OID_CUSTOM_PERF_COUNTERS,\r
+ //   OID_CUSTOM_STRING,\r
+\r
+    OID_GEN_RECEIVE_SCALE_CAPABILITIES,\r
+    OID_GEN_RECEIVE_SCALE_PARAMETERS,\r
+\r
+//\r
+// new and required for NDIS 6 miniports\r
+//\r
+    OID_GEN_LINK_PARAMETERS,\r
+    OID_GEN_INTERRUPT_MODERATION,\r
+    OID_GEN_STATISTICS,\r
+\r
+/* Offload */\r
+    OID_TCP_OFFLOAD_CURRENT_CONFIG,\r
+    OID_TCP_OFFLOAD_PARAMETERS,\r
+    OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES,\r
+    OID_OFFLOAD_ENCAPSULATION,\r
+\r
+/* Header - Data seperation */\r
+   // OID_GEN_HD_SPLIT_PARAMETERS,\r
+ //   OID_GEN_HD_SPLIT_CURRENT_CONFIG,\r
+    \r
+/* VLAN */\r
+  //  OID_ADD_VALN_ID,\r
+ //   OID_DELETE_VLAN_ID,\r
+\r
+/* Set MAC */\r
+  //  OID_SET_MAC_ADDRESS\r
+\r
+};\r
+\r
+static const NDIS_OID SUPPORTED_OIDS[] =\r
+{\r
+    OID_GEN_SUPPORTED_LIST,\r
+    OID_GEN_HARDWARE_STATUS,\r
+    OID_GEN_MEDIA_SUPPORTED,\r
+    OID_GEN_MEDIA_IN_USE,\r
+    OID_GEN_MAXIMUM_LOOKAHEAD,\r
+    OID_GEN_MAXIMUM_FRAME_SIZE,\r
+    OID_GEN_TRANSMIT_BUFFER_SPACE,\r
+    OID_GEN_RECEIVE_BUFFER_SPACE,\r
+    OID_GEN_TRANSMIT_BLOCK_SIZE,\r
+    OID_GEN_RECEIVE_BLOCK_SIZE,\r
+    OID_GEN_VENDOR_ID,\r
+    OID_GEN_VENDOR_DESCRIPTION,\r
+    OID_GEN_VENDOR_DRIVER_VERSION,\r
+    OID_GEN_CURRENT_PACKET_FILTER,\r
+    OID_GEN_CURRENT_LOOKAHEAD,\r
+    OID_GEN_DRIVER_VERSION,\r
+    OID_GEN_MAXIMUM_TOTAL_SIZE,\r
+    OID_GEN_MAC_OPTIONS,\r
+    OID_GEN_MAXIMUM_SEND_PACKETS,\r
+    OID_GEN_XMIT_OK,\r
+    OID_GEN_RCV_OK,\r
+    OID_GEN_XMIT_ERROR,\r
+    OID_GEN_RCV_ERROR,\r
+    OID_GEN_RCV_NO_BUFFER,\r
+    OID_GEN_RCV_CRC_ERROR,\r
+    OID_GEN_TRANSMIT_QUEUE_LENGTH,\r
+    OID_802_3_PERMANENT_ADDRESS,\r
+    OID_802_3_CURRENT_ADDRESS,\r
+    OID_802_3_MULTICAST_LIST,\r
+    OID_802_3_MAXIMUM_LIST_SIZE,\r
+    OID_802_3_RCV_ERROR_ALIGNMENT,\r
+    OID_802_3_XMIT_ONE_COLLISION,\r
+    OID_802_3_XMIT_MORE_COLLISIONS,\r
+    OID_802_3_XMIT_DEFERRED,\r
+    OID_802_3_XMIT_MAX_COLLISIONS,\r
+    OID_802_3_RCV_OVERRUN,\r
+    OID_802_3_XMIT_UNDERRUN,\r
+    OID_802_3_XMIT_HEARTBEAT_FAILURE,\r
+    OID_802_3_XMIT_TIMES_CRS_LOST,\r
+    OID_802_3_XMIT_LATE_COLLISIONS,\r
+\r
+#if !BUILD_W2K\r
+    OID_GEN_PHYSICAL_MEDIUM,\r
+#endif\r
+\r
+    OID_TCP_TASK_OFFLOAD,\r
+    \r
+/* powermanagement */\r
+\r
+    OID_PNP_CAPABILITIES,\r
+    OID_PNP_SET_POWER,\r
+    OID_PNP_QUERY_POWER,\r
+    OID_PNP_ADD_WAKE_UP_PATTERN,\r
+    OID_PNP_REMOVE_WAKE_UP_PATTERN,\r
+    OID_PNP_ENABLE_WAKE_UP,\r
+\r
+#if 0\r
+/* custom oid WMI support */\r
+    OID_CUSTOM_PERF_COUNTERS,\r
+    OID_CUSTOM_STRING,\r
+#endif\r
+\r
+    OID_GEN_RECEIVE_SCALE_CAPABILITIES,\r
+    OID_GEN_RECEIVE_SCALE_PARAMETERS,\r
+   \r
+\r
+//\r
+// new and required for NDIS 6 miniports\r
+//\r
+    OID_GEN_LINK_PARAMETERS,\r
+    OID_GEN_INTERRUPT_MODERATION,\r
+    OID_GEN_STATISTICS,\r
+\r
+/* Offload */\r
+    OID_TCP_OFFLOAD_CURRENT_CONFIG,\r
+    OID_TCP_OFFLOAD_PARAMETERS,\r
+    OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES,\r
+    OID_OFFLOAD_ENCAPSULATION,\r
+    \r
+#if 0\r
+\r
+/* Header - Data seperation */\r
+    OID_GEN_HD_SPLIT_PARAMETERS,\r
+    OID_GEN_HD_SPLIT_CURRENT_CONFIG,\r
+\r
+/* VLAN */\r
+    OID_ADD_VALN_ID,\r
+    OID_DELETE_VLAN_ID,\r
+\r
+\r
+/* Set MAC */\r
+    OID_SET_MAC_ADDRESS\r
+#endif\r
+\r
+};\r
+\r
+static const unsigned char VENDOR_ID[] = {0x00, 0x06, 0x6A, 0x00};\r
+\r
+#define VENDOR_DESCRIPTION "Internet Protocol over InfiniBand"\r
+\r
+#define IB_INFINITE_SERVICE_LEASE      0xFFFFFFFF\r
+\r
+//The mask is 8 bit and can't contain more than 6 non-zero bits\r
+#define MAX_GUID_MAX 0xFC\r
+\r
+\r
+/* Global driver debug level */\r
+uint32_t               g_ipoib_dbg_level = TRACE_LEVEL_ERROR;\r
+uint32_t               g_ipoib_dbg_flags = 0x00000fff;\r
+ipoib_globals_t        g_ipoib = {0};\r
+NDIS_HANDLE            g_IpoibMiniportDriverHandle = NULL;\r
+NDIS_HANDLE            g_IpoibDriverContext = NULL;\r
+\r
+\r
+\r
+typedef struct _IPOIB_REG_ENTRY\r
+{\r
+       NDIS_STRING RegName;                // variable name text\r
+       BOOLEAN     bRequired;              // 1 -> required, 0 -> optional\r
+       UINT        FieldOffset;            // offset in parent struct\r
+       UINT        FieldSize;              // size (in bytes) of the field\r
+       UINT        Default;                // default value to use\r
+       UINT        Min;                    // minimum value allowed\r
+       UINT        Max;                    // maximum value allowed\r
+} IPOIB_REG_ENTRY, *PIPOIB_REG_ENTRY;\r
+\r
+IPOIB_REG_ENTRY HCARegTable[] = {\r
+       // reg value name             If Required  Offset in parentr struct             Field size                  Default         Min     Max\r
+       {NDIS_STRING_CONST("GUIDMask"),         0, IPOIB_OFFSET(guid_mask),             IPOIB_SIZE(guid_mask),          0,          0,    MAX_GUID_MAX},\r
+       /* GUIDMask should be the first element */\r
+       {NDIS_STRING_CONST("RqDepth"),          1, IPOIB_OFFSET(rq_depth),              IPOIB_SIZE(rq_depth),           512,        128,    1024},\r
+       {NDIS_STRING_CONST("RqLowWatermark"),   0, IPOIB_OFFSET(rq_low_watermark),      IPOIB_SIZE(rq_low_watermark),   4,          2,      8},\r
+       {NDIS_STRING_CONST("SqDepth"),          1, IPOIB_OFFSET(sq_depth),              IPOIB_SIZE(sq_depth),           512,        128,    1024},\r
+       {NDIS_STRING_CONST("SendChksum"),       1, IPOIB_OFFSET(send_chksum_offload),   IPOIB_SIZE(send_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS},\r
+       {NDIS_STRING_CONST("RecvChksum"),       1, IPOIB_OFFSET(recv_chksum_offload),   IPOIB_SIZE(recv_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS},\r
+       {NDIS_STRING_CONST("SaTimeout"),        1, IPOIB_OFFSET(sa_timeout),            IPOIB_SIZE(sa_timeout),         1000,       250,    UINT_MAX},\r
+       {NDIS_STRING_CONST("SaRetries"),        1, IPOIB_OFFSET(sa_retry_cnt),          IPOIB_SIZE(sa_retry_cnt),       10,         1,      UINT_MAX},\r
+       {NDIS_STRING_CONST("RecvRatio"),        1, IPOIB_OFFSET(recv_pool_ratio),       IPOIB_SIZE(recv_pool_ratio),    1,          1,      10},\r
+       {NDIS_STRING_CONST("PayloadMtu"),       1, IPOIB_OFFSET(payload_mtu),           IPOIB_SIZE(payload_mtu),        2044,       512,   MAX_UD_PAYLOAD_MTU},\r
+       {NDIS_STRING_CONST("lso"),              0, IPOIB_OFFSET(lso),                   IPOIB_SIZE(lso),                0,          0,      1},\r
+       {NDIS_STRING_CONST("MCLeaveRescan"),    1, IPOIB_OFFSET(mc_leave_rescan),       IPOIB_SIZE(mc_leave_rescan),    260,        1,    3600},\r
+       {NDIS_STRING_CONST("BCJoinRetry"),          1, IPOIB_OFFSET(bc_join_retry),                 IPOIB_SIZE(bc_join_retry),      50,         0,    1000},\r
+       {NDIS_STRING_CONST("CmEnabled"),        0, IPOIB_OFFSET(cm_enabled),            IPOIB_SIZE(cm_enabled),         FALSE,     FALSE, TRUE},\r
+       {NDIS_STRING_CONST("CmPayloadMtu"),     1, IPOIB_OFFSET(cm_payload_mtu),        IPOIB_SIZE(cm_payload_mtu),     MAX_CM_PAYLOAD_MTU, 512, MAX_CM_PAYLOAD_MTU}\r
+\r
+};  \r
+\r
+#define IPOIB_NUM_REG_PARAMS (sizeof (HCARegTable) / sizeof(IPOIB_REG_ENTRY))\r
+\r
+\r
+void\r
+ipoib_create_log(\r
+       NDIS_HANDLE h_adapter,\r
+       UINT ind,\r
+       ULONG eventLogMsgId)\r
+\r
+{\r
+#define cMaxStrLen  40\r
+#define cArrLen  3\r
+\r
+       PWCHAR logMsgArray[cArrLen]; \r
+       WCHAR strVal[cMaxStrLen];\r
+       NDIS_STRING AdapterInstanceName;\r
+\r
+       IPOIB_INIT_NDIS_STRING(&AdapterInstanceName);\r
+       if (NdisMQueryAdapterInstanceName(&AdapterInstanceName, h_adapter)!= NDIS_STATUS_SUCCESS ){\r
+               ASSERT(FALSE);\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR, ("[IPoIB] Init:Failed to retreive adapter name.\n"));\r
+               return;\r
+       }\r
+       logMsgArray[0] = AdapterInstanceName.Buffer;\r
+       \r
+       if (RtlStringCbPrintfW(strVal, sizeof(strVal), L"0x%x", HCARegTable[ind].Default) != STATUS_SUCCESS) {\r
+               ASSERT(FALSE);\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,\r
+               ("[IPoIB] Init: Problem copying string value: exiting\n"));   \r
+               return;\r
+       }\r
+       \r
+       logMsgArray[0] = AdapterInstanceName.Buffer;\r
+       logMsgArray[1] = HCARegTable[ind].RegName.Buffer;\r
+       logMsgArray[2] = strVal;\r
+       \r
+       NdisWriteEventLogEntry(g_p_drv_obj, eventLogMsgId, 0, cArrLen, &logMsgArray, 0, NULL);\r
+\r
+}\r
+\r
+\r
+\r
+NTSTATUS\r
+DriverEntry(\r
+       IN                              PDRIVER_OBJECT                          p_drv_obj,\r
+       IN                              PUNICODE_STRING                         p_reg_path );\r
+\r
+VOID\r
+ipoib_unload(\r
+       IN                              PDRIVER_OBJECT                          p_drv_obj );\r
+\r
+NDIS_STATUS\r
+ipoib_initialize_ex(\r
+       IN                              NDIS_HANDLE                     h_adapter,\r
+    IN                                 NDIS_HANDLE             config_context,\r
+    IN PNDIS_MINIPORT_INIT_PARAMETERS  MiniportInitParameters);\r
+\r
+NDIS_STATUS \r
+MPInitializeTest(\r
+    IN  NDIS_HANDLE                        MiniportAdapterHandle,\r
+    IN  NDIS_HANDLE                        MiniportDriverContext,\r
+    IN  PNDIS_MINIPORT_INIT_PARAMETERS     MiniportInitParameters\r
+    );\r
+\r
+\r
+\r
+BOOLEAN\r
+ipoib_check_for_hang(\r
+       IN                              NDIS_HANDLE                                     adapter_context );\r
+\r
+void\r
+ipoib_halt_ex(\r
+       IN NDIS_HANDLE  adapter_context,\r
+       IN                      NDIS_HALT_ACTION            HaltAction);\r
+\r
+NDIS_STATUS\r
+ipoib_query_info(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              NDIS_OID                                        oid,\r
+       IN                              PVOID                                           info_buf,\r
+       IN                              ULONG                                           info_buf_len,\r
+               OUT                     PULONG                                          p_bytes_written,\r
+               OUT                     PULONG                                          p_bytes_needed );\r
+\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_reset(\r
+    IN  NDIS_HANDLE     adapter_context,\r
+    OUT PBOOLEAN        p_addr_reset);\r
+\r
+NDIS_STATUS\r
+ipoib_set_info(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              NDIS_OID                                        oid,\r
+       IN                              PVOID                                           info_buf,\r
+       IN                              ULONG                                           info_buf_length,\r
+               OUT                     PULONG                                          p_bytes_read,\r
+               OUT                     PULONG                                          p_bytes_needed );\r
+\r
+//NDIS60\r
+void\r
+ipoib_send_net_buffer_list(\r
+    IN  NDIS_HANDLE         adapter_context,\r
+    IN  PNET_BUFFER_LIST    net_buffer_list,\r
+    IN  NDIS_PORT_NUMBER    port_num,\r
+    IN  ULONG               send_flags);\r
+\r
+void\r
+ipoib_pnp_notify(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN PNET_DEVICE_PNP_EVENT  pnp_event);\r
+\r
+VOID\r
+ipoib_shutdown_ex(\r
+       IN NDIS_HANDLE  adapter_context,\r
+       IN NDIS_SHUTDOWN_ACTION  shutdown_action);\r
+\r
+\r
+void\r
+ipoib_cancel_xmit(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              PVOID                                           cancel_id );\r
+\r
+\r
+static void\r
+ipoib_complete_query(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              pending_oid_t* const            p_oid_info,\r
+       IN              const   NDIS_STATUS                                     status,\r
+       IN              const   void* const                                     p_buf,\r
+       IN              const   ULONG                                           buf_len );\r
+\r
+static NDIS_STATUS\r
+__ipoib_set_net_addr(\r
+       IN              ipoib_adapter_t *       p_adapter,\r
+       IN              PVOID                           info_buf,\r
+       IN              ULONG                           info_buf_len,\r
+               OUT     PULONG                          p_bytes_read,\r
+               OUT     PULONG                          p_bytes_needed );\r
+\r
+static NDIS_STATUS\r
+__ipoib_get_tcp_task_offload(\r
+       IN                              ipoib_adapter_t*                        p_adapter,\r
+       OUT                             pending_oid_t                           *pNdisRequest);\r
+\r
+static void\r
+__ipoib_ats_reg_cb(\r
+       IN                              ib_reg_svc_rec_t                        *p_reg_svc_rec );\r
+\r
+static void\r
+__ipoib_ats_dereg_cb(\r
+       IN                              void                                            *context );\r
+\r
+static NTSTATUS\r
+__ipoib_read_registry(\r
+       IN                              UNICODE_STRING* const           p_registry_path );\r
+\r
+static NDIS_STATUS\r
+ipoib_set_options(\r
+    IN NDIS_HANDLE  NdisMiniportDriverHandle,\r
+    IN NDIS_HANDLE  MiniportDriverContext);\r
+\r
+static NDIS_STATUS\r
+ipoib_oid_handler(\r
+    IN  NDIS_HANDLE         adapter_context,\r
+    IN  PNDIS_OID_REQUEST   pNdisRequest);\r
+\r
+static void\r
+ipoib_cancel_oid_request(\r
+    IN  NDIS_HANDLE            adapter_context,\r
+    IN  PVOID                  requestId);\r
+        \r
+static NDIS_STATUS \r
+ipoib_pause(\r
+    IN  NDIS_HANDLE                         adapter_context,    \r
+    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS     pause_parameters);\r
+\r
+static NDIS_STATUS \r
+ipoib_restart(\r
+    IN  NDIS_HANDLE                         adapter_context,    \r
+    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   restart_parameters);\r
+\r
+\r
+\r
+//! Standard Windows Device Driver Entry Point\r
+/*! DriverEntry is the first routine called after a driver is loaded, and\r
+is responsible for initializing the driver.  On W2k this occurs when the PnP\r
+Manager matched a PnP ID to one in an INF file that references this driver.\r
+Any not success return value will cause the driver to fail to load.\r
+IRQL = PASSIVE_LEVEL\r
+\r
+@param p_drv_obj Pointer to Driver Object for this device driver\r
+@param p_registry_path Pointer to unicode string containing path to this driver's registry area\r
+@return STATUS_SUCCESS, NDIS_STATUS_BAD_CHARACTERISTICS, NDIS_STATUS_BAD_VERSION,\r
+NDIS_STATUS_RESOURCES, or NDIS_STATUS_FAILURE\r
+*/\r
+NTSTATUS\r
+DriverEntry(\r
+       IN                              PDRIVER_OBJECT                          p_drv_obj,\r
+       IN                              PUNICODE_STRING                         p_registry_path )\r
+{\r
+       NDIS_STATUS                                             status;\r
+       NDIS_MINIPORT_DRIVER_CHARACTERISTICS characteristics;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       g_p_drv_obj = p_drv_obj;\r
+\r
+#ifdef _DEBUG_\r
+       PAGED_CODE();\r
+#endif\r
+#if defined(EVENT_TRACING)\r
+       WPP_INIT_TRACING(p_drv_obj, p_registry_path);\r
+#endif\r
+       status = CL_INIT;\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_init failed.\n") );\r
+               return status;\r
+       }\r
+\r
+       __ipoib_read_registry(p_registry_path);\r
+       \r
+       KeInitializeSpinLock( &g_ipoib.lock );\r
+       cl_qlist_init( &g_ipoib.adapter_list );\r
+\r
+    NdisZeroMemory(&characteristics, sizeof(characteristics));\r
+\r
+    characteristics.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS,\r
+    characteristics.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS);\r
+    characteristics.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;\r
+\r
+       characteristics.MajorNdisVersion                = MAJOR_NDIS_VERSION;\r
+       characteristics.MinorNdisVersion                = MINOR_NDIS_VERSION;\r
+    characteristics.MajorDriverVersion         = MAJOR_DRIVER_VERSION;\r
+    characteristics.MinorDriverVersion         = MINOR_DRIVER_VERSION;\r
+\r
+\r
+       characteristics.CheckForHangHandlerEx           = ipoib_check_for_hang;\r
+       characteristics.HaltHandlerEx                           = ipoib_halt_ex;\r
+       characteristics.InitializeHandlerEx             = ipoib_initialize_ex;// MPInitializeTest\r
+       characteristics.OidRequestHandler                       = ipoib_oid_handler;\r
+       characteristics.CancelOidRequestHandler         = ipoib_cancel_oid_request;\r
+       characteristics.ResetHandlerEx                          = ipoib_reset;\r
+       characteristics.DevicePnPEventNotifyHandler     = ipoib_pnp_notify;\r
+       characteristics.ReturnNetBufferListsHandler     = ipoib_return_net_buffer_list;\r
+       characteristics.SendNetBufferListsHandler       = ipoib_send_net_buffer_list;\r
+\r
+       characteristics.SetOptionsHandler                       = ipoib_set_options;\r
+       characteristics.PauseHandler                            = ipoib_pause;\r
+       characteristics.RestartHandler                          = ipoib_restart;\r
+       characteristics.UnloadHandler                           = ipoib_unload;\r
+       characteristics.CancelSendHandler                       = ipoib_cancel_xmit;\r
+       characteristics.ShutdownHandlerEx                       = ipoib_shutdown_ex;\r
+\r
+\r
+\r
+//TODO NDIS60 set g_ prefix to global variables\r
+       status = NdisMRegisterMiniportDriver(\r
+               p_drv_obj, p_registry_path,(PNDIS_HANDLE)&g_IpoibDriverContext, &characteristics,&g_IpoibMiniportDriverHandle );\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
+                       ("NdisMRegisterMiniportDriver failed with status of %d\n", status) );\r
+               CL_DEINIT;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+static NDIS_STATUS\r
+ipoib_set_options(\r
+    IN NDIS_HANDLE  NdisMiniportDriverHandle,\r
+    IN NDIS_HANDLE  MiniportDriverContext\r
+    )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+    UNREFERENCED_PARAMETER(NdisMiniportDriverHandle);\r
+    UNREFERENCED_PARAMETER(MiniportDriverContext);\r
+   \r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+    return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static NTSTATUS\r
+__ipoib_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[4];\r
+       UNICODE_STRING                                  param_path;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\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
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_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"DebugLevel";\r
+       table[0].EntryContext = &g_ipoib_dbg_level;\r
+       table[0].DefaultType = REG_DWORD;\r
+       table[0].DefaultData = &g_ipoib_dbg_level;\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 = &g_ipoib_dbg_flags;\r
+       table[1].DefaultType = REG_DWORD;\r
+       table[1].DefaultData = &g_ipoib_dbg_flags;\r
+       table[1].DefaultLength = sizeof(ULONG);\r
+\r
+       table[2].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
+       table[2].Name = L"bypass_check_bcast_rate";\r
+       table[2].EntryContext = &g_ipoib.bypass_check_bcast_rate;\r
+       table[2].DefaultType = REG_DWORD;\r
+       table[2].DefaultData = &g_ipoib.bypass_check_bcast_rate;\r
+       table[2].DefaultLength = sizeof(ULONG);\r
+\r
+       /* Have at it! */\r
+       status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
+               param_path.Buffer, table, NULL, NULL );\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("debug level %d debug flags 0x%.8x\n",\r
+                       g_ipoib_dbg_level,\r
+                       g_ipoib_dbg_flags));\r
+\r
+#if DBG\r
+       if( g_ipoib_dbg_flags & IPOIB_DBG_ERR )\r
+               g_ipoib_dbg_flags |= CL_DBG_ERROR;\r
+#endif\r
+\r
+       cl_free( param_path.Buffer );\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+VOID\r
+ipoib_unload(\r
+       IN                              PDRIVER_OBJECT                          p_drv_obj )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       UNREFERENCED_PARAMETER(p_drv_obj);\r
+       #if defined(EVENT_TRACING)\r
+       WPP_CLEANUP(p_drv_obj);\r
+       #endif\r
+       //NDIS6.0\r
+       NdisMDeregisterMiniportDriver(g_IpoibMiniportDriverHandle);\r
+       UNREFERENCED_PARAMETER( p_drv_obj );\r
+       CL_DEINIT;\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_get_adapter_params(\r
+       IN                              NDIS_HANDLE* const                      wrapper_config_context,\r
+       IN      OUT                     ipoib_adapter_t                         *p_adapter,\r
+       OUT                             PUCHAR                                          *p_mac,\r
+       OUT                             UINT                                            *p_len)\r
+{\r
+       NDIS_STATUS                                             status;\r
+       NDIS_HANDLE                                             h_config;\r
+    NDIS_CONFIGURATION_OBJECT          config_obj;\r
+       NDIS_CONFIGURATION_PARAMETER    *p_param;\r
+       UINT                                                    value;\r
+       PIPOIB_REG_ENTRY                                pRegEntry;\r
+       UINT                                                    i;\r
+       PUCHAR                                                  structPointer;\r
+       \r
+       int sq_depth_step = 128;\r
+\r
+       UNUSED_PARAM(wrapper_config_context);\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+    config_obj.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;\r
+    config_obj.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;\r
+    config_obj.Header.Size = sizeof(NDIS_CONFIGURATION_OBJECT);\r
+    config_obj.NdisHandle = p_adapter->h_adapter;\r
+    config_obj.Flags = 0;\r
+\r
+       status = NdisOpenConfigurationEx( &config_obj, &h_config);\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisOpenConfigurationEx returned 0x%.8x\n", status) );\r
+               return status;\r
+       }\r
+\r
+       // read all the registry values \r
+       for (i = 0, pRegEntry = HCARegTable; i < IPOIB_NUM_REG_PARAMS; ++i)\r
+       {\r
+               // initialize pointer to appropriate place inside 'params'\r
+               structPointer = (PUCHAR) &p_adapter->params + pRegEntry[i].FieldOffset;\r
+\r
+               // Get the configuration value for a specific parameter.  Under NT the\r
+               // parameters are all read in as DWORDs.\r
+               NdisReadConfiguration(\r
+                       &status,\r
+                       &p_param,\r
+                       h_config,\r
+                       &pRegEntry[i].RegName,\r
+                       NdisParameterInteger);\r
+\r
+               // If the parameter was present, then check its value for validity.\r
+               if (status == NDIS_STATUS_SUCCESS)\r
+               {\r
+                       // Check that param value is not too small or too large\r
+                       if (p_param->ParameterData.IntegerData < pRegEntry[i].Min ||\r
+                               p_param->ParameterData.IntegerData > pRegEntry[i].Max)\r
+                       {\r
+                               value = pRegEntry[i].Default;\r
+                               ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+                               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration.Registry %S value is out of range, setting default value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));                                \r
+\r
+                       }\r
+                       else\r
+                       {\r
+                               value = p_param->ParameterData.IntegerData;\r
+                               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));\r
+                       }\r
+               }\r
+\r
+               else\r
+               {\r
+                       value = pRegEntry[i].Default;\r
+                       status = NDIS_STATUS_SUCCESS;\r
+                       if (pRegEntry[i].bRequired)\r
+                       {\r
+                               ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_ERR);\r
+                               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, ("Read configuration.Registry %S value not found, setting default value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));\r
+                       }\r
+                       else\r
+                       {\r
+                               ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_INFO);\r
+                               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S value not found, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));\r
+                       }\r
+\r
+               }\r
+               //\r
+               // Store the value in the adapter structure.\r
+               //\r
+               switch(pRegEntry[i].FieldSize)\r
+               {\r
+                       case 1:\r
+                               *((PUCHAR) structPointer) = (UCHAR) value;\r
+                               break;\r
+\r
+                       case 2:\r
+                               *((PUSHORT) structPointer) = (USHORT) value;\r
+                               break;\r
+\r
+                       case 4:\r
+                               *((PULONG) structPointer) = (ULONG) value;\r
+                               break;\r
+\r
+                       default:\r
+                               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Bogus field size %d\n", pRegEntry[i].FieldSize));\r
+                               break;\r
+               }\r
+       }\r
+\r
+       // Send queue depth needs to be a power of two\r
+       //static const INT sq_depth_step = 128;\r
+\r
+       if (p_adapter->params.sq_depth % sq_depth_step) {\r
+               static const c_sq_ind = 2;\r
+               p_adapter->params.sq_depth = sq_depth_step *(\r
+                       p_adapter->params.sq_depth / sq_depth_step + !!( (p_adapter->params.sq_depth % sq_depth_step) > (sq_depth_step/2) ));\r
+               ipoib_create_log(p_adapter->h_adapter, c_sq_ind, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("SQ DEPTH value was rounded to the closest acceptable value of  0x%x\n", p_adapter->params.sq_depth ));\r
+\r
+       }\r
+\r
+\r
+       // Adjusting the low watermark parameter\r
+       p_adapter->params.rq_low_watermark =\r
+                       p_adapter->params.rq_depth / p_adapter->params.rq_low_watermark;\r
+       \r
+       /* disable CM if LSO is active */\r
+       if( p_adapter->params.cm_enabled )\r
+       {\r
+               p_adapter->params.cm_enabled = !p_adapter->params.lso;\r
+               if( !p_adapter->params.cm_enabled )\r
+               {\r
+                       NdisWriteErrorLogEntry( p_adapter->h_adapter,\r
+                               EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de0 );\r
+               }\r
+       }\r
+\r
+       if( p_adapter->params.cm_enabled )\r
+       {\r
+               p_adapter->params.cm_xfer_block_size = \r
+                       (sizeof(eth_hdr_t) + p_adapter->params.cm_payload_mtu);\r
+       }\r
+\r
+               p_adapter->params.xfer_block_size = \r
+                       (sizeof(eth_hdr_t) + p_adapter->params.payload_mtu);\r
+\r
+       NdisReadNetworkAddress( &status, p_mac, p_len, h_config );\r
+\r
+       NdisCloseConfiguration( h_config );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_get_adapter_guids(\r
+       IN                              NDIS_HANDLE* const                      h_adapter,\r
+       IN      OUT                     ipoib_adapter_t                         *p_adapter )\r
+{\r
+       NTSTATUS                        status;\r
+       ib_al_ifc_data_t        data;\r
+       IO_STACK_LOCATION       io_stack, *p_fwd_io_stack;\r
+       DEVICE_OBJECT           *p_pdo;\r
+       IRP                                     *p_irp;\r
+       KEVENT                          event;\r
+       IO_STATUS_BLOCK         io_status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       NdisMGetDeviceProperty( h_adapter, &p_pdo, NULL, NULL, NULL, NULL );\r
+\r
+       /* Query for our interface */\r
+       data.size = sizeof(ipoib_ifc_data_t);\r
+       data.version = IPOIB_INTERFACE_DATA_VERSION;\r
+       data.type = &GUID_IPOIB_INTERFACE_DATA;\r
+       data.p_data = &p_adapter->guids;\r
+\r
+       io_stack.MinorFunction = IRP_MN_QUERY_INTERFACE;\r
+       io_stack.Parameters.QueryInterface.Version = AL_INTERFACE_VERSION;\r
+       io_stack.Parameters.QueryInterface.Size = sizeof(ib_al_ifc_t);\r
+       io_stack.Parameters.QueryInterface.Interface =\r
+               (INTERFACE*)p_adapter->p_ifc;\r
+       io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data;\r
+       io_stack.Parameters.QueryInterface.InterfaceType = \r
+               &GUID_IB_AL_INTERFACE;\r
+\r
+       KeInitializeEvent( &event, NotificationEvent, FALSE );\r
+\r
+       /* Build the IRP for the HCA. */\r
+       p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_pdo,\r
+               NULL, 0, NULL, &event, &io_status );\r
+       if( !p_irp )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate query interface IRP.\n") );\r
+               return STATUS_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       /* Copy the request query parameters. */\r
+       p_fwd_io_stack = IoGetNextIrpStackLocation( p_irp );\r
+       p_fwd_io_stack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
+       p_fwd_io_stack->Parameters.QueryInterface =\r
+               io_stack.Parameters.QueryInterface;\r
+       p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
+\r
+       /* Send the IRP. */\r
+       status = IoCallDriver( p_pdo, p_irp );\r
+       if( status == STATUS_PENDING )\r
+       {\r
+               KeWaitForSingleObject( &event, Executive, KernelMode,\r
+                       FALSE, NULL );\r
+               status = io_status.Status;\r
+       }\r
+\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Query interface for IPOIB interface returned %08x.\n", status) );\r
+               return status;\r
+       }\r
+\r
+       /*\r
+        * Dereference the interface now so that the bus driver doesn't fail a\r
+        * query remove IRP.  We will always get unloaded before the bus driver\r
+        * since we're a child device.\r
+        */\r
+       if (p_adapter->p_ifc)\r
+       p_adapter->p_ifc->wdm.InterfaceDereference(\r
+               p_adapter->p_ifc->wdm.Context );\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+//! Initialization function called for each IOC discovered\r
+/*  The MiniportInitialize function is a required function that sets up a\r
+NIC (or virtual NIC) for network I/O operations, claims all hardware\r
+resources necessary to the NIC in the registry, and allocates resources\r
+the driver needs to carry out network I/O operations.\r
+IRQL = PASSIVE_LEVEL\r
+\r
+@param p_open_status Pointer to a status field set if this function returns NDIS_STATUS_OPEN_ERROR\r
+@param p_selected_medium_index Pointer to unsigned integer noting index into medium_array for this NIC\r
+@param medium_array Array of mediums for this NIC\r
+@param medium_array_size Number of elements in medium_array\r
+@param h_adapter Handle assigned by NDIS for this NIC\r
+@param wrapper_config_context Handle used for Ndis initialization functions\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_UNSUPPORTED_MEDIA, NDIS_STATUS_RESOURCES,\r
+NDIS_STATUS_NOT_SUPPORTED \r
+*/\r
+\r
+/*void foo1(int i)\r
+{\r
+               char temp[5200];\r
+               if (i ==0) return;\r
+               cl_msg_out("i = %d\n", i);\r
+               foo1(i-1);\r
+        \r
+}*/\r
+       \r
+NDIS_STATUS\r
+SetDeviceRegistrationAttributes(\r
+       ipoib_adapter_t *p_adapter,\r
+    NDIS_HANDLE        h_adapter\r
+    )\r
+{\r
+    NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES atr;\r
+    NTSTATUS Status;\r
+\r
+    NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES));\r
+\r
+    //\r
+    // setting registration attributes\r
+    //\r
+    atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES;\r
+    atr.Header.Revision = NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+    atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+\r
+\r
+    atr.MiniportAddDeviceContext = (NDIS_HANDLE)p_adapter;\r
+    atr.Flags = 0; \r
+\r
+    Status = NdisMSetMiniportAttributes(h_adapter,\r
+                    (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr);\r
+\r
+    return Status;\r
+}\r
+\r
+//NDIS 6.1\r
+#if 0\r
+NDIS_STATUS\r
+SetHardwareAssistAttributes(\r
+    ipoib_adapter_t *p_adapter,\r
+    NDIS_HANDLE        h_adapter\r
+    )\r
+{\r
+    NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES atr;\r
+    NTSTATUS Status;\r
+\r
+    NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES));\r
+\r
+    //\r
+    // setting registration attributes\r
+    //\r
+    atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES;\r
+    atr.Header.Revision = NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;\r
+    atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;\r
+\r
+    NDIS_HD_SPLIT_ATTRIBUTES nhsa;\r
+    NdisZeroMemory(&nhsa, sizeof(nhsa));\r
+\r
+    nhsa.Header.Type = NDIS_OBJECT_TYPE_HD_SPLIT_ATTRIBUTES;\r
+    nhsa.Header.Revision = NDIS_OFFLOAD_REVISION_1;\r
+    nhsa.Header.Size = NDIS_SIZEOF_HD_SPLIT_ATTRIBUTES_REVISION_1;\r
+\r
+    // BUGBUG: We are just cheating here ...\r
+    nhsa.HardwareCapabilities = NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT;\r
+#if 0\r
+    ... Only supported on B0\r
+\r
+                                 NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV4_OPTIONS |\r
+                                 NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV6_EXTENSION_HEADERS |\r
+                                 NDIS_HD_SPLIT_CAPS_SUPPORTS_TCP_OPTIONS;\r
+#endif\r
+\r
+    // The bellow should be left zero\r
+    if (pPort->Config.HeaderDataSplit) {\r
+        nhsa.CurrentCapabilities = NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT;\r
+    } else {\r
+        nhsa.CurrentCapabilities = 0;\r
+    }\r
+\r
+    nhsa.HDSplitFlags = 0;\r
+    nhsa.BackfillSize = 0;\r
+    nhsa.MaxHeaderSize = 0;    \r
+\r
+    atr.HDSplitAttributes = &nhsa;\r
+\r
+    Status = NdisMSetMiniportAttributes(h_adapter,\r
+                    (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr);\r
+\r
+    if (nhsa.HDSplitFlags & NDIS_HD_SPLIT_ENABLE_HEADER_DATA_SPLIT) {\r
+        ASSERT(pPort->Config.HeaderDataSplit == TRUE);\r
+        pPort->Config.HeaderDataSplit = TRUE;\r
+    } \r
+    else {\r
+        ASSERT(pPort->Config.HeaderDataSplit == FALSE);\r
+        pPort->Config.HeaderDataSplit = FALSE;\r
+    }\r
+\r
+    return Status;\r
+}\r
+#endif\r
+\r
+/*++\r
+Routine Description:\r
+    the routine sets attributes that are associated with a miniport adapter.\r
+\r
+Arguments:\r
+    pPort - Pointer to port object\r
+\r
+Return Value:\r
+    NDIS_STATUS\r
+\r
+Note:\r
+    Should be called in PASSIVE_LEVEL\r
+    \r
+--*/\r
+NDIS_STATUS\r
+SetAdapterRegistrationAttributes(\r
+       ipoib_adapter_t *p_adapter,\r
+       NDIS_HANDLE     h_adapter\r
+       )\r
+       {\r
+       NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES atr;\r
+       NTSTATUS Status;\r
+\r
+       NdisZeroMemory(&atr, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));\r
+\r
+       /* setting registration attributes */\r
+\r
+       atr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;\r
+       atr.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+       atr.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+       //TODO NDIS60 Port or adapter\r
+       atr.MiniportAdapterContext = (NDIS_HANDLE)p_adapter; //(NDIS_HANDLE)pPort->p_adapter;\r
+       atr.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER;\r
+       atr.CheckForHangTimeInSeconds = 10;\r
+       atr.InterfaceType = NdisInterfacePci ;   // ???? UH\r
+       //TODO NDIS60 PNP or PCI ?\r
+       //RegistrationAttributes.InterfaceType = NdisInterfacePNPBus;\r
+\r
+       Status = NdisMSetMiniportAttributes(h_adapter,\r
+                       (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&atr);\r
+\r
+       return Status;\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+    the routine sets generic attributes that are associated with a miniport \r
+    adapter.\r
+\r
+Arguments:\r
+    pPort - Pointer to port object\r
+\r
+Return Value:\r
+    NDIS_STATUS\r
+\r
+Note:\r
+    Should be called in PASSIVE_LEVEL\r
+    \r
+--*/\r
+NDIS_STATUS\r
+SetGenericAttributes(\r
+    ipoib_adapter_t *p_adapter,\r
+    NDIS_HANDLE        h_adapter\r
+    )\r
+{\r
+    NDIS_STATUS Status;\r
+\r
+    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES gat;\r
+    NdisZeroMemory(&gat, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));\r
+\r
+       /* set up generic attributes */\r
+\r
+       gat.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;\r
+       gat.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;\r
+       gat.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);\r
+\r
+       gat.MediaType = NdisMedium802_3;    \r
+       gat.MaxXmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+       gat.MaxRcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+       gat.XmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED; //TODO NDIS60 NDIS_LINK_SPEED_UNKNOWN\r
+       gat.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED; // TODO NDIS60 NDIS_LINK_SPEED_UNKNOWN ???\r
+\r
+       gat.MediaConnectState = MediaConnectStateConnected; //TODO NDIS60 Check the current state\r
+       gat.MediaDuplexState = MediaDuplexStateFull;\r
+\r
+       gat.MtuSize = MAX_IB_MTU;\r
+       gat.LookaheadSize = MAX_XFER_BLOCK_SIZE;\r
+       gat.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \r
+                                        NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
+                                        NDIS_MAC_OPTION_NO_LOOPBACK |\r
+                                        NDIS_MAC_OPTION_FULL_DUPLEX;\r
+                                       //NDIS_MAC_OPTION_8021P_PRIORITY; //TODO NDIS60\r
+                                       // DT: Enable for Header Data Split WHQL\r
+                                       // |  NDIS_MAC_OPTION_8021Q_VLAN;\r
+\r
+       gat.SupportedPacketFilters =    NDIS_PACKET_TYPE_DIRECTED |\r
+                                                                       NDIS_PACKET_TYPE_MULTICAST |\r
+                                                                       //NDIS_PACKET_TYPE_ALL_MULTICAST |\r
+                                                                       NDIS_PACKET_TYPE_BROADCAST;\r
+                                        \r
+       gat.MaxMulticastListSize = MAX_MCAST;\r
+\r
+       gat.MacAddressLength = HW_ADDR_LEN;\r
+       \r
+       NdisMoveMemory(gat.PermanentMacAddress,\r
+                                       p_adapter->mac.addr,\r
+                                       HW_ADDR_LEN);\r
+\r
+       NdisMoveMemory(gat.CurrentMacAddress,\r
+                                       p_adapter->params.conf_mac.addr,\r
+                                       HW_ADDR_LEN);\r
+\r
+\r
+       gat.PhysicalMediumType = NdisPhysicalMedium802_3;\r
+       gat.AccessType = NET_IF_ACCESS_BROADCAST; \r
+\r
+       gat.SupportedOidList = (PNDIS_OID)SUPPORTED_OIDS;\r
+       gat.SupportedOidListLength = sizeof(SUPPORTED_OIDS);\r
+\r
+\r
+       gat.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; \r
+       gat.ConnectionType = NET_IF_CONNECTION_DEDICATED; \r
+       gat.IfType = IF_TYPE_ETHERNET_CSMACD; \r
+       gat.IfConnectorPresent = TRUE; \r
+       //TODO NDIS60 This value is absent for ETH driver\r
+       gat.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter\r
+\r
+\r
+       //TODO NDIS60 is it possible to reduce unsupported statistics\r
+       gat.SupportedStatistics = \r
+                               NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
+                               NDIS_STATISTICS_RCV_OK_SUPPORTED |\r
+                               NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |\r
+                               NDIS_STATISTICS_RCV_ERROR_SUPPORTED |\r
+                               NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED |\r
+                               NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED |\r
+                               NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED;\r
+\r
+       //SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
+                                                       // NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;\r
+\r
+\r
+    //\r
+    // Set power management capabilities\r
+    //\r
+    gat.PowerManagementCapabilities = NULL;\r
+#if 0\r
+    NDIS_PNP_CAPABILITIES PowerManagementCapabilities;\r
+    NdisZeroMemory(&PowerManagementCapabilities, sizeof(NDIS_PNP_CAPABILITIES));\r
+    if (MPIsPoMgmtSupported(pPort))\r
+    {\r
+        MPFillPoMgmtCaps(pPort, &PowerManagementCapabilities, &Status, &unUsed);\r
+        ASSERT(NT_SUCCESS(Status)); \r
+        gat.PowerManagementCapabilities = &PowerManagementCapabilities;\r
+    } \r
+    else\r
+    {\r
+        \r
+    }\r
+#endif\r
+\r
+    //\r
+    // Set RSS attributes\r
+    //\r
+    gat.RecvScaleCapabilities = NULL;\r
+#if 0\r
+    NDIS_RECEIVE_SCALE_CAPABILITIES RssCapabilities;\r
+    NdisZeroMemory(&RssCapabilities, sizeof(PNDIS_RECEIVE_SCALE_CAPABILITIES));\r
+    Status = MPFillRssCapabilities(pPort, &RssCapabilities, &unUsed);\r
+    if (NT_SUCCESS(Status)) \r
+    {\r
+        gat.RecvScaleCapabilities = &RssCapabilities;\r
+    } \r
+    else\r
+    {\r
+        //\r
+        // do not fail the call because of failure to get PM caps\r
+        //\r
+        Status = NDIS_STATUS_SUCCESS;\r
+        gat.RecvScaleCapabilities = NULL;\r
+    }\r
+#endif\r
+\r
+       Status = NdisMSetMiniportAttributes(h_adapter,\r
+                       (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&gat);\r
+\r
+       return Status;\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+    The routine sets an NDIS_OFFLOAD structure indicates the current offload \r
+    capabilities that are provided by the miniport adapter \r
+    \r
+Arguments:\r
+    pPort - a pointer to port object\r
+    offload - reference to NDIS_OFFLOAD object that should be filled\r
+\r
+Return Value:\r
+    None.\r
+    \r
+--*/\r
+static\r
+void\r
+OffloadConfig(\r
+       ipoib_adapter_t *p_adapter,\r
+       NDIS_OFFLOAD *p_offload\r
+       )\r
+{ \r
+\r
+       ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q;\r
+\r
+       NdisZeroMemory(p_offload, NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1);\r
+\r
+       p_offload->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;\r
+       p_offload->Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008\r
+       p_offload->Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;\r
+\r
+       p_offload->Checksum.IPv4Transmit.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv4Transmit.IpOptionsSupported = \r
+       p_offload->Checksum.IPv4Transmit.TcpOptionsSupported = \r
+       p_offload->Checksum.IPv4Transmit.TcpChecksum = \r
+       p_offload->Checksum.IPv4Transmit.UdpChecksum = \r
+       p_offload->Checksum.IPv4Transmit.IpChecksum =!!(p_adapter->params.send_chksum_offload);\r
+\r
+       p_offload->Checksum.IPv4Receive.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv4Receive.IpOptionsSupported = \r
+       p_offload->Checksum.IPv4Receive.TcpOptionsSupported = \r
+       p_offload->Checksum.IPv4Receive.TcpChecksum = \r
+       p_offload->Checksum.IPv4Receive.UdpChecksum = \r
+       p_offload->Checksum.IPv4Receive.IpChecksum = !!(p_adapter->params.recv_chksum_offload); //TODO NDIS60\r
+\r
+\r
+       p_offload->Checksum.IPv6Transmit.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv6Transmit.IpExtensionHeadersSupported = \r
+       p_offload->Checksum.IPv6Transmit.TcpOptionsSupported =\r
+       p_offload->Checksum.IPv6Transmit.TcpChecksum = \r
+       p_offload->Checksum.IPv6Transmit.UdpChecksum = FALSE;\r
+\r
+\r
+       p_offload->Checksum.IPv6Receive.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv6Receive.IpExtensionHeadersSupported = \r
+       p_offload->Checksum.IPv6Receive.TcpOptionsSupported = \r
+       p_offload->Checksum.IPv6Receive.TcpChecksum = \r
+       p_offload->Checksum.IPv6Receive.UdpChecksum = FALSE;\r
+\r
+       if (p_adapter->params.lso)\r
+       {\r
+               p_offload->LsoV1.IPv4.Encapsulation = ulEncapsulation;\r
+               p_offload->LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+#define LSO_MIN_SEG_COUNT 2\r
+               p_offload->LsoV1.IPv4.MinSegmentCount = LSO_MIN_SEG_COUNT;\r
+       \r
+               \r
+               p_offload->LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+               p_offload->LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+\r
+               p_offload->LsoV2.IPv4.Encapsulation = ulEncapsulation;\r
+               p_offload->LsoV2.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+               p_offload->LsoV2.IPv4.MinSegmentCount = LSO_MIN_SEG_COUNT;\r
+\r
+               p_offload->LsoV2.IPv6.Encapsulation = ulEncapsulation;\r
+               p_offload->LsoV2.IPv6.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+               p_offload->LsoV2.IPv6.MinSegmentCount = LSO_MIN_SEG_COUNT;\r
+\r
+               p_offload->LsoV2.IPv6.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+               p_offload->LsoV2.IPv6.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;\r
+       }\r
+\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+    The routine sets an NDIS_OFFLOAD structure that indicates all the task \r
+    offload capabilites that are supported by the NIC. These capabilities include\r
+    capabilities that are currently disabled by standardized keywords in the registry. \r
+    \r
+Arguments:\r
+    offload - reference to NDIS_OFFLOAD object that should be filled\r
+\r
+Return Value:\r
+    None.\r
+    \r
+--*/\r
+static\r
+void\r
+OffloadCapabilities(\r
+       NDIS_OFFLOAD    *p_offload\r
+       )\r
+{ \r
+       ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q ;\r
+       NdisZeroMemory(p_offload, NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1);    \r
+\r
+       p_offload->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;\r
+       p_offload->Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008\r
+       p_offload->Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;\r
+\r
+       p_offload->Checksum.IPv4Transmit.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv4Transmit.IpOptionsSupported = TRUE;\r
+       p_offload->Checksum.IPv4Transmit.TcpOptionsSupported = TRUE;\r
+       p_offload->Checksum.IPv4Transmit.TcpChecksum = TRUE;\r
+       p_offload->Checksum.IPv4Transmit.UdpChecksum = TRUE;\r
+       p_offload->Checksum.IPv4Transmit.IpChecksum = TRUE;\r
+\r
+       p_offload->Checksum.IPv4Receive.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv4Receive.IpOptionsSupported = TRUE;\r
+       p_offload->Checksum.IPv4Receive.TcpOptionsSupported = TRUE;\r
+       p_offload->Checksum.IPv4Receive.TcpChecksum = TRUE;\r
+       p_offload->Checksum.IPv4Receive.UdpChecksum = TRUE; \r
+       p_offload->Checksum.IPv4Receive.IpChecksum = TRUE;\r
+\r
+\r
+       //\r
+       //  BUGBUG::\r
+       //  During a HW bug that didn't handle correctly packets with \r
+       //  IPv6 Extension Headers -> we set IpExtensionHeadersSupported to TRUE\r
+       //\r
+       p_offload->Checksum.IPv6Transmit.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv6Transmit.IpExtensionHeadersSupported = TRUE;\r
+       p_offload->Checksum.IPv6Transmit.TcpOptionsSupported = TRUE;\r
+       p_offload->Checksum.IPv6Transmit.TcpChecksum = TRUE;\r
+       p_offload->Checksum.IPv6Transmit.UdpChecksum = TRUE;\r
+\r
+\r
+       p_offload->Checksum.IPv6Receive.Encapsulation = ulEncapsulation;\r
+       p_offload->Checksum.IPv6Receive.IpExtensionHeadersSupported = TRUE;\r
+       p_offload->Checksum.IPv6Receive.TcpOptionsSupported = TRUE;\r
+       p_offload->Checksum.IPv6Receive.TcpChecksum = TRUE;\r
+       p_offload->Checksum.IPv6Receive.UdpChecksum = TRUE;\r
+\r
+       p_offload->LsoV1.IPv4.Encapsulation = ulEncapsulation;\r
+       p_offload->LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+       p_offload->LsoV1.IPv4.MinSegmentCount = 2;\r
+       p_offload->LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+       p_offload->LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+\r
+       p_offload->LsoV2.IPv4.Encapsulation = ulEncapsulation;\r
+       p_offload->LsoV2.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+       p_offload->LsoV2.IPv4.MinSegmentCount = 2;\r
+\r
+       p_offload->LsoV2.IPv6.Encapsulation = ulEncapsulation;\r
+       p_offload->LsoV2.IPv6.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+       p_offload->LsoV2.IPv6.MinSegmentCount = 2;\r
+\r
+       p_offload->LsoV2.IPv6.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+       p_offload->LsoV2.IPv6.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;\r
+\r
+       }\r
+\r
+\r
+/*++\r
+Routine Description:\r
+    The routine sets offload attributes that are associated with a miniport \r
+    adapter.\r
+\r
+Arguments:\r
+    pPort - Pointer to port object\r
+\r
+Return Value:\r
+    NDIS_STATUS\r
+\r
+Note:\r
+    Should be called in PASSIVE_LEVEL\r
+    \r
+--*/\r
+NDIS_STATUS\r
+SetOffloadAttributes(\r
+       ipoib_adapter_t *p_adapter,\r
+       NDIS_HANDLE     h_adapter\r
+       )\r
+{\r
+       NDIS_STATUS Status;\r
+       NDIS_OFFLOAD offload,hwOffload;\r
+       //ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q;\r
+\r
+       NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES oat;    \r
+       NdisZeroMemory(&oat, sizeof(NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES));\r
+\r
+       oat.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;\r
+       oat.Header.Revision = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;\r
+       oat.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;\r
+\r
+\r
+       OffloadConfig(p_adapter, &offload);\r
+\r
+\r
+       OffloadCapabilities(&hwOffload);\r
+\r
+       oat.DefaultOffloadConfiguration = &offload;\r
+       oat.HardwareOffloadCapabilities = &hwOffload;\r
+\r
+       Status = NdisMSetMiniportAttributes(h_adapter,\r
+                               (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&oat);\r
+\r
+       return Status;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+    An NDIS 6.0 miniport driver must call NdisMSetMiniportAttributes\r
+    at least twice. The first call is to register itself with NDIS.\r
+    The second call is to register the miniport driver's general\r
+    attributes with NDIS.\r
+\r
+    NdisMSetMiniportAttributes takes a parameter of type\r
+    NDIS_MINIPORT_ADAPTER_ATTRIBUTES, which is a union of several miniport\r
+    adapter attributes. Miniport drivers must first call\r
+    NdisMSetMiniportAttributes and pass in an\r
+    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES structure\r
+    that contains the pointer to its own context area, attribute flags,\r
+    check-for-hang time, and interface type.\r
+\r
+    All NDIS 6.0 miniport drivers are deserialized by default.\r
+\r
+Arguments:\r
+    pPort - Pointer to port object\r
+\r
+Return Value:\r
+    NDIS_STATUS\r
+\r
+Note:\r
+    Should be called in PASSIVE_LEVEL\r
+    \r
+--*/\r
+       NDIS_STATUS\r
+       SetAttributes(\r
+       ipoib_adapter_t *p_adapter,\r
+       NDIS_HANDLE     h_adapter\r
+       )\r
+       {\r
+       NTSTATUS Status;\r
+\r
+\r
+       Status = SetDeviceRegistrationAttributes(p_adapter, h_adapter);\r
+       if (Status != NDIS_STATUS_SUCCESS)\r
+       {\r
+               //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set device registration failed Error=0x%x\n", Status);\r
+               return Status;\r
+       }\r
+\r
+\r
+       Status = SetAdapterRegistrationAttributes(p_adapter, h_adapter);\r
+       if (Status != NDIS_STATUS_SUCCESS)\r
+       {\r
+               //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set adapter attributes failed Error=0x%x\n", Status);\r
+               return Status;\r
+       }\r
+\r
+       Status = SetOffloadAttributes(p_adapter, h_adapter);\r
+       if (Status != NDIS_STATUS_SUCCESS)\r
+       {\r
+               //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set OFFLOAD attributes failed Error=0x%x\n", Status);\r
+               return Status;\r
+       }\r
+       \r
+#if 0\r
+       if(!pPort->Config.fWHQL)\r
+       {\r
+               Status = SetHardwareAssistAttributes(pPort);\r
+               if (Status != NDIS_STATUS_SUCCESS)\r
+               {\r
+                   //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set Hardware Assist Attributes failed Error=0x%x\n", Status);\r
+                   return Status;\r
+               }\r
+       }\r
+#endif\r
+\r
+       Status = SetGenericAttributes(p_adapter, h_adapter);\r
+       if (Status != NDIS_STATUS_SUCCESS)\r
+       {\r
+           //ETH_PRINT(TRACE_LEVEL_ERROR, ETH_INIT, "Set generic attributes failed Error=0x%x\n", Status);\r
+           return Status;\r
+       }\r
+\r
+       return Status;\r
+}\r
+\r
+\r
+\r
+NDIS_STATUS\r
+InitNdisScatterGatherDma(\r
+       ipoib_adapter_t *p_adapter,\r
+       NDIS_HANDLE             h_adapter\r
+       )\r
+{\r
+       NDIS_STATUS                                             status;\r
+       NDIS_SG_DMA_DESCRIPTION                 DmaDescription;\r
+       \r
+       NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));\r
+\r
+       DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;\r
+       DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;\r
+       DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);\r
+       DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS; \r
+       //\r
+       // Even if offload is enabled, the packet size for mapping shouldn't change\r
+       //\r
+       DmaDescription.MaximumPhysicalMapping = LARGE_SEND_OFFLOAD_SIZE + LSO_MAX_HEADER;\r
+\r
+       DmaDescription.ProcessSGListHandler = ipoib_process_sg_list;\r
+       DmaDescription.SharedMemAllocateCompleteHandler = NULL;\r
+\r
+       DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;\r
+       DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;\r
+       DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);//NDIS_SIZEOF_SG_DMA_DESCRIPTION_REVISION_1;\r
+\r
+       DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS;\r
+       //DmaDescription.MaximumPhysicalMapping = pPort->p_adapter->params.xfer_block_size;\r
+\r
+       DmaDescription.ProcessSGListHandler = ipoib_process_sg_list;\r
+       DmaDescription.SharedMemAllocateCompleteHandler = NULL;\r
+       \r
+       status = NdisMRegisterScatterGatherDma(\r
+                                       h_adapter,\r
+                                       &DmaDescription,\r
+                                       &p_adapter->NdisMiniportDmaHandle);\r
+\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               //TODO NDIS60\r
+               //ipoib_destroy_adapter( p_adapter );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                                ("NdisMRegisterScatterGatherDma returned 0x%.8x.\n", status) );\r
+               \r
+       }\r
+       //NDIS sets this value before it returns from NdisMRegisterScatterGatherDma. \r
+               //Miniport drivers should use this size to preallocate memory for each scatter/gather list. \r
+       p_adapter->sg_list_size = DmaDescription.ScatterGatherListSize ;\r
+       \r
+       return status;\r
+}\r
+\r
+\r
+NDIS_STATUS \r
+MPInitializeTest(\r
+    IN  NDIS_HANDLE                        MiniportAdapterHandle,\r
+    IN  NDIS_HANDLE                        MiniportDriverContext,\r
+    IN  PNDIS_MINIPORT_INIT_PARAMETERS     MiniportInitParameters\r
+    )\r
+/*++\r
+Routine Description:\r
+\r
+    MiniportInitialize handler\r
+\r
+Arguments:\r
+\r
+    MiniportAdapterHandle   The handle NDIS uses to refer to us\r
+    MiniportDriverContext   Handle passed to NDIS when we registered the driver\r
+    MiniportInitParameters  Initialization parameters\r
+    \r
+Return Value:\r
+\r
+    NDIS_STATUS_SUCCESS unless something goes wrong\r
+\r
+--*/\r
+{\r
+\r
+       NDIS_STATUS Status = NDIS_STATUS_SUCCESS;\r
+    //PMP_PORT pPort = NULL;\r
+    ipoib_adapter_t    *p_adapter;\r
+//    NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS  Interrupt;\r
+    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES   RegistrationAttributes;\r
+    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES        GeneralAttributes;\r
+    //NDIS_TIMER_CHARACTERISTICS                      Timer;               \r
+    NDIS_PNP_CAPABILITIES          PowerManagementCapabilities;    \r
+    //PMP_ADAPTER     Adapter = NULL;\r
+    //PVOID           NetworkAddress;\r
+//    UINT            index;\r
+//    UINT            uiPnpCommandValue;\r
+//    ULONG           ulInfoLen;\r
+    //ULONG           InterruptVersion;\r
+//    LARGE_INTEGER   liDueTime;\r
+    //BOOLEAN         isTimerAlreadyInQueue = FALSE;\r
+//     uint8_t portId;\r
+       ib_api_status_t         ib_status;\r
+#if 0   \r
+#if DBG\r
+    LARGE_INTEGER   TS, TD, TE;\r
+#endif\r
+#endif\r
+\r
+    cl_dbg_out ("====> MPInitialize\n");\r
+\r
+    UNREFERENCED_PARAMETER(MiniportDriverContext);\r
+    UNREFERENCED_PARAMETER(MiniportInitParameters);\r
+  \r
+\r
+\r
+       \r
+\r
+    {\r
+\r
+               ib_status = ipoib_create_adapter(MiniportDriverContext, MiniportAdapterHandle, &p_adapter );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       ASSERT(FALSE);\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ipoib_create_adapter returned status %d.\n", ib_status ) );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+\r
+       \r
+\r
+        NdisZeroMemory(&RegistrationAttributes, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));\r
+        NdisZeroMemory(&GeneralAttributes, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));\r
+\r
+        //\r
+        // setting registration attributes\r
+        //\r
+        RegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;\r
+        RegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+        RegistrationAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);\r
+\r
+        RegistrationAttributes.MiniportAdapterContext = (NDIS_HANDLE)p_adapter;\r
+        RegistrationAttributes.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE | \r
+                                                NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER;\r
+        \r
+        RegistrationAttributes.CheckForHangTimeInSeconds = 2;\r
+        RegistrationAttributes.InterfaceType = NdisInterfacePci;\r
+\r
+        Status = NdisMSetMiniportAttributes(MiniportAdapterHandle,\r
+                                            (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&RegistrationAttributes);\r
+\r
+        if (Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            //break;\r
+            return Status;\r
+        }\r
+\r
+#if 0         \r
+        //\r
+        // Read the registry parameters\r
+        //\r
+        Status = NICReadRegParameters(Adapter);\r
+        \r
+        if (Status != NDIS_STATUS_SUCCESS) \r
+        {\r
+            break;\r
+        }\r
+\r
+       \r
+        //\r
+        // Find the physical adapter\r
+        //\r
+        Status = MpFindAdapter(Adapter, MiniportInitParameters->AllocatedResources);\r
+        if (Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            break;\r
+        }\r
+\r
+        //\r
+        // Map bus-relative IO range to system IO space\r
+        //\r
+        Status = NdisMRegisterIoPortRange(\r
+                     (PVOID *)&Adapter->PortOffset,\r
+                     Adapter->AdapterHandle,\r
+                     Adapter->IoBaseAddress,\r
+                     Adapter->IoRange);\r
+        if (Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            DBGPRINT(MP_ERROR, ("NdisMRegisterioPortRange failed\n"));\r
+    \r
+            NdisWriteErrorLogEntry(\r
+                Adapter->AdapterHandle,\r
+                NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS,\r
+                0);\r
+        \r
+            break;\r
+        }\r
+        \r
+        //\r
+        // Read additional info from NIC such as MAC address\r
+        //\r
+        Status = NICReadAdapterInfo(Adapter);\r
+        if (Status != NDIS_STATUS_SUCCESS) \r
+        {\r
+            break;\r
+        }\r
+\r
+#endif\r
+        //\r
+        // set up generic attributes\r
+        //\r
+               \r
+\r
+        GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;\r
+        GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;\r
+        GeneralAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);\r
+\r
+        GeneralAttributes.MediaType = NdisMedium802_3;\r
+\r
+        GeneralAttributes.MtuSize = DEFAULT_MTU;\r
+#define LINE_SPEED_10_GBTS 10000000000\r
+        GeneralAttributes.MaxXmitLinkSpeed = LINE_SPEED_10_GBTS;\r
+        GeneralAttributes.MaxRcvLinkSpeed = LINE_SPEED_10_GBTS;\r
+        GeneralAttributes.XmitLinkSpeed = NDIS_LINK_SPEED_UNKNOWN;\r
+        GeneralAttributes.RcvLinkSpeed = NDIS_LINK_SPEED_UNKNOWN;\r
+        GeneralAttributes.MediaConnectState = MediaConnectStateUnknown;\r
+        GeneralAttributes.MediaDuplexState = MediaDuplexStateUnknown;\r
+        GeneralAttributes.LookaheadSize = MAX_XFER_BLOCK_SIZE;\r
+#if 0\r
+        MPFillPoMgmtCaps (Adapter, \r
+                          &PowerManagementCapabilities, \r
+                          &Status,\r
+                          &ulInfoLen);\r
+#endif\r
+               NdisZeroMemory(&PowerManagementCapabilities, sizeof(NDIS_PNP_CAPABILITIES));\r
+        Status = NDIS_STATUS_NOT_SUPPORTED;\r
+       // ulInfoLen = 0;\r
+\r
+        if (Status == NDIS_STATUS_SUCCESS)\r
+        {\r
+            GeneralAttributes.PowerManagementCapabilities = &PowerManagementCapabilities;\r
+        }\r
+        else\r
+        {\r
+            GeneralAttributes.PowerManagementCapabilities = NULL;\r
+        }\r
+\r
+        //\r
+        // do not fail the call because of failure to get PM caps\r
+        //\r
+        Status = NDIS_STATUS_SUCCESS;\r
+\r
+        GeneralAttributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \r
+                                       NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
+                                       NDIS_MAC_OPTION_NO_LOOPBACK;\r
+\r
+        GeneralAttributes.SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED |\r
+                                                   NDIS_PACKET_TYPE_MULTICAST |\r
+                                                   NDIS_PACKET_TYPE_ALL_MULTICAST |\r
+                                                   NDIS_PACKET_TYPE_BROADCAST;\r
+        \r
+        GeneralAttributes.MaxMulticastListSize = MAX_MCAST;\r
+        GeneralAttributes.MacAddressLength = HW_ADDR_LEN;\r
+      NdisMoveMemory(GeneralAttributes.PermanentMacAddress,\r
+                               p_adapter->mac.addr,\r
+                               HW_ADDR_LEN);\r
+\r
+       NdisMoveMemory(GeneralAttributes.CurrentMacAddress,\r
+                               p_adapter->params.conf_mac.addr,\r
+                               HW_ADDR_LEN);\r
+        GeneralAttributes.RecvScaleCapabilities = NULL;\r
+        GeneralAttributes.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter\r
+        GeneralAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; // NET_IF_DIRECTION_SENDRECEIVE for a typical ethernet adapter\r
+        GeneralAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED;  // NET_IF_CONNECTION_DEDICATED for a typical ethernet adapter\r
+        GeneralAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; // IF_TYPE_ETHERNET_CSMACD for a typical ethernet adapter (regardless of speed)\r
+        GeneralAttributes.IfConnectorPresent = TRUE; // RFC 2665 TRUE if physical adapter\r
+\r
+        GeneralAttributes.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
+                                                NDIS_STATISTICS_RCV_OK_SUPPORTED |\r
+                                                NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |\r
+                                                NDIS_STATISTICS_RCV_ERROR_SUPPORTED |\r
+                                                NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED |\r
+                                                NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED |\r
+                                                NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED |\r
+                                                NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;\r
+                      \r
+        GeneralAttributes.SupportedOidList = NICSupportedOidsTest;\r
+        GeneralAttributes.SupportedOidListLength = sizeof(NICSupportedOidsTest);\r
+\r
+        Status = NdisMSetMiniportAttributes(MiniportAdapterHandle,\r
+                                            (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&GeneralAttributes);\r
+\r
+\r
+#if 0        \r
+        //\r
+        // Allocate all other memory blocks including shared memory\r
+        //\r
+        Status = NICAllocAdapterMemory(Adapter);\r
+        if (Status != NDIS_STATUS_SUCCESS) \r
+        {\r
+            break;\r
+        }\r
+        //\r
+        // Init send data structures\r
+        //\r
+        NICInitSend(Adapter);\r
+\r
+        //\r
+        // Init receive data structures\r
+        //\r
+        Status = NICInitRecv(Adapter);\r
+        if (Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            break;\r
+        }\r
+        //\r
+        // Map bus-relative registers to virtual system-space\r
+        // \r
+        Status = NdisMMapIoSpace(\r
+                     (PVOID *) &(Adapter->CSRAddress),\r
+                     Adapter->AdapterHandle,\r
+                     Adapter->MemPhysAddress,\r
+                     NIC_MAP_IOSPACE_LENGTH);\r
+        if (Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            DBGPRINT(MP_ERROR, ("NdisMMapIoSpace failed\n"));\r
+    \r
+            NdisWriteErrorLogEntry(\r
+                Adapter->AdapterHandle,\r
+                NDIS_ERROR_CODE_RESOURCE_CONFLICT,\r
+                1,\r
+                ERRLOG_MAP_IO_SPACE);\r
+        \r
+            break;\r
+        }\r
+\r
+        DBGPRINT(MP_INFO, ("CSRAddress="PTR_FORMAT"\n", Adapter->CSRAddress));\r
+\r
+        //\r
+        // Disable interrupts here which is as soon as possible\r
+        //\r
+        NICDisableInterrupt(Adapter);\r
+#endif\r
+                     \r
+        //\r
+        // Register the interrupt\r
+        //\r
+        //\r
+        \r
+        //\r
+        // the embeded NDIS interrupt structure is already zero'ed out\r
+        // as part of the adapter structure\r
+        //\r
+ #if 0\r
+        NdisZeroMemory(&Interrupt, sizeof(NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS));\r
+        \r
+        Interrupt.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_INTERRUPT;\r
+        Interrupt.Header.Revision = NDIS_MINIPORT_INTERRUPT_REVISION_1;\r
+        Interrupt.Header.Size = sizeof(NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS);\r
+\r
+        Interrupt.InterruptHandler = MPIsr;\r
+        Interrupt.InterruptDpcHandler = MPHandleInterrupt;\r
+        Interrupt.DisableInterruptHandler = NULL;\r
+        Interrupt.EnableInterruptHandler = NULL;\r
+\r
+\r
+\r
+        Status = NdisMRegisterInterruptEx(Adapter->AdapterHandle,\r
+                                          Adapter,\r
+                                          &Interrupt,\r
+                                          &Adapter->NdisInterruptHandle\r
+                                          );\r
+        \r
+                                        \r
+        if (Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            DBGPRINT(MP_ERROR, ("NdisMRegisterInterrupt failed\n"));\r
+    \r
+            NdisWriteErrorLogEntry(\r
+                Adapter->AdapterHandle,\r
+                NDIS_ERROR_CODE_INTERRUPT_CONNECT,\r
+                0);\r
+        \r
+            break;\r
+        }\r
+        \r
+        //\r
+        // If the driver support MSI\r
+        //\r
+        Adapter->InterruptType = Interrupt.InterruptType;\r
+\r
+        if (Adapter->InterruptType == NDIS_CONNECT_MESSAGE_BASED)\r
+        {\r
+            Adapter->MessageInfoTable = Interrupt.MessageInfoTable;\r
+        }\r
+        \r
+        //\r
+        // If the driver supports MSI, here it should what kind of interrupt is granted. If MSI is granted,\r
+        // the driver can check Adapter->MessageInfoTable to get MSI information\r
+        //\r
+        \r
+        \r
+        MP_SET_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE);\r
+\r
+        //\r
+        // Test our adapter hardware\r
+        //\r
+        Status = NICSelfTest(Adapter);\r
+        if (Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            break;\r
+        }\r
+        \r
+        //\r
+        // Init the hardware and set up everything\r
+        //\r
+        Status = NICInitializeAdapter(Adapter);\r
+        if (Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            break;\r
+        }\r
+        \r
+        //\r
+        // initial state is paused\r
+        //\r
+        Adapter->AdapterState = NicPaused;\r
+        \r
+        //\r
+        // Set the link detection flag\r
+        //\r
+        MP_SET_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION);\r
+      \r
+        //\r
+        // Increment the reference count so halt handler will wait \r
+        //\r
+        MP_INC_REF(Adapter);        \r
+\r
+        //\r
+        // Enable the interrupt\r
+        //\r
+        NICEnableInterrupt(Adapter);\r
+\r
+        \r
+        NdisZeroMemory(&Timer, sizeof(NDIS_TIMER_CHARACTERISTICS));\r
+        \r
+        Timer.Header.Type = NDIS_OBJECT_TYPE_TIMER_CHARACTERISTICS;\r
+        Timer.Header.Revision = NDIS_TIMER_CHARACTERISTICS_REVISION_1;\r
+        Timer.Header.Size = sizeof(NDIS_TIMER_CHARACTERISTICS);\r
+\r
+        Timer.AllocationTag = NIC_TAG;\r
+        Timer.TimerFunction = MpLinkDetectionDpc;\r
+        Timer.FunctionContext = Adapter;\r
+\r
+        //\r
+        // Minimize init-time\r
+        //\r
+        Status = NdisAllocateTimerObject(\r
+            Adapter->AdapterHandle,\r
+            &Timer,\r
+            &Adapter->LinkDetectionTimerHandle);\r
+\r
+        if (Status != NDIS_STATUS_SUCCESS)\r
+        {\r
+            break;\r
+        }\r
+\r
+        liDueTime.QuadPart = NIC_LINK_DETECTION_DELAY;\r
+        isTimerAlreadyInQueue =NdisSetTimerObject(Adapter->LinkDetectionTimerHandle, liDueTime, 0, NULL);\r
+        ASSERT(!isTimerAlreadyInQueue);\r
+#endif       \r
+       }  \r
+#if 0\r
+    if (Adapter && (Status != NDIS_STATUS_SUCCESS))\r
+    {\r
+        //\r
+        // Undo everything if it failed\r
+        //\r
+        MP_DEC_REF(Adapter);\r
+        MpFreeAdapter(Adapter);\r
+    }\r
+\r
+    DBGPRINT_S(Status, ("<==== MPInitialize, Status=%x\n", Status));\r
+#endif\r
+               /* Create the adapter adapter */\r
+               ib_status = ipoib_start_adapter( p_adapter );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       ASSERT(FALSE);\r
+\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ipoib_start_adapter returned status %d.\n", ib_status ) );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+       \r
+               ipoib_ref_ibat();\r
+    return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_initialize_ex(\r
+               IN NDIS_HANDLE  h_adapter,\r
+               IN NDIS_HANDLE  config_context,\r
+               IN PNDIS_MINIPORT_INIT_PARAMETERS  MiniportInitParameters)\r
+       {\r
+               NDIS_STATUS             status;\r
+               ib_api_status_t         ib_status;\r
+               ipoib_adapter_t         *p_adapter;\r
+               //NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES RegistrationAttributes;\r
+               //NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES              GeneralAttributes;\r
+#if IPOIB_USE_DMA\r
+               //NDIS_SG_DMA_DESCRIPTION       DmaDescription;\r
+#endif\r
+               IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       \r
+#ifdef _DEBUG_\r
+               PAGED_CODE();\r
+#endif\r
+               \r
+               UNUSED_PARAM( config_context );\r
+               UNUSED_PARAM( MiniportInitParameters );\r
+               \r
+               //foo1(100);\r
+               /* Create the adapter adapter */\r
+               ib_status = ipoib_create_adapter(config_context, h_adapter, &p_adapter );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       ASSERT(FALSE);\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ipoib_create_adapter returned status %d.\n", ib_status ) );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               p_adapter->ipoib_state = IPOIB_PAUSED;\r
+               status  = SetAttributes(p_adapter, h_adapter);\r
+               if (status != NDIS_STATUS_SUCCESS) {\r
+                       ASSERT(FALSE);\r
+               }\r
+#if 0\r
+               NdisZeroMemory(&RegistrationAttributes, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));\r
+               NdisZeroMemory(&GeneralAttributes, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));\r
+       \r
+               /* setting registration attributes */\r
+               RegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;\r
+               RegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+               RegistrationAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;\r
+       \r
+               RegistrationAttributes.MiniportAdapterContext = (NDIS_HANDLE)p_adapter;\r
+               RegistrationAttributes.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER;\r
+                                                                                                               \r
+               RegistrationAttributes.CheckForHangTimeInSeconds = 10;\r
+               RegistrationAttributes.InterfaceType = NdisInterfacePNPBus;\r
+       \r
+               status = NdisMSetMiniportAttributes(h_adapter,\r
+                                                                                  (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&RegistrationAttributes);\r
+       \r
+               if (status != NDIS_STATUS_SUCCESS)\r
+               {\r
+                       ipoib_destroy_adapter( p_adapter );\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("NdisMSetMiniportAttributes returned 0x%.8x.\n", status) );\r
+                       return status;\r
+               }\r
+       \r
+               /* set up generic attributes */\r
+       \r
+                GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;\r
+                GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;\r
+                GeneralAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);\r
+       \r
+                GeneralAttributes.MediaType = NdisMedium802_3;\r
+               //TODO\r
+                GeneralAttributes.MtuSize = MAX_IB_MTU;\r
+                GeneralAttributes.MaxXmitLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+                GeneralAttributes.MaxRcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+                GeneralAttributes.XmitLinkSpeed = NDIS_LINK_SPEED_UNKNOWN;\r
+                GeneralAttributes.RcvLinkSpeed = NDIS_LINK_SPEED_UNKNOWN;\r
+                GeneralAttributes.MediaConnectState = MediaConnectStateUnknown;\r
+                GeneralAttributes.MediaDuplexState = MediaDuplexStateUnknown;\r
+                GeneralAttributes.LookaheadSize = MAX_XFER_BLOCK_SIZE;\r
+       \r
+                GeneralAttributes.PowerManagementCapabilities = NULL;\r
+       \r
+                GeneralAttributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |\r
+                                                                               NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
+                                                                               NDIS_MAC_OPTION_NO_LOOPBACK |\r
+                                                                               NDIS_MAC_OPTION_FULL_DUPLEX;\r
+       \r
+                GeneralAttributes.SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED |\r
+                                                                                                       NDIS_PACKET_TYPE_MULTICAST |\r
+                                                                                                       NDIS_PACKET_TYPE_ALL_MULTICAST |\r
+                                                                                                       NDIS_PACKET_TYPE_BROADCAST;\r
+                       \r
+                GeneralAttributes.MaxMulticastListSize = MAX_MCAST;\r
+                GeneralAttributes.MacAddressLength = HW_ADDR_LEN;\r
+       \r
+                NdisMoveMemory(GeneralAttributes.PermanentMacAddress,\r
+                                               p_adapter->mac.addr,\r
+                                               HW_ADDR_LEN);\r
+       \r
+                NdisMoveMemory(GeneralAttributes.CurrentMacAddress,\r
+                                               p_adapter->params.conf_mac.addr,\r
+                                               HW_ADDR_LEN);\r
+       \r
+                       \r
+                GeneralAttributes.PhysicalMediumType = NdisPhysicalMediumUnspecified;\r
+                GeneralAttributes.RecvScaleCapabilities = NULL;\r
+                GeneralAttributes.AccessType = NET_IF_ACCESS_BROADCAST; // NET_IF_ACCESS_BROADCAST for a typical ethernet adapter\r
+                GeneralAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; // NET_IF_DIRECTION_SENDRECEIVE for a typical ethernet adapter\r
+                GeneralAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED;  // NET_IF_CONNECTION_DEDICATED for a typical ethernet adapter\r
+                GeneralAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; // IF_TYPE_ETHERNET_CSMACD for a typical ethernet adapter (regardless of speed)\r
+                GeneralAttributes.IfConnectorPresent = TRUE; // RFC 2665 TRUE if physical adapter\r
+       \r
+                GeneralAttributes.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_RCV_OK_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_RCV_ERROR_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED |\r
+                                                                                                NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;\r
+                                                 \r
+                GeneralAttributes.SupportedOidList = (PNDIS_OID)SUPPORTED_OIDS;\r
+                GeneralAttributes.SupportedOidListLength = sizeof(SUPPORTED_OIDS);\r
+       \r
+                status = NdisMSetMiniportAttributes(h_adapter,\r
+                                                                                       (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&GeneralAttributes);\r
+       \r
+                if (status != NDIS_STATUS_SUCCESS)\r
+                {\r
+                        IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                ("NdisMSetMiniportAttributes returned 0x%.8x.\n", status) );\r
+                }\r
+       \r
+#if IPOIB_USE_DMA\r
+       \r
+                NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));\r
+       \r
+                DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;\r
+                DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;\r
+                DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);//NDIS_SIZEOF_SG_DMA_DESCRIPTION_REVISION_1;\r
+       \r
+                DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS;\r
+                DmaDescription.MaximumPhysicalMapping = p_adapter->params.xfer_block_size;\r
+               \r
+                DmaDescription.ProcessSGListHandler = ipoib_process_sg_list;\r
+                DmaDescription.SharedMemAllocateCompleteHandler = NULL;\r
+       \r
+                status = NdisMRegisterScatterGatherDma(\r
+                                               p_adapter->h_adapter,\r
+                                               &DmaDescription,\r
+                                               &p_adapter->NdisMiniportDmaHandle);\r
+                                               \r
+                if( status != NDIS_STATUS_SUCCESS )\r
+                {\r
+                        ipoib_destroy_adapter( p_adapter );\r
+                        IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                                        ("NdisMRegisterScatterGatherDma returned 0x%.8x.\n", status) );\r
+                        return status;\r
+                }\r
+\r
+               \r
+               \r
+#endif\r
+#endif //if 0\r
+\r
+\r
+\r
+#if IPOIB_USE_DMA\r
+\r
+               InitNdisScatterGatherDma(p_adapter, h_adapter);\r
+\r
+\r
+\r
+#endif\r
+               /* Create the adapter adapter */\r
+               ib_status = ipoib_start_adapter( p_adapter );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       ASSERT(FALSE);\r
+                       NdisWriteErrorLogEntry( h_adapter,\r
+                               NDIS_ERROR_CODE_HARDWARE_FAILURE, 0 );\r
+#if  IPOIB_USE_DMA\r
+                       NdisMDeregisterScatterGatherDma(p_adapter->NdisMiniportDmaHandle);\r
+#endif\r
+                       ipoib_destroy_adapter( p_adapter );\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ipoib_start_adapter returned status %d.\n", ib_status ) );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+       \r
+               ipoib_ref_ibat();\r
+       \r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return status;\r
+       }\r
+\r
+\r
+//! Deallocates resources when the NIC is removed and halts the NIC..\r
+//TODO: Dispatch or Passive ?\r
+/*  IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+*/\r
+void\r
+ipoib_halt_ex(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                      NDIS_HALT_ACTION            HaltAction )\r
+{\r
+       ipoib_adapter_t *p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       UNUSED_PARAM(HaltAction);\r
+//return;              \r
+       ipoib_deref_ibat();\r
+\r
+       CL_ASSERT( adapter_context );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Port %016I64x (CA %016I64x port %d) halting\n",\r
+                       p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid,\r
+                       p_adapter->guids.port_num) );\r
+\r
+#if IPOIB_USE_DMA\r
+       if (p_adapter->NdisMiniportDmaHandle != NULL)\r
+       {\r
+               NdisMDeregisterScatterGatherDma(p_adapter->NdisMiniportDmaHandle);\r
+               p_adapter->NdisMiniportDmaHandle = NULL;\r
+       }\r
+#endif\r
+       ipoib_destroy_adapter( p_adapter );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+//! Reports the state of the NIC, or monitors the responsiveness of an underlying device driver.\r
+/*  IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+@return TRUE if the driver determines that its NIC is not operating\r
+*/\r
+BOOLEAN\r
+ipoib_check_for_hang(\r
+       IN                              NDIS_HANDLE                                     adapter_context )\r
+{\r
+       ipoib_adapter_t *p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+//return FALSE;\r
+       CL_ASSERT( adapter_context );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+       if( p_adapter->reset )\r
+       {\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return FALSE;\r
+       }\r
+       if (p_adapter->hung) {\r
+               ipoib_resume_oids(p_adapter);\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return (p_adapter->hung? TRUE:FALSE);\r
+}\r
+\r
+\r
+/*++\r
+Routine Description:\r
+       The routine sets an NDIS_OFFLOAD structure indicates the current offload \r
+       capabilities that are provided by the miniport adapter \r
+\r
+Arguments:\r
+       pPort - a pointer to port object\r
+       offload - reference to NDIS_OFFLOAD object that should be filled\r
+\r
+Return Value:\r
+       None.\r
+\r
+--*/\r
+//TODO\r
+#if 0\r
+static\r
+void\r
+__ipoib_get_offload_config(\r
+       ipoib_port_t *pPort,\r
+       NDIS_OFFLOAD *p_offload\r
+       )\r
+{\r
+       NDIS_STATUS Status;\r
+       ULONG TxChksumOffload = ((MP_GET_PORT_CONFIG(pPort, TxChksumOffload) == TRUE) ? NDIS_OFFLOAD_SET_ON : NDIS_OFFLOAD_SET_OFF);\r
+       ULONG RxChksumOffload = ((MP_GET_PORT_CONFIG(pPort, RxChksumOffload) == TRUE) ? NDIS_OFFLOAD_SET_ON : NDIS_OFFLOAD_SET_OFF);\r
+       BOOLEAN fLargeSendOffload = MP_GET_PORT_CONFIG(pPort, LargeSendOffload);\r
+       ULONG ulEncapsulation = NDIS_ENCAPSULATION_IEEE_802_3 | NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q;\r
+           \r
+       NdisZeroMemory(&*p_offload, sizeof(NDIS_OFFLOAD));\r
+       *p_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;\r
+       *p_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // BUGBUG: do we need to support revision 2? UH 17-May-2008\r
+       *p_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;\r
+\r
+       *p_offload.Checksum.IPv4Transmit.Encapsulation = ulEncapsulation;\r
+       *p_offload.Checksum.IPv4Transmit.IpOptionsSupported = TxChksumOffload;\r
+       *p_offload.Checksum.IPv4Transmit.TcpOptionsSupported = TxChksumOffload;\r
+       *p_offload.Checksum.IPv4Transmit.TcpChecksum = TxChksumOffload;\r
+       *p_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+       *p_offload.Checksum.IPv4Transmit.IpChecksum = TxChksumOffload;\r
+\r
+       *p_offload.Checksum.IPv4Receive.Encapsulation = ulEncapsulation;\r
+       *p_offload.Checksum.IPv4Receive.IpOptionsSupported = RxChksumOffload;\r
+       *p_offload.Checksum.IPv4Receive.TcpOptionsSupported = RxChksumOffload;\r
+       *p_offload.Checksum.IPv4Receive.TcpChecksum = RxChksumOffload;\r
+       *p_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED; \r
+       *p_offload.Checksum.IPv4Receive.IpChecksum = RxChksumOffload;\r
+\r
+       *p_offload.Checksum.IPv6Transmit.Encapsulation = ulEncapsulation;\r
+       *p_offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = TxChksumOffload;\r
+       *p_offload.Checksum.IPv6Transmit.TcpOptionsSupported = TxChksumOffload;\r
+       *p_offload.Checksum.IPv6Transmit.TcpChecksum = TxChksumOffload;\r
+       *p_offload.Checksum.IPv6Transmit.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+\r
+\r
+       *p_offload.Checksum.IPv6Receive.Encapsulation = ulEncapsulation;\r
+       *p_offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = RxChksumOffload;\r
+       *p_offload.Checksum.IPv6Receive.TcpOptionsSupported = RxChksumOffload;\r
+       *p_offload.Checksum.IPv6Receive.TcpChecksum = RxChksumOffload;\r
+       *p_offload.Checksum.IPv6Receive.UdpChecksum = NDIS_OFFLOAD_NOT_SUPPORTED;\r
+\r
+       if (fLargeSendOffload)\r
+       {\r
+           *p_offload.LsoV1.IPv4.Encapsulation = ulEncapsulation;\r
+           *p_offload.LsoV1.IPv4.MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;\r
+           *p_offload.LsoV1.IPv4.MinSegmentCount = 1;\r
+           *p_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+           *p_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED;\r
+       }\r
+}\r
+#endif\r
+\r
+//! Returns information about the capabilities and status of the driver and/or its NIC.\r
+/*  IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+@param oid Object ID representing the query operation to be carried out\r
+@param info_buf Buffer containing any input for this query and location for output\r
+@param info_buf_len Number of bytes available in info_buf\r
+@param p_bytes_written Pointer to number of bytes written into info_buf\r
+@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
+NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_NOT_ACCEPTED, NDIS_STATUS_NOT_SUPPORTED,\r
+NDIS_STATUS_RESOURCES\r
+*/\r
+       NDIS_STATUS\r
+ipoib_query_info(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              NDIS_OID                                        oid,\r
+       IN                              PVOID                                           info_buf,\r
+       IN                              ULONG                                           info_buf_len,\r
+               OUT                     PULONG                                          p_bytes_written,\r
+               OUT                     PULONG                                          p_bytes_needed )\r
+       {\r
+       ipoib_adapter_t         *p_adapter;\r
+               NDIS_STATUS             status;\r
+               USHORT                          version;\r
+       ULONG                           info;\r
+               PVOID                           src_buf;\r
+               ULONG                           buf_len;\r
+               pending_oid_t           oid_info;\r
+       uint8_t                         port_num;\r
+               \r
+               IPOIB_ENTER( IPOIB_DBG_OID );\r
+               \r
+               oid_info.oid = oid;\r
+               oid_info.p_buf = info_buf;\r
+               oid_info.buf_len = info_buf_len;\r
+               oid_info.p_bytes_used = p_bytes_written;\r
+               oid_info.p_bytes_needed = p_bytes_needed;\r
+               \r
+               CL_ASSERT( adapter_context );\r
+               p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+               CL_ASSERT( p_bytes_written );\r
+               CL_ASSERT( p_bytes_needed );\r
+               CL_ASSERT( !p_adapter->pending_query );\r
+               \r
+                       status = NDIS_STATUS_SUCCESS;\r
+                       src_buf = &info;\r
+               buf_len = sizeof(info);\r
+       \r
+               port_num = p_adapter->guids.port_num;\r
+       \r
+               switch( oid )\r
+               {\r
+               /* Required General */\r
+               case OID_GEN_SUPPORTED_LIST:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_SUPPORTED_LIST\n", port_num) );\r
+                       src_buf = (PVOID)SUPPORTED_OIDS;\r
+                       buf_len = sizeof(SUPPORTED_OIDS);\r
+                       break;\r
+       \r
+               case OID_GEN_HARDWARE_STATUS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_HARDWARE_STATUS\n", port_num) );\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       switch( p_adapter->state )\r
+                       {\r
+                       case IB_PNP_PORT_ADD:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NdisHardwareStatusInitializing\n", port_num) );\r
+                               info = NdisHardwareStatusInitializing;\r
+                               break;\r
+                               \r
+                       case IB_PNP_PORT_ACTIVE:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NdisHardwareStatusReady\n", port_num) );\r
+                               info = NdisHardwareStatusReady;\r
+                               break;\r
+       \r
+                       default:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NdisHardwareStatusNotReady\n", port_num) );\r
+                               info = NdisHardwareStatusNotReady;\r
+                       }\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       break;\r
+       \r
+               case OID_GEN_MEDIA_SUPPORTED:\r
+               case OID_GEN_MEDIA_IN_USE:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MEDIA_SUPPORTED "\r
+                               "or OID_GEN_MEDIA_IN_USE\n", port_num) );\r
+                       info = NdisMedium802_3;\r
+                       break;\r
+       \r
+               case OID_GEN_MAXIMUM_FRAME_SIZE:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MAXIMUM_FRAME_SIZE\n", port_num) );\r
+                       if( p_adapter->params.cm_enabled )\r
+                       {\r
+                               info = p_adapter->params.cm_payload_mtu;\r
+                       }\r
+                       else\r
+                       {\r
+                               info = p_adapter->params.payload_mtu;\r
+                       }\r
+                       break;\r
+       \r
+               case OID_GEN_LINK_SPEED:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_LINK_SPEED\n", port_num) );\r
+                       if (info_buf_len < buf_len)\r
+                       {\r
+                               break;\r
+                       }\r
+       \r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       switch( p_adapter->state )\r
+                       {\r
+                       case IB_PNP_PORT_ADD:\r
+                               /* Mark the adapter as pending an OID */\r
+                               p_adapter->pending_query = TRUE;\r
+       \r
+                               /* Save the request parameters. */\r
+                               p_adapter->query_oid = oid_info;\r
+       \r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NDIS_STATUS_PENDING\n", port_num) );\r
+                               status = NDIS_STATUS_PENDING;\r
+                               break;\r
+       \r
+                       case IB_PNP_PORT_REMOVE:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) );\r
+                               status = NDIS_STATUS_NOT_ACCEPTED;\r
+                               break;\r
+       \r
+                       default:\r
+                               CL_ASSERT( p_adapter->p_port );\r
+                               info = p_adapter->port_rate;\r
+                               break;\r
+                       }\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       break;\r
+       \r
+               case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE\n", port_num) );\r
+                       if( p_adapter->params.cm_enabled )\r
+                               info = p_adapter->params.sq_depth * p_adapter->params.cm_xfer_block_size;\r
+                       else\r
+                               info = p_adapter->params.sq_depth * p_adapter->params.xfer_block_size;\r
+                       break;\r
+       \r
+               case OID_GEN_RECEIVE_BUFFER_SPACE:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE "\r
+                               "or OID_GEN_RECEIVE_BUFFER_SPACE\n", port_num) );\r
+                       if( p_adapter->params.cm_enabled )\r
+                               info = p_adapter->params.rq_depth * p_adapter->params.cm_xfer_block_size;\r
+                       else\r
+                               info = p_adapter->params.rq_depth * p_adapter->params.xfer_block_size;\r
+                       break;\r
+       \r
+               case OID_GEN_MAXIMUM_LOOKAHEAD:\r
+               case OID_GEN_CURRENT_LOOKAHEAD:\r
+               case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
+               case OID_GEN_RECEIVE_BLOCK_SIZE:\r
+               case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MAXIMUM_LOOKAHEAD "\r
+                               "or OID_GEN_CURRENT_LOOKAHEAD or "\r
+                               "OID_GEN_TRANSMIT_BLOCK_SIZE or "\r
+                               "OID_GEN_RECEIVE_BLOCK_SIZE or "\r
+                               "OID_GEN_MAXIMUM_TOTAL_SIZE\n", port_num) );\r
+                       if( p_adapter->params.cm_enabled )\r
+                               info = p_adapter->params.cm_xfer_block_size;\r
+                       else\r
+                               info = p_adapter->params.xfer_block_size;\r
+                       break;\r
+       \r
+               case OID_GEN_VENDOR_ID:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_VENDOR_ID\n", port_num) );\r
+                       src_buf = (void*)VENDOR_ID;\r
+               buf_len = sizeof(VENDOR_ID);\r
+                       break;\r
+       \r
+               case OID_GEN_VENDOR_DESCRIPTION:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, \r
+                               ("Port %d received query for OID_GEN_VENDOR_DESCRIPTION\n", port_num) );\r
+                       src_buf = VENDOR_DESCRIPTION;\r
+               buf_len = sizeof(VENDOR_DESCRIPTION);\r
+                       break;\r
+       \r
+               case OID_GEN_VENDOR_DRIVER_VERSION:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_VENDOR_DRIVER_VERSION\n", port_num) );\r
+                       src_buf = &version;\r
+               buf_len = sizeof(version);\r
+                       //TODO: Figure out what the right version is.\r
+                       version = 1 << 8 | 1;\r
+                       break;\r
+       \r
+               case OID_GEN_PHYSICAL_MEDIUM:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_PHYSICAL_MEDIUM\n", port_num) );\r
+                       info = NdisPhysicalMediumUnspecified;\r
+                       break;\r
+       \r
+               case OID_GEN_CURRENT_PACKET_FILTER:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_CURRENT_PACKET_FILTER\n", port_num) );\r
+                       info = p_adapter->packet_filter;\r
+                       break;\r
+       \r
+               case OID_GEN_DRIVER_VERSION:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_DRIVER_VERSION\n", port_num) );\r
+                       src_buf = &version;\r
+               buf_len = sizeof(version);\r
+                       version = MAJOR_NDIS_VERSION << 8 | MINOR_NDIS_VERSION;\r
+                       break;\r
+       \r
+               case OID_GEN_MAC_OPTIONS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MAC_OPTIONS\n", port_num) );\r
+                       info = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |\r
+                               NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
+                               NDIS_MAC_OPTION_NO_LOOPBACK |\r
+                               NDIS_MAC_OPTION_FULL_DUPLEX;\r
+       //TODO: Figure out if we will support priority and VLANs.\r
+       //                              NDIS_MAC_OPTION_8021P_PRIORITY;\r
+       //#ifdef NDIS51_MINIPORT\r
+       //                      info |= NDIS_MAC_OPTION_8021Q_VLAN;\r
+       //#endif\r
+                       break;\r
+       \r
+               case OID_GEN_MEDIA_CONNECT_STATUS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MEDIA_CONNECT_STATUS\n", port_num) );\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       switch( p_adapter->state )\r
+                       {\r
+                       case IB_PNP_PORT_ADD:\r
+                       case IB_PNP_PORT_INIT:\r
+                               /*\r
+                                * Delay reporting media state until we know whether the port is\r
+                                * either up or down.\r
+                                */\r
+                               p_adapter->pending_query = TRUE;\r
+                               p_adapter->query_oid = oid_info;\r
+       \r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NDIS_STATUS_PENDING\n", port_num) );\r
+                               status = NDIS_STATUS_PENDING;\r
+                               break;\r
+       \r
+                       case IB_PNP_PORT_ACTIVE:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NdisMediaStateConnected\n", port_num) );\r
+                               info = NdisMediaStateConnected;\r
+                               break;\r
+       \r
+                       case IB_PNP_PORT_REMOVE:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) );\r
+                               status = NDIS_STATUS_NOT_ACCEPTED;\r
+                               break;\r
+       \r
+                       default:\r
+                               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                       ("Port %d returning NdisMediaStateDisconnected\n", port_num) );\r
+                               info = NdisMediaStateDisconnected;\r
+                       }\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       break;\r
+       \r
+               case OID_GEN_MAXIMUM_SEND_PACKETS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MAXIMUM_SEND_PACKETS\n", port_num) );\r
+                       info = MINIPORT_MAX_SEND_PACKETS;\r
+                       break;\r
+       \r
+               /* Required General Statistics */\r
+               case OID_GEN_STATISTICS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_STATISTICS\n", port_num) );\r
+                       src_buf = NULL;   \r
+                        buf_len =  sizeof(NDIS_STATISTICS_INFO);\r
+                       if (info_buf_len < buf_len)\r
+                       {\r
+                          break;\r
+                       } \r
+                       status = ipoib_get_gen_stat(p_adapter, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_XMIT_OK:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_XMIT_OK\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_SUCCESS, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_RCV_OK:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_RCV_OK\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_SUCCESS, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_XMIT_ERROR:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_XMIT_ERROR\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_ERROR, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_RCV_ERROR:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_RCV_ERROR\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_ERROR, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_RCV_NO_BUFFER:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_RCV_NO_BUFFER\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_DROPPED, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_DIRECTED_BYTES_XMIT:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_DIRECTED_BYTES_XMIT\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_DIRECTED_FRAMES_XMIT:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_DIRECTED_FRAMES_XMIT\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_MULTICAST_BYTES_XMIT:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MULTICAST_BYTES_XMIT\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_MULTICAST_FRAMES_XMIT:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MULTICAST_FRAMES_XMIT\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_BROADCAST_BYTES_XMIT:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_BROADCAST_BYTES_XMIT\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_BROADCAST_FRAMES_XMIT:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_BROADCAST_FRAMES_XMIT\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_DIRECTED_BYTES_RCV:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_DIRECTED_BYTES_RCV\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_DIRECTED_FRAMES_RCV:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_DIRECTED_FRAMES_RCV\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_MULTICAST_BYTES_RCV:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MULTICAST_BYTES_RCV\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_MULTICAST_FRAMES_RCV:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_MULTICAST_FRAMES_RCV\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_BROADCAST_BYTES_RCV:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_BROADCAST_BYTES_RCV\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info );\r
+                       break;\r
+       \r
+               case OID_GEN_BROADCAST_FRAMES_RCV:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_BROADCAST_FRAMES_RCV\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info );\r
+                       break;\r
+       \r
+               /* Required Ethernet operational characteristics */\r
+               case OID_802_3_PERMANENT_ADDRESS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_802_3_PERMANENT_ADDRESS\n", port_num) );\r
+                       src_buf = &p_adapter->mac;\r
+               buf_len = sizeof(p_adapter->mac);\r
+                       break;\r
+       \r
+               case OID_802_3_CURRENT_ADDRESS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_802_3_CURRENT_ADDRESS\n", port_num) );\r
+                       src_buf = &p_adapter->params.conf_mac;\r
+               buf_len = sizeof(p_adapter->params.conf_mac);\r
+                       break;\r
+       \r
+               case OID_802_3_MULTICAST_LIST:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_802_3_MULTICAST_LIST\n", port_num) );\r
+                       src_buf = p_adapter->mcast_array;\r
+               buf_len = p_adapter->mcast_array_size * sizeof(mac_addr_t);\r
+                       break;\r
+       \r
+               case OID_802_3_MAXIMUM_LIST_SIZE:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_802_3_MAXIMUM_LIST_SIZE\n", port_num) );\r
+                       info = MAX_MCAST;\r
+                       break;\r
+       \r
+               case OID_802_3_MAC_OPTIONS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_802_3_MAC_OPTIONS\n", port_num) );\r
+                       info = 0;\r
+                       break;\r
+       \r
+               /* Required Ethernet stats */\r
+               case OID_802_3_RCV_ERROR_ALIGNMENT:\r
+               case OID_802_3_XMIT_ONE_COLLISION:\r
+               case OID_802_3_XMIT_MORE_COLLISIONS:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_802_3_RCV_ERROR_ALIGNMENT or "\r
+                               "OID_802_3_XMIT_ONE_COLLISION or "\r
+                               "OID_802_3_XMIT_MORE_COLLISIONS\n", port_num) );\r
+                       info = 0;\r
+                       break;\r
+       \r
+               case OID_TCP_TASK_OFFLOAD:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
+                       src_buf = NULL;\r
+                       status = __ipoib_get_tcp_task_offload( p_adapter, &oid_info );\r
+                       break;\r
+       \r
+               /* Optional General */\r
+               case OID_GEN_SUPPORTED_GUIDS:\r
+#ifdef NDIS51_MINIPORT\r
+               case OID_GEN_VLAN_ID:\r
+#endif\r
+       \r
+               /* Optional General Stats */\r
+               case OID_GEN_RCV_CRC_ERROR:\r
+               case OID_GEN_TRANSMIT_QUEUE_LENGTH:\r
+       \r
+               /* Optional Ethernet Stats */\r
+               case OID_802_3_XMIT_DEFERRED:\r
+               case OID_802_3_XMIT_MAX_COLLISIONS:\r
+               case OID_802_3_RCV_OVERRUN:\r
+               case OID_802_3_XMIT_UNDERRUN:\r
+               case OID_802_3_XMIT_HEARTBEAT_FAILURE:\r
+               case OID_802_3_XMIT_TIMES_CRS_LOST:\r
+               case OID_802_3_XMIT_LATE_COLLISIONS:\r
+               case OID_PNP_CAPABILITIES:\r
+                       status = NDIS_STATUS_NOT_SUPPORTED;\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid) );\r
+                       break;\r
+       \r
+               case OID_GEN_PROTOCOL_OPTIONS:\r
+               case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
+               case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
+               case OID_PNP_ENABLE_WAKE_UP:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_GEN_PROTOCOL_OPTIONS or OID_GEN_NETWORK_LAYER_ADDRESSES or OID_GEN_TRANSPORT_HEADER_OFFSET  OID_PNP_ENABLE_WAKE_UPn", port_num) );\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Number of OID: 0x%.8X!\n", oid) );\r
+                       status = NDIS_STATUS_SUCCESS; \r
+                       break;\r
+                       \r
+               case OID_PNP_QUERY_POWER:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
+                       // Status is pre-set in this routine to Success\r
+                       status = NDIS_STATUS_SUCCESS; \r
+                       break;\r
+       \r
+               case OID_TCP_OFFLOAD_CURRENT_CONFIG:\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d received query for OID_PNP_QUERY_POWER\n", port_num) );\r
+                               //ulBytesAvailable = ulInfoLen = sizeof(NDIS_OFFLOAD);\r
+                               if (info_buf_len <  sizeof(NDIS_OFFLOAD))\r
+                               {\r
+                                       status = NDIS_STATUS_BUFFER_TOO_SHORT;\r
+                                       *p_bytes_needed = sizeof(NDIS_OFFLOAD) ;\r
+                                       break;\r
+                               }\r
+       \r
+                               //ipoib_offload_config(pPort, &offload);\r
+                               //pInfo = &offload;\r
+                               break;\r
+       \r
+               default:\r
+                       status = NDIS_STATUS_INVALID_OID;\r
+               //      IPOIB_PRINT( TRACE_LEVEL_ERROR,IPOIB_DBG_OID,\r
+                       //      ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid) );\r
+                       break;\r
+               }\r
+       \r
+               /*\r
+                * Complete the request as if it was handled asynchronously to maximize\r
+                * code reuse for when we really handle the requests asynchronously.\r
+                * Note that this requires the QueryInformation entry point to always\r
+                * return NDIS_STATUS_PENDING\r
+                */\r
+               if( status != NDIS_STATUS_PENDING )\r
+               {\r
+                       ipoib_complete_query(\r
+                               p_adapter, &oid_info, status, src_buf, buf_len );\r
+                       return status;\r
+               }\r
+       \r
+               IPOIB_EXIT( IPOIB_DBG_OID );\r
+               return NDIS_STATUS_PENDING;\r
+       }\r
+       \r
+\r
+static void\r
+ipoib_complete_query(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              pending_oid_t* const            p_oid_info,\r
+       IN              const   NDIS_STATUS                                     status,\r
+       IN              const   void* const                                     p_buf,\r
+       IN              const   ULONG                                           buf_len )\r
+{\r
+       NDIS_STATUS             oid_status = status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       CL_ASSERT( status != NDIS_STATUS_PENDING );\r
+\r
+       if( status == NDIS_STATUS_SUCCESS )\r
+       {\r
+               if( p_oid_info->buf_len < buf_len )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Insufficient buffer space.  "\r
+                               "Returning NDIS_STATUS_INVALID_LENGTH.\n") );\r
+                       oid_status = NDIS_STATUS_INVALID_LENGTH;\r
+                       *p_oid_info->p_bytes_needed = buf_len;\r
+                       *p_oid_info->p_bytes_used = 0;\r
+               }\r
+               else if( p_oid_info->p_buf )\r
+               {\r
+                       /* Only copy if we have a distinct source buffer. */\r
+                       if( p_buf )\r
+                       {\r
+                               NdisMoveMemory( p_oid_info->p_buf, p_buf, buf_len );\r
+                               *p_oid_info->p_bytes_used = buf_len;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Returning NDIS_NOT_ACCEPTED") );\r
+                       oid_status = NDIS_STATUS_NOT_ACCEPTED;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               *p_oid_info->p_bytes_used = 0;\r
+       }\r
+\r
+       if (p_adapter->query_oid.p_pending_oid)\r
+       {\r
+               NdisMOidRequestComplete(p_adapter->h_adapter,p_adapter->query_oid.p_pending_oid,oid_status); \r
+               p_adapter->query_oid.p_pending_oid = NULL;\r
+       }\r
+       p_adapter->pending_query = FALSE;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__ipoib_get_tcp_task_offload(\r
+       IN                              ipoib_adapter_t*                        p_adapter,\r
+       OUT                             pending_oid_t                           *pNdisRequest )\r
+{\r
+#ifndef NDIS60_MINIPORT\r
+       NDIS_TASK_OFFLOAD_HEADER        *p_offload_hdr;\r
+       NDIS_TASK_OFFLOAD                       *p_offload_task;\r
+       NDIS_TASK_TCP_IP_CHECKSUM       *p_offload_chksum;\r
+\r
+       NDIS_TASK_TCP_LARGE_SEND        *p_offload_lso;\r
+       ULONG                                           buf_len;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+               ("Port %d received query for OID_TCP_TASK_OFFLOAD\n",\r
+               p_adapter->guids.port_num) );\r
+\r
+       buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
+               offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +\r
+               sizeof(NDIS_TASK_TCP_IP_CHECKSUM) +\r
+               (p_adapter->params.lso  ? \r
+                       sizeof(NDIS_TASK_OFFLOAD) + sizeof(NDIS_TASK_TCP_LARGE_SEND)\r
+                       : 0);\r
+\r
+       pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = buf_len;\r
+\r
+       if( pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength < buf_len )\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+\r
+       p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;\r
+       if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
+               return NDIS_STATUS_INVALID_DATA;\r
+\r
+       if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
+               IEEE_802_3_Encapsulation )\r
+       {\r
+               return NDIS_STATUS_INVALID_DATA;\r
+       }\r
+\r
+       p_offload_hdr->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER);\r
+       p_offload_task = (NDIS_TASK_OFFLOAD*)(p_offload_hdr + 1);\r
+       p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;\r
+       p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);\r
+       p_offload_task->Task = TcpIpChecksumNdisTask;\r
+       p_offload_task->OffsetNextTask = 0;\r
+       p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);\r
+       p_offload_chksum =\r
+               (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
+       \r
+       p_offload_chksum->V4Transmit.IpOptionsSupported =\r
+       p_offload_chksum->V4Transmit.TcpOptionsSupported =\r
+       p_offload_chksum->V4Transmit.TcpChecksum =\r
+       p_offload_chksum->V4Transmit.UdpChecksum =\r
+       p_offload_chksum->V4Transmit.IpChecksum =\r
+               !!(p_adapter->params.send_chksum_offload);\r
+\r
+       p_offload_chksum->V4Receive.IpOptionsSupported =\r
+       p_offload_chksum->V4Receive.TcpOptionsSupported =\r
+       p_offload_chksum->V4Receive.TcpChecksum =\r
+       p_offload_chksum->V4Receive.UdpChecksum =\r
+       p_offload_chksum->V4Receive.IpChecksum =\r
+               !!(p_adapter->params.recv_chksum_offload);\r
+\r
+       p_offload_chksum->V6Transmit.IpOptionsSupported = FALSE;\r
+       p_offload_chksum->V6Transmit.TcpOptionsSupported = FALSE;\r
+       p_offload_chksum->V6Transmit.TcpChecksum = FALSE;\r
+       p_offload_chksum->V6Transmit.UdpChecksum = FALSE;\r
+\r
+       p_offload_chksum->V6Receive.IpOptionsSupported = FALSE;\r
+       p_offload_chksum->V6Receive.TcpOptionsSupported = FALSE;\r
+       p_offload_chksum->V6Receive.TcpChecksum = FALSE;\r
+       p_offload_chksum->V6Receive.UdpChecksum = FALSE;\r
+\r
+\r
+       if (p_adapter->params.lso) {\r
+               // set the previous pointer to the correct place\r
+               p_offload_task->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) +\r
+                                               p_offload_task->TaskBufferLength;\r
+               // set the LSO packet\r
+               p_offload_task = (PNDIS_TASK_OFFLOAD)\r
+                                               ((PUCHAR)p_offload_task + p_offload_task->OffsetNextTask);\r
+\r
+               p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;\r
+               p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);\r
+               p_offload_task->Task = TcpLargeSendNdisTask;\r
+               p_offload_task->OffsetNextTask = 0;\r
+               p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);\r
+\r
+               p_offload_lso = (PNDIS_TASK_TCP_LARGE_SEND) p_offload_task->TaskBuffer;\r
+\r
+               p_offload_lso->Version = 0;\r
+               //TODO optimal size: 60000, 64000 or 65536\r
+               //TODO LSO_MIN_SEG_COUNT to be 1\r
+               p_offload_lso->MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE; \r
+#define LSO_MIN_SEG_COUNT 2\r
+               p_offload_lso->MinSegmentCount = LSO_MIN_SEG_COUNT;\r
+               p_offload_lso->TcpOptions = TRUE;\r
+               p_offload_lso->IpOptions = TRUE;\r
+       }\r
+\r
+               pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten = buf_len\r
+\r
+       return NDIS_STATUS_SUCCESS;\r
+#endif\r
+       UNUSED_PARAM(p_adapter);\r
+       UNUSED_PARAM(pNdisRequest);\r
+       return NDIS_STATUS_NOT_SUPPORTED;\r
+\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__ipoib_set_tcp_task_offload(\r
+       IN                              ipoib_adapter_t*                        p_adapter,\r
+       IN                              void* const                                     p_info_buf,\r
+       IN                              ULONG* const                            p_info_len )\r
+{\r
+#ifndef NDIS60_MINIPORT\r
+       NDIS_TASK_OFFLOAD_HEADER        *p_offload_hdr;\r
+       NDIS_TASK_OFFLOAD                       *p_offload_task;\r
+       NDIS_TASK_TCP_IP_CHECKSUM       *p_offload_chksum;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+               ("Port %d received set for OID_TCP_TASK_OFFLOAD\n",\r
+               p_adapter->guids.port_num) );\r
+\r
+       p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_info_buf;\r
+\r
+       if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+\r
+       if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
+               return NDIS_STATUS_INVALID_DATA;\r
+\r
+       if( p_offload_hdr->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+\r
+       if( !p_offload_hdr->OffsetFirstTask )\r
+               return NDIS_STATUS_SUCCESS;\r
+\r
+       if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
+               IEEE_802_3_Encapsulation )\r
+       {\r
+               return NDIS_STATUS_INVALID_DATA;\r
+       }\r
+\r
+       p_offload_task = (NDIS_TASK_OFFLOAD*)\r
+               (((UCHAR*)p_offload_hdr) + p_offload_hdr->OffsetFirstTask);\r
+\r
+       if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
+               offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +\r
+               sizeof(NDIS_TASK_TCP_IP_CHECKSUM) )\r
+       {\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+       }\r
+\r
+       if( p_offload_task->Version != NDIS_TASK_OFFLOAD_VERSION )\r
+               return NDIS_STATUS_INVALID_DATA;\r
+       p_offload_chksum =\r
+               (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
+\r
+       if( !p_adapter->params.send_chksum_offload &&\r
+               (p_offload_chksum->V4Transmit.IpOptionsSupported ||\r
+               p_offload_chksum->V4Transmit.TcpOptionsSupported ||\r
+               p_offload_chksum->V4Transmit.TcpChecksum ||\r
+               p_offload_chksum->V4Transmit.UdpChecksum ||\r
+               p_offload_chksum->V4Transmit.IpChecksum) )\r
+       {\r
+               return NDIS_STATUS_NOT_SUPPORTED;\r
+       }\r
+\r
+       if( !p_adapter->params.recv_chksum_offload &&\r
+               (p_offload_chksum->V4Receive.IpOptionsSupported ||\r
+               p_offload_chksum->V4Receive.TcpOptionsSupported ||\r
+               p_offload_chksum->V4Receive.TcpChecksum ||\r
+               p_offload_chksum->V4Receive.UdpChecksum ||\r
+               p_offload_chksum->V4Receive.IpChecksum) )\r
+       {\r
+               return NDIS_STATUS_NOT_SUPPORTED;\r
+       }\r
+\r
+       return NDIS_STATUS_SUCCESS;\r
+#endif \r
+       UNUSED_PARAM(p_adapter);\r
+       UNUSED_PARAM(p_info_buf);\r
+       UNUSED_PARAM(p_info_len);\r
+       return NDIS_STATUS_NOT_SUPPORTED;\r
+}\r
+\r
+\r
+//! Issues a hardware reset to the NIC and/or resets the driver's software state.\r
+/*  Tear down the connection and start over again.  This is only called when there is a problem.\r
+For example, if a send, query info, or set info had a time out.  MiniportCheckForHang will\r
+be called first.\r
+IRQL = DISPATCH_LEVEL\r
+\r
+@param p_addr_resetPointer to BOOLLEAN that is set to TRUE if the NDIS\r
+library should call MiniportSetInformation to restore addressing information to the current values.\r
+@param adapter_context The adapter context allocated at start\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_NOT_RESETTABLE,\r
+NDIS_STATUS_RESET_IN_PROGRESS, NDIS_STATUS_SOFT_ERRORS, NDIS_STATUS_HARD_ERRORS\r
+*/\r
+NDIS_STATUS\r
+ipoib_reset(\r
+    IN  NDIS_HANDLE     adapter_context,\r
+    OUT PBOOLEAN        p_addr_reset)\r
+{\r
+       ipoib_adapter_t* p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+//return NDIS_STATUS_SUCCESS;\r
+       CL_ASSERT( p_addr_reset );\r
+       CL_ASSERT( adapter_context );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+       switch( ipoib_reset_adapter( p_adapter ) )\r
+       {\r
+       case IB_NOT_DONE:\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return NDIS_STATUS_PENDING;\r
+\r
+       case IB_SUCCESS:\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               *p_addr_reset = TRUE;\r
+               return NDIS_STATUS_SUCCESS;\r
+\r
+       case IB_INVALID_STATE:\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return NDIS_STATUS_RESET_IN_PROGRESS;\r
+\r
+       default:\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return NDIS_STATUS_HARD_ERRORS;\r
+       }\r
+}\r
+\r
+\r
+//! Request changes in the state information that the miniport driver maintains\r
+/*  For example, this is used to set multicast addresses and the packet filter.\r
+IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+@param oid Object ID representing the set operation to be carried out\r
+@param info_buf Buffer containing input for this set and location for any output\r
+@param info_buf_len Number of bytes available in info_buf\r
+@param p_bytes_read Pointer to number of bytes read from info_buf\r
+@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
+NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_INVALID_DATA, NDIS_STATUS_NOT_ACCEPTED,\r
+NDIS_STATUS_NOT_SUPPORTED, NDIS_STATUS_RESOURCES\r
+*/\r
+NDIS_STATUS\r
+ipoib_set_info(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              NDIS_OID                                        oid,\r
+       IN                              PVOID                                           info_buf,\r
+       IN                              ULONG                                           info_buf_len,\r
+               OUT                     PULONG                                          p_bytes_read,\r
+               OUT                     PULONG                                          p_bytes_needed )\r
+{\r
+       ipoib_adapter_t*        p_adapter;\r
+       NDIS_STATUS                     status;\r
+\r
+       ULONG                           buf_len;\r
+       uint8_t                         port_num;\r
+\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+       \r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       CL_ASSERT( adapter_context );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+       CL_ASSERT( p_bytes_read );\r
+       CL_ASSERT( p_bytes_needed );\r
+       CL_ASSERT( !p_adapter->pending_set );\r
+\r
+       status = NDIS_STATUS_SUCCESS;\r
+       *p_bytes_needed = 0;\r
+       buf_len = sizeof(ULONG);\r
+\r
+       port_num = p_adapter->guids.port_num;\r
+       \r
+       cl_obj_lock( &p_adapter->obj );\r
+\r
+       if( p_adapter->state == IB_PNP_PORT_REMOVE )\r
+       {\r
+               *p_bytes_read = 0;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               return NDIS_STATUS_NOT_ACCEPTED;\r
+       }\r
+\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       switch( oid )\r
+       {\r
+       /* Required General */\r
+       case OID_GEN_CURRENT_PACKET_FILTER:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num));\r
+               if( info_buf_len < sizeof(p_adapter->packet_filter) )\r
+               {\r
+                       status = NDIS_STATUS_INVALID_LENGTH;\r
+               }\r
+               else if( !info_buf )\r
+               {\r
+                       status = NDIS_STATUS_INVALID_DATA;\r
+               }\r
+               else\r
+               {\r
+                       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       switch( p_adapter->state )\r
+                       {\r
+                       case IB_PNP_PORT_ADD:\r
+                               p_adapter->set_oid.oid = oid;\r
+                               p_adapter->set_oid.p_buf = info_buf;\r
+                               p_adapter->set_oid.buf_len = info_buf_len;\r
+                               p_adapter->set_oid.p_bytes_used = p_bytes_read;\r
+                               p_adapter->set_oid.p_bytes_needed = p_bytes_needed;\r
+                               p_adapter->pending_set = TRUE;\r
+                               status = NDIS_STATUS_PENDING;\r
+                               break;\r
+\r
+                       case IB_PNP_PORT_REMOVE:\r
+                               status = NDIS_STATUS_NOT_ACCEPTED;\r
+                               break;\r
+\r
+                       default:\r
+                               if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) )\r
+                               {\r
+                                       cl_qlist_insert_tail(\r
+                                               &g_ipoib.adapter_list, &p_adapter->entry );\r
+\r
+                                       /*\r
+                                        * Filter was zero, now non-zero.  Register IP addresses\r
+                                        * with SA.\r
+                                        */\r
+                                       ipoib_reg_addrs( p_adapter );\r
+                               }\r
+                               else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) )\r
+                               {\r
+                                       /*\r
+                                        * Filter was non-zero, now zero.  Deregister IP addresses.\r
+                                        */\r
+                                       ipoib_dereg_addrs( p_adapter );\r
+\r
+                                       ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
+                                       cl_qlist_remove_item(\r
+                                               &g_ipoib.adapter_list, &p_adapter->entry );\r
+                               }\r
+\r
+                               p_adapter->packet_filter = *(uint32_t*)info_buf;\r
+                       }\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       KeReleaseInStackQueuedSpinLock( &hdl );\r
+               }\r
+               break;\r
+\r
+       case OID_GEN_CURRENT_LOOKAHEAD:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num));\r
+               if( info_buf_len < buf_len )\r
+                       status = NDIS_STATUS_INVALID_LENGTH;\r
+               break;\r
+\r
+       case OID_GEN_PROTOCOL_OPTIONS:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num));\r
+               if( info_buf_len < buf_len )\r
+                       status = NDIS_STATUS_INVALID_LENGTH;\r
+               break;\r
+\r
+       case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
+               status = __ipoib_set_net_addr( p_adapter, info_buf, info_buf_len, p_bytes_read, p_bytes_needed);\r
+               break;\r
+\r
+#ifdef NDIS51_MINIPORT\r
+       case OID_GEN_MACHINE_NAME:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) );\r
+               break;\r
+#endif\r
+\r
+       /* Required Ethernet operational characteristics */\r
+       case OID_802_3_MULTICAST_LIST:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) );\r
+               if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) );\r
+                       status = NDIS_STATUS_MULTICAST_FULL;\r
+                       *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t);\r
+               }\r
+               else if( info_buf_len % sizeof(mac_addr_t) )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
+                       status = NDIS_STATUS_INVALID_DATA;\r
+               }\r
+               else if( !info_buf && info_buf_len )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
+                       status = NDIS_STATUS_INVALID_DATA;\r
+               }\r
+               else\r
+               {\r
+                       ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf,\r
+                               (uint8_t)(info_buf_len / sizeof(mac_addr_t)) );\r
+\r
+                       buf_len = info_buf_len;\r
+                       /*\r
+                        * Note that we don't return pending.  It will likely take longer\r
+                        * for our SA transactions to complete than NDIS will give us\r
+                        * before reseting the adapter.  If an SA failure is encountered,\r
+                        * the adapter will be marked as hung and we will get reset.\r
+                        */\r
+                       status = NDIS_STATUS_SUCCESS;\r
+               }\r
+               break;\r
+\r
+       case OID_TCP_TASK_OFFLOAD:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
+\r
+               buf_len = info_buf_len;\r
+               status =\r
+                       __ipoib_set_tcp_task_offload( p_adapter, info_buf, &buf_len );\r
+               break;\r
+\r
+       /* Optional General */\r
+       case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
+#ifdef NDIS51_MINIPORT\r
+       case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
+       case OID_GEN_VLAN_ID:\r
+#endif\r
+               status = NDIS_STATUS_NOT_SUPPORTED;\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid));\r
+               break;\r
+\r
+       case OID_GEN_SUPPORTED_LIST:\r
+       case OID_GEN_HARDWARE_STATUS:\r
+       case OID_GEN_MEDIA_SUPPORTED:\r
+       case OID_GEN_MEDIA_IN_USE:\r
+       case OID_GEN_MAXIMUM_FRAME_SIZE:\r
+       case OID_GEN_LINK_SPEED:\r
+       case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
+       case OID_GEN_RECEIVE_BUFFER_SPACE:\r
+       case OID_GEN_MAXIMUM_LOOKAHEAD:\r
+       case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
+       case OID_GEN_RECEIVE_BLOCK_SIZE:\r
+       case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
+       case OID_GEN_VENDOR_ID:\r
+       case OID_GEN_VENDOR_DESCRIPTION:\r
+       case OID_GEN_VENDOR_DRIVER_VERSION:\r
+       case OID_GEN_DRIVER_VERSION:\r
+       case OID_GEN_MAC_OPTIONS:\r
+       case OID_GEN_MEDIA_CONNECT_STATUS:\r
+       case OID_GEN_MAXIMUM_SEND_PACKETS:\r
+       case OID_GEN_SUPPORTED_GUIDS:\r
+       case OID_GEN_PHYSICAL_MEDIUM:\r
+       default:\r
+               status = NDIS_STATUS_INVALID_OID;\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid));\r
+               break;\r
+       }\r
+\r
+       if( status == NDIS_STATUS_SUCCESS )\r
+       {\r
+               *p_bytes_read = buf_len;\r
+       }\r
+       else\r
+       {\r
+               if( status == NDIS_STATUS_INVALID_LENGTH )\r
+               {\r
+                       if ( !*p_bytes_needed )\r
+                       {\r
+                               *p_bytes_needed = buf_len;\r
+                       }\r
+               }\r
+\r
+               *p_bytes_read = 0;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+       return status;\r
+}\r
+\r
+#ifdef NNN\r
+NDIS_STATUS\r
+ipoib_set_info(\r
+       ipoib_adapter_t*           p_adapter,\r
+       IN PNDIS_OID_REQUEST   pNdisRequest)\r
+{\r
+       NDIS_STATUS                     status;\r
+       NDIS_OID            oid;\r
+       UINT                            info_buf_len;\r
+       UINT                            buf_len;\r
+       uint8_t                         port_num;\r
+       PVOID                           info_buf;\r
+       UINT                            *p_bytes_needed;\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+    oid                        = pNdisRequest->DATA.SET_INFORMATION.Oid;\r
+    info_buf           = pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;\r
+    info_buf_len       = pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;\r
+       p_bytes_needed  = &pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;\r
+       status = NDIS_STATUS_SUCCESS;\r
+\r
+       buf_len = sizeof(UINT);\r
+       port_num = p_adapter->guids.port_num;\r
+\r
+       switch( oid )\r
+       {\r
+       /* Required General */\r
+       case OID_GEN_CURRENT_PACKET_FILTER:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num));\r
+               if( info_buf_len < sizeof(p_adapter->packet_filter) )\r
+               {\r
+                       status = NDIS_STATUS_INVALID_LENGTH;\r
+               }\r
+               else if( !info_buf )\r
+               {\r
+                       status = NDIS_STATUS_INVALID_DATA;\r
+               }\r
+               else\r
+               {\r
+                       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       switch( p_adapter->state )\r
+                       {\r
+                       case IB_PNP_PORT_ADD:\r
+                               p_adapter->p_oid_request = pNdisRequest;\r
+                               status = NDIS_STATUS_PENDING;\r
+                               break;\r
+\r
+                       case IB_PNP_PORT_REMOVE:\r
+                               status = NDIS_STATUS_NOT_ACCEPTED;\r
+                               break;\r
+\r
+                       default:\r
+                               if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) )\r
+                               {\r
+                                       cl_qlist_insert_tail(\r
+                                               &g_ipoib.adapter_list, &p_adapter->entry );\r
+\r
+                                       /*\r
+                                        * Filter was zero, now non-zero.  Register IP addresses\r
+                                        * with SA.\r
+                                        */\r
+                                       ipoib_reg_addrs( p_adapter );\r
+                               }\r
+                               else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) )\r
+                               {\r
+                                       /*\r
+                                        * Filter was non-zero, now zero.  Deregister IP addresses.\r
+                                        */\r
+                                       ipoib_dereg_addrs( p_adapter );\r
+\r
+                                       ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
+                                       cl_qlist_remove_item(\r
+                                               &g_ipoib.adapter_list, &p_adapter->entry );\r
+                               }\r
+\r
+                               p_adapter->packet_filter = *(uint32_t*)info_buf;\r
+                       }\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       KeReleaseInStackQueuedSpinLock( &hdl );\r
+               }\r
+               break;\r
+\r
+       case OID_GEN_CURRENT_LOOKAHEAD:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num));\r
+               if( info_buf_len < buf_len )\r
+                       status = NDIS_STATUS_INVALID_LENGTH;\r
+               break;\r
+\r
+       case OID_GEN_PROTOCOL_OPTIONS:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num));\r
+               if( info_buf_len < buf_len )\r
+                       status = NDIS_STATUS_INVALID_LENGTH;\r
+               break;\r
+\r
+       case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
+               status = __ipoib_set_net_addr( p_adapter, pNdisRequest);\r
+               break;\r
+\r
+       case OID_GEN_MACHINE_NAME:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) );\r
+               break;\r
+\r
+\r
+       /* Required Ethernet operational characteristics */\r
+       case OID_802_3_MULTICAST_LIST:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) );\r
+               if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) );\r
+                       status = NDIS_STATUS_MULTICAST_FULL;\r
+                       *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t);\r
+               }\r
+               else if( info_buf_len % sizeof(mac_addr_t) )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
+                       status = NDIS_STATUS_INVALID_DATA;\r
+               }\r
+               else if( !info_buf && info_buf_len )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
+                       status = NDIS_STATUS_INVALID_DATA;\r
+               }\r
+               else\r
+               {\r
+                       ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf,\r
+                               (uint8_t)(info_buf_len / sizeof(mac_addr_t)) );\r
+\r
+                       buf_len = info_buf_len;\r
+                       /*\r
+                        * Note that we don't return pending.  It will likely take longer\r
+                        * for our SA transactions to complete than NDIS will give us\r
+                        * before reseting the adapter.  If an SA failure is encountered,\r
+                        * the adapter will be marked as hung and we will get reset.\r
+                        */\r
+                       status = NDIS_STATUS_SUCCESS;\r
+               }\r
+               break;\r
+\r
+       case OID_TCP_TASK_OFFLOAD:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
+\r
+               buf_len = info_buf_len;\r
+               status =\r
+                       __ipoib_set_tcp_task_offload( p_adapter, pNdisRequest );\r
+               break;\r
+\r
+       /* Optional General */\r
+       case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
+#ifdef NDIS51_MINIPORT\r
+       case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
+       case OID_GEN_VLAN_ID:\r
+#endif\r
+               status = NDIS_STATUS_NOT_SUPPORTED;\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid));\r
+               break;\r
+\r
+       case OID_GEN_SUPPORTED_LIST:\r
+       case OID_GEN_HARDWARE_STATUS:\r
+       case OID_GEN_MEDIA_SUPPORTED:\r
+       case OID_GEN_MEDIA_IN_USE:\r
+       case OID_GEN_MAXIMUM_FRAME_SIZE:\r
+       case OID_GEN_LINK_SPEED:\r
+       case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
+       case OID_GEN_RECEIVE_BUFFER_SPACE:\r
+       case OID_GEN_MAXIMUM_LOOKAHEAD:\r
+       case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
+       case OID_GEN_RECEIVE_BLOCK_SIZE:\r
+       case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
+       case OID_GEN_VENDOR_ID:\r
+       case OID_GEN_VENDOR_DESCRIPTION:\r
+       case OID_GEN_VENDOR_DRIVER_VERSION:\r
+       case OID_GEN_DRIVER_VERSION:\r
+       case OID_GEN_MAC_OPTIONS:\r
+       case OID_GEN_MEDIA_CONNECT_STATUS:\r
+       case OID_GEN_MAXIMUM_SEND_PACKETS:\r
+       case OID_GEN_SUPPORTED_GUIDS:\r
+       case OID_GEN_PHYSICAL_MEDIUM:\r
+       default:\r
+               status = NDIS_STATUS_INVALID_OID;\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid));\r
+               break;\r
+       }\r
+\r
+       if( status == NDIS_STATUS_SUCCESS )\r
+       {\r
+               pNdisRequest->DATA.SET_INFORMATION.BytesRead = buf_len;\r
+       }\r
+       else\r
+       {\r
+               if( status == NDIS_STATUS_INVALID_LENGTH )\r
+               {\r
+                       if ( !*p_bytes_needed )\r
+                       {\r
+                               *p_bytes_needed = buf_len;\r
+                       }\r
+               }\r
+\r
+               pNdisRequest->DATA.SET_INFORMATION.BytesRead = 0;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+       return status;\r
+}\r
+#endif\r
+static NDIS_STATUS\r
+ipoib_oid_handler(\r
+    IN  NDIS_HANDLE         adapter_context,\r
+    IN  PNDIS_OID_REQUEST   pNdisRequest)\r
+{\r
+    NDIS_REQUEST_TYPE       RequestType;\r
+       NDIS_STATUS     status = NDIS_STATUS_SUCCESS;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       RequestType = pNdisRequest->RequestType;\r
+\r
+       switch(RequestType)\r
+       {\r
+        case NdisRequestSetInformation:            \r
+            status = ipoib_set_info(adapter_context,\r
+                                               pNdisRequest->DATA.SET_INFORMATION.Oid,\r
+                                               pNdisRequest->DATA.SET_INFORMATION.InformationBuffer,\r
+                                               pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength,\r
+                                               (PULONG)&pNdisRequest->DATA.SET_INFORMATION.BytesRead,\r
+                                               (PULONG)&pNdisRequest->DATA.SET_INFORMATION.BytesNeeded);\r
+            break;\r
+                \r
+        case NdisRequestQueryInformation:\r
+        case NdisRequestQueryStatistics:\r
+            status = ipoib_query_info(adapter_context,\r
+                                               pNdisRequest->DATA.QUERY_INFORMATION.Oid,\r
+                                               pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,\r
+                                               pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,\r
+                                               (PULONG)&pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten,\r
+                                               (PULONG)&pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);\r
+                                               \r
+            break;\r
+\r
+        default:\r
+            status = NDIS_STATUS_NOT_SUPPORTED;\r
+            break;\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+       return status;\r
+}\r
+\r
+//! Transfers some number of packets, specified as an array of packet pointers, over the network. \r
+/*  For a deserialized driver, these packets are completed asynchronously\r
+using NdisMSendComplete.\r
+IRQL <= DISPATCH_LEVEL\r
+\r
+@param adapter_context Pointer to ipoib_adapter_t structure with per NIC state\r
+@param packet_array Array of packets to send\r
+@param numPackets Number of packets in the array\r
+*/\r
+void\r
+ipoib_send_net_buffer_list(\r
+    IN  NDIS_HANDLE         adapter_context,\r
+    IN  PNET_BUFFER_LIST    net_buffer_list,\r
+    IN  NDIS_PORT_NUMBER    port_num,\r
+    IN  ULONG               send_flags\r
+    )\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       ipoib_port_t            *p_port;\r
+       ULONG                           send_complete_flags;\r
+    PNET_BUFFER_LIST    curr_net_buffer_list;\r
+    PNET_BUFFER_LIST    next_net_buffer_list;\r
+       NDIS_STATUS     status = NDIS_STATUS_SUCCESS;\r
+       \r
+       UNREFERENCED_PARAMETER(port_num);\r
+       PERF_DECLARE( SendPackets );\r
+       PERF_DECLARE( PortSend );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+       cl_perf_start( SendPackets );\r
+\r
+       CL_ASSERT( adapter_context );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+       p_port = p_adapter->p_port;\r
+\r
+       cl_obj_lock( &p_adapter->obj );\r
+       if( p_adapter->ipoib_state == IPOIB_PAUSING ||\r
+               p_adapter->ipoib_state == IPOIB_PAUSED)\r
+       {\r
+               status = NDIS_STATUS_PAUSED; \r
+               cl_obj_unlock( &p_adapter->obj );\r
+               goto compl_status;\r
+       }\r
+\r
+       if( p_adapter->state != IB_PNP_PORT_ACTIVE || !p_adapter->p_port )\r
+       {\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               status = NDIS_STATUS_FAILURE; \r
+               goto compl_status;\r
+       }\r
+\r
+       p_port = p_adapter->p_port;\r
+       ipoib_port_ref( p_port, ref_send_packets );\r
+       cl_obj_unlock( &p_adapter->obj );\r
+       //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+       //                      ("Starting NET BUFFER LIST \n") );\r
+       for (curr_net_buffer_list = net_buffer_list;\r
+               curr_net_buffer_list != NULL;\r
+               curr_net_buffer_list = next_net_buffer_list)\r
+       {\r
+               next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(curr_net_buffer_list);\r
+               cl_perf_start( PortSend );\r
+               \r
+               ipoib_port_send( p_port, curr_net_buffer_list, send_flags);\r
+               cl_perf_stop( &adapter->perf, PortSend );\r
+       }\r
+       ipoib_port_deref( p_port, ref_send_packets );\r
+\r
+       cl_perf_stop( &p_adapter->perf, SendPackets );\r
+\r
+       cl_perf_log( &p_adapter->perf, SendBundle, num_packets );\r
+\r
+compl_status:\r
+    if (status != NDIS_STATUS_SUCCESS)\r
+       {\r
+               //ASSERT(FALSE); //????\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Got bad status \n") );\r
+               send_complete_flags = 0;\r
+           \r
+               for (curr_net_buffer_list = net_buffer_list;\r
+                                curr_net_buffer_list != NULL;\r
+                                curr_net_buffer_list = next_net_buffer_list)\r
+               {\r
+                       next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(curr_net_buffer_list);\r
+                       NET_BUFFER_LIST_STATUS(curr_net_buffer_list) = status;\r
+                       ipoib_inc_send_stat( p_adapter, IP_STAT_DROPPED, 0 );\r
+               }\r
+\r
+\r
+               if (NDIS_TEST_SEND_AT_DISPATCH_LEVEL(send_flags))\r
+               {\r
+                       NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
+               }\r
+                     \r
+               NdisMSendNetBufferListsComplete(\r
+                       p_adapter->h_adapter,\r
+                       net_buffer_list,\r
+                       send_complete_flags);  \r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+void\r
+ipoib_pnp_notify(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN PNET_DEVICE_PNP_EVENT  pnp_event)\r
+{\r
+       ipoib_adapter_t *p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_PNP );\r
+\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP, ("Event %d\n", pnp_event->DevicePnPEvent) );\r
+       if( pnp_event->DevicePnPEvent != NdisDevicePnPEventPowerProfileChanged )\r
+       {\r
+               cl_obj_lock( &p_adapter->obj );\r
+               p_adapter->state = IB_PNP_PORT_REMOVE;\r
+               cl_obj_unlock( &p_adapter->obj );\r
+\r
+               ipoib_resume_oids( p_adapter );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_PNP );\r
+}\r
+\r
+\r
+VOID\r
+ipoib_shutdown_ex(\r
+       IN NDIS_HANDLE  adapter_context,\r
+       IN NDIS_SHUTDOWN_ACTION  shutdown_action)\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       UNUSED_PARAM( adapter_context );\r
+       UNUSED_PARAM( shutdown_action );\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+void\r
+ipoib_resume_oids(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       ULONG                           info;\r
+       NDIS_STATUS                     status;\r
+       boolean_t                       pending_query, pending_set;\r
+       pending_oid_t           query_oid = {0};\r
+       pending_oid_t           set_oid = {0};\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       cl_obj_lock( &p_adapter->obj );\r
+       /*\r
+        * Set the status depending on our state.  Fail OID requests that\r
+        * are pending while we reset the adapter.\r
+        */\r
+       switch( p_adapter->state )\r
+       {\r
+       case IB_PNP_PORT_ADD:\r
+               status = NDIS_STATUS_FAILURE;\r
+               break;\r
+\r
+       case IB_PNP_PORT_REMOVE:\r
+               status = NDIS_STATUS_NOT_ACCEPTED;\r
+               break;\r
+               \r
+       default:\r
+               status = NDIS_STATUS_SUCCESS;\r
+       }\r
+\r
+       pending_query = p_adapter->pending_query;\r
+       if( pending_query )\r
+       {\r
+               query_oid = p_adapter->query_oid;\r
+               p_adapter->pending_query = FALSE;\r
+       }\r
+       pending_set = p_adapter->pending_set;\r
+       if( pending_set )\r
+       {\r
+               set_oid = p_adapter->set_oid;\r
+               p_adapter->pending_set = FALSE;\r
+       }\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       /*\r
+        * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
+        * complete it now.  Note that we hold the object lock since\r
+        * NdisMQueryInformationComplete is called at DISPATCH_LEVEL.\r
+        */\r
+       if( pending_query )\r
+       {\r
+               switch( query_oid.oid )\r
+               {\r
+               case OID_GEN_LINK_SPEED:\r
+                       ipoib_complete_query( p_adapter, &query_oid,\r
+                               status, &p_adapter->port_rate, sizeof(p_adapter->port_rate) );\r
+                       break;\r
+\r
+               case OID_GEN_MEDIA_CONNECT_STATUS:\r
+                       info = NdisMediaStateConnected;\r
+                       ipoib_complete_query( p_adapter, &query_oid,\r
+                               status, &info, sizeof(info) );\r
+                       break;\r
+\r
+               default:\r
+                       CL_ASSERT( query_oid.oid == OID_GEN_LINK_SPEED ||\r
+                               query_oid.oid == OID_GEN_MEDIA_CONNECT_STATUS );\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if( pending_set )\r
+       {\r
+               switch( set_oid.oid )\r
+               {\r
+               case OID_GEN_CURRENT_PACKET_FILTER:\r
+                       /* Validation already performed in the SetInformation path. */\r
+\r
+                       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+                       cl_obj_lock( &p_adapter->obj );\r
+                       if( !p_adapter->packet_filter && (*(PULONG)set_oid.p_buf) )\r
+                       {\r
+                               cl_qlist_insert_tail(\r
+                                       &g_ipoib.adapter_list, &p_adapter->entry );\r
+                               /*\r
+                                * Filter was zero, now non-zero.  Register IP addresses\r
+                                * with SA.\r
+                                */\r
+                               ipoib_reg_addrs( p_adapter );\r
+                       }\r
+                       else if( p_adapter->packet_filter && !(*(PULONG)set_oid.p_buf) )\r
+                       {\r
+                               /* Filter was non-zero, now zero.  Deregister IP addresses. */\r
+                               ipoib_dereg_addrs( p_adapter );\r
+\r
+                               ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
+                               cl_qlist_remove_item(\r
+                                       &g_ipoib.adapter_list, &p_adapter->entry );\r
+                       }\r
+                       p_adapter->packet_filter = *(PULONG)set_oid.p_buf;\r
+\r
+                       cl_obj_unlock( &p_adapter->obj );\r
+                       KeReleaseInStackQueuedSpinLock( &hdl );\r
+                       p_adapter->set_oid.p_pending_oid = NULL;\r
+                       NdisMOidRequestComplete( p_adapter->h_adapter, set_oid.p_pending_oid, status );\r
+                       break;\r
+\r
+               case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
+                       status = __ipoib_set_net_addr( p_adapter,\r
+                                                                                  p_adapter->set_oid.p_buf,\r
+                                                                                  p_adapter->set_oid.buf_len,\r
+                                                                                  p_adapter->set_oid.p_bytes_used,\r
+                                                                                  p_adapter->set_oid.p_bytes_needed );\r
+\r
+                       if( status != NDIS_STATUS_PENDING )\r
+                       {\r
+                               p_adapter->set_oid.p_pending_oid = NULL;\r
+                               NdisMOidRequestComplete( p_adapter->h_adapter, set_oid.p_pending_oid, status );\r
+                       }\r
+                       break;\r
+\r
+               default:\r
+                       CL_ASSERT( set_oid.oid && 0 );\r
+                       break;\r
+               }\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__ipoib_set_net_addr(\r
+       IN              ipoib_adapter_t *       p_adapter,\r
+       IN              PVOID                           info_buf,\r
+       IN              ULONG                           info_buf_len,\r
+               OUT     PULONG                          p_bytes_read,\r
+               OUT     PULONG                          p_bytes_needed )\r
+{\r
+       NDIS_STATUS                             status;\r
+       PNETWORK_ADDRESS_LIST   p_net_addrs;\r
+       PNETWORK_ADDRESS                p_net_addr_oid;\r
+       PNETWORK_ADDRESS_IP             p_ip_addr;\r
+\r
+       net_address_item_t              *p_addr_item;\r
+\r
+       cl_status_t                             cl_status;\r
+\r
+       size_t                                  idx;\r
+       LONG                                    i;\r
+       ULONG                                   addr_size;\r
+       ULONG                                   total_size;\r
+\r
+       uint8_t                                 port_num;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       status = NDIS_STATUS_SUCCESS;\r
+       port_num = p_adapter->guids.port_num;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+               ("Port %d received set for OID_GEN_NETWORK_LAYER_ADDRESSES\n",\r
+               port_num) );\r
+\r
+       if( !info_buf )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                       "NULL buffer\n", port_num) );\r
+               IPOIB_EXIT( IPOIB_DBG_OID );\r
+               return NDIS_STATUS_INVALID_DATA;\r
+       }\r
+\r
+       /*\r
+        * Must use field offset because the structures define array's of size one\r
+        * of a the incorrect type for what is really stored.\r
+        */\r
+       if( info_buf_len < FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
+                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                       "bad length of %d, not enough "\r
+                       "for NETWORK_ADDRESS_LIST (%d)\n", port_num, info_buf_len,\r
+                       FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address)) );\r
+               *p_bytes_needed = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address);\r
+               IPOIB_EXIT( IPOIB_DBG_OID );\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+       }\r
+\r
+       p_net_addrs = (PNETWORK_ADDRESS_LIST)info_buf;\r
+       if( p_net_addrs->AddressCount == 0)\r
+       {\r
+               if( p_net_addrs->AddressType == NDIS_PROTOCOL_ID_TCP_IP )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                               ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                               "clear TCP/IP addresses\n", port_num) );\r
+               }\r
+               else\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                               ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                               "Non TCP/IP address type of 0x%.4X on clear\n",\r
+                               port_num, p_net_addrs->AddressType) );\r
+                       IPOIB_EXIT( IPOIB_DBG_OID );\r
+                       return NDIS_STATUS_SUCCESS;\r
+               }\r
+       }\r
+\r
+       addr_size = FIELD_OFFSET(NETWORK_ADDRESS, Address) +\r
+               NETWORK_ADDRESS_LENGTH_IP;\r
+       total_size = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) +\r
+               addr_size * p_net_addrs->AddressCount;\r
+\r
+       if( info_buf_len < total_size )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                       "bad length of %d, %d required for %d addresses\n",\r
+                       port_num, info_buf_len, total_size, p_net_addrs->AddressCount) );\r
+               *p_bytes_needed = total_size;\r
+               IPOIB_EXIT( IPOIB_DBG_OID );\r
+               return NDIS_STATUS_INVALID_LENGTH;\r
+       }\r
+\r
+       /* Lock lists for duration since SA callbacks can occur on other CPUs */\r
+       cl_obj_lock( &p_adapter->obj );\r
+\r
+       /* Set the capacity of the vector to accomodate all assinged addresses. */\r
+       cl_status = cl_vector_set_capacity(\r
+               &p_adapter->ip_vector, p_net_addrs->AddressCount );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                       "Failed to set IP vector capacity: %#x\n", port_num,\r
+                       cl_status) );\r
+               IPOIB_EXIT( IPOIB_DBG_OID );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+\r
+       *p_bytes_read = total_size;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+               ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - List contains %d addresses\n",\r
+                       port_num, p_net_addrs->AddressCount));\r
+\r
+       /* First look for addresses we had that should be removed */\r
+       for( idx = 0; idx != cl_vector_get_size( &p_adapter->ip_vector ); idx++ )\r
+       {\r
+               p_addr_item = (net_address_item_t*)\r
+                       cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
+               p_net_addr_oid = (PNETWORK_ADDRESS)p_net_addrs->Address;\r
+\r
+               for( i = 0; i < p_net_addrs->AddressCount; ++i, p_net_addr_oid =\r
+                       (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid +\r
+                       FIELD_OFFSET(NETWORK_ADDRESS, Address) +\r
+                       p_net_addr_oid->AddressLength) )\r
+               {\r
+\r
+                       if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
+                                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, "\r
+                                               "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType,\r
+                                               NDIS_PROTOCOL_ID_TCP_IP));\r
+                               continue;\r
+                       }\r
+\r
+                       if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP)\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
+                                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, "\r
+                                               "should be %d\n", port_num, i, p_net_addr_oid->AddressLength,\r
+                                               NETWORK_ADDRESS_LENGTH_IP));\r
+                               continue;\r
+                       }\r
+\r
+                       p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address;\r
+                       if( !cl_memcmp( &p_ip_addr->in_addr,\r
+                               &p_addr_item->address.as_ulong, sizeof(ULONG) ) )\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if( i == p_net_addrs->AddressCount )\r
+               {\r
+                       /* Didn't find a match, delete from SA */\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                               ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Deleting Address %d.%d.%d.%d\n",\r
+                                       port_num,\r
+                                       p_addr_item->address.as_bytes[0],\r
+                                       p_addr_item->address.as_bytes[1],\r
+                                       p_addr_item->address.as_bytes[2],\r
+                                       p_addr_item->address.as_bytes[3]));\r
+\r
+                       if( p_addr_item->p_reg )\r
+                       {\r
+                               if( p_addr_item->p_reg->h_reg_svc )\r
+                               {\r
+                                       p_adapter->p_ifc->dereg_svc(\r
+                                               p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
+                               }\r
+                               else\r
+                               {\r
+                                       cl_free( p_addr_item->p_reg );\r
+                               }\r
+                               p_addr_item->p_reg = NULL;\r
+                       }\r
+                       p_addr_item->address.as_ulong = 0;\r
+               }\r
+       }\r
+\r
+       /* Now look for new addresses */\r
+       p_net_addr_oid = (NETWORK_ADDRESS *)p_net_addrs->Address;\r
+       idx = 0;\r
+       for( i = 0; i < p_net_addrs->AddressCount; i++, p_net_addr_oid =\r
+               (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid +\r
+               FIELD_OFFSET(NETWORK_ADDRESS, Address) + p_net_addr_oid->AddressLength) )\r
+       {\r
+\r
+               if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP )\r
+               {\r
+                       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                               ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, "\r
+                                       "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType,\r
+                                       NDIS_PROTOCOL_ID_TCP_IP));\r
+                       continue;\r
+               }\r
+\r
+               if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP)\r
+               {\r
+                       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
+                               ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, "\r
+                                       "should be %d\n", port_num, i, p_net_addr_oid->AddressLength,\r
+                                       NETWORK_ADDRESS_LENGTH_IP));\r
+                       continue;\r
+               }\r
+\r
+               p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address;\r
+\r
+               /* Size the vector as needed. */\r
+               if( cl_vector_get_size( &p_adapter->ip_vector ) <= idx )\r
+                       cl_vector_set_size( &p_adapter->ip_vector, idx + 1 );\r
+\r
+               p_addr_item = cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
+               if( !cl_memcmp( &p_ip_addr->in_addr, &p_addr_item->address.as_ulong,\r
+                       sizeof(ULONG) ) )\r
+               {\r
+                       idx++;\r
+                       /* Already have this address - no change needed */\r
+                       continue;\r
+               }\r
+\r
+               /*\r
+                * Copy the address information, but don't register yet - the port\r
+                * could be down.\r
+                */\r
+               if( p_addr_item->p_reg )\r
+               {\r
+                       /* If in use by some other address, deregister. */\r
+                       if( p_addr_item->p_reg->h_reg_svc )\r
+                       {\r
+                               p_adapter->p_ifc->dereg_svc(\r
+                                       p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
+                       }\r
+                       else\r
+                       {\r
+                               cl_free( p_addr_item->p_reg );\r
+                       }\r
+                       p_addr_item->p_reg = NULL;\r
+               }\r
+               memcpy ((void *)&p_addr_item->address.as_ulong, (const void *)&p_ip_addr->in_addr, sizeof(ULONG) );\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Adding Address %d.%d.%d.%d\n",\r
+                       port_num,\r
+                       p_addr_item->address.as_bytes[0],\r
+                       p_addr_item->address.as_bytes[1],\r
+                       p_addr_item->address.as_bytes[2],\r
+                       p_addr_item->address.as_bytes[3]) );\r
+               idx++;\r
+       }\r
+\r
+       /* Now clear any extra entries that shouldn't be there. */\r
+       while( idx < cl_vector_get_size( &p_adapter->ip_vector ) )\r
+       {\r
+               p_addr_item = (net_address_item_t*)\r
+                       cl_vector_get_ptr( &p_adapter->ip_vector,\r
+                       cl_vector_get_size( &p_adapter->ip_vector ) - 1 );\r
+\r
+               if( p_addr_item->p_reg )\r
+               {\r
+                       if( p_addr_item->p_reg->h_reg_svc )\r
+                       {\r
+                               p_adapter->p_ifc->dereg_svc(\r
+                                       p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
+                       }\r
+                       else\r
+                       {\r
+                               cl_free( p_addr_item->p_reg );\r
+                       }\r
+                       p_addr_item->p_reg = NULL;\r
+                       p_addr_item->address.as_ulong = 0;\r
+               }\r
+\r
+               /* No need to check return value - shrinking always succeeds. */\r
+               cl_vector_set_size( &p_adapter->ip_vector,\r
+                       cl_vector_get_size( &p_adapter->ip_vector ) - 1 );\r
+       }\r
+\r
+       if( p_adapter->state == IB_PNP_PORT_ACTIVE && p_adapter->packet_filter )\r
+               ipoib_reg_addrs( p_adapter );\r
+\r
+       cl_obj_unlock( &p_adapter->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+/* Object lock is held when this function is called. */\r
+void\r
+ipoib_reg_addrs(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       net_address_item_t              *p_addr_item;\r
+\r
+       size_t                                  idx;\r
+\r
+       uint8_t                                 port_num;\r
+\r
+       ib_api_status_t                 ib_status;\r
+       ib_reg_svc_req_t                ib_service;\r
+       ib_gid_t                                port_gid;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       if(p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,\r
+               ("ATS Service available for default pkey only\n"));      \r
+               return;\r
+       }\r
+       port_num = p_adapter->guids.port_num;\r
+\r
+       /* Setup our service call with things common to all calls */\r
+       cl_memset( &ib_service, 0, sizeof(ib_service) );\r
+\r
+       /* BUGBUG Only register local subnet GID prefix for now */\r
+       ib_gid_set_default( &port_gid, p_adapter->guids.port_guid.guid );\r
+       ib_service.svc_rec.service_gid          = port_gid;\r
+\r
+       ib_service.svc_rec.service_pkey         = IB_DEFAULT_PKEY;\r
+       ib_service.svc_rec.service_lease        = IB_INFINITE_SERVICE_LEASE;\r
+\r
+       /* Must cast here because the service name is an array of unsigned chars but\r
+        * strcpy want a pointer to a signed char */\r
+       if ( StringCchCopy( (char *)ib_service.svc_rec.service_name, \r
+               sizeof(ib_service.svc_rec.service_name) / sizeof(char), ATS_NAME ) != S_OK) {\r
+               ASSERT(FALSE);\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,\r
+               ("Problem copying ATS name: exiting\n"));\r
+               return;\r
+       }\r
+    \r
+       /* IP Address in question will be put in below */\r
+       ib_service.port_guid            = p_adapter->guids.port_guid.guid;\r
+       ib_service.timeout_ms           = p_adapter->params.sa_timeout;\r
+       ib_service.retry_cnt            = p_adapter->params.sa_retry_cnt;\r
+\r
+       /* Can't set IB_FLAGS_SYNC here because I can't wait at dispatch */\r
+       ib_service.flags                        = 0;\r
+\r
+       /* Service context will be put in below */\r
+\r
+       ib_service.svc_data_mask        = IB_SR_COMPMASK_SID            |\r
+                                                                 IB_SR_COMPMASK_SGID           |\r
+                                                                 IB_SR_COMPMASK_SPKEY          |\r
+                                                                 IB_SR_COMPMASK_SLEASE         |\r
+                                                                 IB_SR_COMPMASK_SNAME          |\r
+                                                                 IB_SR_COMPMASK_SDATA8_12      |\r
+                                                                 IB_SR_COMPMASK_SDATA8_13      |\r
+                                                                 IB_SR_COMPMASK_SDATA8_14      |\r
+                                                                 IB_SR_COMPMASK_SDATA8_15;\r
+       ib_service.pfn_reg_svc_cb = __ipoib_ats_reg_cb;\r
+\r
+       for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ )\r
+       {\r
+               p_addr_item = (net_address_item_t*)\r
+                       cl_vector_get_ptr(  &p_adapter->ip_vector, idx );\r
+\r
+               if( p_addr_item->p_reg )\r
+                       continue;\r
+\r
+               p_addr_item->p_reg = cl_zalloc( sizeof(ats_reg_t) );\r
+               if( !p_addr_item->p_reg )\r
+                       break;\r
+\r
+               p_addr_item->p_reg->p_adapter = p_adapter;\r
+\r
+               ib_service.svc_context          = p_addr_item->p_reg;\r
+\r
+               ib_service.svc_rec.service_id =\r
+                       ATS_SERVICE_ID & CL_HTON64(0xFFFFFFFFFFFFFF00);\r
+               /* ATS service IDs start at 0x10000CE100415453 */\r
+               ib_service.svc_rec.service_id |= ((uint64_t)(idx + 0x53)) << 56;\r
+\r
+               cl_memcpy( &ib_service.svc_rec.service_data8[ATS_IPV4_OFFSET],\r
+                       p_addr_item->address.as_bytes, IPV4_ADDR_SIZE );\r
+\r
+               /* Take a reference for each service request. */\r
+               cl_obj_ref(&p_adapter->obj);\r
+               ib_status = p_adapter->p_ifc->reg_svc(\r
+                       p_adapter->h_al, &ib_service, &p_addr_item->p_reg->h_reg_svc );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       if( ib_status == IB_INVALID_GUID )\r
+                       {\r
+                               /* If this occurs, we log the error but do not fail the OID yet */\r
+                               IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
+                                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
+                                       "Failed to register IP Address "\r
+                                       "of %d.%d.%d.%d with error IB_INVALID_GUID\n",\r
+                                       port_num,\r
+                                       p_addr_item->address.as_bytes[0],\r
+                                       p_addr_item->address.as_bytes[1],\r
+                                       p_addr_item->address.as_bytes[2],\r
+                                       p_addr_item->address.as_bytes[3]) );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Fatal error. */\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address "\r
+                                       "of %d.%d.%d.%d with error %s\n",\r
+                                       port_num,\r
+                                       p_addr_item->address.as_bytes[0],\r
+                                       p_addr_item->address.as_bytes[1],\r
+                                       p_addr_item->address.as_bytes[2],\r
+                                       p_addr_item->address.as_bytes[3],\r
+                                       p_adapter->p_ifc->get_err_str( ib_status )) );\r
+                               p_adapter->hung = TRUE;\r
+                       }\r
+                       cl_obj_deref(&p_adapter->obj);\r
+                       cl_free( p_addr_item->p_reg );\r
+                       p_addr_item->p_reg = NULL;\r
+               }\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
+\r
+\r
+/* Object lock is held when this function is called. */\r
+void\r
+ipoib_dereg_addrs(\r
+       IN                              ipoib_adapter_t* const          p_adapter )\r
+{\r
+       net_address_item_t              *p_addr_item;\r
+\r
+       size_t                                  idx;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ )\r
+       {\r
+               p_addr_item = (net_address_item_t*)\r
+                       cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
+\r
+               if( !p_addr_item->p_reg )\r
+                       continue;\r
+\r
+               if( p_addr_item->p_reg->h_reg_svc )\r
+               {\r
+                       p_adapter->p_ifc->dereg_svc(\r
+                               p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
+               }\r
+               else\r
+               {\r
+                       cl_free( p_addr_item->p_reg );\r
+               }\r
+               p_addr_item->p_reg = NULL;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
+\r
+\r
+void\r
+ipoib_cancel_xmit(\r
+       IN                              NDIS_HANDLE             adapter_context,\r
+       IN                              PVOID                   cancel_id )\r
+{\r
+/*     ipoib_adapter_t* const p_adapter =\r
+               (ipoib_adapter_t* const )adapter_context;\r
+       \r
+\r
+if 0\r
+       if( p_adapter && p_adapter->p_port )\r
+       {\r
+               ipoib_port_cancel_xmit( p_adapter->p_port, cancel_id );\r
+       }\r
+endif\r
+*/\r
+\r
+       UNUSED_PARAM(adapter_context);\r
+       UNUSED_PARAM(cancel_id);\r
+\r
+       return; //TODO return this functionality\r
+\r
+}\r
+\r
+\r
+static void\r
+__ipoib_ats_reg_cb(\r
+       IN                              ib_reg_svc_rec_t                        *p_reg_svc_rec )\r
+{\r
+       ats_reg_t                               *p_reg;\r
+       uint8_t                                 port_num;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+\r
+       CL_ASSERT( p_reg_svc_rec );\r
+       CL_ASSERT( p_reg_svc_rec->svc_context );\r
+\r
+       p_reg = (ats_reg_t*)p_reg_svc_rec->svc_context;\r
+       port_num = p_reg->p_adapter->guids.port_num;\r
+\r
+       cl_obj_lock( &p_reg->p_adapter->obj );\r
+\r
+       if( p_reg_svc_rec->req_status == IB_SUCCESS &&\r
+               !p_reg_svc_rec->resp_status )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
+                                        ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Registered IP Address "\r
+                                         "of %d.%d.%d.%d\n",\r
+                                         port_num,\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET],\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1],\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2],\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3]) );\r
+       }\r
+       else if( p_reg_svc_rec->req_status != IB_CANCELED )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OID,\r
+                                        ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address "\r
+                                         "of %d.%d.%d.%d with error %s\n",\r
+                                         port_num,\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET],\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1],\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2],\r
+                                         p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3],\r
+                                         p_reg->p_adapter->p_ifc->get_err_str( p_reg_svc_rec->resp_status )) );\r
+               p_reg->p_adapter->hung = TRUE;\r
+               p_reg->h_reg_svc = NULL;\r
+       }\r
+\r
+       cl_obj_unlock( &p_reg->p_adapter->obj );\r
+       cl_obj_deref(&p_reg->p_adapter->obj);\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
+\r
+\r
+static void\r
+__ipoib_ats_dereg_cb(\r
+       IN                              void                                            *context )\r
+{\r
+       cl_free( context );\r
+}\r
+\r
+static NDIS_STATUS \r
+ipoib_pause(\r
+    IN  NDIS_HANDLE                         adapter_context,    \r
+    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS     pause_parameters)\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+\r
+       UNREFERENCED_PARAMETER(pause_parameters);\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+//return NDIS_STATUS_SUCCESS;\r
+       CL_ASSERT(adapter_context);\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+       CL_ASSERT(p_adapter->ipoib_state == IPOIB_RUNNING);\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+       p_adapter->ipoib_state = IPOIB_PAUSING;\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+       //TODO: \r
+       ipoib_port_resume(p_adapter->p_port,FALSE);\r
+//     ASSERT(FALSE);\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+       p_adapter->ipoib_state = IPOIB_PAUSED;\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static NDIS_STATUS \r
+ipoib_restart(\r
+    IN  NDIS_HANDLE                         adapter_context,    \r
+    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   restart_parameters)\r
+{\r
+       ipoib_adapter_t         *p_adapter;\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+    PNDIS_RESTART_ATTRIBUTES     NdisRestartAttributes;\r
+    PNDIS_RESTART_GENERAL_ATTRIBUTES  NdisGeneralAttributes;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+       NdisRestartAttributes = restart_parameters->RestartAttributes;\r
+\r
+    if (NdisRestartAttributes != NULL)\r
+    {\r
+        CL_ASSERT(NdisRestartAttributes->Oid == OID_GEN_MINIPORT_RESTART_ATTRIBUTES);\r
+        NdisGeneralAttributes = (PNDIS_RESTART_GENERAL_ATTRIBUTES)NdisRestartAttributes->Data;   \r
+        //\r
+        // Check to see if we need to change any attributes\r
+    }\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+       p_adapter->ipoib_state = IPOIB_RUNNING;\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+    return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+/*++\r
+Routine Description:\r
+\r
+    This function aborts the request pending in the miniport.\r
+\r
+Arguments:\r
+\r
+    MiniportAdapterContext  Pointer to the adapter structure\r
+    RequestId               Specify the request to be cancelled.\r
+    \r
+Return Value:\r
+    \r
+--*/\r
+static void\r
+ipoib_cancel_oid_request(\r
+    IN  NDIS_HANDLE            adapter_context,\r
+    IN  PVOID                  requestId\r
+    )\r
+{\r
+    PNDIS_OID_REQUEST    pending_request;\r
+       ipoib_adapter_t          *p_adapter;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_OID );\r
+       p_adapter = (ipoib_adapter_t*)adapter_context;\r
+\r
+    cl_obj_lock( &p_adapter->obj );\r
+    \r
+    if ( p_adapter->query_oid.p_pending_oid &&\r
+               p_adapter->query_oid.p_pending_oid->RequestId == requestId)\r
+       {\r
+               pending_request = p_adapter->query_oid.p_pending_oid;\r
+               p_adapter->query_oid.p_pending_oid = NULL;\r
+               p_adapter->pending_query = FALSE;\r
+       }\r
+       else if(p_adapter->set_oid.p_pending_oid && \r
+                       p_adapter->set_oid.p_pending_oid->RequestId == requestId)\r
+       {\r
+                pending_request = p_adapter->set_oid.p_pending_oid;\r
+                p_adapter->set_oid.p_pending_oid = NULL;\r
+                p_adapter->pending_set = FALSE;\r
+       }\r
+       else\r
+       {\r
+               cl_obj_unlock( &p_adapter->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+               ("No Pending OID found\n") );\r
+               return;\r
+       }\r
+    cl_obj_unlock( &p_adapter->obj );\r
+\r
+    NdisMOidRequestComplete(p_adapter->h_adapter, \r
+                            pending_request, \r
+                            NDIS_STATUS_REQUEST_ABORTED);\r
+\r
+    IPOIB_EXIT( IPOIB_DBG_OID );\r
+}\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.h b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_driver.h
new file mode 100644 (file)
index 0000000..0e3b7f2
--- /dev/null
@@ -0,0 +1,166 @@
+/*\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: ipoib_driver.h 4494 2009-06-22 14:31:08Z xalex $\r
+ */\r
+\r
+\r
+#ifndef _IPOIB_DRIVER_H_\r
+#define _IPOIB_DRIVER_H_\r
+\r
+\r
+#include "ipoib_log.h"\r
+#include "ipoib_adapter.h"\r
+#include <complib/cl_spinlock.h>\r
+#include <complib/cl_qlist.h>\r
+#include "ipoib_debug.h"\r
+\r
+\r
+/*\r
+ * Definitions\r
+ */\r
+#define MAX_BUNDLE_ID_LENGTH   32\r
+\r
+/* The maximum number of send packets the MiniportSendPackets function can accept */\r
+#define MINIPORT_MAX_SEND_PACKETS      200\r
+\r
+/* MLX4 supports 4K MTU */\r
+#define MAX_IB_MTU                     4096\r
+#define DEFAULT_MTU                    2048\r
+/*\r
+ * Header length as defined by IPoIB spec:\r
+ * http://www.ietf.org/internet-drafts/draft-ietf-ipoib-ip-over-infiniband-04.txt\r
+ */\r
\r
+#define MAX_UD_PAYLOAD_MTU             (MAX_IB_MTU - sizeof(ipoib_hdr_t))\r
+#define DEFAULT_PAYLOAD_MTU            (DEFAULT_MTU - sizeof(ipoib_hdr_t))\r
+#define MAX_CM_PAYLOAD_MTU             (65520)\r
+#define MAX_WRS_PER_MSG                        ((MAX_CM_PAYLOAD_MTU/DEFAULT_PAYLOAD_MTU)+1)\r
+/*\r
+ * Only the protocol type is sent as part of the UD payload\r
+ * since the rest of the Ethernet header is encapsulated in the\r
+ * various IB headers.  We report out buffer space as if we\r
+ * transmit the ethernet headers.\r
+ */\r
+#define MAX_XFER_BLOCK_SIZE            (sizeof(eth_hdr_t) + MAX_UD_PAYLOAD_MTU)\r
+#define DATA_OFFSET                            (sizeof(eth_hdr_t) - sizeof(ipoib_hdr_t))\r
+\r
+#define IPOIB_CM_FLAG_RC               (0x80)\r
+#define IPOIB_CM_FLAG_UC               (0x40)\r
+#define IPOIB_CM_FLAG_SVCID            (0x10) // OFED set IETF bit this way ( open OFED PR 1121 )\r
+\r
+#define MAX_SEND_SGE                   (8)\r
+\r
+/* Amount of physical memory to register. */\r
+#define MEM_REG_SIZE   0xFFFFFFFFFFFFFFFF\r
+\r
+/* Number of work completions to chain for send and receive polling. */\r
+#define MAX_SEND_WC            5\r
+#define MAX_RECV_WC            16\r
+\r
+typedef struct _ipoib_globals\r
+{\r
+       KSPIN_LOCK              lock;\r
+       cl_qlist_t              adapter_list;\r
+       cl_qlist_t              bundle_list;\r
+\r
+       atomic32_t              laa_idx;\r
+\r
+       NDIS_HANDLE             h_ndis_wrapper;\r
+       PDEVICE_OBJECT  h_ibat_dev;\r
+       NDIS_HANDLE             h_ibat_dev_handle;      //MSDN: this handle is a required parameter to the \r
+                                                                               //NdisDeregisterDeviceEx function that the driver calls subsequently\r
+       volatile LONG   ibat_ref;\r
+       uint32_t                bypass_check_bcast_rate;\r
+\r
+}      ipoib_globals_t;\r
+/*\r
+* FIELDS\r
+*      lock\r
+*              Spinlock to protect list access.\r
+*\r
+*      adapter_list\r
+*              List of all adapter instances.  Used for address translation support.\r
+*\r
+*      bundle_list\r
+*              List of all adapter bundles.\r
+*\r
+*      laa_idx\r
+*              Global counter for generating LAA MACs\r
+*\r
+*      h_ibat_dev\r
+*              Device handle returned by NdisMRegisterDevice.\r
+*********/\r
+\r
+extern ipoib_globals_t g_ipoib;\r
+extern NDIS_HANDLE             g_IpoibMiniportDriverHandle;\r
+\r
+\r
+\r
+typedef struct _ipoib_bundle\r
+{\r
+       cl_list_item_t  list_item;\r
+       char                    bundle_id[MAX_BUNDLE_ID_LENGTH];\r
+       cl_qlist_t              adapter_list;\r
+\r
+}      ipoib_bundle_t;\r
+/*\r
+* FIELDS\r
+*      list_item\r
+*              List item for storing the bundle in a quick list.\r
+*\r
+*      bundle_id\r
+*              Bundle identifier.\r
+*\r
+*      adapter_list\r
+*              List of adapters in the bundle.  The adapter at the head is the\r
+*              primary adapter of the bundle.\r
+*********/\r
+void\r
+ipoib_create_log(\r
+       NDIS_HANDLE h_adapter,\r
+       UINT ind,\r
+       ULONG eventLogMsgId);\r
+\r
+#define GUID_MASK_LOG_INDEX 0\r
+\r
+void\r
+ipoib_resume_oids(\r
+       IN                              ipoib_adapter_t* const          p_adapter );\r
+\r
+#define IPOIB_OFFSET(field)   ((UINT)FIELD_OFFSET(ipoib_params_t,field))\r
+#define IPOIB_SIZE(field)     sizeof(((ipoib_params_t*)0)->field)\r
+#define IPOIB_INIT_NDIS_STRING(str)                        \\r
+    (str)->Length = 0;                                  \\r
+    (str)->MaximumLength = 0;                           \\r
+    (str)->Buffer = NULL;\r
+\r
+\r
+\r
+#endif /* _IPOIB_DRIVER_H_ */\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_endpoint.c b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_endpoint.c
new file mode 100644 (file)
index 0000000..1e82e5a
--- /dev/null
@@ -0,0 +1,1170 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_endpoint.c 4226 2009-04-06 06:01:03Z xalex $\r
+ */\r
+\r
+\r
+\r
+#include "ipoib_endpoint.h"\r
+#include "ipoib_port.h"\r
+#include "ipoib_debug.h"\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_endpoint.tmh"\r
+#endif\r
+#include <complib/cl_atomic.h>\r
+#include <complib/cl_math.h>\r
+\r
+\r
+static void\r
+__endpt_destroying(\r
+       IN                              cl_obj_t*                                       p_obj );\r
+\r
+static void\r
+__endpt_cleanup(\r
+       IN                              cl_obj_t*                                       p_obj );\r
+\r
+static void\r
+__endpt_free(\r
+       IN                              cl_obj_t*                                       p_obj );\r
+\r
+static ib_api_status_t\r
+__create_mcast_av(\r
+       IN                              ib_pd_handle_t                          h_pd,\r
+       IN                              uint8_t                                         port_num,\r
+       IN                              ib_member_rec_t* const          p_member_rec,\r
+               OUT                     ib_av_handle_t* const           ph_av );\r
+\r
+static inline ipoib_port_t*\r
+__endpt_parent(\r
+       IN                              ipoib_endpt_t* const            p_endpt );\r
+\r
+static void\r
+__path_query_cb(\r
+       IN                              ib_query_rec_t                          *p_query_rec );\r
+\r
+static void\r
+__endpt_resolve(\r
+       IN                              ipoib_endpt_t* const            p_endpt );\r
+\r
+static void\r
+__endpt_cm_send_cb(\r
+       IN              const   ib_cq_handle_t                  h_cq,\r
+       IN                              void                                    *cq_context );\r
+static void\r
+__endpt_cm_recv_cb(\r
+       IN              const   ib_cq_handle_t                  h_cq,\r
+       IN                              void                                    *cq_context );\r
+\r
+static void\r
+__endpt_cm_buf_mgr_construct(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr );\r
+static void\r
+__conn_reply_cb(\r
+       IN              ib_cm_rep_rec_t                 *p_cm_rep );\r
+\r
+static void\r
+__conn_mra_cb(\r
+       IN              ib_cm_mra_rec_t                 *p_mra_rec );\r
+\r
+static void\r
+__conn_rej_cb(\r
+       IN              ib_cm_rej_rec_t                 *p_rej_rec );\r
+\r
+static void\r
+__conn_dreq_cb(\r
+        IN     ib_cm_dreq_rec_t                        *p_dreq_rec );\r
+\r
+#if 0 //CM\r
+static cl_status_t\r
+__cm_recv_desc_ctor(\r
+       IN              void* const                                     p_object,\r
+       IN              void*                                           context,\r
+       OUT             cl_pool_item_t** const          pp_pool_item );\r
+\r
+static void\r
+__cm_recv_desc_dtor(\r
+       IN              const   cl_pool_item_t* const           p_pool_item,\r
+       IN                              void                                            *context );\r
+\r
+static NDIS_PACKET*\r
+__endpt_cm_get_ndis_pkt(\r
+       IN              ipoib_port_t* const                     p_port,\r
+       IN              ipoib_cm_desc_t* const          p_desc );\r
+\r
+static inline ipoib_cm_desc_t*\r
+__endpt_cm_buf_mgr_get_recv(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr );\r
+\r
+static boolean_t\r
+__cm_recv_is_dhcp(\r
+       IN              const ipoib_pkt_t* const        p_ipoib );\r
+\r
+static ib_api_status_t\r
+__endpt_cm_recv_arp(\r
+       IN              ipoib_port_t* const                     p_port,\r
+       IN              const   ipoib_pkt_t* const      p_ipoib,\r
+       OUT             eth_pkt_t* const                        p_eth,\r
+       IN              ipoib_endpt_t* const            p_src_endpt );\r
+\r
+static ib_api_status_t\r
+__endpt_cm_recv_udp(\r
+       IN              ipoib_port_t* const                     p_port,\r
+       IN              ib_wc_t* const                          p_wc,\r
+       IN              const   ipoib_pkt_t* const      p_ipoib,\r
+       OUT             eth_pkt_t* const                        p_eth,\r
+       IN              ipoib_endpt_t* const            p_src_endpt );\r
+#endif\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_create(\r
+       IN              const   ib_gid_t* const                         p_dgid,\r
+       IN              const   net16_t                                         dlid,\r
+       IN              const   net32_t                                         qpn )\r
+{\r
+       ipoib_endpt_t   *p_endpt;\r
+       cl_status_t             status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       p_endpt = cl_zalloc( sizeof(ipoib_endpt_t) );\r
+       if( !p_endpt )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate endpoint (%d bytes)\n",\r
+                       sizeof(ipoib_endpt_t)) );\r
+               return NULL;\r
+       }\r
+\r
+       cl_obj_construct( &p_endpt->obj, IPOIB_OBJ_ENDPOINT );\r
+\r
+       status = cl_obj_init( &p_endpt->obj, CL_DESTROY_ASYNC,\r
+               __endpt_destroying, __endpt_cleanup, __endpt_free );\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+               ("Created endpoint: [ %p ] DLID: %#x QPN: %#x \n", \r
+               p_endpt, cl_ntoh16(dlid), cl_ntoh32(qpn) ) );\r
+\r
+       p_endpt->dgid = *p_dgid;\r
+       p_endpt->dlid = dlid;\r
+       p_endpt->qpn = qpn;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return p_endpt;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__create_mcast_av(\r
+       IN                              ib_pd_handle_t                          h_pd,\r
+       IN                              uint8_t                                         port_num,\r
+       IN                              ib_member_rec_t* const          p_member_rec,\r
+               OUT                     ib_av_handle_t* const           ph_av )\r
+{\r
+       ib_av_attr_t    av_attr;\r
+       uint32_t                flow_lbl;\r
+       uint8_t                 hop_lmt;\r
+       ib_api_status_t status;\r
+       ipoib_endpt_t   *p_endpt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+       p_endpt = PARENT_STRUCT(ph_av, ipoib_endpt_t, h_av );\r
+\r
+       cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
+       av_attr.port_num = port_num;\r
+       ib_member_get_sl_flow_hop( p_member_rec->sl_flow_hop,\r
+               &av_attr.sl, &flow_lbl, &hop_lmt );\r
+       av_attr.dlid = p_member_rec->mlid;\r
+       av_attr.grh_valid = TRUE;\r
+       av_attr.grh.hop_limit = hop_lmt;\r
+       av_attr.grh.dest_gid = p_member_rec->mgid;\r
+       av_attr.grh.src_gid = p_member_rec->port_gid;\r
+       av_attr.grh.ver_class_flow =\r
+               ib_grh_set_ver_class_flow( 6, p_member_rec->tclass, flow_lbl );\r
+       av_attr.static_rate = p_member_rec->rate & IB_PATH_REC_BASE_MASK;\r
+       av_attr.path_bits = 0;\r
+       /* port is not attached to endpoint at this point, so use endpt ifc reference */\r
+       status = p_endpt->p_ifc->create_av( h_pd, &av_attr, ph_av );\r
+\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_av returned %s\n",\r
+                       p_endpt->p_ifc->get_err_str( status )) );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+       return status;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ipoib_endpt_set_mcast(\r
+       IN                              ipoib_endpt_t* const            p_endpt,\r
+       IN                              ib_pd_handle_t                          h_pd,\r
+       IN                              uint8_t                                         port_num,\r
+       IN                              ib_mcast_rec_t* const           p_mcast_rec )\r
+{\r
+       ib_api_status_t status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+               ("Create av for MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+               p_endpt->mac.addr[0], p_endpt->mac.addr[1],\r
+               p_endpt->mac.addr[2], p_endpt->mac.addr[3],\r
+               p_endpt->mac.addr[4], p_endpt->mac.addr[5]) );\r
+               \r
+       status = __create_mcast_av( h_pd, port_num, p_mcast_rec->p_member_rec,\r
+               &p_endpt->h_av );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__create_mcast_av returned %s\n", \r
+                       p_endpt->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+       p_endpt->h_mcast = p_mcast_rec->h_mcast;\r
+       CL_ASSERT(p_endpt->dlid == 0);\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+__endpt_destroying(\r
+       IN                              cl_obj_t*                                       p_obj )\r
+{\r
+       ipoib_endpt_t   *p_endpt;\r
+       ipoib_port_t    *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
+       p_port = __endpt_parent( p_endpt );\r
+\r
+       cl_obj_lock( p_obj );\r
+       if( p_endpt->h_query )\r
+       {\r
+               p_port->p_adapter->p_ifc->cancel_query(\r
+                       p_port->p_adapter->h_al, p_endpt->h_query );\r
+               p_endpt->h_query = NULL;\r
+       }\r
+\r
+       /* Leave the multicast group if it exists. */\r
+       if( p_endpt->h_mcast )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+                       ("Leaving MCast group\n") );\r
+               ipoib_port_ref(p_port, ref_leave_mcast);\r
+               p_port->p_adapter->p_ifc->leave_mcast( p_endpt->h_mcast, ipoib_leave_mcast_cb );\r
+       }\r
+#if 0\r
+       else if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               p_endpt->cm_flag = 0;\r
+               CL_ASSERT( endpt_cm_get_state( p_endpt ) == IPOIB_CM_DISCONNECTED );\r
+       }\r
+#endif\r
+\r
+       cl_obj_unlock( p_obj );\r
+       \r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+static void\r
+__endpt_cleanup(\r
+       IN                              cl_obj_t*                                       p_obj )\r
+{\r
+       ipoib_endpt_t   *p_endpt;\r
+       ipoib_port_t    *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
+       p_port = __endpt_parent( p_endpt );\r
+\r
+       /* Destroy the AV if it exists. */\r
+       if( p_endpt->h_av )\r
+               p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+static void\r
+__endpt_free(\r
+       IN                              cl_obj_t*                                       p_obj )\r
+{\r
+       ipoib_endpt_t   *p_endpt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       p_endpt = PARENT_STRUCT( p_obj, ipoib_endpt_t, obj );\r
+\r
+       cl_obj_deinit( p_obj );\r
+       cl_free( p_endpt );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+static inline ipoib_port_t*\r
+__endpt_parent(\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       return PARENT_STRUCT( p_endpt->rel.p_parent_obj, ipoib_port_t, obj );\r
+}\r
+\r
+ipoib_port_t*\r
+ipoib_endpt_parent(\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       return __endpt_parent( p_endpt );\r
+}\r
+\r
+/*\r
+ * This function is called with the port object's send lock held and\r
+ * a reference held on the endpoint.  If we fail, we release the reference.\r
+ */\r
+NDIS_STATUS\r
+ipoib_endpt_queue(\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       ib_api_status_t status;\r
+       ipoib_port_t    *p_port;\r
+       ib_av_attr_t    av_attr;\r
+       net32_t                 flow_lbl;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       if( p_endpt->h_av )\r
+       {\r
+               IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+               return NDIS_STATUS_SUCCESS;\r
+       }\r
+\r
+       if( p_endpt->qpn == CL_HTON32(0x00FFFFFF) )\r
+       {\r
+               /*\r
+                * Handle a race between the mcast callback and a receive/send.  The QP\r
+                * is joined to the MC group before the MC callback is received, so it\r
+                * can receive packets, and NDIS can try to respond.  We need to delay\r
+                * a response until the MC callback runs and sets the AV.\r
+                */\r
+               ipoib_endpt_deref( p_endpt );\r
+               IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+               return NDIS_STATUS_PENDING;\r
+       }\r
+\r
+       /* This is the first packet for this endpoint.  Create the AV. */\r
+       p_port = __endpt_parent( p_endpt );\r
+\r
+       cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
+\r
+       av_attr.port_num = p_port->port_num;\r
+\r
+       ib_member_get_sl_flow_hop(\r
+               p_port->ib_mgr.bcast_rec.sl_flow_hop,\r
+               &av_attr.sl,\r
+               &flow_lbl,\r
+               &av_attr.grh.hop_limit\r
+               );\r
+\r
+       av_attr.dlid = p_endpt->dlid;\r
+\r
+       /*\r
+        * We always send the GRH so that we preferably lookup endpoints\r
+        * by GID rather than by LID.  This allows certain WHQL tests\r
+        * such as the 2c_MediaCheck test to succeed since they don't use\r
+        * IP.  This allows endpoints to be created on the fly for requests\r
+        * for which there is no match, something that doesn't work when\r
+        * using LIDs only.\r
+        */\r
+       av_attr.grh_valid = TRUE;\r
+       av_attr.grh.ver_class_flow = ib_grh_set_ver_class_flow(\r
+               6, p_port->ib_mgr.bcast_rec.tclass, flow_lbl );\r
+       av_attr.grh.resv1 = 0;\r
+       av_attr.grh.resv2 = 0;\r
+       ib_gid_set_default( &av_attr.grh.src_gid, p_port->p_adapter->guids.port_guid.guid );\r
+       av_attr.grh.dest_gid = p_endpt->dgid;\r
+\r
+       av_attr.static_rate = p_port->ib_mgr.bcast_rec.rate;\r
+       av_attr.path_bits = 0;\r
+\r
+       /* Create the AV. */\r
+       status = p_port->p_adapter->p_ifc->create_av(\r
+               p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               p_port->p_adapter->hung = TRUE;\r
+               ipoib_endpt_deref( p_endpt );\r
+               cl_obj_unlock( &p_endpt->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_av failed with %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return NDIS_STATUS_FAILURE;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+#if 0\r
+\r
+static void\r
+__endpt_cm_buf_mgr_construct(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       cl_qpool_construct( &p_buf_mgr->recv_pool );\r
+\r
+       p_buf_mgr->h_packet_pool = NULL;\r
+       p_buf_mgr->h_buffer_pool = NULL;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+ib_api_status_t\r
+endpt_cm_buf_mgr_init(\r
+       IN                              ipoib_port_t* const                             p_port )\r
+{\r
+       cl_status_t             cl_status;\r
+       NDIS_STATUS             ndis_status;\r
+       ib_api_status_t ib_status = IB_SUCCESS;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       if( p_port->cm_buf_mgr.pool_init )\r
+               return ib_status;\r
+\r
+       cl_qlist_init( &p_port->cm_buf_mgr.posted_list );\r
+\r
+       __endpt_cm_buf_mgr_construct( &p_port->cm_buf_mgr );\r
+       p_port->cm_recv_mgr.rq_depth = \r
+               min( (uint32_t)p_port->p_adapter->params.rq_depth * 8,\r
+                               p_port->p_ca_attrs->max_srq_wrs/2 );\r
+       p_port->cm_recv_mgr.depth = 0;\r
+       /* Allocate the receive descriptors pool */\r
+       cl_status = cl_qpool_init( &p_port->cm_buf_mgr.recv_pool,\r
+               p_port->cm_recv_mgr.rq_depth ,\r
+               0,\r
+               0,\r
+               sizeof( ipoib_cm_desc_t ),\r
+               __cm_recv_desc_ctor,\r
+               __cm_recv_desc_dtor,\r
+               p_port );\r
+\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_POOL, 1, cl_status );\r
+               \r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_qpool_init for cm recvs returned %#x\n", cl_status) );\r
+               \r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       /* Allocate the NDIS buffer and packet pools for receive indication. */\r
+       NdisAllocatePacketPool( &ndis_status, \r
+                                                       &p_port->cm_buf_mgr.h_packet_pool,\r
+                                                       p_port->cm_recv_mgr.rq_depth, \r
+                                                       PROTOCOL_RESERVED_SIZE_IN_PACKET );\r
+       if( ndis_status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_PKT_POOL, 1, ndis_status );\r
+\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisAllocatePacketPool returned %08X\n", ndis_status) );\r
+               \r
+               ib_status = IB_INSUFFICIENT_RESOURCES;\r
+               goto pkt_pool_failed;\r
+       }\r
+\r
+       NdisAllocateBufferPool( &ndis_status, \r
+                                                       &p_port->cm_buf_mgr.h_buffer_pool,\r
+                                                       p_port->cm_recv_mgr.rq_depth );\r
+       if( ndis_status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_BUF_POOL, 1, ndis_status );\r
+               \r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
+               \r
+               ib_status = IB_INSUFFICIENT_RESOURCES;\r
+               goto buf_pool_failed;\r
+       }\r
+       //NDIS60\r
+       //p_port->cm_recv_mgr.recv_pkt_array = \r
+               //cl_zalloc( sizeof(NDIS_PACKET*) * p_port->cm_recv_mgr.rq_depth );\r
+       p_port->cm_recv_mgr.recv_lst_array = \r
+               cl_zalloc( sizeof(NET_BUFFER_LIST*) * p_port->cm_recv_mgr.rq_depth );\r
+       \r
+               \r
+\r
+       if( !p_port->cm_recv_mgr.recv_pkt_array )\r
+       {\r
+               //NDIS60\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_zalloc for NET_BUFFER_LIST array failed.\n") );\r
+               \r
+               ib_status = IB_INSUFFICIENT_MEMORY;\r
+               goto pkt_array_failed;\r
+       }\r
+\r
+       p_port->cm_buf_mgr.pool_init = TRUE;\r
+       return IB_SUCCESS;\r
+\r
+pkt_array_failed:\r
+       if( p_port->cm_buf_mgr.h_buffer_pool )\r
+               NdisFreeBufferPool( p_port->cm_buf_mgr.h_buffer_pool );\r
+buf_pool_failed:\r
+       if( p_port->cm_buf_mgr.h_packet_pool )\r
+               NdisFreePacketPool( p_port->cm_buf_mgr.h_packet_pool );\r
+pkt_pool_failed:\r
+               cl_qpool_destroy( &p_port->cm_buf_mgr.recv_pool );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return ib_status;\r
+}\r
+\r
+void\r
+endpt_cm_buf_mgr_reset(\r
+       IN              ipoib_port_t* const             p_port )\r
+{\r
+       cl_list_item_t          *p_item;\r
+\r
+       if( !p_port->cm_buf_mgr.pool_init )\r
+               return;\r
+\r
+       if( cl_qlist_count( &p_port->cm_buf_mgr.posted_list ) )\r
+       {\r
+               for( p_item = cl_qlist_remove_head( &p_port->cm_buf_mgr.posted_list );\r
+                       p_item != cl_qlist_end( &p_port->cm_buf_mgr.posted_list );\r
+                       p_item =  cl_qlist_remove_head( &p_port->cm_buf_mgr.posted_list ) )\r
+               {\r
+                       cl_qpool_put( &p_port->cm_buf_mgr.recv_pool, \r
+                               &( PARENT_STRUCT( p_item, ipoib_cm_desc_t, list_item ))->item );\r
+               }\r
+       }\r
+}\r
+\r
+void\r
+endpt_cm_buf_mgr_destroy(\r
+       IN              ipoib_port_t* const             p_port )\r
+{\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_port );\r
+       \r
+       /* Free the receive descriptors. */\r
+       if( !p_port->cm_buf_mgr.pool_init )\r
+               return;\r
+\r
+       endpt_cm_buf_mgr_reset( p_port );\r
+\r
+       p_port->cm_buf_mgr.pool_init = FALSE;\r
+       \r
+       if( p_port->cm_recv_mgr.recv_pkt_array )\r
+       {\r
+               cl_free( p_port->cm_recv_mgr.recv_pkt_array );\r
+       }\r
+\r
+       /* Destroy the receive packet and buffer pools. */\r
+       if( p_port->cm_buf_mgr.h_buffer_pool )\r
+               NdisFreeBufferPool( p_port->cm_buf_mgr.h_buffer_pool );\r
+       if( p_port->cm_buf_mgr.h_packet_pool )\r
+               NdisFreePacketPool( p_port->cm_buf_mgr.h_packet_pool );\r
+\r
+       cl_qpool_destroy( &p_port->cm_buf_mgr.recv_pool );\r
+       \r
+       IPOIB_EXIT(  IPOIB_DBG_INIT );\r
+}\r
+\r
+static cl_status_t\r
+__cm_recv_desc_ctor(\r
+       IN                              void* const                                     p_object,\r
+       IN                              void*                                           context,\r
+               OUT                     cl_pool_item_t** const          pp_pool_item )\r
+{\r
+       ipoib_cm_desc_t*        p_desc;\r
+       ipoib_port_t*           p_port;\r
+       ib_mr_create_t          create_mr;\r
+       net32_t                         rkey;\r
+\r
+       CL_ASSERT( p_object );\r
+       CL_ASSERT( context );\r
+\r
+       p_desc = (ipoib_cm_desc_t*)p_object;\r
+       p_port = (ipoib_port_t*)context;\r
+\r
+#define BUF_ALIGN              (16)\r
+\r
+       p_desc->alloc_buf_size = \r
+               ROUNDUP( p_port->p_adapter->params.cm_xfer_block_size, BUF_ALIGN );\r
+       \r
+       p_desc->p_alloc_buf = (uint8_t *)ExAllocatePoolWithTag( \r
+               NonPagedPool, p_desc->alloc_buf_size, 'DOMC' );\r
+\r
+       if( p_desc->p_alloc_buf == NULL )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate receive buffer size %d bytes.\n", p_desc->alloc_buf_size ) );\r
+               return CL_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       create_mr.vaddr  = p_desc->p_alloc_buf;\r
+       create_mr.length  = p_desc->alloc_buf_size;\r
+       create_mr.access_ctrl = IB_AC_LOCAL_WRITE;\r
+\r
+       \r
+       if( p_port->p_adapter->p_ifc->reg_mem( \r
+                                                       p_port->ib_mgr.h_pd,\r
+                                                       &create_mr,\r
+                                                       &p_desc->lkey,\r
+                                                       &rkey,\r
+                                                       &p_desc->h_mr ) != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to create Memory Region size %d bytes.\n", p_desc->alloc_buf_size ) );\r
+               goto ctor_failed;\r
+       }\r
+       p_desc->p_buf = p_desc->p_alloc_buf + (BUF_ALIGN - sizeof( ipoib_hdr_t));\r
+       p_desc->buf_size = p_desc->alloc_buf_size - (BUF_ALIGN - sizeof( ipoib_hdr_t));\r
+\r
+       /* Setup the local data segment. */\r
+       p_desc->local_ds[0].vaddr = (uint64_t)(uintn_t)p_desc->p_buf;\r
+       p_desc->local_ds[0].length = p_desc->buf_size;\r
+       p_desc->local_ds[0].lkey = p_desc->lkey;\r
+\r
+       /* Setup the work request. */\r
+       p_desc->wr.wr_id = (uintn_t)p_desc;\r
+       p_desc->wr.ds_array = p_desc->local_ds;\r
+       p_desc->wr.num_ds = 1;\r
+       p_desc->type = PKT_TYPE_CM_UCAST;\r
+       \r
+       *pp_pool_item = &p_desc->item;\r
+       return CL_SUCCESS;\r
+\r
+ctor_failed:\r
+       ExFreePoolWithTag( p_desc->p_alloc_buf, 'DOMC' );\r
+       return CL_INSUFFICIENT_MEMORY;\r
+}\r
+\r
+static void\r
+__cm_recv_desc_dtor(\r
+       IN              const   cl_pool_item_t* const           p_pool_item,\r
+       IN                              void                                            *context )\r
+{\r
+       ipoib_cm_desc_t *p_desc;\r
+       ipoib_port_t*   p_port;\r
+\r
+       if( p_pool_item == NULL || context == NULL )\r
+               return;\r
+\r
+       p_port = (ipoib_port_t*)context;\r
+       p_desc = PARENT_STRUCT( p_pool_item, ipoib_cm_desc_t, item );\r
+\r
+       if( p_desc->h_mr )\r
+               p_port->p_adapter->p_ifc->dereg_mr( p_desc->h_mr );\r
+\r
+       if( p_desc->p_alloc_buf )\r
+               ExFreePoolWithTag( p_desc->p_alloc_buf, 'DOMC' );\r
+}\r
+\r
+\r
+static NDIS_PACKET*\r
+__endpt_cm_get_ndis_pkt(\r
+       IN              ipoib_port_t* const                     p_port,\r
+       IN              ipoib_cm_desc_t* const  p_desc )\r
+{\r
+       NDIS_STATUS                             status;\r
+       NDIS_PACKET                             *p_packet;\r
+       NDIS_BUFFER                             *p_buffer;\r
+       \r
+       IPOIB_ENTER(  IPOIB_DBG_RECV );\r
+\r
+       NdisDprAllocatePacketNonInterlocked( &status, &p_packet,\r
+                       p_port->cm_buf_mgr.h_packet_pool );\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate NDIS_PACKET: %08x\n", status) );\r
+               return NULL;\r
+       }\r
+\r
+       IPOIB_PORT_FROM_PACKET( p_packet ) = p_port;\r
+       IPOIB_RECV_FROM_PACKET( p_packet ) = p_desc;\r
+\r
+       NdisAllocateBuffer( \r
+                       &status, \r
+                       &p_buffer,\r
+                       p_port->cm_buf_mgr.h_buffer_pool, \r
+                       (void *)(p_desc->p_buf - DATA_OFFSET),\r
+                       p_desc->len + DATA_OFFSET );\r
+\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate NDIS_BUFFER: %08x\n", status) );\r
+               NdisDprFreePacketNonInterlocked( p_packet );\r
+               return NULL;\r
+       }\r
+\r
+       NdisChainBufferAtFront( p_packet, p_buffer );\r
+       NDIS_SET_PACKET_HEADER_SIZE( p_packet, sizeof(eth_hdr_t) );\r
+\r
+       IPOIB_EXIT(  IPOIB_DBG_RECV );\r
+       return p_packet;\r
+}\r
+\r
+static inline ipoib_cm_desc_t*\r
+__endpt_cm_buf_mgr_get_recv(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr )\r
+{\r
+       ipoib_cm_desc_t *p_desc;\r
+\r
+       p_desc = (ipoib_cm_desc_t*)cl_qpool_get( &p_buf_mgr->recv_pool );\r
+       if( p_desc )\r
+               cl_qlist_insert_tail( &p_buf_mgr->posted_list, &p_desc->list_item );\r
+\r
+       return p_desc;\r
+}\r
+\r
+void\r
+endpt_cm_buf_mgr_put_recv(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr,\r
+       IN              ipoib_cm_desc_t* const  p_desc )\r
+{\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_RECV );\r
+\r
+       /* Return the descriptor to it's pool. */\r
+       cl_qlist_remove_item( &p_buf_mgr->posted_list, &p_desc->list_item );\r
+       cl_qpool_put( &p_buf_mgr->recv_pool, &p_desc->item );\r
+\r
+       IPOIB_EXIT(  IPOIB_DBG_RECV );\r
+}\r
+\r
+void\r
+endpt_cm_buf_mgr_put_recv_list(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr,\r
+       IN              cl_qlist_t* const                       p_list )\r
+{\r
+       cl_qpool_put_list( &p_buf_mgr->recv_pool, p_list );\r
+}\r
+\r
+uint32_t\r
+endpt_cm_recv_mgr_build_pkt_array(\r
+       IN                      ipoib_port_t* const                     p_port,\r
+       IN                      ipoib_endpt_t* const            p_endpt,\r
+       IN                      cl_qlist_t* const                       p_done_list,\r
+       IN OUT          uint32_t*                                       p_bytes_recv )\r
+{\r
+       cl_list_item_t                  *p_item;\r
+       ipoib_cm_desc_t         *p_desc;\r
+       uint32_t                                i = 0;\r
+       NDIS_PACKET                             *p_packet;\r
+       NDIS_TCP_IP_CHECKSUM_PACKET_INFO        chksum;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+       UNUSED_PARAM( p_endpt );\r
+\r
+       p_item = cl_qlist_remove_head( p_done_list );\r
+       \r
+       *p_bytes_recv = 0;\r
+\r
+       for( p_item; p_item != cl_qlist_end( p_done_list );\r
+               p_item = cl_qlist_remove_head( p_done_list ) )\r
+       {\r
+               p_desc = (ipoib_cm_desc_t*)p_item;\r
+\r
+               p_packet = __endpt_cm_get_ndis_pkt( p_port, p_desc );\r
+               if( !p_packet )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get Packet from descriptor\n" ) );\r
+                       endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_desc );\r
+                       p_port->cm_recv_mgr.depth--;\r
+                       continue;\r
+               }\r
+               chksum.Value = 0;\r
+               switch( p_port->p_adapter->params.recv_chksum_offload )\r
+               {\r
+               default:\r
+                       CL_ASSERT( FALSE );\r
+               case CSUM_DISABLED:\r
+               case CSUM_ENABLED:\r
+               NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo ) =\r
+                               (void*)(uintn_t)chksum.Value;\r
+                       break;\r
+               case CSUM_BYPASS:\r
+                       /* Flag the checksums as having been calculated. */\r
+                       chksum.Receive.NdisPacketTcpChecksumSucceeded = TRUE;\r
+                       chksum.Receive.NdisPacketUdpChecksumSucceeded = TRUE;\r
+                       chksum.Receive.NdisPacketIpChecksumSucceeded = TRUE;\r
+                       NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo ) =\r
+                               (void*)(uintn_t)chksum.Value;\r
+                       break;\r
+               }\r
+\r
+               NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_SUCCESS );\r
+               p_port->cm_recv_mgr.recv_pkt_array[i] = p_packet;\r
+               i++;            \r
+               *p_bytes_recv += p_desc->len;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return i;\r
+}\r
+void\r
+endpt_cm_flush_recv(\r
+       IN                              ipoib_port_t* const             p_port,\r
+       IN                              ipoib_endpt_t* const    p_endpt )\r
+{\r
+       ib_api_status_t         ib_status = IB_SUCCESS;\r
+       ib_qp_mod_t                     mod_attr;\r
+       ib_wc_t                         wc[MAX_RECV_WC];\r
+       ib_wc_t                         *p_free_wc;\r
+       ib_wc_t                         *p_done_wc;\r
+       ib_wc_t                         *p_wc;\r
+       ipoib_cm_desc_t         *p_desc;\r
+       size_t                          i;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       CL_ASSERT( p_endpt );\r
+\r
+       if( p_endpt->conn.h_recv_qp )\r
+       {\r
+               cl_memclr( &mod_attr, sizeof( mod_attr ) );\r
+               mod_attr.req_state = IB_QPS_ERROR;\r
+               p_port->p_adapter->p_ifc->modify_qp( p_endpt->conn.h_send_qp, &mod_attr );\r
+               p_port->p_adapter->p_ifc->modify_qp( p_endpt->conn.h_recv_qp, &mod_attr );\r
+\r
+               for( i = 0; i < MAX_RECV_WC; i++ )\r
+                       wc[i].p_next = &wc[i + 1];\r
+               wc[MAX_RECV_WC - 1].p_next = NULL;\r
+\r
+               do\r
+               {\r
+                       p_free_wc = wc;\r
+                       ib_status = \r
+                               p_port->p_adapter->p_ifc->poll_cq( p_endpt->conn.h_recv_cq, \r
+                               &p_free_wc, &p_done_wc );\r
+                       if( ib_status != IB_SUCCESS && \r
+                               ib_status != IB_NOT_FOUND )\r
+                       {\r
+                               /* connection CQ failed */\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Poll Recv CQ failed status %#x\n", ib_status ) );\r
+                               break;\r
+                       }\r
+                       cl_spinlock_acquire( &p_port->recv_lock );\r
+                       for( p_wc = p_done_wc; p_wc; p_wc = p_wc->p_next )\r
+                       {\r
+                               p_desc = (ipoib_cm_desc_t *)(uintn_t)p_wc->wr_id;\r
+                               endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_desc );\r
+                               p_port->cm_recv_mgr.depth--;\r
+                       }\r
+                       cl_spinlock_release( &p_port->recv_lock );\r
+               } while( !p_free_wc );\r
+\r
+               ib_status = p_port->p_adapter->p_ifc->destroy_qp( p_endpt->conn.h_recv_qp, NULL );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Destroy Recv QP failed status %#x\n", ib_status ) );\r
+               }\r
+               p_endpt->conn.h_recv_qp = NULL;\r
+       }\r
+\r
+       if( p_endpt->conn.h_send_qp )\r
+       {\r
+               ib_status = p_port->p_adapter->p_ifc->destroy_qp( p_endpt->conn.h_send_qp, NULL );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Destroy Send QP failed status %#x\n", ib_status ) );\r
+               }\r
+               p_endpt->conn.h_send_qp = NULL;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+int32_t\r
+endpt_cm_recv_mgr_filter(\r
+       IN              ipoib_endpt_t* const            p_endpt,\r
+       IN              ib_wc_t* const                          p_done_wc_list,\r
+       OUT             cl_qlist_t* const                       p_done_list,\r
+       OUT             cl_qlist_t* const                       p_bad_list )\r
+{\r
+       ib_api_status_t                 ib_status;\r
+       ipoib_cm_desc_t                 *p_desc;\r
+       ib_wc_t                                 *p_wc;\r
+       ipoib_pkt_t                             *p_ipoib;\r
+       eth_pkt_t                               *p_eth;\r
+       ipoib_port_t*                   p_port;\r
+       int32_t                                 recv_cnt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       p_port = ipoib_endpt_parent( p_endpt );\r
+\r
+       for( p_wc = p_done_wc_list, recv_cnt = 0; p_wc; p_wc = p_wc->p_next )\r
+       {\r
+               p_desc = (ipoib_cm_desc_t *)(uintn_t)p_wc->wr_id;\r
+               recv_cnt++;\r
+               if(  p_wc->status != IB_WCS_SUCCESS )\r
+               {\r
+                       if( p_wc->status != IB_WCS_WR_FLUSHED_ERR )\r
+                       {\r
+                               \r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Failed completion %s  (vendor specific %#x)\n",\r
+                                       p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
+                                       (int)p_wc->vendor_specific) );\r
+                       }\r
+                       else\r
+                       {\r
+                               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+                                       ("Flushed completion %s\n",\r
+                                       p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status )) );\r
+                       }\r
+                       \r
+                       ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+\r
+                       cl_qlist_remove_item( &p_port->cm_buf_mgr.posted_list,&p_desc->list_item );\r
+                       cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                       continue;\r
+               }\r
+\r
+               /* Successful completion                \r
+                Setup the ethernet/ip/arp header and queue descriptor for report. */\r
+               ib_status = IB_SUCCESS;\r
+               p_ipoib = (ipoib_pkt_t *)((uint8_t*)p_desc->p_buf );\r
+               p_eth = (eth_pkt_t *)((uint8_t*)p_desc->p_buf - DATA_OFFSET );\r
+               \r
+               switch( p_ipoib->hdr.type )\r
+               {\r
+               case ETH_PROT_TYPE_ARP:\r
+                       if( p_wc->length < (sizeof(ipoib_hdr_t) + sizeof(ipoib_arp_pkt_t)) )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Received ARP packet too short\n") );\r
+                               ib_status = IB_ERROR;\r
+                               break;\r
+                       }\r
+                       ib_status = \r
+                               __endpt_cm_recv_arp( p_port, p_ipoib, p_eth, p_endpt );\r
+                       break;\r
+               case ETH_PROT_TYPE_IP:\r
+                       if( p_wc->length < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Received IP packet too short\n") );\r
+                               ib_status = IB_ERROR;\r
+                               break;\r
+                       }\r
+                       if( p_ipoib->type.ip.hdr.prot == IP_PROT_UDP )\r
+                       {\r
+                               ib_status = \r
+                                       __endpt_cm_recv_udp( p_port, p_wc, p_ipoib, p_eth, p_endpt );\r
+                       }\r
+               \r
+                       break;\r
+               }\r
+\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+                       cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                       continue;\r
+               }\r
+\r
+               p_eth->hdr.type = p_ipoib->hdr.type;\r
+               p_eth->hdr.src = p_endpt->mac;\r
+               p_eth->hdr.dst = p_port->p_adapter->mac;\r
+\r
+               /* save payload length */\r
+               p_desc->len = p_wc->length;\r
+               \r
+               cl_qlist_insert_tail( p_done_list, &p_desc->item.list_item );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return recv_cnt;\r
+}\r
+\r
+ib_api_status_t\r
+endpt_cm_post_recv(\r
+       IN              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t         ib_status = IB_SUCCESS;\r
+       ipoib_cm_desc_t         *p_head_desc = NULL;\r
+       ipoib_cm_desc_t         *p_tail_desc = NULL;\r
+       ipoib_cm_desc_t         *p_next_desc;\r
+       ib_recv_wr_t            *p_failed_wc = NULL;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       while( cl_qpool_count( &p_port->cm_buf_mgr.recv_pool )  > 1  )\r
+       {\r
+                       /* Pull receives out of the pool and chain them up. */\r
+               p_next_desc = __endpt_cm_buf_mgr_get_recv( \r
+                                                                       &p_port->cm_buf_mgr );\r
+               if( !p_next_desc )\r
+               {\r
+                       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+                               ("Out of receive descriptors! Endpt recv queue depth 0x%x\n",\r
+                               p_port->cm_recv_mgr.depth ) );\r
+                       break;\r
+               }\r
+\r
+               if( !p_tail_desc )\r
+               {\r
+                       p_tail_desc = p_next_desc;\r
+                       p_next_desc->wr.p_next = NULL;\r
+               }\r
+               else\r
+               {\r
+                       p_next_desc->wr.p_next = &p_head_desc->wr;\r
+               }\r
+\r
+               p_head_desc = p_next_desc;\r
+\r
+               p_port->cm_recv_mgr.depth++;\r
+       }\r
+\r
+       if( p_head_desc )\r
+       {\r
+               ib_status = p_port->p_adapter->p_ifc->post_srq_recv(\r
+                       p_port->ib_mgr.h_srq, &p_head_desc->wr, &p_failed_wc );\r
+\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ip_post_recv returned %s\n", \r
+                               p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+                       \r
+                       /* put descriptors back to the pool */\r
+                       while( p_failed_wc )\r
+                       {\r
+                               p_head_desc = PARENT_STRUCT( p_failed_wc, ipoib_cm_desc_t, wr );\r
+                               p_failed_wc = p_failed_wc->p_next;\r
+                               endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, p_head_desc );\r
+                               p_port->cm_recv_mgr.depth--;\r
+                       }\r
+               }\r
+       }\r
+\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return( ib_status );\r
+}\r
+\r
+static ib_api_status_t\r
+__endpt_cm_recv_arp(\r
+       IN              ipoib_port_t* const                             p_port,\r
+       IN              const   ipoib_pkt_t* const              p_ipoib,\r
+       OUT             eth_pkt_t* const                                p_eth,\r
+       IN              ipoib_endpt_t* const                    p_src_endpt )\r
+{\r
+       const ipoib_arp_pkt_t   *p_ib_arp;\r
+       arp_pkt_t                               *p_arp;\r
+       \r
+       p_ib_arp = &p_ipoib->type.arp;\r
+       p_arp = &p_eth->type.arp;\r
+       \r
+       if( p_ib_arp->hw_type != ARP_HW_TYPE_IB ||\r
+               p_ib_arp->hw_size != sizeof(ipoib_hw_addr_t) ||\r
+               p_ib_arp->prot_type != ETH_PROT_TYPE_IP )\r
+       {\r
+               return IB_ERROR;\r
+       }\r
+       \r
+       p_arp->hw_type = ARP_HW_TYPE_ETH;\r
+       p_arp->hw_size = sizeof(mac_addr_t);\r
+       p_arp->src_hw = p_src_endpt->mac;\r
+       p_arp->src_ip = p_ib_arp->src_ip;\r
+       p_arp->dst_hw = p_port->p_local_endpt->mac;\r
+       p_arp->dst_ip = p_ib_arp->dst_ip;\r
+\r
+       return IB_SUCCESS;      \r
+}\r
+\r
+static ib_api_status_t\r
+__endpt_cm_recv_udp(\r
+       IN      ipoib_port_t* const     p_port,\r
+       IN                      ib_wc_t* const                          p_wc,\r
+       IN              const   ipoib_pkt_t* const              p_ipoib,\r
+       OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                      ipoib_endpt_t* const            p_src_endpt )\r
+{\r
+       ib_api_status_t                 ib_status = IB_SUCCESS;\r
+\r
+       if( p_wc->length <\r
+               (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Received UDP packet too short\n") );\r
+               return IB_ERROR;\r
+       }\r
+       if( __cm_recv_is_dhcp( p_ipoib ) )\r
+       {\r
+               ib_status = ipoib_recv_dhcp(\r
+                       p_port, p_ipoib, p_eth, p_src_endpt, p_port->p_local_endpt );\r
+       }\r
+\r
+       return ib_status;\r
+}\r
+\r
+static boolean_t\r
+__cm_recv_is_dhcp(\r
+       IN      const ipoib_pkt_t* const        p_ipoib )\r
+{\r
+       return( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_SERVER &&\r
+                               p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) ||\r
+                               (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT &&\r
+                               p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_SERVER) );\r
+}\r
+#endif\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_endpoint.h b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_endpoint.h
new file mode 100644 (file)
index 0000000..547d465
--- /dev/null
@@ -0,0 +1,257 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_endpoint.h 4226 2009-04-06 06:01:03Z xalex $\r
+ */\r
+\r
+\r
+#ifndef _IPOIB_ENDPOINT_H_\r
+#define _IPOIB_ENDPOINT_H_\r
+\r
+\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_qlist.h>\r
+#include <complib/cl_qmap.h>\r
+#include <complib/cl_fleximap.h>\r
+#include <complib/cl_obj.h>\r
+#include "iba/ipoib_ifc.h"\r
+#include <ip_packet.h>\r
+#include "ipoib_debug.h"\r
+\r
+\r
+typedef struct _endpt_buf_mgr\r
+{\r
+       cl_qpool_t                      recv_pool;\r
+       NDIS_HANDLE                     h_packet_pool;\r
+       NDIS_HANDLE                     h_buffer_pool;\r
+       cl_qlist_t                      posted_list;\r
+       boolean_t                       pool_init;\r
+} endpt_buf_mgr_t;\r
+\r
+typedef struct _endpt_recv_mgr\r
+{\r
+       int32_t                 depth;\r
+       int32_t                 rq_depth;\r
+       //NDIS60\r
+       //NDIS_PACKET           **recv_pkt_array;\r
+       NET_BUFFER_LIST *recv_lst_array;\r
+\r
+}      endpt_recv_mgr_t;\r
+\r
+\r
+typedef enum _cm_state \r
+{\r
+       IPOIB_CM_DISCONNECTED,\r
+       IPOIB_CM_INIT,\r
+       IPOIB_CM_CONNECT,\r
+       IPOIB_CM_CONNECTED,\r
+       IPOIB_CM_LISTEN,\r
+       IPOIB_CM_DREP_SENT,\r
+       IPOIB_CM_DREQ_SENT,\r
+       IPOIB_CM_REJ_RECVD,\r
+       IPOIB_CM_DESTROY\r
+} cm_state_t;\r
+\r
+typedef struct _cm_private_data \r
+{\r
+       ib_net32_t              ud_qpn;\r
+       ib_net32_t              recv_mtu;\r
+} cm_private_data_t;\r
+\r
+typedef struct _endpt_conn \r
+{\r
+       ib_net64_t                      service_id;\r
+       cm_private_data_t       private_data;\r
+       ib_qp_handle_t          h_send_qp;\r
+       ib_qp_handle_t          h_recv_qp;\r
+       ib_qp_handle_t          h_work_qp;\r
+       ib_cq_handle_t          h_send_cq;\r
+       ib_cq_handle_t          h_recv_cq;\r
+       ib_listen_handle_t  h_cm_listen;\r
+       cm_state_t                      state;\r
+\r
+} endpt_conn_t;\r
+\r
+typedef struct _ipoib_endpt\r
+{\r
+       cl_obj_t                                obj;\r
+       cl_obj_rel_t                    rel;\r
+       cl_map_item_t                   mac_item;\r
+       cl_fmap_item_t                  gid_item;\r
+       cl_map_item_t                   lid_item;\r
+       cl_fmap_item_t                  conn_item;\r
+       LIST_ENTRY                              list_item;\r
+       ib_query_handle_t               h_query;\r
+       ib_mcast_handle_t               h_mcast;\r
+       mac_addr_t                              mac;\r
+       ib_gid_t                                dgid;\r
+       net16_t                                 dlid;\r
+       net32_t                                 qpn;\r
+       uint8_t                                 cm_flag;\r
+       ib_av_handle_t                  h_av;\r
+       endpt_conn_t                    conn;\r
+\r
+       ib_al_ifc_t                             *p_ifc;\r
+       boolean_t                       is_in_use;\r
+       boolean_t                               is_mcast_listener;\r
+}      ipoib_endpt_t;\r
+/*\r
+* FIELDS\r
+*      mac_item\r
+*              Map item for storing the endpoint in a map.  The key is the\r
+*              destination MAC address.\r
+*\r
+*      lid_item\r
+*              Map item for storing the endpoint in a map.  The key is the\r
+*              destination LID.\r
+*\r
+*      gid_item\r
+*              Map item for storing the endpoint in a map.  The key is the\r
+*              destination GID.\r
+*\r
+*      h_query\r
+*              Query handle for cancelling SA queries.\r
+*\r
+*      h_mcast\r
+*              For multicast endpoints, the multicast handle.\r
+*\r
+*      mac\r
+*              MAC address.\r
+*\r
+*      dgid\r
+*              Destination GID.\r
+*\r
+*      dlid\r
+*              Destination LID.  The destination LID is only set for endpoints\r
+*              that are on the same subnet.  It is used as key in the LID map.\r
+*\r
+*      qpn\r
+*              Destination queue pair number.\r
+*\r
+*      h_av\r
+*              Address vector for sending data.\r
+*\r
+*      expired\r
+*              Flag to indicate that the endpoint should be flushed.\r
+*\r
+*      connection\r
+*              for connected mode endpoints\r
+*\r
+*      p_ifc\r
+*              Reference to transport functions, can be used\r
+*              while endpoint is not attached to port yet.\r
+*\r
+* NOTES\r
+*      If the h_mcast member is set, the endpoint is never expired.\r
+*********/\r
+\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_create(\r
+       IN              const   ib_gid_t* const                         p_dgid,\r
+       IN              const   net16_t                                         dlid,\r
+       IN              const   net32_t                                         qpn );\r
+\r
+\r
+ib_api_status_t\r
+ipoib_endpt_set_mcast(\r
+       IN                              ipoib_endpt_t* const            p_endpt,\r
+       IN                              ib_pd_handle_t                          h_pd,\r
+       IN                              uint8_t                                         port_num,\r
+       IN                              ib_mcast_rec_t* const           p_mcast_rec );\r
+\r
+\r
+static inline void\r
+ipoib_endpt_ref(\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       CL_ASSERT( p_endpt );\r
+\r
+       cl_obj_ref( &p_endpt->obj );\r
+       /*\r
+        * Anytime we reference the endpoint, we're either receiving data\r
+        * or trying to send data to that endpoint.  Clear the expired flag\r
+        * to prevent the AV from being flushed.\r
+        */\r
+}\r
+\r
+\r
+static inline void\r
+ipoib_endpt_deref(\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       cl_obj_deref( &p_endpt->obj );\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+ipoib_endpt_queue(\r
+       IN                              ipoib_endpt_t* const            p_endpt );\r
+\r
+struct _ipoib_port *\r
+ipoib_endpt_parent(\r
+       IN              ipoib_endpt_t* const            p_endpt );\r
+\r
+inline cm_state_t\r
+endpt_cm_set_state(\r
+       IN              ipoib_endpt_t* const            p_endpt,\r
+       IN              cm_state_t                                      state )\r
+{\r
+       return(cm_state_t)InterlockedExchange( \r
+                               (volatile LONG *)&p_endpt->conn.state, \r
+                               (LONG)state );\r
+}\r
+\r
+inline cm_state_t\r
+endpt_cm_get_state(\r
+       IN              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       return( cm_state_t )InterlockedCompareExchange( \r
+                               (volatile LONG *)&p_endpt->conn.state, \r
+                               IPOIB_CM_DISCONNECTED, IPOIB_CM_DISCONNECTED );\r
+}\r
+\r
+ib_api_status_t\r
+endpt_cm_create_qp( \r
+       IN              ipoib_endpt_t*  const   p_endpt,\r
+       IN              ib_qp_handle_t* const   p_h_qp );\r
+\r
+ib_api_status_t\r
+ipoib_endpt_connect(\r
+       IN              ipoib_endpt_t* const            p_endpt );\r
+\r
+int32_t\r
+endpt_cm_recv_mgr_filter(\r
+       IN              ipoib_endpt_t* const            p_endpt,\r
+       IN              ib_wc_t* const                          p_done_wc_list,\r
+       OUT             cl_qlist_t* const                       p_done_list,\r
+       OUT             cl_qlist_t* const                       p_bad_list );\r
+\r
+#endif /* _IPOIB_ENDPOINT_H_ */\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_ibat.c b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_ibat.c
new file mode 100644 (file)
index 0000000..a770366
--- /dev/null
@@ -0,0 +1,693 @@
+/*\r
+ * Copyright (c) 2005 Mellanox Technologies.  All rights reserved.\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_ibat.c 4494 2009-06-22 14:31:08Z xalex $\r
+ */\r
+\r
+\r
+#include "ipoib_driver.h"\r
+#include "ipoib_adapter.h"\r
+#include "ipoib_port.h"\r
+#include "ipoib_debug.h"\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_ibat.tmh"\r
+#endif\r
+#include <iba/ib_at_ioctl.h>\r
+\r
+extern PDRIVER_OBJECT                          g_p_drv_obj;\r
+\r
+static NTSTATUS\r
+__ipoib_create(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp );\r
+\r
+static NTSTATUS\r
+__ipoib_cleanup(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp );\r
+\r
+static NTSTATUS\r
+__ipoib_close(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp );\r
+\r
+static NTSTATUS\r
+__ipoib_dispatch(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp );\r
+\r
+\r
+static NTSTATUS\r
+__ibat_get_ports(\r
+       IN                              IRP                                                     *pIrp,\r
+       IN                              IO_STACK_LOCATION                       *pIoStack )\r
+{\r
+       IOCTL_IBAT_PORTS_IN             *pIn;\r
+       IOCTL_IBAT_PORTS_OUT    *pOut;\r
+       KLOCK_QUEUE_HANDLE              hdl;\r
+       cl_list_item_t                  *pItem;\r
+       ipoib_adapter_t                 *pAdapter;\r
+       LONG                                    nPorts;\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+       if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+               sizeof(IOCTL_IBAT_PORTS_IN) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid input buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+       \r
+       if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength <\r
+               sizeof(IOCTL_IBAT_PORTS_OUT) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid output buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       pIn = pIrp->AssociatedIrp.SystemBuffer;\r
+       pOut = pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+       if( pIn->Version != IBAT_IOCTL_VERSION )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid version.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+       nPorts = (LONG)cl_qlist_count( &g_ipoib.adapter_list );\r
+       switch( nPorts )\r
+       {\r
+       case 0:\r
+               cl_memclr( pOut->Ports, sizeof(pOut->Ports) );\r
+               /* Fall through */\r
+       case 1:\r
+               pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT);\r
+               break;\r
+\r
+       default:\r
+               pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT) + \r
+                       (sizeof(IBAT_PORT_RECORD) * (nPorts - 1));\r
+               break;\r
+       }\r
+\r
+       pIrp->IoStatus.Information = pOut->Size;\r
+\r
+       if( pOut->Size > pIoStack->Parameters.DeviceIoControl.OutputBufferLength )\r
+       {\r
+               nPorts = 1 +\r
+                       (pIoStack->Parameters.DeviceIoControl.OutputBufferLength -\r
+                       sizeof(IOCTL_IBAT_PORTS_OUT)) / sizeof(IBAT_PORT_RECORD);\r
+\r
+               pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_PORTS_OUT) +\r
+                       ((nPorts - 1) * sizeof(IBAT_PORT_RECORD));\r
+       }\r
+\r
+       pOut->NumPorts = 0;\r
+       pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+       while( pOut->NumPorts != nPorts )\r
+       {\r
+               pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+               pOut->Ports[pOut->NumPorts].CaGuid = pAdapter->guids.ca_guid;\r
+               pOut->Ports[pOut->NumPorts].PortGuid = pAdapter->guids.port_guid.guid;\r
+               pOut->Ports[pOut->NumPorts].PKey = IB_DEFAULT_PKEY;\r
+               pOut->Ports[pOut->NumPorts].PortNum = pAdapter->guids.port_num;\r
+               pOut->NumPorts++;\r
+\r
+               pItem = cl_qlist_next( pItem );\r
+       }\r
+\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ibat_get_ips(\r
+       IN                              IRP                                                     *pIrp,\r
+       IN                              IO_STACK_LOCATION                       *pIoStack )\r
+{\r
+       IOCTL_IBAT_IP_ADDRESSES_IN      *pIn;\r
+       IOCTL_IBAT_IP_ADDRESSES_OUT     *pOut;\r
+       KLOCK_QUEUE_HANDLE                      hdl;\r
+       cl_list_item_t                          *pItem;\r
+       ipoib_adapter_t                         *pAdapter;\r
+       LONG                                            nIps, maxIps;\r
+       size_t                                          idx;\r
+       net_address_item_t                      *pAddr;\r
+       UINT64                                          PortGuid;\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+       if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+               sizeof(IOCTL_IBAT_IP_ADDRESSES_IN) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid input buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+       \r
+       if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength <\r
+               sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid output buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       pIn = pIrp->AssociatedIrp.SystemBuffer;\r
+       pOut = pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+       if( pIn->Version != IBAT_IOCTL_VERSION )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid version.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       PortGuid = pIn->PortGuid;\r
+\r
+       nIps = 0;\r
+       pOut->AddressCount = 0;\r
+       maxIps = 1 +\r
+               ((pIoStack->Parameters.DeviceIoControl.OutputBufferLength -\r
+               sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT)) / sizeof(IP_ADDRESS));\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+       for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+               pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
+               pItem = cl_qlist_next( pItem ) )\r
+       {\r
+               pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+               if( PortGuid && pAdapter->guids.port_guid.guid != PortGuid )\r
+                       continue;\r
+\r
+               cl_obj_lock( &pAdapter->obj );\r
+               nIps += (LONG)cl_vector_get_size( &pAdapter->ip_vector );\r
+\r
+               for( idx = 0;\r
+                       idx < cl_vector_get_size( &pAdapter->ip_vector );\r
+                       idx++ )\r
+               {\r
+                       if( pOut->AddressCount == maxIps )\r
+                               break;\r
+\r
+                       pAddr = (net_address_item_t*)\r
+                               cl_vector_get_ptr( &pAdapter->ip_vector, idx );\r
+\r
+                       pOut->Address[pOut->AddressCount].IpVersion = 4;\r
+                       cl_memclr( &pOut->Address[pOut->AddressCount].Address,\r
+                               sizeof(IP_ADDRESS) );\r
+                       cl_memcpy( &pOut->Address[pOut->AddressCount].Address[12],\r
+                               pAddr->address.as_bytes, IPV4_ADDR_SIZE );\r
+\r
+                       pOut->AddressCount++;\r
+               }\r
+               cl_obj_unlock( &pAdapter->obj );\r
+       }\r
+\r
+       pOut->Size = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);\r
+       if( --nIps )\r
+               pOut->Size += sizeof(IP_ADDRESS) * nIps;\r
+\r
+       pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);\r
+       if( --maxIps < nIps )\r
+               pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * maxIps);\r
+       else\r
+               pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * nIps);\r
+\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ibat_mac_to_gid(\r
+       IN                              IRP                                                     *pIrp,\r
+       IN                              IO_STACK_LOCATION                       *pIoStack )\r
+{\r
+       NTSTATUS                                        status = STATUS_INVALID_PARAMETER;\r
+       IOCTL_IBAT_MAC_TO_GID_IN        *pIn;\r
+       IOCTL_IBAT_MAC_TO_GID_OUT       *pOut;\r
+       KLOCK_QUEUE_HANDLE                      hdl;\r
+       cl_list_item_t                          *pItem;\r
+       ipoib_adapter_t                         *pAdapter;\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+       if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+               sizeof(IOCTL_IBAT_MAC_TO_GID_IN) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid input buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+       \r
+       if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
+               sizeof(IOCTL_IBAT_MAC_TO_GID_OUT) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid output buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       pIn = pIrp->AssociatedIrp.SystemBuffer;\r
+       pOut = pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+       if( pIn->Version != IBAT_IOCTL_VERSION )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid version.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+\r
+       for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+               pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
+               pItem = cl_qlist_next( pItem ) )\r
+       {\r
+               pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+               if( pIn->PortGuid != pAdapter->guids.port_guid.guid )\r
+                       continue;\r
+\r
+               /* Found the port - lookup the MAC. */\r
+               cl_obj_lock( &pAdapter->obj );\r
+               if( pAdapter->p_port )\r
+               {\r
+                       status = ipoib_mac_to_gid(\r
+                               pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->DestGid );\r
+                       if( NT_SUCCESS( status ) )\r
+                       {\r
+                               pIrp->IoStatus.Information =\r
+                                       sizeof(IOCTL_IBAT_MAC_TO_GID_OUT);\r
+                       }\r
+               }\r
+               cl_obj_unlock( &pAdapter->obj );\r
+               break;\r
+       }\r
+\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ibat_mac_to_path(\r
+       IN                              IRP                                                     *pIrp,\r
+       IN                              IO_STACK_LOCATION                       *pIoStack )\r
+{\r
+       NTSTATUS                                        status = STATUS_INVALID_PARAMETER;\r
+       IOCTL_IBAT_MAC_TO_PATH_IN       *pIn;\r
+       IOCTL_IBAT_MAC_TO_PATH_OUT      *pOut;\r
+       KLOCK_QUEUE_HANDLE                      hdl;\r
+       cl_list_item_t                          *pItem;\r
+       ipoib_adapter_t                         *pAdapter;\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+       if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+               sizeof(IOCTL_IBAT_MAC_TO_PATH_IN) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid input buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+       \r
+       if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
+               sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid output buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       pIn = pIrp->AssociatedIrp.SystemBuffer;\r
+       pOut = pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+       if( pIn->Version != IBAT_IOCTL_VERSION )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid version.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+\r
+       for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+               pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
+               pItem = cl_qlist_next( pItem ) )\r
+       {\r
+               pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+               if( pIn->PortGuid != pAdapter->guids.port_guid.guid )\r
+                       continue;\r
+\r
+               /* Found the port - lookup the MAC. */\r
+               cl_obj_lock( &pAdapter->obj );\r
+               if( pAdapter->p_port )\r
+               {\r
+                       status = ipoib_mac_to_path(\r
+                               pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->Path );\r
+\r
+                       if( NT_SUCCESS( status ) )\r
+                       {\r
+                               pIrp->IoStatus.Information =\r
+                                       sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT);\r
+                       }\r
+               }\r
+               cl_obj_unlock( &pAdapter->obj );\r
+               break;\r
+       }\r
+\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return status;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ibat_ip_to_port(\r
+       IN                              IRP                                                     *pIrp,\r
+       IN                              IO_STACK_LOCATION                       *pIoStack )\r
+{\r
+       IOCTL_IBAT_IP_TO_PORT_IN        *pIn;\r
+       IOCTL_IBAT_IP_TO_PORT_OUT       *pOut;\r
+       KLOCK_QUEUE_HANDLE                      hdl;\r
+       cl_list_item_t                                  *pItem;\r
+       ipoib_adapter_t                         *pAdapter;\r
+       size_t                                          idx;\r
+       net_address_item_t                      *pAddr;\r
+       NTSTATUS status = STATUS_NOT_FOUND;\r
+\r
+       IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
+\r
+       if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
+               sizeof(IOCTL_IBAT_IP_TO_PORT_IN) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid input buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+       \r
+       if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
+               sizeof(IOCTL_IBAT_IP_TO_PORT_OUT) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid output buffer size.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       pIn = pIrp->AssociatedIrp.SystemBuffer;\r
+       pOut = pIrp->AssociatedIrp.SystemBuffer;\r
+\r
+       if( pIn->Version != IBAT_IOCTL_VERSION )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid version.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (pIn->Address.IpVersion != 4)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid IP version (%d). Supported only 4\n", pIn->Address.IpVersion) );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
+       for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
+               pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
+               pItem = cl_qlist_next( pItem ) )\r
+       {\r
+               pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
+\r
+               cl_obj_lock( &pAdapter->obj );\r
+\r
+               for( idx = 0;\r
+                       idx < cl_vector_get_size( &pAdapter->ip_vector );\r
+                       idx++ )\r
+               {\r
+                       pAddr = (net_address_item_t*)\r
+                               cl_vector_get_ptr( &pAdapter->ip_vector, idx );\r
+\r
+                       if (!memcmp( &pIn->Address.Address[12], pAddr->address.as_bytes, IPV4_ADDR_SIZE))\r
+                       {\r
+                               pOut->Port.CaGuid = pAdapter->guids.ca_guid;\r
+                               pOut->Port.PortGuid = pAdapter->guids.port_guid.guid;\r
+                               pOut->Port.PKey = IB_DEFAULT_PKEY;\r
+                               pOut->Port.PortNum = pAdapter->guids.port_num;\r
+                               pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_TO_PORT_OUT);\r
+                               status = STATUS_SUCCESS;\r
+                               break;\r
+                       }\r
+               }\r
+               cl_obj_unlock( &pAdapter->obj );\r
+               if (status == STATUS_SUCCESS)\r
+                       break;\r
+       }\r
+\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return status;\r
+}\r
+\r
+void\r
+ipoib_ref_ibat()\r
+{\r
+       UNICODE_STRING      DeviceName;\r
+    UNICODE_STRING      DeviceLinkUnicodeString;\r
+    NDIS_DEVICE_OBJECT_ATTRIBUTES   DeviceObjectAttributes;\r
+    PDRIVER_DISPATCH    DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];\r
+\r
+       NDIS_STATUS         Status = NDIS_STATUS_SUCCESS;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+       if( InterlockedIncrement( &g_ipoib.ibat_ref ) == 1 )\r
+       {\r
+\r
+               NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH));\r
+                               \r
+               DispatchTable[IRP_MJ_CREATE]                                    = __ipoib_create;\r
+               DispatchTable[IRP_MJ_CLEANUP]                                   = __ipoib_cleanup;\r
+               DispatchTable[IRP_MJ_CLOSE]                                             = __ipoib_close;\r
+               DispatchTable[IRP_MJ_DEVICE_CONTROL]                    = __ipoib_dispatch;\r
+               DispatchTable[IRP_MJ_INTERNAL_DEVICE_CONTROL]   = __ipoib_dispatch;             \r
+               \r
+                               \r
+               NdisInitUnicodeString( &DeviceName, IBAT_DEV_NAME );\r
+               NdisInitUnicodeString( &DeviceLinkUnicodeString, IBAT_DOS_DEV_NAME );\r
+                               \r
+               \r
+               NdisZeroMemory(&DeviceObjectAttributes, sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES));\r
+               \r
+               DeviceObjectAttributes.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; // type implicit from the context\r
+               DeviceObjectAttributes.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;\r
+               DeviceObjectAttributes.Header.Size = sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES);\r
+               DeviceObjectAttributes.DeviceName = &DeviceName;\r
+               DeviceObjectAttributes.SymbolicName = &DeviceLinkUnicodeString;\r
+               DeviceObjectAttributes.MajorFunctions = &DispatchTable[0];\r
+               DeviceObjectAttributes.ExtensionSize = 0;\r
+               DeviceObjectAttributes.DefaultSDDLString = NULL;\r
+               DeviceObjectAttributes.DeviceClassGuid = 0;\r
+               \r
+               Status = NdisRegisterDeviceEx(\r
+                                                       g_IpoibMiniportDriverHandle,\r
+                                                       &DeviceObjectAttributes,\r
+                                                       &g_ipoib.h_ibat_dev,\r
+                                                       &g_ipoib.h_ibat_dev_handle);\r
+\r
+\r
+       \r
+               if( Status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
+                               ("NdisRegisterDeviceEx failed with status of %d\n", Status) );\r
+               }\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+}\r
+\r
+\r
+void\r
+ipoib_deref_ibat()\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+       if( InterlockedDecrement( &g_ipoib.ibat_ref ) )\r
+       {\r
+               IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+               return;\r
+       }\r
+\r
+       if( g_ipoib.h_ibat_dev )\r
+       {\r
+               NdisDeregisterDeviceEx( g_ipoib.h_ibat_dev_handle );\r
+               g_ipoib.h_ibat_dev = NULL;\r
+               g_ipoib.h_ibat_dev_handle = NULL; //TODO set here INVALID_HANDLE_VALUE\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ipoib_create(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+       UNREFERENCED_PARAMETER( pDevObj );\r
+\r
+       ipoib_ref_ibat();\r
+\r
+       pIrp->IoStatus.Status = STATUS_SUCCESS;\r
+       pIrp->IoStatus.Information = 0;\r
+       IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ipoib_cleanup(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+       UNREFERENCED_PARAMETER( pDevObj );\r
+\r
+       ipoib_deref_ibat();\r
+\r
+       pIrp->IoStatus.Status = STATUS_SUCCESS;\r
+       pIrp->IoStatus.Information = 0;\r
+       IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ipoib_close(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+       UNREFERENCED_PARAMETER( pDevObj );\r
+\r
+       pIrp->IoStatus.Status = STATUS_SUCCESS;\r
+       pIrp->IoStatus.Information = 0;\r
+       IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NTSTATUS\r
+__ipoib_dispatch(\r
+       IN                              DEVICE_OBJECT* const            pDevObj,\r
+       IN                              IRP* const                                      pIrp )\r
+{\r
+       IO_STACK_LOCATION       *pIoStack;\r
+       NTSTATUS                        status = STATUS_SUCCESS;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
+\r
+       UNREFERENCED_PARAMETER( pDevObj );\r
+\r
+       pIoStack = IoGetCurrentIrpStackLocation( pIrp );\r
+\r
+       pIrp->IoStatus.Information = 0;\r
+\r
+       switch( pIoStack->Parameters.DeviceIoControl.IoControlCode )\r
+       {\r
+       case IOCTL_IBAT_PORTS:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+                       ("IOCTL_IBAT_PORTS received\n") );\r
+               status = __ibat_get_ports( pIrp, pIoStack );\r
+               break;\r
+\r
+       case IOCTL_IBAT_IP_ADDRESSES:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+                       ("IOCTL_IBAT_IP_ADDRESSES received\n" ));\r
+               status = __ibat_get_ips( pIrp, pIoStack );\r
+               break;\r
+\r
+       case IOCTL_IBAT_MAC_TO_GID:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+                       ("IOCTL_IBAT_MAC_TO_GID received\n" ));\r
+               status = __ibat_mac_to_gid( pIrp, pIoStack );\r
+               break;\r
+\r
+       case IOCTL_IBAT_IP_TO_PORT:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+                       ("IOCTL_IBAT_IP_TO_PORT received\n" ));\r
+               status = __ibat_ip_to_port( pIrp, pIoStack );\r
+               break;\r
+\r
+       case IOCTL_IBAT_MAC_TO_PATH:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
+                       ("IOCTL_IBAT_MAC_TO_PATH received\n" ));\r
+               status = __ibat_mac_to_path( pIrp, pIoStack );\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_IOCTL,\r
+                       ("unknow IOCTL code = 0x%x\n",\r
+                       pIoStack->Parameters.DeviceIoControl.IoControlCode) );\r
+               status = STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       pIrp->IoStatus.Status = status;\r
+       IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
+       return status;\r
+}\r
+\r
+\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_ibat.h b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_ibat.h
new file mode 100644 (file)
index 0000000..efcb0a6
--- /dev/null
@@ -0,0 +1,45 @@
+/*\r
+ * Copyright (c) 2005 Mellanox Technologies.  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
+ * $Id: ipoib_ibat.h 1611 2006-08-20 14:48:55Z sleybo $\r
+ */\r
+\r
+\r
+#ifndef _IPOIB_IBAT_H_\r
+#define _IPOIB_IBAT_H_\r
+\r
+\r
+void\r
+ipoib_ref_ibat();\r
+\r
+void\r
+ipoib_deref_ibat();\r
+\r
+\r
+#endif /* _IPOIB_IBAT_H_ */\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_log.mc b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_log.mc
new file mode 100644 (file)
index 0000000..bb7d1c1
--- /dev/null
@@ -0,0 +1,334 @@
+;/*++\r
+;=============================================================================\r
+;Copyright (c) 2001 Mellanox Technologies\r
+;\r
+;Module Name:\r
+;\r
+;    ipoiblog.mc\r
+;\r
+;Abstract:\r
+;\r
+;    IPoIB Driver event log messages\r
+;\r
+;Authors:\r
+;\r
+;    Yossi Leybovich\r
+;\r
+;Environment:\r
+;\r
+;   Kernel Mode .\r
+;\r
+;=============================================================================\r
+;--*/\r
+;\r
+MessageIdTypedef = NDIS_ERROR_CODE\r
+\r
+SeverityNames = (\r
+       Success                 = 0x0:STATUS_SEVERITY_SUCCESS\r
+       Informational   = 0x1:STATUS_SEVERITY_INFORMATIONAL\r
+       Warning                 = 0x2:STATUS_SEVERITY_WARNING\r
+       Error                   = 0x3:STATUS_SEVERITY_ERROR\r
+       )\r
+\r
+FacilityNames = (\r
+       System                  = 0x0\r
+       RpcRuntime              = 0x2:FACILITY_RPC_RUNTIME\r
+       RpcStubs                = 0x3:FACILITY_RPC_STUBS\r
+       Io                              = 0x4:FACILITY_IO_ERROR_CODE\r
+       IPoIB                   = 0x7:FACILITY_IPOIB_ERROR_CODE\r
+       )\r
+\r
+\r
+MessageId=0x0001\r
+Facility=IPoIB\r
+Severity=Warning\r
+SymbolicName=EVENT_IPOIB_PORT_DOWN\r
+Language=English\r
+%2: Network controller link is down.\r
+.\r
+\r
+MessageId=0x0002\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP\r
+Language=English\r
+%2: Network controller link is up.\r
+.\r
+\r
+\r
+MessageId=0x0003\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP1\r
+Language=English\r
+%2: Network controller link is up at 2.5Gbps.\r
+.\r
+\r
+MessageId=0x0004\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP2\r
+Language=English\r
+%2: Network controller link is up at 5Gbps.\r
+.\r
+\r
+MessageId=0x0006\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP3\r
+Language=English\r
+%2: Network controller link is up at 10Gbps.\r
+.\r
+\r
+MessageId=0x000a\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP4\r
+Language=English\r
+%2: Network controller link is up at 20Gps.\r
+.\r
+\r
+MessageId=0x000e\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP5\r
+Language=English\r
+%2: Network controller link is up at 30Gps.\r
+.\r
+\r
+MessageId=0x0012\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP6\r
+Language=English\r
+%2: Network controller link is up at 40Gps.\r
+.\r
+\r
+MessageId=0x001a\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP7\r
+Language=English\r
+%2: Network controller link is up at 60Gps.\r
+.\r
+\r
+MessageId=0x0032\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_PORT_UP8\r
+Language=English\r
+%2: Network controller link is up at 120Gps.\r
+.\r
+\r
+MessageId=0x0040\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_INIT_SUCCESS\r
+Language=English\r
+%2: Driver Initialized succesfully.\r
+.\r
+\r
+MessageId=0x0041\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_OPEN_CA\r
+Language=English\r
+%2: Failed to open Channel Adapter.\r
+.\r
+\r
+MessageId=0x0042\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_ALLOC_PD\r
+Language=English\r
+%2: Failed to allocate Protection Domain.\r
+.\r
+\r
+MessageId=0x0043\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_CREATE_RECV_CQ\r
+Language=English\r
+%2: Failed to create receive Completion Queue.\r
+.\r
+\r
+MessageId=0x0044\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_CREATE_SEND_CQ\r
+Language=English\r
+%2: Failed to create send Completion Queue.\r
+.\r
+\r
+MessageId=0x0045\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_CREATE_QP\r
+Language=English\r
+%2: Failed to create Queue Pair.\r
+.\r
+\r
+MessageId=0x0046\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_QUERY_QP\r
+Language=English\r
+%2: Failed to get Queue Pair number.\r
+.\r
+\r
+MessageId=0x0047\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_REG_PHYS\r
+Language=English\r
+%2: Failed to create DMA Memory Region.\r
+.\r
+\r
+MessageId=0x0048\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_RECV_POOL\r
+Language=English\r
+%2: Failed to create receive descriptor pool.\r
+.\r
+\r
+MessageId=0x0049\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_RECV_PKT_POOL\r
+Language=English\r
+%2: Failed to create NDIS_PACKET pool for receive indications.\r
+.\r
+\r
+MessageId=0x004A\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_RECV_BUF_POOL\r
+Language=English\r
+%2: Failed to create NDIS_BUFFER pool for receive indications.\r
+.\r
+\r
+MessageId=0x004B\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_SEND_PKT_POOL\r
+Language=English\r
+%2: Failed to create NDIS_PACKET pool for send processing.\r
+.\r
+\r
+MessageId=0x004C\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_SEND_BUF_POOL\r
+Language=English\r
+%2: Failed to create NDIS_BUFFER pool for send processing.\r
+.\r
+\r
+MessageId=0x004D\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_RECV_PKT_ARRAY\r
+Language=English\r
+%2: Failed to allocate receive indication array.\r
+.\r
+\r
+MessageId=0x004E\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_PORT_INFO_TIMEOUT\r
+Language=English\r
+%2: Subnet Administrator query for port information timed out. \r
+Make sure the SA is functioning properly.  Increasing the number\r
+of retries and retry timeout adapter parameters may solve the\r
+issue.\r
+.\r
+\r
+MessageId=0x004F\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_PORT_INFO_REJECT\r
+Language=English\r
+%2: Subnet Administrator failed the query for port information.\r
+Make sure the SA is functioning properly and compatible.\r
+.\r
+\r
+MessageId=0x0050\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_QUERY_PORT_INFO\r
+Language=English\r
+%2: Subnet Administrator query for port information failed.\r
+.\r
+\r
+MessageId=0x0055\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_BCAST_GET\r
+Language=English\r
+%2: Subnet Administrator failed query for broadcast group information.\r
+.\r
+\r
+MessageId=0x0056\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_BCAST_JOIN\r
+Language=English\r
+%2: Subnet Administrator failed request to joing broadcast group.\r
+.\r
+\r
+MessageId=0x0057\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_BCAST_RATE\r
+Language=English\r
+%2: The local port rate is too slow for the existing broadcast MC group.\r
+.\r
+\r
+MessageId=0x0058\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_WRONG_PARAMETER_ERR\r
+Language=English\r
+%2: Incorrect value or non-existing registry  for the required IPoIB parameter %3, overriding it by default value: %4\r
+.\r
+\r
+MessageId=0x0059\r
+Facility=IPoIB\r
+Severity=Warning\r
+SymbolicName=EVENT_IPOIB_WRONG_PARAMETER_WRN\r
+Language=English\r
+%2: Incorrect value or non-existing registry entry  for the required IPoIB parameter %3, overriding it by default value: %4\r
+.\r
+\r
+MessageId=0x005A\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_WRONG_PARAMETER_INFO\r
+Language=English\r
+%2: Incorrect value or non-existing registry  for the optional IPoIB parameter %3, overriding it by default value: %4\r
+.\r
+\r
+MessageId=0x005B\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_PARTITION_ERR\r
+Language=English\r
+%2: Pkey index not found for partition , change switch pkey configuration.\r
+.\r
+\r
+MessageId=0x005C\r
+Facility=IPoIB\r
+Severity=Error\r
+SymbolicName=EVENT_IPOIB_CONNECTED_MODE_ERR\r
+Language=English\r
+%2: Connected Mode failed to initialize, disabled. Interface will use default UD QP transport.\r
+.\r
+\r
+MessageId=0x005D\r
+Facility=IPoIB\r
+Severity=Informational\r
+SymbolicName=EVENT_IPOIB_CONNECTED_MODE_UP\r
+Language=English\r
+%2: Connected Mode initialized and operational.\r
+.\r
+\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.c b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.c
new file mode 100644 (file)
index 0000000..89e1a0c
--- /dev/null
@@ -0,0 +1,8123 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_port.c 4506 2009-06-23 14:40:54Z xalex $\r
+ */\r
+\r
+\r
+\r
+#include "ipoib_endpoint.h"\r
+#include "ipoib_port.h"\r
+#include "ipoib_adapter.h"\r
+#include "ipoib_debug.h"\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_port.tmh"\r
+#endif\r
+#include <offload.h>\r
+\r
+#include "wdm.h"\r
+#include <ntddk.h>\r
+\r
+\r
+\r
+ib_gid_t       bcast_mgid_template = {\r
+       0xff,                                                           /* multicast field */\r
+       0x12,                                                           /* scope (to be filled in) */\r
+       0x40, 0x1b,                                                     /* IPv4 signature */\r
+       0xff, 0xff,                                                     /* 16 bits of P_Key (to be filled in) */\r
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     /* 48 bits of zeros */\r
+       0xff, 0xff, 0xff, 0xff,                         /* 32 bit IPv4 broadcast address */\r
+};\r
+\r
+\r
+#ifdef _DEBUG_\r
+/* Handy pointer for debug use. */\r
+ipoib_port_t   *gp_ipoib_port;\r
+#endif\r
+\r
+static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2);\r
+static void __port_do_mcast_garbage(ipoib_port_t* const        p_port );\r
+\r
+\r
+static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2);\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Declarations\r
+*\r
+******************************************************************************/\r
+static void\r
+__port_construct(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static ib_api_status_t\r
+__port_init(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              ib_pnp_port_rec_t* const        p_pnp_rec );\r
+\r
+static void\r
+__port_destroying(\r
+       IN                              cl_obj_t* const                         p_obj );\r
+\r
+static void\r
+__port_cleanup(\r
+       IN                              cl_obj_t* const                         p_obj );\r
+\r
+static void\r
+__port_free(\r
+       IN                              cl_obj_t* const                         p_obj );\r
+\r
+static ib_api_status_t\r
+__port_query_ca_attrs( \r
+       IN              ipoib_port_t* const                                     p_port,\r
+       IN              ib_ca_attr_t**                                          pp_ca_attrs );\r
+\r
+static void\r
+__srq_async_event_cb(\r
+IN                     ib_async_event_rec_t            *p_event_rec );\r
+\r
+/******************************************************************************\r
+*\r
+* IB resource manager operations\r
+*\r
+******************************************************************************/\r
+static void\r
+__ib_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static ib_api_status_t\r
+__ib_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__ib_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__qp_event(\r
+       IN                              ib_async_event_rec_t            *p_event_rec );\r
+\r
+static void\r
+__cq_event(\r
+       IN                              ib_async_event_rec_t            *p_event_rec );\r
+\r
+static ib_api_status_t\r
+__ib_mgr_activate(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+/******************************************************************************\r
+*\r
+* Buffer manager operations.\r
+*\r
+******************************************************************************/\r
+static void\r
+__buf_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static ib_api_status_t\r
+__buf_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__buf_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static cl_status_t\r
+__recv_ctor(\r
+       IN                              void* const                                     p_object,\r
+       IN                              void*                                           context,\r
+               OUT                     cl_pool_item_t** const          pp_pool_item );\r
+\r
+#if !IPOIB_INLINE_RECV\r
+static void\r
+__recv_dtor(\r
+       IN              const   cl_pool_item_t* const           p_pool_item,\r
+       IN                              void                                            *context );\r
+#endif /* IPOIB_INLINE_RECV */\r
+\r
+static inline ipoib_send_desc_t*\r
+__buf_mgr_get_send(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static inline void\r
+__buf_mgr_put_send(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc );\r
+\r
+static inline ipoib_recv_desc_t*\r
+__buf_mgr_get_recv(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static inline void\r
+__buf_mgr_put_recv(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc,\r
+       IN                              NET_BUFFER_LIST* const          p_net_buffer_list OPTIONAL );\r
+\r
+static inline void\r
+__buf_mgr_put_recv_list(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              cl_qlist_t* const                       p_list );\r
+\r
+//NDIS60\r
+static inline NET_BUFFER_LIST*\r
+__buf_mgr_get_ndis_pkt(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc );\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Receive manager operations.\r
+*\r
+******************************************************************************/\r
+static void\r
+__recv_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static ib_api_status_t\r
+__recv_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__recv_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+/* Posts receive buffers to the receive queue. */\r
+static ib_api_status_t\r
+__recv_mgr_repost(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__recv_cb(\r
+       IN              const   ib_cq_handle_t                          h_cq,\r
+       IN                              void                                            *cq_context );\r
+\r
+static void\r
+__recv_get_endpts(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc,\r
+       IN                              ib_wc_t* const                          p_wc,\r
+               OUT                     ipoib_endpt_t** const           pp_src,\r
+               OUT                     ipoib_endpt_t** const           pp_dst );\r
+\r
+static int32_t\r
+__recv_mgr_filter(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_wc_t* const                          p_done_wc_list,\r
+               OUT                     cl_qlist_t* const                       p_done_list,\r
+               OUT                     cl_qlist_t* const                       p_bad_list );\r
+\r
+static ib_api_status_t\r
+__recv_gen(\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t* const            p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst );\r
+\r
+static ib_api_status_t\r
+__recv_dhcp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t* const            p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst );\r
+\r
+static ib_api_status_t\r
+__recv_arp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_wc_t* const                          p_wc,\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t** const           p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst );\r
+\r
+static ib_api_status_t\r
+__recv_mgr_prepare_pkt(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc,\r
+               OUT                     NET_BUFFER_LIST** const         pp_net_buffer_list );\r
+\r
+static uint32_t\r
+__recv_mgr_build_pkt_array(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              int32_t                                         shortage,\r
+               OUT                     cl_qlist_t* const                       p_done_list,\r
+               OUT                     int32_t* const                          p_discarded );\r
+\r
+/******************************************************************************\r
+*\r
+* Send manager operations.\r
+*\r
+******************************************************************************/\r
+static void\r
+__send_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__send_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static NDIS_STATUS\r
+__send_gen(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN                              INT                                             lso_data_index);\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_ip(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc );\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_igmp_v2(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+    IN         const   ip_hdr_t* const                         p_ip_hdr,\r
+       IN                              size_t                                          iph_options_size,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len );\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_udp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ip_hdr_t* const                         p_ip_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc );\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_dhcp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   udp_hdr_t* const                        p_udp_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc );\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_arp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc );\r
+\r
+static void\r
+__process_failed_send(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc,\r
+       IN              const   NDIS_STATUS                                     status,\r
+       IN              ULONG                                           send_complete_flags );\r
+\r
+static inline NDIS_STATUS\r
+__send_mgr_queue(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              eth_hdr_t* const                        p_eth_hdr,\r
+               OUT                     ipoib_endpt_t** const           pp_endpt );\r
+\r
+static NDIS_STATUS\r
+__build_send_desc(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL* const                                      p_mdl,\r
+       IN              const   size_t                                          mdl_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc );\r
+\r
+\r
+static void\r
+__send_cb(\r
+       IN              const   ib_cq_handle_t                          h_cq,\r
+       IN                              void                                            *cq_context );\r
+\r
+static NDIS_STATUS \r
+GetLsoHeaderSize(\r
+       IN              PNET_BUFFER             pNetBuffer,\r
+       IN              LsoData                 *pLsoData,\r
+       OUT     UINT                    *IndexOfData,\r
+       IN              ipoib_hdr_t *ipoib_hdr );\r
+\r
+\r
+static NDIS_STATUS\r
+__build_lso_desc(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc,\r
+       IN                              ULONG                                           mss,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN                              int32_t                                         hdr_idx,\r
+       IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info );\r
+\r
+static NDIS_STATUS\r
+__send_fragments(\r
+       IN              ipoib_port_t* const                                     p_port,\r
+       IN              ipoib_send_desc_t* const                        p_desc,\r
+       IN              eth_hdr_t* const                                        p_eth_hdr,\r
+       IN              ip_hdr_t* const                                         p_ip_hdr,\r
+       IN              uint32_t                                                        buf_len,\r
+       IN              NDIS_BUFFER*                                            p_ndis_buf );\r
+\r
+static void\r
+__update_fragment_ip_hdr(\r
+IN             ip_hdr_t* const         p_ip_hdr,\r
+IN             uint16_t                        fragment_size, \r
+IN             uint16_t                        fragment_offset, \r
+IN             BOOLEAN                         more_fragments );\r
+\r
+static void\r
+__copy_ip_options(\r
+IN             uint8_t*                        p_buf,\r
+IN             uint8_t*                        p_options,\r
+IN             uint32_t                        options_len,\r
+IN             BOOLEAN                         copy_all );\r
+/******************************************************************************\r
+*\r
+* Endpoint manager operations\r
+*\r
+******************************************************************************/\r
+static void\r
+__endpt_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static void\r
+__endpt_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+/****f* IPoIB/__endpt_mgr_remove_all\r
+* NAME\r
+*      __endpt_mgr_remove_all\r
+*\r
+* DESCRIPTION\r
+*      Removes all enpoints from the port, dereferencing them to initiate\r
+*      destruction.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static void\r
+__endpt_mgr_remove_all(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+/*\r
+********/\r
+\r
+static void\r
+__endpt_mgr_remove(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_endpt_t* const            p_endpt );\r
+\r
+static void\r
+__endpt_mgr_reset_all(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static inline NDIS_STATUS\r
+__endpt_mgr_ref(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ipoib_endpt_t** const           pp_endpt );\r
+\r
+static inline NDIS_STATUS\r
+__endpt_mgr_get_gid_qpn(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ib_gid_t* const                         p_gid,\r
+               OUT                     UNALIGNED net32_t* const        p_qpn );\r
+\r
+static inline ipoib_endpt_t*\r
+__endpt_mgr_get_by_gid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ib_gid_t* const                         p_gid );\r
+\r
+static inline ipoib_endpt_t*\r
+__endpt_mgr_get_by_lid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   net16_t                                         lid );\r
+\r
+static inline ib_api_status_t\r
+__endpt_mgr_insert_locked(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+       IN                              ipoib_endpt_t* const            p_endpt );\r
+\r
+static inline ib_api_status_t\r
+__endpt_mgr_insert(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+       IN                              ipoib_endpt_t* const            p_endpt );\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_add_local(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_port_info_t* const           p_port_info );\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_add_bcast(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_mcast_rec_t                          *p_mcast_rec );\r
+\r
+/******************************************************************************\r
+*\r
+* MCast operations.\r
+*\r
+******************************************************************************/\r
+static ib_api_status_t\r
+__port_get_bcast(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+static ib_api_status_t\r
+__port_join_bcast(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_member_rec_t* const          p_member_rec );\r
+\r
+static ib_api_status_t\r
+__port_create_bcast(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+\r
+\r
+static void\r
+__bcast_get_cb(\r
+       IN                              ib_query_rec_t                          *p_query_rec );\r
+\r
+\r
+static void\r
+__bcast_cb(\r
+       IN                              ib_mcast_rec_t                          *p_mcast_rec );\r
+\r
+\r
+static void\r
+__mcast_cb(\r
+       IN                              ib_mcast_rec_t                          *p_mcast_rec );\r
+\r
+void\r
+__leave_error_mcast_cb(\r
+       IN                              void                            *context );\r
+\r
+\r
+static intn_t\r
+__gid_cmp(\r
+       IN              const   void* const                                     p_key1,\r
+       IN              const   void* const                                     p_key2 )\r
+{\r
+       return cl_memcmp( p_key1, p_key2, sizeof(ib_gid_t) );\r
+}\r
+\r
+\r
+inline void ipoib_port_ref( ipoib_port_t * p_port, int type )\r
+{\r
+       cl_obj_ref( &p_port->obj );\r
+#if DBG\r
+       cl_atomic_inc( &p_port->ref[type % ref_mask] );\r
+       if ((p_port->obj.ref_cnt % 20)==0)\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
+               ("ref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) );\r
+       //TODO remove\r
+       //ASSERT (p_port->obj.ref_cnt < 100);\r
+#else\r
+       UNREFERENCED_PARAMETER(type);\r
+#endif\r
+}\r
+\r
+\r
+inline void ipoib_port_deref(ipoib_port_t * p_port, int type)\r
+{\r
+#if DBG\r
+       cl_atomic_dec( &p_port->ref[type % ref_mask] );\r
+       if ((p_port->obj.ref_cnt % 20) == 0)\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
+               ("deref type %d ref_cnt %d\n", type, p_port->obj.ref_cnt) );\r
+#else\r
+       UNREFERENCED_PARAMETER(type);\r
+#endif\r
+       cl_obj_deref( &p_port->obj );\r
+\r
+}\r
+\r
+/* function returns pointer to payload that is going after IP header.\r
+*  asssuming that payload and IP header are in the same buffer\r
+*/\r
+static void* GetIpPayloadPtr(const     ip_hdr_t* const p_ip_hdr)\r
+{\r
+       return (void*)((uint8_t*)p_ip_hdr + IP_HEADER_LENGTH(p_ip_hdr));\r
+}\r
+\r
+/******************************************************************************\r
+*\r
+* Implementation\r
+*\r
+******************************************************************************/\r
+ib_api_status_t\r
+ipoib_create_port(\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              ib_pnp_port_rec_t* const        p_pnp_rec,\r
+               OUT                     ipoib_port_t** const            pp_port )\r
+{\r
+       ib_api_status_t         status;\r
+       ipoib_port_t            *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( !p_adapter->p_port );\r
+\r
+       p_port = cl_zalloc( sizeof(ipoib_port_t) +\r
+               (sizeof(ipoib_hdr_t) * (p_adapter->params.sq_depth - 1)) );\r
+       if( !p_port )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate ipoib_port_t (%d bytes)\n",\r
+                       sizeof(ipoib_port_t)) );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+#ifdef _DEBUG_\r
+       gp_ipoib_port = p_port;\r
+#endif\r
+\r
+       __port_construct( p_port );\r
+\r
+       status = __port_init( p_port, p_adapter, p_pnp_rec );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_port_init returned %s.\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               __port_cleanup( &p_port->obj );\r
+               __port_free( &p_port->obj );\r
+               return status;\r
+       }\r
+\r
+       *pp_port = p_port;\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+ipoib_port_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_port );\r
+       CL_ASSERT( p_port->p_adapter );\r
+       CL_ASSERT( !p_port->p_adapter->p_port );\r
+\r
+       cl_obj_destroy( &p_port->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__port_construct(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_port->state = IB_QPS_RESET;\r
+\r
+       cl_obj_construct( &p_port->obj, IPOIB_OBJ_PORT );\r
+       cl_spinlock_construct( &p_port->send_lock );\r
+       cl_spinlock_construct( &p_port->recv_lock );\r
+       __ib_mgr_construct( p_port );\r
+       __buf_mgr_construct( p_port );\r
+\r
+       __recv_mgr_construct( p_port );\r
+       __send_mgr_construct( p_port );\r
+\r
+       __endpt_mgr_construct( p_port );\r
+\r
+       KeInitializeEvent( &p_port->sa_event, NotificationEvent, TRUE );\r
+       KeInitializeEvent( &p_port->leave_mcast_event, NotificationEvent, TRUE );\r
+       \r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__port_init(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_adapter_t* const          p_adapter,\r
+       IN                              ib_pnp_port_rec_t* const        p_pnp_rec )\r
+{\r
+       cl_status_t                     cl_status;\r
+       ib_api_status_t         status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_port->port_num = p_pnp_rec->p_port_attr->port_num;\r
+       p_port->p_adapter = p_adapter;\r
+\r
+       cl_status = cl_spinlock_init( &p_port->send_lock );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_spinlock_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       cl_status = cl_spinlock_init( &p_port->recv_lock );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_spinlock_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       /* Initialize the IB resource manager. */\r
+       status = __ib_mgr_init( p_port );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__ib_mgr_init returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Initialize the buffer manager. */\r
+       status = __buf_mgr_init( p_port );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__buf_mgr_init returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Initialize the receive manager. */\r
+       status = __recv_mgr_init( p_port );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__recv_mgr_init returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Initialize the endpoint manager. */\r
+       status = __endpt_mgr_init( p_port );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__endpt_mgr_init returned %s\n", \r
+                       p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+        KeInitializeDpc(&p_port->recv_dpc,(PKDEFERRED_ROUTINE)__recv_cb_dpc,p_port);\r
+\r
+\r
+        /* Initialize multicast garbage collector timer and DPC object */\r
+        KeInitializeDpc(&p_port->gc_dpc,(PKDEFERRED_ROUTINE)__port_mcast_garbage_dpc,p_port);\r
+        KeInitializeTimerEx(&p_port->gc_timer,SynchronizationTimer);\r
+\r
+       /* We only ever destroy from the PnP callback thread. */\r
+       cl_status = cl_obj_init( &p_port->obj, CL_DESTROY_SYNC,\r
+               __port_destroying, __port_cleanup, __port_free );\r
+\r
+#if DBG\r
+       cl_atomic_inc( &p_port->ref[ref_init] );\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
+               ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) );\r
+#endif\r
+\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_obj_init returned %#x\n", cl_status) );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       cl_status = cl_obj_insert_rel( &p_port->rel, &p_adapter->obj, &p_port->obj );\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_obj_insert_rel returned %#x\n", cl_status) );\r
+               cl_obj_destroy( &p_port->obj );\r
+               return IB_ERROR;\r
+       }\r
+\r
+#if DBG\r
+       cl_atomic_inc( &p_port->ref[ref_init] );\r
+       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OBJ,\r
+               ("ref type %d ref_cnt %d\n", ref_init, p_port->obj.ref_cnt) );\r
+#endif\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+__port_destroying(\r
+       IN                              cl_obj_t* const                         p_obj )\r
+{\r
+       ipoib_port_t    *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_obj );\r
+\r
+       p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
+\r
+       ipoib_port_down( p_port );\r
+\r
+       __endpt_mgr_remove_all( p_port );\r
+\r
+#if 0\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               endpt_cm_buf_mgr_destroy(  p_port );\r
+               ipoib_port_srq_destroy( p_port );\r
+               p_port->endpt_mgr.thread_is_done = 1;\r
+               cl_event_signal( &p_port->endpt_mgr.event );\r
+       }\r
+#endif\r
+       ASSERT(FALSE);\r
+       //TODO NDIS6.0\r
+       ipoib_port_resume( p_port, FALSE );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__port_cleanup(\r
+       IN                              cl_obj_t* const                         p_obj )\r
+{\r
+       ipoib_port_t    *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_obj );\r
+\r
+       p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
+\r
+       /* Wait for all sends and receives to get flushed. */\r
+       while( p_port->send_mgr.depth || p_port->recv_mgr.depth )\r
+               cl_thread_suspend( 0 );\r
+\r
+       /* Destroy the send and receive managers before closing the CA. */\r
+       __ib_mgr_destroy( p_port );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__port_free(\r
+       IN                              cl_obj_t* const                         p_obj )\r
+{\r
+       ipoib_port_t    *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_obj );\r
+\r
+       p_port = PARENT_STRUCT( p_obj, ipoib_port_t, obj );\r
+\r
+       KeCancelTimer(&p_port->gc_timer);\r
+       KeFlushQueuedDpcs();\r
+       __endpt_mgr_destroy( p_port );\r
+       __recv_mgr_destroy( p_port );\r
+       __send_mgr_destroy( p_port );\r
+       __buf_mgr_destroy( p_port );\r
+\r
+       cl_spinlock_destroy( &p_port->send_lock );\r
+       cl_spinlock_destroy( &p_port->recv_lock );\r
+\r
+       cl_obj_deinit( p_obj );\r
+       if( p_port->p_ca_attrs )\r
+       {\r
+               cl_free ( p_port->p_ca_attrs );\r
+       }\r
+       cl_free( p_port );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* IB resource manager implementation.\r
+*\r
+******************************************************************************/\r
+static void\r
+__ib_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       cl_memclr( &p_port->ib_mgr, sizeof(ipoib_ib_mgr_t) );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__ib_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_cq_create_t          cq_create;\r
+       ib_qp_create_t          qp_create;\r
+       ib_phys_create_t        phys_create;\r
+       ib_phys_range_t         phys_range;\r
+       uint64_t                        vaddr;\r
+       net32_t                         rkey;\r
+       ib_qp_attr_t            qp_attr;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /* Open the CA. */\r
+       status = p_port->p_adapter->p_ifc->open_ca(\r
+               p_port->p_adapter->h_al, p_port->p_adapter->guids.ca_guid,\r
+               NULL, p_port, &p_port->ib_mgr.h_ca );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_OPEN_CA, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_open_ca returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       status = __port_query_ca_attrs( p_port, &p_port->p_ca_attrs );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Query CA attributes failed\n" ) );\r
+               return status;\r
+       }\r
+#if 0\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               uint32_t payload_mtu = __port_attr_to_mtu_size( \r
+                       p_port->p_ca_attrs->p_port_attr[p_port->port_num - 1].mtu )\r
+                       - sizeof(ipoib_hdr_t);\r
+               /* adjust ipoib UD payload MTU to actual port MTU size. */\r
+               p_port->p_adapter->params.payload_mtu = \r
+                               max( DEFAULT_PAYLOAD_MTU, payload_mtu );\r
+               p_port->p_adapter->params.xfer_block_size = \r
+                       (sizeof(eth_hdr_t) + p_port->p_adapter->params.payload_mtu);\r
+       }\r
+#endif\r
+#if IPOIB_USE_DMA\r
+       /* init DMA only once while running MiniportInitialize */\r
+       if ( !p_port->p_adapter->reset )\r
+       {\r
+               ULONG max_phys_mapping;\r
+               if( p_port->p_adapter->params.cm_enabled )\r
+               {\r
+                       max_phys_mapping = p_port->p_adapter->params.cm_xfer_block_size;\r
+               }\r
+               else if( p_port->p_adapter->params.lso )\r
+               {\r
+                       max_phys_mapping = LARGE_SEND_OFFLOAD_SIZE;\r
+               }\r
+               else\r
+               {\r
+                       max_phys_mapping = p_port->p_adapter->params.xfer_block_size;\r
+               }\r
+               /*if( NdisMInitializeScatterGatherDma( p_port->p_adapter->h_adapter,\r
+                                                       TRUE, max_phys_mapping )!= NDIS_STATUS_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("NdisMInitializeScatterGatherDma failed\n" ) );\r
+                       return IB_INSUFFICIENT_RESOURCES;\r
+               }*/\r
+       }\r
+#endif\r
+\r
+       /* Allocate the PD. */\r
+       status = p_port->p_adapter->p_ifc->alloc_pd(\r
+               p_port->ib_mgr.h_ca, IB_PDT_UD, p_port, &p_port->ib_mgr.h_pd );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_ALLOC_PD, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_alloc_pd returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Allocate receive CQ. */\r
+       cq_create.size = p_port->p_adapter->params.rq_depth;\r
+       cq_create.pfn_comp_cb = __recv_cb;\r
+       cq_create.h_wait_obj = NULL;\r
+\r
+       status = p_port->p_adapter->p_ifc->create_cq(\r
+               p_port->ib_mgr.h_ca, &cq_create, p_port,\r
+               __cq_event, &p_port->ib_mgr.h_recv_cq );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_CREATE_RECV_CQ, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_cq returned %s.\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Allocate send CQ. */\r
+       cq_create.size = p_port->p_adapter->params.sq_depth;\r
+       cq_create.pfn_comp_cb = __send_cb;\r
+\r
+       status = p_port->p_adapter->p_ifc->create_cq(\r
+               p_port->ib_mgr.h_ca, &cq_create, p_port,\r
+               __cq_event, &p_port->ib_mgr.h_send_cq );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_CREATE_SEND_CQ, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_cq returned %s.\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+       \r
+       /* Allocate the QP. */\r
+       cl_memclr( &qp_create, sizeof(qp_create) );\r
+       qp_create.qp_type = IB_QPT_UNRELIABLE_DGRM;\r
+       qp_create.rq_depth = p_port->p_adapter->params.rq_depth;\r
+       qp_create.rq_sge = 2;   /* To support buffers spanning pages. */\r
+       qp_create.h_rq_cq = p_port->ib_mgr.h_recv_cq;\r
+       qp_create.sq_depth = p_port->p_adapter->params.sq_depth;\r
+\r
+#define UD_QP_USED_SGE 3\r
+       qp_create.sq_sge = MAX_SEND_SGE < p_port->p_ca_attrs->max_sges ? \r
+                       MAX_SEND_SGE  : ( p_port->p_ca_attrs->max_sges - UD_QP_USED_SGE );\r
+       if ( !p_port->p_ca_attrs->ipoib_csum ) \r
+       { \r
+               /* checksum is not supported by device\r
+               user must specify BYPASS to explicitly cancel checksum calculation */\r
+               if (p_port->p_adapter->params.send_chksum_offload == CSUM_ENABLED)\r
+                       p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED;\r
+               if (p_port->p_adapter->params.recv_chksum_offload == CSUM_ENABLED)\r
+                       p_port->p_adapter->params.recv_chksum_offload = CSUM_DISABLED;\r
+       }\r
+\r
+       qp_create.h_sq_cq = p_port->ib_mgr.h_send_cq;\r
+       qp_create.sq_signaled = FALSE;\r
+       status = p_port->p_adapter->p_ifc->create_qp(\r
+               p_port->ib_mgr.h_pd, &qp_create, p_port,\r
+               __qp_event, &p_port->ib_mgr.h_qp );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_CREATE_QP, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_qp returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+       /* Query the QP so we can get our QPN. */\r
+       status = p_port->p_adapter->p_ifc->query_qp(\r
+               p_port->ib_mgr.h_qp, &qp_attr );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_QUERY_QP, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_query_qp returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+       p_port->ib_mgr.qpn = qp_attr.num;\r
+\r
+       /* Register all of physical memory */\r
+       phys_create.length = MEM_REG_SIZE;\r
+       phys_create.num_ranges = 1;\r
+       phys_create.range_array = &phys_range;\r
+       phys_create.buf_offset = 0;\r
+       phys_create.hca_page_size = PAGE_SIZE;\r
+       phys_create.access_ctrl = IB_AC_LOCAL_WRITE;\r
+       phys_range.base_addr = 0;\r
+       phys_range.size = MEM_REG_SIZE;\r
+       vaddr = 0;\r
+       status = p_port->p_adapter->p_ifc->reg_phys(\r
+               p_port->ib_mgr.h_pd, &phys_create, &vaddr,\r
+               &p_port->ib_mgr.lkey, &rkey, &p_port->ib_mgr.h_mr );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_REG_PHYS, 1, status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_reg_phys returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       status = ipoib_port_srq_init( p_port );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_port_srq_init failed %s\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               /* disable further CM initialization */\r
+               p_port->p_adapter->params.cm_enabled = FALSE;\r
+\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                               EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de1 );\r
+\r
+       }\r
+//CM\r
+#if 0\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               status = endpt_cm_buf_mgr_init( p_port );\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("CM Init buf mgr failed status %#x\n", status ) );\r
+                       ipoib_port_srq_destroy( p_port );\r
+                       p_port->p_adapter->params.cm_enabled = FALSE;\r
+\r
+                       NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                               EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de2 );\r
+               }\r
+               else \r
+               {\r
+                       if ( p_port->p_adapter->params.send_chksum_offload )\r
+                       p_port->p_adapter->params.send_chksum_offload = CSUM_DISABLED;\r
+               }\r
+       }\r
+#endif\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+static void\r
+__srq_async_event_cb(\r
+IN                     ib_async_event_rec_t            *p_event_rec )\r
+{\r
+       ipoib_port_t* p_port = \r
+               (ipoib_port_t *)p_event_rec->context;\r
+\r
+       switch( p_event_rec->code )\r
+       {\r
+       case IB_AE_SRQ_LIMIT_REACHED:\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("SRQ ASYNC EVENT CODE %d: %s\n", \r
+                       p_event_rec->code, "IB_AE_SRQ_LIMIT_REACHED" ) );\r
+                       break;\r
+       case IB_AE_SRQ_CATAS_ERROR:\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("SRQ ASYNC EVENT CODE %d: %s\n", \r
+                               p_event_rec->code, "IB_AE_SRQ_CATAS_ERROR" ) );\r
+                       /*SRQ is in err state, must reinitialize */\r
+                       p_port->p_adapter->hung = TRUE;\r
+                       break;\r
+       case IB_AE_SRQ_QP_LAST_WQE_REACHED:\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("SRQ ASYNC EVENT CODE %d: %s\n", \r
+                               p_event_rec->code, "IB_AE_SRQ_QP_LAST_WQE_REACHED" ) );\r
+                       /*SRQ is in err state, must reinitialize */\r
+                       p_port->p_adapter->hung = TRUE;\r
+                       break;\r
+       default:\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ASYNC EVENT CODE ARRIVED %d(%#x)\n", \r
+                               p_event_rec->code, p_event_rec->code ) );\r
+       }\r
+}\r
+\r
+ib_api_status_t\r
+ipoib_port_srq_init(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t         ib_status;\r
+       ib_srq_handle_t         h_srq;\r
+       ib_srq_attr_t           srq_attr;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       \r
+       if( !p_port->p_adapter->params.cm_enabled )\r
+               return IB_SUCCESS;\r
+\r
+       srq_attr.max_sge = min( 2, p_port->p_ca_attrs->max_srq_sges );\r
+       srq_attr.srq_limit = 10;\r
+       srq_attr.max_wr = \r
+               min( (uint32_t)p_port->p_adapter->params.rq_depth * 8,\r
+                               p_port->p_ca_attrs->max_srq_wrs/2 );\r
+\r
+       ib_status = p_port->p_adapter->p_ifc->create_srq( \r
+                                                               p_port->ib_mgr.h_pd, \r
+                                                               &srq_attr, \r
+                                                               p_port, \r
+                                                               __srq_async_event_cb, \r
+                                                               &h_srq );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_CREATE_QP, 1, ib_status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_srq failed status %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+               return ib_status;\r
+       }\r
+       p_port->ib_mgr.h_srq = h_srq;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+\r
+       return ib_status;\r
+}\r
+\r
+/*  __port_query_ca_attrs() \r
+ *  returns a pointer to allocated memory.\r
+ *  must be released by caller.\r
+ */\r
+static ib_api_status_t\r
+__port_query_ca_attrs( \r
+       IN              ipoib_port_t* const             p_port,\r
+       IN              ib_ca_attr_t**                  pp_ca_attrs )\r
+{\r
+       ib_api_status_t         ib_status;\r
+       uint32_t                        attr_size;\r
+       ib_ca_attr_t*           p_ca_attrs;\r
+\r
+       *pp_ca_attrs = NULL;\r
+\r
+       ib_status = \r
+               p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, NULL , &attr_size );\r
+       if( ib_status != IB_INSUFFICIENT_MEMORY )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_query_ca failed status %s\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+               goto done;\r
+       }\r
+       CL_ASSERT( attr_size );\r
+\r
+       p_ca_attrs = cl_zalloc( attr_size );\r
+       if ( p_ca_attrs == NULL )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Allocate %d bytes failed for CA Attributes\n", attr_size ));\r
+               ib_status = IB_INSUFFICIENT_MEMORY;\r
+               goto done;\r
+       }\r
+\r
+       ib_status = \r
+               p_port->p_adapter->p_ifc->query_ca( p_port->ib_mgr.h_ca, p_ca_attrs , &attr_size );\r
+       if ( ib_status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("CA attributes query failed\n") );\r
+               cl_free ( p_ca_attrs );\r
+               goto done;\r
+       }\r
+\r
+       *pp_ca_attrs = p_ca_attrs;\r
+done:\r
+       return ib_status;\r
+}\r
+\r
+void\r
+ipoib_port_srq_destroy( \r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t status;\r
+\r
+       if( p_port->ib_mgr.h_srq )\r
+       {\r
+               status =\r
+                       p_port->p_adapter->p_ifc->destroy_srq( p_port->ib_mgr.h_srq, NULL );\r
+               CL_ASSERT( status == IB_SUCCESS );\r
+               p_port->ib_mgr.h_srq = NULL;\r
+       }\r
+}\r
+\r
+static void\r
+__ib_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       if( p_port->ib_mgr.h_ca )\r
+       {\r
+               status =\r
+                       p_port->p_adapter->p_ifc->close_ca( p_port->ib_mgr.h_ca, NULL );\r
+               CL_ASSERT( status == IB_SUCCESS );\r
+               p_port->ib_mgr.h_ca = NULL;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Buffer manager implementation.\r
+*\r
+******************************************************************************/\r
+static void\r
+__buf_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       cl_qpool_construct( &p_port->buf_mgr.recv_pool );\r
+\r
+       p_port->buf_mgr.h_packet_pool = NULL;\r
+       p_port->buf_mgr.h_buffer_pool = NULL;\r
+\r
+       NdisInitializeNPagedLookasideList( &p_port->buf_mgr.send_buf_list,\r
+               NULL, NULL, 0, MAX_XFER_BLOCK_SIZE, 'bipi', 0 );\r
+\r
+       p_port->buf_mgr.h_send_pkt_pool = NULL;\r
+       p_port->buf_mgr.h_send_buf_pool = NULL;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__buf_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       cl_status_t             cl_status;\r
+       ipoib_params_t  *p_params;\r
+       NET_BUFFER_LIST_POOL_PARAMETERS pool_parameters;\r
+       IPOIB_ENTER(IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_port );\r
+       CL_ASSERT( p_port->p_adapter );\r
+\r
+       p_params = &p_port->p_adapter->params;\r
+\r
+       /* Allocate the receive descriptor pool */\r
+       cl_status = cl_qpool_init( &p_port->buf_mgr.recv_pool,\r
+               p_params->rq_depth * p_params->recv_pool_ratio,\r
+#if IPOIB_INLINE_RECV\r
+               0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, NULL, p_port );\r
+#else  /* IPOIB_INLINE_RECV */\r
+               0, 0, sizeof(ipoib_recv_desc_t), __recv_ctor, __recv_dtor, p_port );\r
+#endif /* IPOIB_INLINE_RECV */\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_POOL, 1, cl_status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_qpool_init for recvs returned %#x\n",\r
+                       cl_status) );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       /* Allocate the NET BUFFER list pools for receive indication. */\r
+       NdisZeroMemory(&pool_parameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));\r
+    pool_parameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+    pool_parameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;\r
+    pool_parameters.Header.Size = sizeof(pool_parameters);\r
+    pool_parameters.ProtocolId = 0;\r
+    pool_parameters.ContextSize = 0;\r
+    pool_parameters.fAllocateNetBuffer = TRUE;\r
+    pool_parameters.PoolTag = 'CRPI';\r
+\r
+    p_port->buf_mgr.h_packet_pool = NdisAllocateNetBufferListPool(\r
+                p_port->p_adapter->h_adapter,\r
+                &pool_parameters); \r
+\r
+       if( !p_port->buf_mgr.h_packet_pool )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_PKT_POOL, 1, NDIS_STATUS_RESOURCES  );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+/*\r
+       NdisAllocateBufferPool( &ndis_status, &p_port->buf_mgr.h_buffer_pool,\r
+               p_params->rq_depth );\r
+       if( ndis_status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_BUF_POOL, 1, ndis_status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+*/\r
+       /* Allocate the NET buffer list pool for send formatting. */\r
+    pool_parameters.PoolTag = 'XTPI';\r
+\r
+    p_port->buf_mgr.h_send_pkt_pool = NdisAllocateNetBufferListPool(\r
+                p_port->p_adapter->h_adapter,\r
+                &pool_parameters); \r
+       if( !p_port->buf_mgr.h_send_pkt_pool)\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_SEND_PKT_POOL, 1, NDIS_STATUS_RESOURCES );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisAllocatePacketPool returned %08X\n", (UINT)NDIS_STATUS_RESOURCES) );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+/*\r
+       NdisAllocateBufferPool( &ndis_status,\r
+               &p_port->buf_mgr.h_send_buf_pool, 1 );\r
+       if( ndis_status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_SEND_BUF_POOL, 1, ndis_status );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisAllocateBufferPool returned %08X\n", ndis_status) );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+*/\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+__buf_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER(IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( p_port );\r
+\r
+       /* Destroy the send packet and buffer pools. \r
+       if( p_port->buf_mgr.h_send_buf_pool )\r
+               NdisFreeBufferPool( p_port->buf_mgr.h_send_buf_pool );*/\r
+       if( p_port->buf_mgr.h_send_pkt_pool )\r
+               NdisFreeNetBufferListPool ( p_port->buf_mgr.h_send_pkt_pool );\r
+\r
+       /* Destroy the receive packet and buffer pools. \r
+       if( p_port->buf_mgr.h_buffer_pool )\r
+               NdisFreeBufferPool( p_port->buf_mgr.h_buffer_pool );*/\r
+       if( p_port->buf_mgr.h_packet_pool )\r
+               NdisFreeNetBufferListPool ( p_port->buf_mgr.h_packet_pool );\r
+\r
+       /* Free the receive and send descriptors. */\r
+       cl_qpool_destroy( &p_port->buf_mgr.recv_pool );\r
+\r
+       /* Free the lookaside list of scratch buffers. */\r
+       NdisDeleteNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+\r
+       IPOIB_EXIT(  IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static cl_status_t\r
+__recv_ctor(\r
+       IN                              void* const                                     p_object,\r
+       IN                              void*                                           context,\r
+               OUT                     cl_pool_item_t** const          pp_pool_item )\r
+{\r
+       ipoib_recv_desc_t       *p_desc;\r
+       ipoib_port_t            *p_port;\r
+\r
+#if IPOIB_INLINE_RECV\r
+       uint32_t                        ds0_len;\r
+#endif\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ALLOC );\r
+\r
+       CL_ASSERT( p_object );\r
+       CL_ASSERT( context );\r
+\r
+       p_desc = (ipoib_recv_desc_t*)p_object;\r
+       p_port = (ipoib_port_t*)context;\r
+\r
+       /* Setup the work request. */\r
+       p_desc->wr.ds_array = p_desc->local_ds;\r
+       p_desc->wr.wr_id = (uintn_t)p_desc;\r
+\r
+#if IPOIB_INLINE_RECV\r
+       /* Sanity check on the receive buffer layout */\r
+       CL_ASSERT( (void*)&p_desc->buf.eth.pkt.type ==\r
+               (void*)&p_desc->buf.ib.pkt.type );\r
+       CL_ASSERT( sizeof(recv_buf_t) == sizeof(ipoib_pkt_t) + sizeof(ib_grh_t) );\r
+\r
+       /* Setup the local data segment. */\r
+       p_desc->local_ds[0].vaddr = cl_get_physaddr( &p_desc->buf );\r
+       p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey;\r
+       ds0_len =\r
+               PAGE_SIZE - ((uint32_t)p_desc->local_ds[0].vaddr & (PAGE_SIZE - 1));\r
+       if( ds0_len >= sizeof(recv_buf_t) )\r
+       {\r
+               /* The whole buffer is within a page. */\r
+               p_desc->local_ds[0].length = ds0_len;\r
+               p_desc->wr.num_ds = 1;\r
+       }\r
+       else\r
+       {\r
+               /* The buffer crosses page boundaries. */\r
+               p_desc->local_ds[0].length = ds0_len;\r
+               p_desc->local_ds[1].vaddr = cl_get_physaddr( \r
+                       ((uint8_t*)&p_desc->buf) + ds0_len );\r
+               p_desc->local_ds[1].lkey = p_port->ib_mgr.lkey;\r
+               p_desc->local_ds[1].length = sizeof(recv_buf_t) - ds0_len;\r
+               p_desc->wr.num_ds = 2;\r
+       }\r
+#else  /* IPOIB_INLINE_RECV */\r
+       /* Allocate the receive buffer. */\r
+       p_desc->p_buf = (recv_buf_t*)cl_zalloc( sizeof(recv_buf_t) );\r
+       if( !p_desc->p_buf )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate receive buffer.\n") );\r
+               return CL_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       /* Sanity check on the receive buffer layout */\r
+       CL_ASSERT( (void*)&p_desc->p_buf->eth.pkt.type ==\r
+               (void*)&p_desc->p_buf->ib.pkt.type );\r
+\r
+       /* Setup the local data segment. */\r
+       p_desc->local_ds[0].vaddr = cl_get_physaddr( p_desc->p_buf );\r
+       p_desc->local_ds[0].length = sizeof(ipoib_pkt_t) + sizeof(ib_grh_t);\r
+       p_desc->local_ds[0].lkey = p_port->ib_mgr.lkey;\r
+       p_desc->wr.num_ds = 1;\r
+#endif /* IPOIB_INLINE_RECV */\r
+\r
+       *pp_pool_item = &p_desc->item;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ALLOC );\r
+       return CL_SUCCESS;\r
+}\r
+\r
+\r
+#if !IPOIB_INLINE_RECV\r
+static void\r
+__recv_dtor(\r
+       IN              const   cl_pool_item_t* const           p_pool_item,\r
+       IN                              void                                            *context )\r
+{\r
+       ipoib_recv_desc_t       *p_desc;\r
+\r
+       IPOIB_ENTER(  IPOIB_DBG_ALLOC );\r
+\r
+       UNUSED_PARAM( context );\r
+\r
+       p_desc = PARENT_STRUCT( p_pool_item, ipoib_recv_desc_t, item );\r
+\r
+       if( p_desc->p_buf )\r
+               cl_free( p_desc->p_buf );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ALLOC );\r
+}\r
+#endif\r
+\r
+\r
+static inline ipoib_recv_desc_t*\r
+__buf_mgr_get_recv(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ipoib_recv_desc_t       *p_desc;\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+       p_desc = (ipoib_recv_desc_t*)cl_qpool_get( &p_port->buf_mgr.recv_pool );\r
+       /* Reference the port object for the send. */\r
+       if( p_desc )\r
+       {\r
+               ipoib_port_ref( p_port, ref_get_recv );\r
+               CL_ASSERT( p_desc->wr.wr_id == (uintn_t)p_desc );\r
+#if IPOIB_INLINE_RECV\r
+               CL_ASSERT( p_desc->local_ds[0].vaddr ==\r
+                       cl_get_physaddr( &p_desc->buf ) );\r
+#else  /* IPOIB_INLINE_RECV */\r
+               CL_ASSERT( p_desc->local_ds[0].vaddr ==\r
+                       cl_get_physaddr( p_desc->p_buf ) );\r
+               CL_ASSERT( p_desc->local_ds[0].length ==\r
+                       (sizeof(ipoib_pkt_t) + sizeof(ib_grh_t)) );\r
+#endif /* IPOIB_INLINE_RECV */\r
+               CL_ASSERT( p_desc->local_ds[0].lkey == p_port->ib_mgr.lkey );\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return p_desc;\r
+}\r
+\r
+\r
+//NDIS60\r
+static inline void\r
+__buf_mgr_put_recv(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc,\r
+       IN                              NET_BUFFER_LIST* const          p_net_buffer_list OPTIONAL )\r
+{\r
+       NET_BUFFER              *p_buf = NULL;\r
+       MDL                             *p_mdl = NULL;\r
+       IPOIB_ENTER(IPOIB_DBG_RECV );\r
+\r
+       if( p_net_buffer_list )\r
+       {\r
+               NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+               p_buf = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list);\r
+               CL_ASSERT( p_buf );\r
+               p_mdl = NET_BUFFER_FIRST_MDL(p_buf);\r
+               CL_ASSERT( p_mdl );\r
+               NdisFreeMdl(p_mdl);\r
+               NdisFreeNetBufferList(p_net_buffer_list);\r
+       }\r
+\r
+       /* Return the descriptor to its pools. */\r
+       cl_qpool_put( &p_port->buf_mgr.recv_pool, &p_desc->item );\r
+\r
+       /*\r
+        * Dereference the port object since the receive is no longer outstanding.\r
+        */\r
+       ipoib_port_deref( p_port, ref_get_recv );\r
+       IPOIB_EXIT(  IPOIB_DBG_RECV );\r
+}\r
+\r
+\r
+static inline void\r
+__buf_mgr_put_recv_list(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              cl_qlist_t* const                       p_list )\r
+{\r
+       //IPOIB_ENTER(  IPOIB_DBG_RECV );\r
+       cl_qpool_put_list( &p_port->buf_mgr.recv_pool, p_list );\r
+       //IPOIB_EXIT(  IPOIB_DBG_RECV );\r
+}\r
+\r
+\r
+static inline NET_BUFFER_LIST*\r
+__buf_mgr_get_ndis_pkt(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc )\r
+{\r
+       NET_BUFFER_LIST                 *p_net_buffer_list;\r
+       MDL                                             *p_mdl;\r
+\r
+       IPOIB_ENTER(  IPOIB_DBG_RECV );\r
+\r
+       p_mdl = NdisAllocateMdl(p_port->p_adapter->h_adapter,\r
+                                                       &p_desc->buf.eth.pkt,\r
+                                                       p_desc->len );\r
+       if( !p_mdl )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate MDL\n") );\r
+               return NULL;\r
+       }\r
+\r
+       p_net_buffer_list = NdisAllocateNetBufferAndNetBufferList(\r
+                                               p_port->buf_mgr.h_packet_pool,\r
+                                               0,\r
+                                               0,\r
+                                               p_mdl,\r
+                                               0,\r
+                                               0);\r
+\r
+       if( !p_net_buffer_list )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate NET_BUFFER_LIST\n") );\r
+               NdisFreeMdl(p_mdl);\r
+               return NULL;\r
+       }\r
+\r
+       NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+       IPOIB_PORT_FROM_PACKET( p_net_buffer_list ) = p_port;\r
+       IPOIB_RECV_FROM_PACKET( p_net_buffer_list ) = p_desc;\r
+       p_net_buffer_list->SourceHandle = p_port->p_adapter->h_adapter;\r
+\r
+       IPOIB_EXIT(  IPOIB_DBG_RECV );\r
+       return p_net_buffer_list;\r
+}\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Receive manager implementation.\r
+*\r
+******************************************************************************/\r
+static void\r
+__recv_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       cl_qlist_init( &p_port->recv_mgr.done_list );\r
+\r
+       p_port->recv_mgr.recv_pkt_array = NULL;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /* Allocate the NDIS_PACKET pointer array for indicating receives. */\r
+       p_port->recv_mgr.recv_pkt_array = cl_malloc(\r
+               sizeof(NET_BUFFER_LIST*) * p_port->p_adapter->params.rq_depth );\r
+       if( !p_port->recv_mgr.recv_pkt_array )\r
+       {\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_RECV_PKT_ARRAY, 0 );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("cl_malloc for PNDIS_PACKET array failed.\n") );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+__recv_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       CL_ASSERT( cl_is_qlist_empty( &p_port->recv_mgr.done_list ) );\r
+       CL_ASSERT( !p_port->recv_mgr.depth );\r
+\r
+       if( p_port->recv_mgr.recv_pkt_array )\r
+               cl_free( p_port->recv_mgr.recv_pkt_array );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+/*\r
+ * Posts receive buffers to the receive queue and returns the number\r
+ * of receives needed to bring the RQ to its low water mark.  Note\r
+ * that the value is signed, and can go negative.  All tests must\r
+ * be for > 0.\r
+ */\r
+static int32_t\r
+__recv_mgr_repost(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ipoib_recv_desc_t       *p_head = NULL, *p_tail = NULL, *p_next;\r
+       ib_api_status_t         status;\r
+       ib_recv_wr_t            *p_failed;\r
+       PERF_DECLARE( GetRecv );\r
+       PERF_DECLARE( PostRecv );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       CL_ASSERT( p_port );\r
+       cl_obj_lock( &p_port->obj );\r
+       if( p_port->state != IB_QPS_RTS )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+                       ("Port in invalid state.  Not reposting.\n") );\r
+               return 0;\r
+       }\r
+       ipoib_port_ref( p_port, ref_repost );\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       while( p_port->recv_mgr.depth < p_port->p_adapter->params.rq_depth )\r
+       {\r
+               /* Pull receives out of the pool and chain them up. */\r
+               cl_perf_start( GetRecv );\r
+               p_next = __buf_mgr_get_recv( p_port );\r
+               cl_perf_stop( &p_port->p_adapter->perf, GetRecv );\r
+               if( !p_next )\r
+               {\r
+                       IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
+                               ("Out of receive descriptors! recv queue depth 0x%x\n",p_port->recv_mgr.depth) );\r
+                       break;\r
+               }\r
+\r
+               if( !p_tail )\r
+               {\r
+                       p_tail = p_next;\r
+                       p_next->wr.p_next = NULL;\r
+               }\r
+               else\r
+               {\r
+                       p_next->wr.p_next = &p_head->wr;\r
+               }\r
+\r
+               p_head = p_next;\r
+\r
+               p_port->recv_mgr.depth++;\r
+       }\r
+\r
+       if( p_head )\r
+       {\r
+               cl_perf_start( PostRecv );\r
+               status = p_port->p_adapter->p_ifc->post_recv(\r
+                       p_port->ib_mgr.h_qp, &p_head->wr, &p_failed );\r
+               cl_perf_stop( &p_port->p_adapter->perf, PostRecv );\r
+\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ip_post_recv returned %s\n", \r
+                               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                       /* return the descriptors to the pool */\r
+                       while( p_failed )\r
+                       {\r
+                               p_head = PARENT_STRUCT( p_failed, ipoib_recv_desc_t, wr );\r
+                               p_failed = p_failed->p_next;\r
+\r
+                               __buf_mgr_put_recv( p_port, p_head, NULL );\r
+                               p_port->recv_mgr.depth--;\r
+                       }\r
+               }\r
+       }\r
+\r
+       ipoib_port_deref( p_port, ref_repost );\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return p_port->p_adapter->params.rq_low_watermark - p_port->recv_mgr.depth;\r
+}\r
+\r
+void\r
+ipoib_return_net_buffer_list(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              NET_BUFFER_LIST                         *p_net_buffer_lists,\r
+       IN                              ULONG                                           return_flags)\r
+{\r
+//     cl_list_item_t          *p_item;\r
+       ipoib_port_t            *p_port;\r
+       ipoib_recv_desc_t       *p_desc;\r
+       NET_BUFFER_LIST         *cur_net_buffer_list,*next_net_buffer_list;\r
+//     ib_api_status_t         status = IB_NOT_DONE;\r
+//     int32_t                         shortage;\r
+//     ULONG                           complete_flags = 0;\r
+       PERF_DECLARE( ReturnPacket );\r
+       PERF_DECLARE( ReturnPutRecv );\r
+       PERF_DECLARE( ReturnRepostRecv );\r
+       PERF_DECLARE( ReturnPreparePkt );\r
+       PERF_DECLARE( ReturnNdisIndicate );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       UNUSED_PARAM( return_flags );\r
+\r
+       p_port = ((ipoib_adapter_t*)adapter_context)->p_port;\r
+       CL_ASSERT( p_net_buffer_lists );\r
+\r
+       cl_perf_start( ReturnPacket );\r
+       cl_spinlock_acquire( &p_port->recv_lock );\r
+       for (cur_net_buffer_list = p_net_buffer_lists;\r
+                cur_net_buffer_list != NULL;\r
+                cur_net_buffer_list = next_net_buffer_list)\r
+       {\r
+               next_net_buffer_list = NET_BUFFER_LIST_NEXT_NBL(cur_net_buffer_list);\r
+\r
+               /* Get the port and descriptor from the packet. */\r
+               CL_ASSERT(p_port == IPOIB_PORT_FROM_PACKET( cur_net_buffer_list ));\r
+               p_desc = IPOIB_RECV_FROM_PACKET( cur_net_buffer_list );\r
+\r
+               \r
+               //TODO: NDIS60, rewrite this block\r
+               /* Get descriptor from the packet. */\r
+#if 0\r
+               if( p_desc->type == PKT_TYPE_CM_UCAST )\r
+               {\r
+                       NDIS_BUFFER             *p_buf;\r
+\r
+                       /* Unchain the NDIS buffer. */\r
+                       NdisUnchainBufferAtFront( p_packet, &p_buf );\r
+                       CL_ASSERT( p_buf );\r
+                       /* Return the NDIS packet and NDIS buffer to their pools. */\r
+                       NdisDprFreePacketNonInterlocked( p_packet );\r
+                       NdisFreeBuffer( p_buf );\r
+\r
+                       endpt_cm_buf_mgr_put_recv( &p_port->cm_buf_mgr, (ipoib_cm_desc_t *)p_desc );\r
+                       status = endpt_cm_post_recv( p_port );\r
+                       if(  status != IB_SUCCESS )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Post Recv QP failed\n" ) );\r
+                       }\r
+                       cl_spinlock_release( &p_port->recv_lock );\r
+                       return;\r
+               }\r
+#endif\r
+\r
+               cl_perf_start( ReturnPutRecv );\r
+               __buf_mgr_put_recv( p_port, p_desc, cur_net_buffer_list );\r
+               cl_perf_stop( &p_port->p_adapter->perf, ReturnPutRecv );\r
+       }\r
+#if 0           \r
+       /* Repost buffers. */\r
+       cl_perf_start( ReturnRepostRecv );\r
+       shortage = __recv_mgr_repost( p_port );\r
+       cl_perf_stop( &p_port->p_adapter->perf, ReturnRepostRecv );\r
+\r
+       for( p_item = cl_qlist_remove_head( &p_port->recv_mgr.done_list );\r
+               p_item != cl_qlist_end( &p_port->recv_mgr.done_list );\r
+               p_item = cl_qlist_remove_head( &p_port->recv_mgr.done_list ) )\r
+       {\r
+               p_desc = (ipoib_recv_desc_t*)p_item;\r
+\r
+               cl_perf_start( ReturnPreparePkt );\r
+               status = __recv_mgr_prepare_pkt( p_port, p_desc, &cur_net_buffer_list );\r
+               cl_perf_stop( &p_port->p_adapter->perf, ReturnPreparePkt );\r
+               if( status == IB_SUCCESS )\r
+               {\r
+                       if( shortage > 0 )\r
+                               NET_BUFFER_LIST_STATUS( cur_net_buffer_list) = NDIS_STATUS_RESOURCES;\r
+                       else\r
+                               NET_BUFFER_LIST_STATUS( cur_net_buffer_list) = NDIS_STATUS_SUCCESS;\r
+\r
+                       cl_spinlock_release( &p_port->recv_lock );\r
+                       NET_BUFFER_LIST_NEXT_NBL(cur_net_buffer_list) = NULL;\r
+                       cl_perf_start( ReturnNdisIndicate );\r
+                       NdisMRecvIndicate( p_port->p_adapter->h_adapter,\r
+                               cur_net_buffer_list, complete_flags );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, ReturnNdisIndicate );\r
+                       cl_spinlock_acquire( &p_port->recv_lock );\r
+\r
+                       if( shortage > 0 )\r
+                       {\r
+                               cl_perf_start( ReturnPutRecv );\r
+                               __buf_mgr_put_recv( p_port, p_desc, cur_net_buffer_list );\r
+                               cl_perf_stop( &p_port->p_adapter->perf, ReturnPutRecv );\r
+\r
+                               /* Repost buffers. */\r
+                               cl_perf_start( ReturnRepostRecv );\r
+                               shortage = __recv_mgr_repost( p_port );\r
+                               cl_perf_stop( &p_port->p_adapter->perf, ReturnRepostRecv );\r
+                       }\r
+               }\r
+               else if( status != IB_NOT_DONE )\r
+               {\r
+                       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+                               ("__recv_mgr_prepare_pkt returned %s\n",\r
+                               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                       /* Return the item to the head of the list. */\r
+                       cl_qlist_insert_head( &p_port->recv_mgr.done_list, p_item );\r
+                       break;\r
+               }\r
+       }\r
+       #endif\r
+       cl_spinlock_release( &p_port->recv_lock );\r
+       cl_perf_stop( &p_port->p_adapter->perf, ReturnPacket );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+static void __recv_cb_dpc(KDPC *p_gc_dpc,void *context,void * s_arg1 , void * s_arg2)\r
+{\r
+\r
+       ipoib_port_t *p_port = context;\r
+\r
+       UNREFERENCED_PARAMETER(p_gc_dpc);\r
+       UNREFERENCED_PARAMETER(s_arg1);\r
+       UNREFERENCED_PARAMETER(s_arg2);\r
+\r
+\r
+       __recv_cb(NULL, p_port);\r
+       ipoib_port_deref( p_port, ref_recv_cb );\r
+\r
+\r
+}\r
+\r
+\r
+static void\r
+__recv_cb(\r
+       IN              const   ib_cq_handle_t                          h_cq,\r
+       IN                              void                                            *cq_context )\r
+{\r
+       ipoib_port_t            *p_port;\r
+       ib_api_status_t         status;\r
+       ib_wc_t                         wc[MAX_RECV_WC], *p_free, *p_wc;\r
+       int32_t                         pkt_cnt, recv_cnt = 0, shortage, discarded;\r
+       cl_qlist_t                      done_list, bad_list;\r
+       size_t                          i;\r
+       ULONG                           recv_complete_flags = 0;\r
+\r
+       PERF_DECLARE( RecvCompBundle );\r
+       PERF_DECLARE( RecvCb );\r
+       PERF_DECLARE( PollRecv );\r
+       PERF_DECLARE( RepostRecv );\r
+       PERF_DECLARE( FilterRecv );\r
+       PERF_DECLARE( BuildPktArray );\r
+       PERF_DECLARE( RecvNdisIndicate );\r
+       PERF_DECLARE( RearmRecv );\r
+       PERF_DECLARE( PutRecvList );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       cl_perf_clr( RecvCompBundle );\r
+\r
+       cl_perf_start( RecvCb );\r
+//return ;\r
+       UNUSED_PARAM( h_cq );\r
+\r
+       NDIS_SET_SEND_COMPLETE_FLAG(recv_complete_flags, NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL );\r
+\r
+       p_port = (ipoib_port_t*)cq_context;\r
+\r
+       cl_qlist_init( &done_list );\r
+       cl_qlist_init( &bad_list );\r
+\r
+       ipoib_port_ref( p_port, ref_recv_cb );\r
+       for( i = 0; i < MAX_RECV_WC; i++ )\r
+               wc[i].p_next = &wc[i + 1];\r
+       wc[MAX_RECV_WC - 1].p_next = NULL;\r
+\r
+       /*\r
+        * We'll be accessing the endpoint map so take a reference\r
+        * on it to prevent modifications.\r
+        */\r
+       cl_obj_lock( &p_port->obj );\r
+       cl_atomic_inc( &p_port->endpt_rdr );\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       do\r
+       {\r
+               /* If we get here, then the list of WCs is intact. */\r
+               p_free = wc;\r
+\r
+               cl_perf_start( PollRecv );\r
+               status = p_port->p_adapter->p_ifc->poll_cq(\r
+                       p_port->ib_mgr.h_recv_cq, &p_free, &p_wc );\r
+               cl_perf_stop( &p_port->p_adapter->perf, PollRecv );\r
+               CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND );\r
+\r
+               /* Look at the payload now and filter ARP and DHCP packets. */\r
+               cl_perf_start( FilterRecv );\r
+               recv_cnt += __recv_mgr_filter( p_port, p_wc, &done_list, &bad_list );\r
+               cl_perf_stop( &p_port->p_adapter->perf, FilterRecv );\r
+\r
+       } while( (!p_free) && (recv_cnt < 128));\r
+\r
+       /* We're done looking at the endpoint map, release the reference. */\r
+       cl_atomic_dec( &p_port->endpt_rdr );\r
+\r
+       cl_perf_log( &p_port->p_adapter->perf, RecvCompBundle, recv_cnt );\r
+\r
+       cl_spinlock_acquire( &p_port->recv_lock );\r
+\r
+       /* Update our posted depth. */\r
+       p_port->recv_mgr.depth -= recv_cnt;\r
+\r
+       /* Return any discarded receives to the pool */\r
+       cl_perf_start( PutRecvList );\r
+       __buf_mgr_put_recv_list( p_port, &bad_list );\r
+       cl_perf_stop( &p_port->p_adapter->perf, PutRecvList );\r
+\r
+       do\r
+       {\r
+               int32_t cnt;\r
+               /* Repost ASAP so we don't starve the RQ. */\r
+               cl_perf_start( RepostRecv );\r
+               shortage = __recv_mgr_repost( p_port );\r
+               cl_perf_stop( &p_port->p_adapter->perf, RepostRecv );\r
+\r
+               cl_perf_start( BuildPktArray );\r
+               /* Notify NDIS of any and all possible receive buffers. */\r
+               pkt_cnt = __recv_mgr_build_pkt_array(\r
+                       p_port, shortage, &done_list, &discarded );\r
+               cl_perf_stop( &p_port->p_adapter->perf, BuildPktArray );\r
+\r
+               /* Only indicate receives if we actually had any. */\r
+               if( discarded && shortage > 0 )\r
+               {\r
+                       /* We may have thrown away packets, and have a shortage */\r
+                       cl_perf_start( RepostRecv );\r
+                       __recv_mgr_repost( p_port );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, RepostRecv );\r
+               }\r
+\r
+               if( !pkt_cnt )\r
+                       break;\r
+\r
+               cl_spinlock_release( &p_port->recv_lock );\r
+               for( cnt = 0; cnt < pkt_cnt -1; cnt++)\r
+               {\r
+                       NET_BUFFER_LIST_NEXT_NBL(p_port->recv_mgr.recv_pkt_array[cnt]) = \r
+                               p_port->recv_mgr.recv_pkt_array[cnt + 1];\r
+               }\r
+               cl_perf_start( RecvNdisIndicate );\r
+#ifndef NDIS_DEFAULT_PORT_NUMBER\r
+#define NDIS_DEFAULT_PORT_NUMBER 0\r
+#endif\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Indicate NDIS with  %d received NBs\n",\r
+                                       pkt_cnt) );\r
+               NdisMIndicateReceiveNetBufferLists(\r
+                       p_port->p_adapter->h_adapter,\r
+                       p_port->recv_mgr.recv_pkt_array[0],\r
+                       NDIS_DEFAULT_PORT_NUMBER,\r
+                       pkt_cnt,\r
+                       recv_complete_flags);\r
+\r
+               cl_perf_stop( &p_port->p_adapter->perf, RecvNdisIndicate );\r
+\r
+               /*\r
+                * Cap the number of receives to put back to what we just indicated\r
+                * with NDIS_STATUS_RESOURCES.\r
+                */\r
+               if( shortage > 0 )\r
+               {\r
+                       if( pkt_cnt < shortage )\r
+                               shortage = pkt_cnt;\r
+\r
+                       /* Return all but the last packet to the pool. */\r
+                       cl_spinlock_acquire( &p_port->recv_lock );\r
+                       while( shortage-- > 1 )\r
+                       {\r
+                               __buf_mgr_put_recv( p_port,\r
+                                       (ipoib_recv_desc_t *)IPOIB_RECV_FROM_PACKET( p_port->recv_mgr.recv_pkt_array[shortage] ),\r
+                                       p_port->recv_mgr.recv_pkt_array[shortage] );\r
+                       }\r
+                       cl_spinlock_release( &p_port->recv_lock );\r
+\r
+                       /*\r
+                        * Return the last packet as if NDIS returned it, so that we repost\r
+                        * and report any other pending receives.\r
+                        */\r
+                       ipoib_return_net_buffer_list( NULL, p_port->recv_mgr.recv_pkt_array[0],recv_complete_flags );\r
+               }\r
+               cl_spinlock_acquire( &p_port->recv_lock );\r
+\r
+       } while( pkt_cnt );\r
+       cl_spinlock_release( &p_port->recv_lock );\r
+\r
+       if (p_free ) {\r
+               /*\r
+                * Rearm after filtering to prevent contention on the enpoint maps\r
+                * and eliminate the possibility of having a call to\r
+                * __endpt_mgr_insert find a duplicate.\r
+                */\r
+               cl_perf_start( RearmRecv );\r
+               status = p_port->p_adapter->p_ifc->rearm_cq(\r
+                       p_port->ib_mgr.h_recv_cq, FALSE );\r
+               cl_perf_stop( &p_port->p_adapter->perf, RearmRecv );\r
+               CL_ASSERT( status == IB_SUCCESS );\r
+\r
+               ipoib_port_deref( p_port, ref_recv_cb );\r
+       } else {\r
+               // Please note the reference is still up\r
+               KeInsertQueueDpc(&p_port->recv_dpc, NULL, NULL);\r
+       }\r
+\r
+       cl_perf_stop( &p_port->p_adapter->perf, RecvCb );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+\r
+static void\r
+__recv_get_endpts(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t* const        p_desc,\r
+       IN                              ib_wc_t* const                          p_wc,\r
+               OUT                     ipoib_endpt_t** const           pp_src,\r
+               OUT                     ipoib_endpt_t** const           pp_dst )\r
+{\r
+       ib_api_status_t         status;\r
+       mac_addr_t                      mac;\r
+       PERF_DECLARE( GetEndptByGid );\r
+       PERF_DECLARE( GetEndptByLid );\r
+       PERF_DECLARE( EndptInsert );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       /* Setup our shortcut pointers based on whether GRH is valid. */\r
+       if( p_wc->recv.ud.recv_opt & IB_RECV_OPT_GRH_VALID )\r
+       {\r
+               /* Lookup the source endpoints based on GID. */\r
+               cl_perf_start( GetEndptByGid );\r
+               *pp_src =\r
+#if IPOIB_INLINE_RECV\r
+                       __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.src_gid );\r
+#else  /* IPOIB_INLINE_RECV */\r
+                       __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.src_gid );\r
+#endif /* IPOIB_INLINE_RECV */\r
+               cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid );\r
+\r
+               /*\r
+                * Lookup the destination endpoint based on GID.\r
+                * This is used along with the packet filter to determine\r
+                * whether to report this to NDIS.\r
+                */\r
+               cl_perf_start( GetEndptByGid );\r
+               *pp_dst =\r
+#if IPOIB_INLINE_RECV\r
+                       __endpt_mgr_get_by_gid( p_port, &p_desc->buf.ib.grh.dest_gid );\r
+#else  /* IPOIB_INLINE_RECV */\r
+                       __endpt_mgr_get_by_gid( p_port, &p_desc->p_buf->ib.grh.dest_gid );\r
+#endif /* IPOIB_INLINE_RECV */\r
+               cl_perf_stop( &p_port->p_adapter->perf, GetEndptByGid );\r
+\r
+               /*\r
+                * Create the source endpoint if it does not exist.  Note that we\r
+                * can only do this for globally routed traffic since we need the\r
+                * information from the GRH to generate the MAC.\r
+                */\r
+               if( !*pp_src )\r
+               {\r
+                       status = ipoib_mac_from_guid(\r
+#if IPOIB_INLINE_RECV\r
+                               p_desc->buf.ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
+#else  /* IPOIB_INLINE_RECV */\r
+                               p_desc->p_buf->ib.grh.src_gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
+#endif /* IPOIB_INLINE_RECV */\r
+                       if( status != IB_SUCCESS )\r
+                       {\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("ipoib_mac_from_guid returned %s\n",\r
+                                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                               return;\r
+                       }\r
+\r
+                       /* Create the endpoint. */\r
+#if IPOIB_INLINE_RECV\r
+                       *pp_src = ipoib_endpt_create( &p_desc->buf.ib.grh.src_gid,\r
+#else  /* IPOIB_INLINE_RECV */\r
+                       *pp_src = ipoib_endpt_create( &p_desc->p_buf->ib.grh.src_gid,\r
+#endif /* IPOIB_INLINE_RECV */\r
+                               p_wc->recv.ud.remote_lid, p_wc->recv.ud.remote_qp );\r
+                       if( !*pp_src )\r
+                       {\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("ipoib_endpt_create failed\n") );\r
+                               return;\r
+                       }\r
+                       cl_perf_start( EndptInsert );\r
+                       cl_obj_lock( &p_port->obj );\r
+                       status = __endpt_mgr_insert( p_port, mac, *pp_src );\r
+                       if( status != IB_SUCCESS )\r
+                       {\r
+                               cl_obj_unlock( &p_port->obj );\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("__endpt_mgr_insert returned %s\n",\r
+                                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                               *pp_src = NULL;\r
+                               return;\r
+                       }\r
+                       cl_obj_unlock( &p_port->obj );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, EndptInsert );\r
+               }\r
+       }\r
+       else\r
+       {\r
+               /*\r
+                * Lookup the remote endpoint based on LID.  Note that only\r
+                * unicast traffic can be LID routed.\r
+                */\r
+               cl_perf_start( GetEndptByLid );\r
+               *pp_src = __endpt_mgr_get_by_lid( p_port, p_wc->recv.ud.remote_lid );\r
+               cl_perf_stop( &p_port->p_adapter->perf, GetEndptByLid );\r
+               *pp_dst = p_port->p_local_endpt;\r
+               CL_ASSERT( *pp_dst );\r
+       }\r
+\r
+       if( *pp_src && !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) &&\r
+               (*pp_src)->qpn != p_wc->recv.ud.remote_qp )\r
+       {\r
+               /* Update the QPN for the endpoint. */\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+                       ("Updating QPN for MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+                       (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1],\r
+                       (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3],\r
+                       (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5]) );\r
+//             (*pp_src)->qpn = p_wc->recv.ud.remote_qp;\r
+       }\r
+\r
+       if( *pp_src && *pp_dst )\r
+       {\r
+               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
+                       ("Recv:\n"\r
+                       "\tsrc MAC: %02X-%02X-%02X-%02X-%02X-%02X\n"\r
+                       "\tdst MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+                       (*pp_src )->mac.addr[0], (*pp_src )->mac.addr[1],\r
+                       (*pp_src )->mac.addr[2], (*pp_src )->mac.addr[3],\r
+                       (*pp_src )->mac.addr[4], (*pp_src )->mac.addr[5],\r
+                       (*pp_dst )->mac.addr[0], (*pp_dst )->mac.addr[1],\r
+                       (*pp_dst )->mac.addr[2], (*pp_dst )->mac.addr[3],\r
+                       (*pp_dst )->mac.addr[4], (*pp_dst )->mac.addr[5]) );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+}\r
+\r
+\r
+static int32_t\r
+__recv_mgr_filter(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_wc_t* const                          p_done_wc_list,\r
+               OUT                     cl_qlist_t* const                       p_done_list,\r
+               OUT                     cl_qlist_t* const                       p_bad_list )\r
+{\r
+       ipoib_recv_desc_t               *p_desc;\r
+       ib_wc_t                                 *p_wc;\r
+       ipoib_pkt_t                             *p_ipoib;\r
+       eth_pkt_t                               *p_eth;\r
+       ipoib_endpt_t                   *p_src, *p_dst;\r
+       ib_api_status_t                 status;\r
+       uint32_t                                len;\r
+       int32_t                                 recv_cnt = 0;\r
+       PERF_DECLARE( GetRecvEndpts );\r
+       PERF_DECLARE( RecvGen );\r
+       PERF_DECLARE( RecvTcp );\r
+       PERF_DECLARE( RecvUdp );\r
+       PERF_DECLARE( RecvDhcp );\r
+       PERF_DECLARE( RecvArp );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       for( p_wc = p_done_wc_list; p_wc; p_wc = p_wc->p_next )\r
+       {\r
+               CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_RECV );\r
+               p_desc = (ipoib_recv_desc_t*)(uintn_t)p_wc->wr_id;\r
+               recv_cnt++;\r
+\r
+               if( p_wc->status != IB_WCS_SUCCESS )\r
+               {\r
+                       if( p_wc->status != IB_WCS_WR_FLUSHED_ERR )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Failed completion %s  (vendor specific %#x)\n",\r
+                                       p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
+                                       (int)p_wc->vendor_specific) );\r
+                               ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+                       }\r
+                       else\r
+                       {\r
+                               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_RECV,\r
+                                       ("Flushed completion %s\n",\r
+                                       p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status )) );\r
+                               ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_DROPPED, 0, 0 );\r
+                       }\r
+                       cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                       /* Dereference the port object on behalf of the failed receive. */\r
+                       ipoib_port_deref( p_port, ref_failed_recv_wc );\r
+                       continue;\r
+               }\r
+\r
+               len = p_wc->length - sizeof(ib_grh_t);\r
+\r
+               if( len < sizeof(ipoib_hdr_t) )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Received ETH packet < min size\n") );\r
+                       ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+                       cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                       ipoib_port_deref( p_port, ref_recv_inv_len );\r
+                       continue;\r
+               }\r
+\r
+               if((len - sizeof(ipoib_hdr_t)) > p_port->p_adapter->params.payload_mtu)\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Received ETH packet len %d > payload MTU (%d)\n",\r
+                               (len - sizeof(ipoib_hdr_t)),\r
+                               p_port->p_adapter->params.payload_mtu) );\r
+                       ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+                       cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                       ipoib_port_deref( p_port, ref_recv_inv_len );\r
+                       continue;\r
+                       \r
+               }\r
+               /* Successful completion.  Get the receive information. */\r
+               p_desc->ndis_csum.Value = ( ( p_wc->recv.ud.recv_opt & IB_RECV_OPT_CSUM_MASK ) >> 8 );\r
+               p_desc->len = len + 14 - 4 ;\r
+               cl_perf_start( GetRecvEndpts );\r
+               __recv_get_endpts( p_port, p_desc, p_wc, &p_src, &p_dst );\r
+               cl_perf_stop( &p_port->p_adapter->perf, GetRecvEndpts );\r
+\r
+#if IPOIB_INLINE_RECV\r
+               p_ipoib = &p_desc->buf.ib.pkt;\r
+               p_eth = &p_desc->buf.eth.pkt;\r
+#else  /* IPOIB_INLINE_RECV */\r
+               p_ipoib = &p_desc->p_buf->ib.pkt;\r
+               p_eth = &p_desc->p_buf->eth.pkt;\r
+#endif /*IPOIB_INLINE_RECV */\r
+\r
+               if( p_src )\r
+               {\r
+                       /* Don't report loopback traffic - we requested SW loopback. */\r
+                       if( !cl_memcmp( &p_port->p_adapter->params.conf_mac,\r
+                               &p_src->mac, sizeof(p_port->p_adapter->params.conf_mac) ) )\r
+                       {\r
+                               /*\r
+                                * "This is not the packet you're looking for" - don't update\r
+                                * receive statistics, the packet never happened.\r
+                                */\r
+                               cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                               /* Dereference the port object on behalf of the failed recv. */\r
+                               ipoib_port_deref( p_port, ref_recv_loopback );\r
+                               continue;\r
+                       }\r
+               }\r
+\r
+               switch( p_ipoib->hdr.type )\r
+               {\r
+               case ETH_PROT_TYPE_IP:\r
+                       if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t)) )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Received IP packet < min size\n") );\r
+                               status = IB_INVALID_SETTING;\r
+                               break;\r
+                       }\r
+\r
+                       if( p_ipoib->type.ip.hdr.offset ||\r
+                               p_ipoib->type.ip.hdr.prot != IP_PROT_UDP )\r
+                       {\r
+                               /* Unfiltered.  Setup the ethernet header and report. */\r
+                               cl_perf_start( RecvTcp );\r
+                               status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
+                               cl_perf_stop( &p_port->p_adapter->perf, RecvTcp );\r
+                               break;\r
+                       }\r
+\r
+                       /* First packet of a UDP transfer. */\r
+                       if( len <\r
+                               (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) + sizeof(udp_hdr_t)) )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Received UDP packet < min size\n") );\r
+                               status = IB_INVALID_SETTING;\r
+                               break;\r
+                       }\r
+\r
+                       /* Check if DHCP conversion is required. */\r
+                       if( (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_SERVER &&\r
+                               p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_CLIENT) ||\r
+                               (p_ipoib->type.ip.prot.udp.hdr.dst_port == DHCP_PORT_CLIENT &&\r
+                               p_ipoib->type.ip.prot.udp.hdr.src_port == DHCP_PORT_SERVER) )\r
+                       {\r
+                               if( len < (sizeof(ipoib_hdr_t) + sizeof(ip_hdr_t) +\r
+                                       sizeof(udp_hdr_t) + DHCP_MIN_SIZE) )\r
+                               {\r
+                                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Received DHCP < min size\n") );\r
+                                       status = IB_INVALID_SETTING;\r
+                                       break;\r
+                               }\r
+                               if ((p_ipoib->type.ip.hdr.ver_hl & 0x0f) != 5 ) {\r
+                                       // If there are IP options in this message, we are in trouble in any case\r
+                                       status = IB_INVALID_SETTING;\r
+                                       break;                                  \r
+                               }\r
+                               /* UDP packet with BOOTP ports in src/dst port numbers. */\r
+                               cl_perf_start( RecvDhcp );\r
+                               status = __recv_dhcp( p_port, p_ipoib, p_eth, p_src, p_dst );\r
+                               cl_perf_stop( &p_port->p_adapter->perf, RecvDhcp );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Unfiltered.  Setup the ethernet header and report. */\r
+                               cl_perf_start( RecvUdp );\r
+                               status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
+                               cl_perf_stop( &p_port->p_adapter->perf, RecvUdp );\r
+                       }\r
+                       break;\r
+\r
+               case ETH_PROT_TYPE_ARP:\r
+                       if( len < (sizeof(ipoib_hdr_t) + sizeof(ipoib_arp_pkt_t)) )\r
+                       {\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Received ARP < min size\n") );\r
+                               status = IB_INVALID_SETTING;\r
+                               break;\r
+                       }\r
+                       cl_perf_start( RecvArp );\r
+                       status = __recv_arp( p_port, p_wc, p_ipoib, p_eth, &p_src, p_dst );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, RecvArp );\r
+                       len = sizeof(ipoib_hdr_t) + sizeof(arp_pkt_t);\r
+                       break;\r
+\r
+               default:\r
+                       /* Unfiltered.  Setup the ethernet header and report. */\r
+                       cl_perf_start( RecvGen );\r
+                       status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, RecvGen );\r
+               }\r
+\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       /* Update stats. */\r
+                       ipoib_inc_recv_stat( p_port->p_adapter, IP_STAT_ERROR, 0, 0 );\r
+                       cl_qlist_insert_tail( p_bad_list, &p_desc->item.list_item );\r
+                       /* Dereference the port object on behalf of the failed receive. */\r
+                       ipoib_port_deref( p_port, ref_recv_filter );\r
+               }\r
+               else\r
+               {\r
+                       ip_stat_sel_t               ip_stat;\r
+                       p_desc->len =\r
+                               len + sizeof(eth_hdr_t) - sizeof(ipoib_hdr_t);\r
+                       if( p_dst->h_mcast)\r
+                       {\r
+                               if( p_dst->dgid.multicast.raw_group_id[10] == 0xFF &&\r
+                                       p_dst->dgid.multicast.raw_group_id[11] == 0xFF &&\r
+                                       p_dst->dgid.multicast.raw_group_id[12] == 0xFF &&\r
+                                       p_dst->dgid.multicast.raw_group_id[13] == 0xFF )\r
+                               {\r
+                                       p_desc->type = PKT_TYPE_BCAST;\r
+                                       ip_stat = IP_STAT_BCAST_BYTES;\r
+                               }\r
+                               else\r
+                               {\r
+                                       p_desc->type = PKT_TYPE_MCAST;\r
+                                       ip_stat = IP_STAT_MCAST_BYTES;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               p_desc->type = PKT_TYPE_UCAST;\r
+                               ip_stat = IP_STAT_UCAST_BYTES;\r
+                               \r
+                       }\r
+                       cl_qlist_insert_tail( p_done_list, &p_desc->item.list_item );\r
+                       ipoib_inc_recv_stat( p_port->p_adapter, ip_stat, len, 1 );  \r
+               }\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return recv_cnt;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_gen(\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t* const            p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       if( !p_src || !p_dst )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Received packet with no matching endpoints.\n") );\r
+               return IB_NOT_DONE;\r
+       }\r
+\r
+       /*\r
+        * Fill in the ethernet header.  Note that doing so will overwrite\r
+        * the IPoIB header, so start by moving the information from the IPoIB\r
+        * header.\r
+        */\r
+       p_eth->hdr.type = p_ipoib->hdr.type;\r
+       p_eth->hdr.src = p_src->mac;\r
+       p_eth->hdr.dst = p_dst->mac;\r
+\r
+       if ( p_eth->hdr.dst.addr[0] == 1 && \r
+                p_eth->hdr.type == ETH_PROT_TYPE_IP &&\r
+                p_eth->hdr.dst.addr[2] == 0x5E)  \r
+       {\r
+               p_eth->hdr.dst.addr[1] = 0;\r
+               p_eth->hdr.dst.addr[3] = p_eth->hdr.dst.addr[3] & 0x7f;\r
+       }\r
+       if (p_dst->h_mcast)\r
+               p_dst->is_in_use = TRUE;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_dhcp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t* const            p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst )\r
+{\r
+       ib_api_status_t         status;\r
+       dhcp_pkt_t                      *p_dhcp;\r
+       uint8_t                         *p_option;\r
+       uint8_t                         *p_cid = NULL;\r
+       ib_gid_t                        gid;\r
+       uint8_t                         msg = 0;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       UNUSED_PARAM( p_port );\r
+\r
+       /* Create the ethernet header. */\r
+       status = __recv_gen( p_ipoib, p_eth, p_src, p_dst );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__recv_gen returned %s.\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Fixup the payload. */\r
+       p_dhcp = &p_eth->type.ip.prot.udp.dhcp;\r
+       if( p_dhcp->op != DHCP_REQUEST && p_dhcp->op != DHCP_REPLY )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalid DHCP op code.\n") );\r
+               return IB_INVALID_SETTING;\r
+       }\r
+\r
+       /*\r
+        * Find the client identifier option, making sure to skip\r
+        * the "magic cookie".\r
+        */\r
+       p_option = &p_dhcp->options[0];\r
+       if ( *(uint32_t *)p_option != DHCP_COOKIE )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("DHCP cookie corrupted.\n") );\r
+               return IB_INVALID_PARAMETER;\r
+       }\r
+\r
+       p_option = &p_dhcp->options[4];\r
+       while( *p_option != DHCP_OPT_END && p_option < &p_dhcp->options[312] )\r
+       {\r
+               switch( *p_option )\r
+               {\r
+               case DHCP_OPT_PAD:\r
+                       p_option++;\r
+                       break;\r
+\r
+               case DHCP_OPT_MSG:\r
+                       msg = p_option[2];\r
+                       p_option += 3;\r
+                       break;\r
+\r
+               case DHCP_OPT_CLIENT_ID:\r
+                       p_cid = p_option;\r
+                       /* Fall through. */\r
+\r
+               default:\r
+                       /*\r
+                        * All other options have a length byte following the option code.\r
+                        * Offset by the length to get to the next option.\r
+                        */\r
+                       p_option += (p_option[1] + 2);\r
+               }\r
+       }\r
+\r
+       switch( msg )\r
+       {\r
+       /* message from client */\r
+       case DHCPDISCOVER:\r
+       case DHCPREQUEST:\r
+       case DHCPDECLINE:\r
+       case DHCPRELEASE:\r
+       case DHCPINFORM:\r
+               if( !p_cid )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to find required Client-identifier option.\n") );\r
+                       return IB_INVALID_SETTING;\r
+               }\r
+               if( p_dhcp->htype != DHCP_HW_TYPE_IB )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Invalid hardware address type.\n") );\r
+                       return IB_INVALID_SETTING;\r
+               }\r
+               break;\r
+       /* message from DHCP server */\r
+       case DHCPOFFER:\r
+       case DHCPACK:\r
+       case DHCPNAK:\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalide message type.\n") );\r
+               return IB_INVALID_PARAMETER;\r
+       }\r
+       p_eth->type.ip.prot.udp.hdr.chksum = 0;\r
+       p_dhcp->htype = DHCP_HW_TYPE_ETH;\r
+       p_dhcp->hlen = HW_ADDR_LEN;\r
+\r
+       if( p_cid ) /* from client */\r
+       {\r
+               /* Validate that the length and type of the option is as required. */\r
+               if( p_cid[1] != 21 )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Client-identifier length not 21 as required.\n") );\r
+                       return IB_INVALID_SETTING;\r
+               }\r
+               if( p_cid[2] != DHCP_HW_TYPE_IB )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Client-identifier type is wrong.\n") );\r
+                       return IB_INVALID_SETTING;\r
+               }\r
+               /*\r
+                * Copy the GID value from the option so that we can make aligned\r
+                * accesses to the contents.\r
+                * Recover CID to standard type.\r
+                */\r
+               cl_memcpy( &gid, &p_cid[7], sizeof(ib_gid_t) );\r
+               p_cid[1] =  HW_ADDR_LEN +1;// CID length \r
+               p_cid[2] =  DHCP_HW_TYPE_ETH;// CID type \r
+               status = ipoib_mac_from_guid( gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, (mac_addr_t*)&p_cid[3] );\r
+               if (status == IB_INVALID_GUID_MASK)\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
+                               ("Invalid GUID mask received, rejecting it") );\r
+                       ipoib_create_log(p_port->p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+                       status = IB_SUCCESS;\r
+               }\r
+               p_cid[HW_ADDR_LEN + 3] = DHCP_OPT_END; //terminate tag\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return status;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_arp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_wc_t* const                          p_wc,\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t** const           pp_src,\r
+       IN                              ipoib_endpt_t* const            p_dst )\r
+{\r
+       ib_api_status_t                 status;\r
+       arp_pkt_t                               *p_arp;\r
+       const ipoib_arp_pkt_t   *p_ib_arp;\r
+       ib_gid_t                                gid;\r
+       mac_addr_t                              mac;\r
+       ipoib_hw_addr_t                 null_hw = {0};\r
+       uint8_t                                 cm_capable = 0;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       if( !p_dst )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Unknown destination endpoint\n") );\r
+               return IB_INVALID_SETTING;\r
+       }\r
+\r
+       p_ib_arp = &p_ipoib->type.arp;\r
+       p_arp = &p_eth->type.arp;\r
+\r
+       if( p_ib_arp->hw_type != ARP_HW_TYPE_IB )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ARP hardware type is not IB\n") );\r
+               return IB_INVALID_SETTING;\r
+       }\r
+\r
+       if( p_ib_arp->hw_size != sizeof(ipoib_hw_addr_t) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ARP hardware address size is not sizeof(ipoib_hw_addr_t)\n") );\r
+               return IB_INVALID_SETTING;\r
+       }\r
+\r
+       if( p_ib_arp->prot_type != ETH_PROT_TYPE_IP )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ARP protocal type not IP\n") );\r
+               return IB_INVALID_SETTING;\r
+       }\r
+\r
+       cm_capable = ipoib_addr_get_flags( &p_ib_arp->src_hw );\r
+\r
+       /*\r
+        * If we don't have a source, lookup the endpoint specified in the payload.\r
+        */\r
+       if( !*pp_src )\r
+               *pp_src = __endpt_mgr_get_by_gid( p_port, &p_ib_arp->src_hw.gid );\r
+\r
+       /*\r
+        * If the endpoint exists for the GID, make sure\r
+        * the dlid and qpn match the arp.\r
+        */\r
+       if( *pp_src )\r
+       {\r
+               if( cl_memcmp( &(*pp_src)->dgid, &p_ib_arp->src_hw.gid,\r
+                       sizeof(ib_gid_t) ) )\r
+               {\r
+                       /*\r
+                        * GIDs for the endpoint are different.  The ARP must\r
+                        * have been proxied.  Dereference it.\r
+                        */\r
+                       *pp_src = NULL;\r
+               }\r
+               else if( (*pp_src)->dlid &&\r
+                       (*pp_src)->dlid != p_wc->recv.ud.remote_lid )\r
+               {\r
+                       /* Out of date!  Destroy the endpoint and replace it. */\r
+                       __endpt_mgr_remove( p_port, *pp_src );\r
+                       *pp_src = NULL;\r
+               }\r
+               else if ( ! ((*pp_src)->dlid)) {\r
+                       /* Out of date!  Destroy the endpoint and replace it. */\r
+                       __endpt_mgr_remove( p_port, *pp_src );\r
+                       *pp_src = NULL;\r
+               }\r
+               else if( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) )\r
+               {\r
+                       if( (*pp_src)->qpn != ipoib_addr_get_qpn( &p_ib_arp->src_hw ) &&\r
+                                p_wc->recv.ud.remote_qp !=     ipoib_addr_get_qpn( &p_ib_arp->src_hw ) )\r
+                       {\r
+                               /* Out of date!  Destroy the endpoint and replace it. */\r
+                               __endpt_mgr_remove( p_port, *pp_src );\r
+                               *pp_src = NULL;\r
+                       }\r
+               }\r
+               else if( (*pp_src)->qpn != p_wc->recv.ud.remote_qp )\r
+               {\r
+                       /* Out of date!  Destroy the endpoint and replace it. */\r
+                       __endpt_mgr_remove( p_port, *pp_src );\r
+                       *pp_src = NULL;\r
+               }\r
+       }\r
+\r
+       /* Do we need to create an endpoint for this GID? */\r
+       if( !*pp_src )\r
+       {\r
+               /* Copy the src GID to allow aligned access */\r
+               cl_memcpy( &gid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) );\r
+               status = ipoib_mac_from_guid( gid.unicast.interface_id, p_port->p_adapter->params.guid_mask, &mac );\r
+               if (status == IB_INVALID_GUID_MASK)\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
+                               ("Invalid GUID mask received, rejecting it") );\r
+                       ipoib_create_log(p_port->p_adapter->h_adapter, GUID_MASK_LOG_INDEX, EVENT_IPOIB_WRONG_PARAMETER_WRN);\r
+               }\r
+               else if( status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ipoib_mac_from_guid returned %s\n",\r
+                               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                       return status;\r
+               }\r
+               /*\r
+                * Create the endpoint.\r
+                */\r
+               *pp_src = ipoib_endpt_create( &p_ib_arp->src_hw.gid,\r
+                       p_wc->recv.ud.remote_lid, ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
+\r
+               if( !*pp_src )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ipoib_endpt_create failed\n") );\r
+                       return status;\r
+               }\r
+\r
+               cl_obj_lock( &p_port->obj );\r
+               status = __endpt_mgr_insert( p_port, mac, *pp_src );\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       cl_obj_unlock( &p_port->obj );\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("__endpt_mgr_insert return %s \n",\r
+                               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                       return status;\r
+               }\r
+\r
+               cl_obj_unlock( &p_port->obj );\r
+       }\r
+\r
+       (*pp_src)->cm_flag = cm_capable;\r
+\r
+       CL_ASSERT( !cl_memcmp(\r
+               &(*pp_src)->dgid, &p_ib_arp->src_hw.gid, sizeof(ib_gid_t) ) );\r
+       CL_ASSERT( ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) ||\r
+               (*pp_src)->qpn == ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
+#if 0\r
+       if( p_port->p_adapter->params.cm_enabled &&\r
+               p_ib_arp->op == ARP_OP_REQ &&\r
+               cm_capable == IPOIB_CM_FLAG_RC )\r
+       {\r
+               /* if we've got ARP request and RC flag is set, \r
+               save SID for connect REQ to be sent in ARP reply\r
+               when requestor's path get resolved */\r
+               if( endpt_cm_get_state( (*pp_src) ) == IPOIB_CM_DISCONNECTED )\r
+               {\r
+                       (*pp_src)->cm_flag = cm_capable;\r
+                       ipoib_addr_set_sid( \r
+                               &(*pp_src)->conn.service_id,\r
+                               ipoib_addr_get_qpn( &p_ib_arp->src_hw ) );\r
+               }\r
+       }\r
+#endif\r
+#if 0 //DBG\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       (" ARP %s from ENDPT[%p] state %d CM cap: %d QPN: %#x MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+                       ((p_ib_arp->op == ARP_OP_REQ )? "REQUEST" : "REPLY"),\r
+                       *pp_src, endpt_cm_get_state( *pp_src ), \r
+                       ((cm_capable == IPOIB_CM_FLAG_RC)? 1: 0),\r
+                       cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->src_hw ) ),\r
+                       (*pp_src)->mac.addr[0], (*pp_src)->mac.addr[1],\r
+                       (*pp_src)->mac.addr[2], (*pp_src)->mac.addr[3],\r
+                       (*pp_src)->mac.addr[4], (*pp_src)->mac.addr[5] ));\r
+       }\r
+#endif\r
+\r
+       /* Now swizzle the data. */\r
+       p_arp->hw_type = ARP_HW_TYPE_ETH;\r
+       p_arp->hw_size = sizeof(mac_addr_t);\r
+       p_arp->src_hw = (*pp_src)->mac;\r
+       p_arp->src_ip = p_ib_arp->src_ip;\r
+\r
+       if( cl_memcmp( &p_ib_arp->dst_hw, &null_hw, sizeof(ipoib_hw_addr_t) ) )\r
+       {\r
+               if( cl_memcmp( &p_dst->dgid, &p_ib_arp->dst_hw.gid, sizeof(ib_gid_t) ) )\r
+               {\r
+                       /*\r
+                        * We received bcast ARP packet that means\r
+                        * remote port lets everyone know it was changed IP/MAC\r
+                        * or just activated\r
+                        */\r
+\r
+                       /* Guy: TODO: Check why this check fails in case of Voltaire IPR */\r
+\r
+                       if ( !ipoib_is_voltaire_router_gid( &(*pp_src)->dgid ) &&\r
+                                !ib_gid_is_multicast( (const ib_gid_t*)&p_dst->dgid ) )\r
+                       {\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("ARP: is not ARP MCAST\n") );\r
+                               return IB_INVALID_SETTING;\r
+                       }\r
+\r
+                       p_arp->dst_hw = p_port->p_local_endpt->mac;\r
+                       p_dst->mac = p_port->p_local_endpt->mac;\r
+                       /*\r
+                        * we don't care what receiver ip addr is,\r
+                        * as long as OS' ARP table is global  ???\r
+                        */\r
+                       p_arp->dst_ip = (net32_t)0;\r
+               }\r
+               else /* we've got reply to our ARP request */\r
+               {\r
+                       p_arp->dst_hw = p_dst->mac;\r
+                       p_arp->dst_ip = p_ib_arp->dst_ip;\r
+                       CL_ASSERT( p_dst->qpn == ipoib_addr_get_qpn( &p_ib_arp->dst_hw ) );\r
+               }\r
+       }\r
+       else /* we got ARP reqeust */\r
+       {\r
+               cl_memclr( &p_arp->dst_hw, sizeof(mac_addr_t) );\r
+               p_arp->dst_ip = p_ib_arp->dst_ip;\r
+       }\r
+\r
+       /*\r
+        * Create the ethernet header.  Note that this is done last so that\r
+        * we have a chance to create a new endpoint.\r
+        */\r
+       status = __recv_gen( p_ipoib, p_eth, *pp_src, p_dst );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__recv_gen returned %s.\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__recv_mgr_prepare_pkt(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_recv_desc_t*      const   p_desc,\r
+               OUT                     NET_BUFFER_LIST** const         pp_net_buffer_list )\r
+{\r
+       NDIS_STATUS                                                     status;\r
+       uint32_t                                                        pkt_filter;\r
+       ip_stat_sel_t                                           type;\r
+       //NDIS60\r
+       NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO       chksum;\r
+       //NDIS_TCP_IP_CHECKSUM_PACKET_INFO      chksum;\r
+\r
+       PERF_DECLARE( GetNdisPkt );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       pkt_filter = p_port->p_adapter->packet_filter;\r
+       /* Check the packet filter. */\r
+       switch( p_desc->type )\r
+       {\r
+       default:\r
+       case PKT_TYPE_UCAST:\r
+               \r
+               if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ||\r
+                       pkt_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL ||\r
+                       pkt_filter & NDIS_PACKET_TYPE_SOURCE_ROUTING ||\r
+                       pkt_filter & NDIS_PACKET_TYPE_DIRECTED )\r
+               {\r
+                       /* OK to report. */\r
+                       type = IP_STAT_UCAST_BYTES;\r
+                       status = NDIS_STATUS_SUCCESS;\r
+                       IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
+                       ("Received UCAST PKT.\n"));\r
+               }\r
+               else\r
+               {\r
+                       type = IP_STAT_DROPPED;\r
+                       status = NDIS_STATUS_FAILURE;\r
+                       IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
+                       ("Received UCAST PKT with ERROR !!!!\n"));\r
+               }\r
+               break;\r
+       case PKT_TYPE_BCAST:\r
+               if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ||\r
+                       pkt_filter & NDIS_PACKET_TYPE_BROADCAST )\r
+               {\r
+                       /* OK to report. */\r
+                       type = IP_STAT_BCAST_BYTES;\r
+                       status = NDIS_STATUS_SUCCESS;\r
+                       IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
+                       ("Received BCAST PKT.\n"));\r
+               }\r
+               else\r
+               {\r
+                       type = IP_STAT_DROPPED;\r
+                       status = NDIS_STATUS_FAILURE;\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Received BCAST PKT with ERROR !!!!\n"));\r
+               }\r
+               break;\r
+       case PKT_TYPE_MCAST:\r
+               if( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS ||\r
+                       pkt_filter & NDIS_PACKET_TYPE_ALL_MULTICAST ||\r
+                       pkt_filter & NDIS_PACKET_TYPE_MULTICAST )\r
+               {\r
+                       /* OK to report. */\r
+                       type = IP_STAT_MCAST_BYTES;\r
+                       status = NDIS_STATUS_SUCCESS;\r
+                       IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR,\r
+                       ("Received UCAST PKT.\n"));\r
+               }\r
+               else\r
+               {\r
+                       type = IP_STAT_DROPPED;\r
+                       status = NDIS_STATUS_FAILURE;\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Received MCAST PKT with ERROR !!!!\n"));\r
+               }\r
+               break;\r
+       }\r
+\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               ipoib_inc_recv_stat( p_port->p_adapter, type, 0, 0 );\r
+               /* Return the receive descriptor to the pool. */\r
+               __buf_mgr_put_recv( p_port, p_desc, NULL );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_RECV,\r
+                       ("Packet filter doesn't match receive.  Dropping.\n") );\r
+               /*\r
+                * Return IB_NOT_DONE since the packet has been completed,\r
+                * but has not consumed an array entry.\r
+                */\r
+               return IB_NOT_DONE;\r
+       }\r
+\r
+       cl_perf_start( GetNdisPkt );\r
+       *pp_net_buffer_list = __buf_mgr_get_ndis_pkt( p_port, p_desc );\r
+       cl_perf_stop( &p_port->p_adapter->perf, GetNdisPkt );\r
+       if( !*pp_net_buffer_list )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__buf_mgr_get_ndis_pkt failed\n") );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       chksum.Value = 0;\r
+\r
+{\r
+       PNET_BUFFER NetBuffer = NET_BUFFER_LIST_FIRST_NB(*pp_net_buffer_list);\r
+       NET_BUFFER_DATA_LENGTH(NetBuffer) = p_desc->len;\r
+}\r
+       \r
+       switch( p_port->p_adapter->params.recv_chksum_offload )\r
+       {\r
+         default:\r
+               CL_ASSERT( FALSE );\r
+         case CSUM_DISABLED:\r
+               //NDIS60\r
+               //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) =\r
+               //(void*)(uintn_t)chksum.Value;\r
+               NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) = \r
+               (void*)(uintn_t)chksum.Value;\r
+               break;\r
+         case CSUM_ENABLED:\r
+               /* Get the checksums directly from packet information. */\r
+               /* In this case, no one of cheksum's cat get false value */\r
+               /* If hardware checksum failed or wasn't calculated, NDIS will recalculate it again */\r
+               //NDIS60\r
+               //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) = \r
+               NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) =\r
+                       (void*)(uintn_t)(p_desc->ndis_csum.Value);\r
+               break;\r
+         case CSUM_BYPASS:\r
+               /* Flag the checksums as having been calculated. */\r
+               chksum.Receive.TcpChecksumSucceeded = TRUE;\r
+               chksum.Receive.UdpChecksumSucceeded = TRUE;\r
+               chksum.Receive.IpChecksumSucceeded = TRUE;\r
+               //NDIS60\r
+               //NDIS_PER_PACKET_INFO_FROM_PACKET( *pp_packet, TcpIpChecksumPacketInfo ) =\r
+               NET_BUFFER_LIST_INFO(*pp_net_buffer_list, TcpIpChecksumNetBufferListInfo) =\r
+               (void*)(uintn_t)chksum.Value;\r
+               break;\r
+       }\r
+       ipoib_inc_recv_stat( p_port->p_adapter, type, p_desc->len, 1 );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static uint32_t\r
+__recv_mgr_build_pkt_array(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              int32_t                                         shortage,\r
+               OUT                     cl_qlist_t* const                       p_done_list,\r
+               OUT                     int32_t* const                          p_discarded )\r
+{\r
+       cl_list_item_t                  *p_item;\r
+       ipoib_recv_desc_t               *p_desc;\r
+       uint32_t                                i = 0;\r
+       ib_api_status_t                 status;\r
+       PERF_DECLARE( PreparePkt );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_RECV );\r
+\r
+       *p_discarded = 0;\r
+\r
+       /* Move any existing receives to the head to preserve ordering. */\r
+       cl_qlist_insert_list_head( p_done_list, &p_port->recv_mgr.done_list );\r
+       p_item = cl_qlist_remove_head( p_done_list );\r
+       while( p_item != cl_qlist_end( p_done_list ) )\r
+       {\r
+               p_desc = (ipoib_recv_desc_t*)p_item;\r
+\r
+               cl_perf_start( PreparePkt );\r
+               status = __recv_mgr_prepare_pkt( p_port, p_desc,\r
+                       &p_port->recv_mgr.recv_pkt_array[i] );\r
+               cl_perf_stop( &p_port->p_adapter->perf, PreparePkt );\r
+               if( status == IB_SUCCESS )\r
+               {\r
+                       CL_ASSERT( p_port->recv_mgr.recv_pkt_array[i] );\r
+                       if( shortage-- > 0 )\r
+                       {\r
+                               NET_BUFFER_LIST_STATUS(p_port->recv_mgr.recv_pkt_array[i])= NDIS_STATUS_RESOURCES;                                      \r
+                       }\r
+                       else\r
+                       {\r
+                               NET_BUFFER_LIST_STATUS(p_port->recv_mgr.recv_pkt_array[i])=  NDIS_STATUS_SUCCESS;\r
+                       }\r
+                       i++;\r
+               }\r
+               else if( status == IB_NOT_DONE )\r
+               {\r
+                       (*p_discarded)++;\r
+               }\r
+               else\r
+               {\r
+                       IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_RECV,\r
+                               ("__recv_mgr_prepare_pkt returned %s\n",\r
+                               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                       /* Put all completed receives on the port's done list. */\r
+                       cl_qlist_insert_tail( &p_port->recv_mgr.done_list, p_item );\r
+                       cl_qlist_insert_list_tail( &p_port->recv_mgr.done_list, p_done_list );\r
+                       break;\r
+               }\r
+\r
+               p_item = cl_qlist_remove_head( p_done_list );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_RECV );\r
+       return i;\r
+}\r
+\r
+\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Send manager implementation.\r
+*\r
+******************************************************************************/\r
+static void\r
+__send_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+       p_port->send_mgr.depth = 0;\r
+       cl_qlist_init( &p_port->send_mgr.pending_list );\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+\r
+static void \r
+__pending_list_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       cl_list_item_t  *p_item;\r
+       NET_BUFFER_LIST         **pp_net_buffer_list, *p_head;\r
+       \r
+       p_head = NULL;\r
+       cl_spinlock_acquire( &p_port->send_lock );\r
+       /* Complete any pending packets. */\r
+       pp_net_buffer_list = &p_head;\r
+       for( p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list );\r
+               p_item != cl_qlist_end( &p_port->send_mgr.pending_list );\r
+               p_item = cl_qlist_remove_head( &p_port->send_mgr.pending_list ) )\r
+       {\r
+               *pp_net_buffer_list = IPOIB_PACKET_FROM_LIST_ITEM( p_item );\r
+               NET_BUFFER_LIST_STATUS(*pp_net_buffer_list) = NDIS_STATUS_RESET_IN_PROGRESS;\r
+               pp_net_buffer_list = &(NET_BUFFER_LIST_NEXT_NBL(*pp_net_buffer_list));\r
+       }\r
+       cl_spinlock_release( &p_port->send_lock );\r
+       if(p_head)\r
+               NdisMSendNetBufferListsComplete(\r
+            p_port->p_adapter->h_adapter,\r
+            p_head,\r
+            0);   \r
+}\r
+\r
+static void\r
+__send_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+       __pending_list_destroy(p_port);\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL* const                                      p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc )\r
+{\r
+       NDIS_STATUS             status;\r
+\r
+       PERF_DECLARE( FilterIp );\r
+       PERF_DECLARE( FilterArp );\r
+       PERF_DECLARE( SendGen );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       /*\r
+        * We already checked the ethernet header length, so we know it's safe\r
+        * to decrement the buf_len without underflowing.\r
+        */\r
+       buf_len -= sizeof(eth_hdr_t);\r
+\r
+       switch( p_eth_hdr->type )\r
+       {\r
+       case ETH_PROT_TYPE_IP:\r
+               cl_perf_start( FilterIp );\r
+               status = __send_mgr_filter_ip(\r
+                       p_port, p_eth_hdr, p_mdl, buf_len, p_sgl, p_desc);\r
+               cl_perf_stop( &p_port->p_adapter->perf, FilterIp );\r
+               break;\r
+\r
+       case ETH_PROT_TYPE_ARP:\r
+               cl_perf_start( FilterArp );\r
+               status = __send_mgr_filter_arp(\r
+                       p_port, p_eth_hdr, p_mdl, buf_len, p_desc );\r
+               p_desc->send_dir = SEND_UD_QP;\r
+               cl_perf_stop( &p_port->p_adapter->perf, FilterArp );\r
+               break;\r
+\r
+       default:\r
+               /*\r
+                * The IPoIB spec doesn't define how to send non IP or ARP packets.\r
+                * Just send the payload and hope for the best.\r
+                */\r
+\r
+               p_desc->send_dir = SEND_UD_QP;\r
+               cl_perf_start( SendGen );\r
+               status = __send_gen( p_port, p_desc, p_sgl, 0 );\r
+               cl_perf_stop( &p_port->p_adapter->perf, SendGen );\r
+               break;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return status;\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__send_copy(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc )\r
+{\r
+       NET_BUFFER_LIST                 *p_net_buffer_list;\r
+       NET_BUFFER                              *p_netbuffer;\r
+       MDL                                             *p_mdl;\r
+       UINT                                    tot_len = 0;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       UNREFERENCED_PARAMETER(p_port);\r
+       UNREFERENCED_PARAMETER(p_desc);\r
+\r
+       p_desc->p_buf = \r
+               NdisAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+       if( !p_desc->p_buf )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate buffer for packet copy.\n") );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+\r
+       p_mdl = NdisAllocateMdl(p_port->p_adapter->h_adapter,\r
+                                                       p_desc->p_buf,\r
+                                                       p_port->p_adapter->params.xfer_block_size );\r
+       if( !p_mdl )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate MDL\n") );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+\r
+       p_net_buffer_list = NdisAllocateNetBufferAndNetBufferList(\r
+                                               p_port->buf_mgr.h_send_buf_pool,\r
+                                               0,\r
+                                               0,\r
+                                               p_mdl,\r
+                                               0,\r
+                                               0);\r
+\r
+       if( !p_net_buffer_list )\r
+       {\r
+               NdisFreeMdl(p_mdl);\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+                       ("Failed to allocate NDIS_PACKET for copy.\n") );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+\r
+       for (p_netbuffer = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list); \r
+                p_netbuffer != NULL;\r
+                p_netbuffer = NET_BUFFER_NEXT_NB(p_netbuffer))\r
+       {\r
+               tot_len +=NET_BUFFER_DATA_LENGTH(p_netbuffer);\r
+       }\r
+\r
+       /* Setup the work request. */\r
+       p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr(\r
+               ((uint8_t*)p_desc->p_buf) + sizeof(eth_hdr_t) );\r
+       p_desc->send_wr[0].local_ds[1].length = tot_len - sizeof(eth_hdr_t);\r
+       p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey;\r
+       p_desc->send_wr[0].wr.num_ds = 2;\r
+       \r
+       /* Free our temp packet now that the data is copied. */\r
+       NdisFreeMdl(p_mdl);\r
+       NdisFreeNetBufferList(p_net_buffer_list);\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static inline NDIS_STATUS\r
+__send_mgr_get_eth_hdr(\r
+       IN                              PNET_BUFFER                                     p_net_buffer,\r
+               OUT                     MDL** const                                     pp_mdl,\r
+               OUT                     eth_hdr_t** const                       pp_eth_hdr,\r
+               OUT                     UINT*                                           p_mdl_len)\r
+{\r
+       PUCHAR  p_head = NULL;\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       *pp_mdl = NET_BUFFER_FIRST_MDL(p_net_buffer);\r
+\r
+       NdisQueryMdl(*pp_mdl,&p_head,p_mdl_len,NormalPagePriority);\r
+       if( ! p_head )\r
+       {\r
+               /* Failed to get first buffer. */\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("NdisQueryMdl failed.\n") );\r
+               return NDIS_STATUS_FAILURE;\r
+       }\r
+\r
+       if( *p_mdl_len < sizeof(eth_hdr_t) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("First buffer in packet smaller than eth_hdr_t: %d.\n",\r
+                       *p_mdl_len) );\r
+               return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+       }\r
+\r
+       *pp_eth_hdr = (eth_hdr_t*)(p_head + NET_BUFFER_CURRENT_MDL_OFFSET(p_net_buffer));\r
+\r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+               ("Ethernet header:\n"\r
+               "\tsrc MAC: %02X-%02X-%02X-%02X-%02X-%02X\n"\r
+               "\tdst MAC: %02X-%02X-%02X-%02X-%02X-%02X\n"\r
+               "\tprotocol type: %04X\n",\r
+               (*pp_eth_hdr)->src.addr[0], (*pp_eth_hdr)->src.addr[1],\r
+               (*pp_eth_hdr)->src.addr[2], (*pp_eth_hdr)->src.addr[3],\r
+               (*pp_eth_hdr)->src.addr[4], (*pp_eth_hdr)->src.addr[5],\r
+               (*pp_eth_hdr)->dst.addr[0], (*pp_eth_hdr)->dst.addr[1],\r
+               (*pp_eth_hdr)->dst.addr[2], (*pp_eth_hdr)->dst.addr[3],\r
+               (*pp_eth_hdr)->dst.addr[4], (*pp_eth_hdr)->dst.addr[5],\r
+               cl_ntoh16( (*pp_eth_hdr)->type )) );\r
+\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+#if !IPOIB_USE_DMA\r
+/* Send using the MDL's page information rather than the SGL. */\r
+static ib_api_status_t\r
+__send_gen(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc )\r
+{\r
+       uint32_t                                i, j = 1;\r
+       ULONG                                   offset;\r
+       MDL                                             *p_mdl;\r
+       UINT                                    num_pages, tot_len;\r
+       ULONG                                   buf_len;\r
+       PPFN_NUMBER                             page_array;\r
+       boolean_t                               hdr_done = FALSE;\r
+       ib_api_status_t                 status;\r
+       PNET_BUFFER                             p_net_buf;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+       p_net_buf = NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list);\r
+       NdisQueryBuffer( p_net_buf, &num_pages, NULL, &p_mdl,\r
+               &tot_len );\r
+\r
+       if( !p_mdl )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("No buffers associated with packet.\n") );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       /* Remember that one of the DS entries is reserved for the IPoIB header. */\r
+       if( num_pages >= MAX_SEND_SGE )\r
+       {\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+                       ("Too many buffers to fit in WR ds_array.  Copying data.\n") );\r
+               status = __send_copy( p_port, p_desc );\r
+               IPOIB_EXIT( IPOIB_DBG_SEND );\r
+               return status;\r
+       }\r
+\r
+       CL_ASSERT( tot_len > sizeof(eth_hdr_t) );\r
+       CL_ASSERT( tot_len <= p_port->p_adapter->params.xfer_block_size );\r
+       /*\r
+        * Assume that the ethernet header is always fully contained\r
+        * in the first page of the first MDL.  This makes for much\r
+        * simpler code.\r
+        */\r
+       offset = MmGetMdlByteOffset( p_mdl ) + sizeof(eth_hdr_t);\r
+       CL_ASSERT( offset <= PAGE_SIZE );\r
+\r
+       while( tot_len )\r
+       {\r
+               buf_len = MmGetMdlByteCount( p_mdl );\r
+               page_array = MmGetMdlPfnArray( p_mdl );\r
+               CL_ASSERT( page_array );\r
+               i = 0;\r
+               if( !hdr_done )\r
+               {\r
+                       CL_ASSERT( buf_len >= sizeof(eth_hdr_t) );\r
+                       /* Skip the ethernet header. */\r
+                       buf_len -= sizeof(eth_hdr_t);\r
+                       CL_ASSERT( buf_len <= p_port->p_adapter->params.payload_mtu );\r
+                       if( buf_len )\r
+                       {\r
+                               /* The ethernet header is a subset of this MDL. */\r
+                               CL_ASSERT( i == 0 );\r
+                               if( offset < PAGE_SIZE )\r
+                               {\r
+                                       p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
+                                       p_desc->send_wr[0].local_ds[j].vaddr = (page_array[i] << PAGE_SHIFT);\r
+                                       /* Add the byte offset since we're on the 1st page. */\r
+                                       p_desc->send_wr[0].local_ds[j].vaddr += offset;\r
+                                       if( offset + buf_len > PAGE_SIZE )\r
+                                       {\r
+                                               p_desc->send_wr[0].local_ds[j].length = PAGE_SIZE - offset;\r
+                                               buf_len -= p_desc->send_wr[0].local_ds[j].length;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               p_desc->send_wr[0].local_ds[j].length = buf_len;\r
+                                               buf_len = 0;\r
+                                       }\r
+                                       /* This data segment is done.  Move to the next. */\r
+                                       j++;\r
+                               }\r
+                               /* This page is done.  Move to the next. */\r
+                               i++;\r
+                       }\r
+                       /* Done handling the ethernet header. */\r
+                       hdr_done = TRUE;\r
+               }\r
+\r
+               /* Finish this MDL */\r
+               while( buf_len )\r
+               {\r
+                       p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
+                       p_desc->send_wr[0].local_ds[j].vaddr = (page_array[i] << PAGE_SHIFT);\r
+                       /* Add the first page's offset if we're on the first page. */\r
+                       if( i == 0 )\r
+                               p_desc->send_wr[0].local_ds[j].vaddr += MmGetMdlByteOffset( p_mdl );\r
+\r
+                       if( i == 0 && (MmGetMdlByteOffset( p_mdl ) + buf_len) > PAGE_SIZE )\r
+                       {\r
+                               /* Buffers spans pages. */\r
+                               p_desc->send_wr[0].local_ds[j].length =\r
+                                       PAGE_SIZE - MmGetMdlByteOffset( p_mdl );\r
+                               buf_len -= p_desc->send_wr[0].local_ds[j].length;\r
+                               /* This page is done.  Move to the next. */\r
+                               i++;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Last page of the buffer. */\r
+                               p_desc->send_wr[0].local_ds[j].length = buf_len;\r
+                               buf_len = 0;\r
+                       }\r
+                       /* This data segment is done.  Move to the next. */\r
+                       j++;\r
+               }\r
+\r
+               tot_len -= MmGetMdlByteCount( p_mdl );\r
+               if( !tot_len )\r
+                       break;\r
+\r
+               NdisGetNextBuffer( p_mdl, &p_mdl );\r
+               if( !p_mdl )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get next buffer.\n") );\r
+                       return IB_ERROR;\r
+               }\r
+       }\r
+\r
+       /* Set the number of data segments. */\r
+       p_desc->send_wr[0].wr.num_ds = j;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+#else\r
+\r
+#if 0\r
+void \r
+ipoib_process_sg_list1(\r
+    IN  PDEVICE_OBJECT          pDO,\r
+    IN  PVOID                   pIrp,\r
+    IN  PSCATTER_GATHER_LIST    p_sgl,\r
+    IN  PVOID                   context\r
+    )\r
+{\r
+       int i;\r
+       char temp[200];\r
+       for (i = 0 ; i < 1;i++)\r
+               temp[i] = 5;\r
+}\r
+#endif\r
+\r
+void \r
+ipoib_process_sg_list(\r
+    IN  PDEVICE_OBJECT          pDO,\r
+    IN  PVOID                   pIrp,\r
+    IN  PSCATTER_GATHER_LIST    p_sgl,\r
+    IN  PVOID                   context\r
+    )\r
+{      \r
+       NDIS_STATUS                             status;\r
+       ipoib_port_t                    *p_port;\r
+       MDL                                             *p_mdl;\r
+       eth_hdr_t                               *p_eth_hdr;\r
+       UINT                                    mdl_len;\r
+       static ipoib_send_desc_t                *p_desc = NULL;\r
+       ib_send_wr_t                    *p_wr_failed;\r
+       NET_BUFFER_LIST                 *p_net_buffer_list;\r
+       NET_BUFFER                              *p_netbuf;\r
+       boolean_t                               from_queue;\r
+       ib_api_status_t                 ib_status;\r
+       ULONG                                   complete_flags = 0;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       UNREFERENCED_PARAMETER(pDO);\r
+       UNREFERENCED_PARAMETER(pIrp);\r
+\r
+       PERF_DECLARE( SendCopy );\r
+       PERF_DECLARE( BuildSendDesc );\r
+       PERF_DECLARE( GetEthHdr );\r
+       PERF_DECLARE( QueuePacket );\r
+       PERF_DECLARE( SendMgrQueue );\r
+       PERF_DECLARE( PostSend );\r
+       PERF_DECLARE( ProcessFailedSends );\r
+       PERF_DECLARE( GetEndpt );\r
+\r
+\r
+       p_netbuf = (NET_BUFFER*)context;\r
+       p_net_buffer_list = (NET_BUFFER_LIST*)IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_netbuf);\r
+       p_port = (ipoib_port_t*)IPOIB_PORT_FROM_PACKET(p_net_buffer_list);\r
+       NDIS_SET_SEND_COMPLETE_FLAG(complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
+\r
+\r
+       cl_spinlock_acquire( &p_port->send_lock );\r
+       if (p_desc == NULL) {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_SEND, ("Allocating send_desc First Time\n") );\r
+               p_desc = ExAllocatePoolWithTag(NonPagedPool ,sizeof (ipoib_send_desc_t), 'XMXA');\r
+       }\r
+       ASSERT(p_desc);\r
+       p_desc->p_netbuf_list = p_net_buffer_list;\r
+       p_desc->p_endpt = NULL;\r
+       p_desc->p_buf = NULL;\r
+       p_desc->num_wrs = 1;\r
+\r
+       //IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+               //                              ("\n*******\nRECEIVED NB= %x with SG= %x\n********\n", p_netbuf, p_sgl) );\r
+       /* Get the ethernet header so we can find the endpoint. */\r
+       cl_perf_start( GetEthHdr );\r
+       status = __send_mgr_get_eth_hdr(\r
+               p_netbuf, &p_mdl, &p_eth_hdr, &mdl_len );\r
+       cl_perf_stop( &p_port->p_adapter->perf, GetEthHdr );\r
+\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               cl_perf_start( ProcessFailedSends );\r
+               /* fail  net buffer list */\r
+               __process_failed_send( p_port, p_desc, status, complete_flags);\r
+               cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+               goto send_end;\r
+       }\r
+       //from_queue = (boolean_t)(IPOIB_FROM_QUEUE(p_netbuf) == (void*)1);\r
+       from_queue = (boolean_t)(IPOIB_FROM_QUEUE(p_netbuf) != NULL);\r
+       if (from_queue)\r
+       {\r
+               cl_perf_start( GetEndpt );\r
+               status = __endpt_mgr_ref( p_port, p_eth_hdr->dst, &p_desc->p_endpt );\r
+               cl_perf_stop( &p_port->p_adapter->perf, GetEndpt );\r
+               if( status == NDIS_STATUS_PENDING )\r
+               {\r
+                       IPOIB_FROM_QUEUE(p_netbuf) = p_sgl;\r
+                       cl_qlist_insert_head( &p_port->send_mgr.pending_list,\r
+                               IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_netbuf_list ) );\r
+                       goto send_end;\r
+               }\r
+               else if( status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       ASSERT( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION );\r
+\r
+                       if( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) )\r
+                       {\r
+                               if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst,\r
+                                       IB_MC_REC_STATE_FULL_MEMBER) == IB_SUCCESS )\r
+                               {\r
+                                       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+                                               ("Multicast Mac - trying to join.\n") );\r
+                                       IPOIB_FROM_QUEUE(p_netbuf) = p_sgl;\r
+                                       cl_qlist_insert_head( &p_port->send_mgr.pending_list,\r
+                                               IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_netbuf_list ) );\r
+                                       goto send_end;\r
+                               }\r
+                       }\r
+                       /*\r
+                        * Complete the send as if we sent it - WHQL tests don't like the\r
+                        * sends to fail.\r
+                        */\r
+                       cl_perf_start( ProcessFailedSends );\r
+                       __process_failed_send( p_port, p_desc, NDIS_STATUS_SUCCESS,complete_flags );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+                       goto send_end;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               cl_perf_start( SendMgrQueue );\r
+               if ( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) && \r
+                        p_eth_hdr->type == ETH_PROT_TYPE_IP &&\r
+                        !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) ) \r
+               {\r
+                       ip_hdr_t                        *p_ip_hdr;\r
+                       uint8_t                         *p_tmp;\r
+                       MDL                                     *p_ip_hdr_mdl;\r
+                       UINT                            ip_hdr_mdl_len;\r
+\r
+                       if(mdl_len >= sizeof(ip_hdr_t) + sizeof(eth_hdr_t))\r
+                       {\r
+                               p_ip_hdr = (ip_hdr_t*)(p_eth_hdr + 1);\r
+                       }\r
+                       else\r
+                       {\r
+                               NdisGetNextMdl(p_mdl,&p_ip_hdr_mdl);\r
+                               // Extract the ip hdr \r
+                               if( !p_ip_hdr_mdl )\r
+                               {\r
+                                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Failed to get IP header buffer.\n") );\r
+                                       goto mc_end;\r
+                               }       \r
+                               NdisQueryMdl(p_ip_hdr_mdl,&p_tmp,&ip_hdr_mdl_len,NormalPagePriority);\r
+                               if( !p_tmp )\r
+                               {\r
+                                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Failed to get IP header.\n") );\r
+                                       goto mc_end;\r
+                               }                                       \r
+                               if( ip_hdr_mdl_len < sizeof(ip_hdr_t) )\r
+                               {\r
+                                       /* This buffer is done for.  Get the next buffer. */\r
+                                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Buffer too small for IP packet.\n") );\r
+                                       goto mc_end;\r
+                               }\r
+                               p_ip_hdr = (ip_hdr_t*)(p_tmp + NET_BUFFER_CURRENT_MDL_OFFSET(p_netbuf));\r
+                               p_eth_hdr->dst.addr[1] = ((unsigned char*)&p_ip_hdr->dst_ip)[0] & 0x0f;\r
+                               p_eth_hdr->dst.addr[3] = ((unsigned char*)&p_ip_hdr->dst_ip)[1];\r
+                       }\r
+               }\r
+mc_end:\r
+               status = __send_mgr_queue( p_port, p_eth_hdr, &p_desc->p_endpt );\r
+               cl_perf_stop( &p_port->p_adapter->perf, SendMgrQueue );\r
+               if( status == NDIS_STATUS_PENDING )\r
+               {\r
+                       /* Queue net buffer list. */\r
+                       cl_perf_start( QueuePacket );\r
+                       NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+                       IPOIB_FROM_QUEUE(p_netbuf) = p_sgl;\r
+                       cl_qlist_insert_tail( &p_port->send_mgr.pending_list,\r
+                                       IPOIB_LIST_ITEM_FROM_PACKET(p_net_buffer_list) );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, QueuePacket );\r
+                       goto send_end;\r
+               }\r
+               if( status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       ASSERT( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION );\r
+                       /*\r
+                        * Complete the send as if we sent it - WHQL tests don't like the\r
+                        * sends to fail.\r
+                        */\r
+                       cl_perf_start( ProcessFailedSends );\r
+                       __process_failed_send( p_port, p_desc, NDIS_STATUS_SUCCESS, complete_flags );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+                       goto send_end;\r
+               }\r
+       }\r
+       cl_perf_start( BuildSendDesc );\r
+       status = __build_send_desc( p_port, p_eth_hdr, p_mdl, mdl_len, p_sgl, p_desc );\r
+       cl_perf_stop( &p_port->p_adapter->perf, BuildSendDesc );\r
+\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               cl_perf_start( ProcessFailedSends );\r
+               __process_failed_send( p_port, p_desc, status, complete_flags );\r
+               cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+               goto send_end;\r
+       }\r
+\r
+       /* Post the WR. */\r
+       cl_perf_start( PostSend );\r
+       cl_msg_out("sending packet with wr-id =0x%x\n",&p_desc->send_wr[0].wr.wr_id );\r
+       ib_status = p_port->p_adapter->p_ifc->post_send( p_port->ib_mgr.h_qp, &p_desc->send_wr[0].wr, &p_wr_failed );\r
+       cl_perf_stop( &p_port->p_adapter->perf, PostSend );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_post_send returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+               cl_perf_start( ProcessFailedSends );\r
+               __process_failed_send( p_port, p_desc, NDIS_STATUS_FAILURE, complete_flags );\r
+               cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+               /* Flag the adapter as hung since posting is busted. */\r
+               p_port->p_adapter->hung = TRUE;\r
+       }\r
+       cl_atomic_inc( &p_port->send_mgr.depth );\r
+\r
+send_end:\r
+       if (status != NDIS_STATUS_SUCCESS) {\r
+//             IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_SEND,\r
+       //                                      ("Free S/G List: 0x%x.\n", (UINT) (PVOID) p_sgl) );\r
+               /*NdisMFreeNetBufferSGList(\r
+                       p_port->p_adapter->NdisMiniportDmaHandle,\r
+                       p_sgl,\r
+                       p_netbuf);*/\r
+               \r
+       }\r
+                       \r
+                       \r
+       cl_spinlock_release( &p_port->send_lock );\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+static NDIS_STATUS\r
+__send_gen(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN                              INT                                                     lso_data_index\r
+        )\r
+{\r
+       ib_api_status_t                 status;\r
+       uint32_t                                i, j = 1;\r
+       uint32_t                                offset = sizeof(eth_hdr_t);\r
+       PERF_DECLARE( SendCopy );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       if( !p_sgl )\r
+       {\r
+               ASSERT( p_sgl );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to get SGL from packet.\n") );\r
+               return NDIS_STATUS_FAILURE;\r
+       }\r
+\r
+       /* Remember that one of the DS entries is reserved for the IPoIB header. */\r
+       if( ( p_sgl->NumberOfElements >= MAX_SEND_SGE ||\r
+               p_sgl->Elements[0].Length < sizeof(eth_hdr_t)) )\r
+       {\r
+\r
+               IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+                       ("Too many buffers %d to fit in WR ds_array[%d] \\r
+                        Or buffer[0] length %d < Eth header. Copying data.\n",\r
+                       p_sgl->NumberOfElements, MAX_SEND_SGE,  p_sgl->Elements[0].Length ) );\r
+               status = NDIS_STATUS_RESOURCES;\r
+               if( !p_port->p_adapter->params.cm_enabled )\r
+               {\r
+                       cl_perf_start( SendCopy );\r
+                       status = __send_copy( p_port, p_desc );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, SendCopy );\r
+               }\r
+               IPOIB_EXIT( IPOIB_DBG_SEND );\r
+               return status;\r
+       }\r
+\r
+       /*\r
+        * Skip the ethernet header.  It is either the first element,\r
+        * or part of it.\r
+        */\r
+       i = 0;\r
+       if( lso_data_index )\r
+       { /* we have an LSO packet */\r
+               i = lso_data_index;\r
+               j = 0;\r
+       }\r
+       else while( offset )\r
+       {\r
+               if( p_sgl->Elements[i].Length <= offset )\r
+               {\r
+                       offset -= p_sgl->Elements[i++].Length;\r
+               }\r
+               else\r
+               {\r
+                       p_desc->send_wr[0].local_ds[j].vaddr =\r
+                               p_sgl->Elements[i].Address.QuadPart + offset;\r
+                       p_desc->send_wr[0].local_ds[j].length =\r
+                               p_sgl->Elements[i].Length - offset;\r
+                       p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
+                       i++;\r
+                       j++;\r
+                       break;\r
+               }\r
+       }\r
+       /* Now fill in the rest of the local data segments. */\r
+       while( i < p_sgl->NumberOfElements )\r
+       {\r
+               p_desc->send_wr[0].local_ds[j].vaddr = p_sgl->Elements[i].Address.QuadPart;\r
+               p_desc->send_wr[0].local_ds[j].length = p_sgl->Elements[i].Length;\r
+               p_desc->send_wr[0].local_ds[j].lkey = p_port->ib_mgr.lkey;\r
+               i++;\r
+               j++;\r
+       }\r
+\r
+       /* Set the number of data segments. */\r
+       p_desc->send_wr[0].wr.num_ds = j;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+#endif\r
+\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_ip(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc )\r
+{\r
+       NDIS_STATUS             status;\r
+       ip_hdr_t                *p_ip_hdr;\r
+       uint32_t                ip_packet_len;\r
+       size_t                  iph_size_in_bytes;\r
+       size_t                  iph_options_size;\r
+       \r
+       PERF_DECLARE( QueryIp );\r
+       PERF_DECLARE( SendTcp );\r
+       PERF_DECLARE( FilterUdp );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       if( !buf_len )\r
+       {\r
+               cl_perf_start( QueryIp );\r
+               NdisGetNextMdl ( p_mdl, &p_mdl );\r
+               if( !p_mdl )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get IP header buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+\r
+               NdisQueryMdl(p_mdl, &p_ip_hdr, &buf_len, NormalPagePriority);\r
+               if( !p_ip_hdr )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to query IP header buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               cl_perf_stop( &p_port->p_adapter->perf, QueryIp );\r
+       }\r
+       else\r
+       {\r
+               p_ip_hdr = (ip_hdr_t*)(p_eth_hdr + 1);\r
+       }\r
+       if( buf_len < sizeof(ip_hdr_t) )\r
+       {\r
+               /* This buffer is done for.  Get the next buffer. */\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Buffer too small for IP packet.\n") );\r
+               return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+       }\r
+\r
+       switch( p_ip_hdr->prot )\r
+       {\r
+       case IP_PROT_UDP:\r
+\r
+               cl_perf_start( FilterUdp );\r
+               status = __send_mgr_filter_udp(\r
+                       p_port, p_ip_hdr, p_mdl, (buf_len - sizeof(ip_hdr_t)), p_sgl, p_desc );\r
+               cl_perf_stop( &p_port->p_adapter->perf, FilterUdp );\r
+               if( status == NDIS_STATUS_PENDING )\r
+               {  /* not DHCP packet, keep going */\r
+                       if( ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) )\r
+                               p_desc->send_dir = SEND_UD_QP;\r
+                       else\r
+                               p_desc->send_dir = SEND_RC_QP;\r
+                       break;\r
+               }\r
+               return status;\r
+       \r
+       case IP_PROT_TCP:\r
+               p_desc->send_dir = SEND_RC_QP;\r
+               break;\r
+       case IP_PROT_IGMP:\r
+               /*\r
+               In igmp packet I saw that iph arrive in 2 NDIS_BUFFERs:\r
+               1. iph\r
+               2. ip options\r
+                               So to get the IGMP packet we need to skip the ip options NDIS_BUFFER\r
+                       */\r
+                       iph_size_in_bytes = (p_ip_hdr->ver_hl & 0xf) * 4;\r
+                       iph_options_size = iph_size_in_bytes - buf_len;\r
+                       buf_len -= sizeof(ip_hdr_t);//without ipheader\r
+\r
+                       /*\r
+               Could be a case that arrived igmp packet not from type IGMPv2 ,\r
+               but IGMPv1 or IGMPv3.\r
+               We anyway pass it to __send_mgr_filter_igmp_v2().\r
+               */\r
+               status =\r
+                       __send_mgr_filter_igmp_v2( p_port, p_ip_hdr, iph_options_size, p_mdl, buf_len );\r
+               if( status != NDIS_STATUS_SUCCESS )\r
+                       return status;\r
+\r
+       case IP_PROT_ICMP:\r
+               p_desc->send_dir = SEND_UD_QP;\r
+       default:\r
+               break;\r
+       }\r
+       \r
+       if( !p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               p_desc->send_dir = SEND_UD_QP;\r
+               goto send_gen;\r
+       }\r
+       else if( endpt_cm_get_state( p_desc->p_endpt ) != IPOIB_CM_CONNECTED )\r
+       {\r
+               p_desc->send_dir = SEND_UD_QP;\r
+       }\r
+       if( p_desc->send_dir == SEND_UD_QP )\r
+       {\r
+               ip_packet_len = cl_ntoh16( p_ip_hdr->length );\r
+               if( ip_packet_len  > p_port->p_adapter->params.payload_mtu )\r
+               {\r
+                       //TODO: NDIS60\r
+                       #if 0\r
+                       status = __send_fragments( p_port, p_desc, (eth_hdr_t* const)p_eth_hdr,\r
+                                               (ip_hdr_t* const)p_ip_hdr, (uint32_t)buf_len, p_mdl );\r
+                       return status;\r
+                       #endif\r
+                       ASSERT(FALSE);\r
+               }\r
+       }\r
+\r
+send_gen:\r
+       cl_perf_start( SendTcp );\r
+       status = __send_gen( p_port, p_desc, p_sgl, 0 );\r
+       cl_perf_stop( &p_port->p_adapter->perf, SendTcp );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return status;\r
+}\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_igmp_v2(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ip_hdr_t* const                         p_ip_hdr,\r
+       IN                              size_t                                          iph_options_size,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len )\r
+{\r
+       igmp_v2_hdr_t           *p_igmp_v2_hdr = NULL;\r
+       NDIS_STATUS                     endpt_status;\r
+       ipoib_endpt_t*          p_endpt = NULL;\r
+       mac_addr_t                      fake_mcast_mac;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+                        ("buf_len = %d,iph_options_size = %d\n",(int)buf_len,(int)iph_options_size ) );\r
+\r
+       if( !buf_len )\r
+       {\r
+               // To get the IGMP packet we need to skip the ip options NDIS_BUFFER (if exists)\r
+               while ( iph_options_size )\r
+               {\r
+                       NdisGetNextMdl( p_mdl, &p_mdl );\r
+                       if( !p_mdl )\r
+                       {\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Failed to get IGMPv2 header buffer.\n") );\r
+                               return NDIS_STATUS_FAILURE;\r
+                       }\r
+                       NdisQueryMdl( p_mdl, &p_igmp_v2_hdr, &buf_len, NormalPagePriority );\r
+                       if( !p_igmp_v2_hdr )\r
+                       {\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Failed to query IGMPv2 header buffer.\n") );\r
+                               return NDIS_STATUS_FAILURE;\r
+                       }\r
+                       iph_options_size-=buf_len;\r
+               }\r
+        \r
+               NdisGetNextMdl( p_mdl, &p_mdl );\r
+               if( !p_mdl )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get IGMPv2 header buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               NdisQueryMdl( p_mdl, &p_igmp_v2_hdr, &buf_len, NormalPagePriority );\r
+               if( !p_igmp_v2_hdr )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to query IGMPv2 header buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               /* assuming ip header and options are in the same packet */\r
+               p_igmp_v2_hdr = GetIpPayloadPtr(p_ip_hdr);\r
+       }\r
+       /* Get the IGMP header length. */\r
+       if( buf_len < sizeof(igmp_v2_hdr_t) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Buffer not large enough for IGMPv2 packet.\n") );\r
+               return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+       }\r
+\r
+       // build fake mac from igmp packet group address\r
+       fake_mcast_mac.addr[0] = 1;\r
+       fake_mcast_mac.addr[1] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[0] & 0x0f;\r
+       fake_mcast_mac.addr[2] = 0x5E;\r
+       fake_mcast_mac.addr[3] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[1];\r
+       fake_mcast_mac.addr[4] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[2];\r
+       fake_mcast_mac.addr[5] = ((unsigned char*)&p_igmp_v2_hdr->group_address)[3];\r
+\r
+       switch ( p_igmp_v2_hdr->type )\r
+       {\r
+       case IGMP_V2_MEMBERSHIP_REPORT:\r
+               /* \r
+                       This mean that some body open listener on this group \r
+                       Change type of mcast endpt to SEND_RECV endpt. So mcast garbage collector \r
+                       will not delete this mcast endpt.\r
+               */\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+                       ("Catched IGMP_V2_MEMBERSHIP_REPORT message\n") );\r
+               endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt );\r
+               if ( p_endpt )\r
+               {\r
+                       cl_obj_lock( &p_port->obj );\r
+                       p_endpt->is_mcast_listener = TRUE;\r
+                       cl_obj_unlock( &p_port->obj );\r
+            ipoib_endpt_deref( p_endpt );\r
+               }\r
+               break;\r
+\r
+       case IGMP_V2_LEAVE_GROUP:\r
+               /* \r
+                       This mean that somebody CLOSE listener on this group .\r
+                   Change type of mcast endpt to SEND_ONLY endpt. So mcast \r
+                       garbage collector will delete this mcast endpt next time.\r
+               */\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+                            ("Catched IGMP_V2_LEAVE_GROUP message\n") );\r
+               endpt_status = __endpt_mgr_ref( p_port, fake_mcast_mac, &p_endpt );\r
+               if ( p_endpt )\r
+               {\r
+                       cl_obj_lock( &p_port->obj );\r
+                       p_endpt->is_mcast_listener = FALSE;\r
+                       p_endpt->is_in_use = FALSE;\r
+                       cl_obj_unlock( &p_port->obj );\r
+                       ipoib_endpt_deref( p_endpt );\r
+               }\r
+\r
+               __port_do_mcast_garbage(p_port);\r
+\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+                            ("Send Unknown IGMP message: 0x%x \n", p_igmp_v2_hdr->type ) );\r
+               break;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_udp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ip_hdr_t* const                         p_ip_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc )\r
+{\r
+       ib_api_status_t         status;\r
+       udp_hdr_t                       *p_udp_hdr;\r
+       PERF_DECLARE( QueryUdp );\r
+       PERF_DECLARE( SendUdp );\r
+       PERF_DECLARE( FilterDhcp );\r
+       //TODO NDIS60 remove this param\r
+       UNUSED_PARAM(p_sgl);\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       if( !buf_len )\r
+       {\r
+               cl_perf_start( QueryUdp );\r
+               NdisGetNextMdl( p_mdl, &p_mdl );\r
+               if( !p_mdl )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get UDP header buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               NdisQueryMdl( p_mdl, &p_udp_hdr, &buf_len, NormalPagePriority );\r
+               if( !p_udp_hdr )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to query UDP header buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               cl_perf_stop( &p_port->p_adapter->perf, QueryUdp );\r
+       }\r
+       else\r
+       {\r
+               p_udp_hdr = (udp_hdr_t*)GetIpPayloadPtr(p_ip_hdr);\r
+       }\r
+       /* Get the UDP header and check the destination port numbers. */\r
+       \r
+       if (p_ip_hdr->offset > 0) {\r
+               /* This is a fragmented part of UDP packet\r
+                * Only first packet will contain UDP header in such case\r
+                * So, return if offset > 0\r
+                */\r
+                return NDIS_STATUS_PENDING;\r
+       }\r
+                \r
+       if( buf_len < sizeof(udp_hdr_t) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Buffer not large enough for UDP packet.\n") );\r
+               return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+       }\r
+\r
+       if( (p_udp_hdr->src_port != DHCP_PORT_CLIENT ||\r
+               p_udp_hdr->dst_port != DHCP_PORT_SERVER) &&\r
+               (p_udp_hdr->src_port != DHCP_PORT_SERVER ||\r
+               p_udp_hdr->dst_port != DHCP_PORT_CLIENT) )\r
+       {\r
+               /* Not a DHCP packet. */\r
+               return NDIS_STATUS_PENDING;\r
+       }\r
+\r
+       buf_len -= sizeof(udp_hdr_t);\r
+\r
+       /* Allocate our scratch buffer. */\r
+       p_desc->p_buf = (send_buf_t*)\r
+               ExAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+       if( !p_desc->p_buf )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to query DHCP packet buffer.\n") );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+       /* Copy the IP and UDP headers. */\r
+       cl_memcpy( &p_desc->p_buf->ip.hdr, p_ip_hdr , sizeof(ip_hdr_t) );\r
+       cl_memcpy(\r
+               &p_desc->p_buf->ip.prot.udp.hdr, p_udp_hdr, sizeof(udp_hdr_t) );\r
+\r
+       cl_perf_start( FilterDhcp );\r
+       status = __send_mgr_filter_dhcp(\r
+               p_port, p_udp_hdr, p_mdl, buf_len, p_desc );\r
+       cl_perf_stop( &p_port->p_adapter->perf, FilterDhcp );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return status;\r
+}\r
+\r
+unsigned short ipchksum(unsigned short *ip, int len)\r
+{\r
+    unsigned long sum = 0;\r
+\r
+    len >>= 1;\r
+    while (len--) {\r
+        sum += *(ip++);\r
+        if (sum > 0xFFFF)\r
+            sum -= 0xFFFF;\r
+    }\r
+    return (unsigned short)((~sum) & 0x0000FFFF);\r
+}\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_dhcp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   udp_hdr_t* const                        p_udp_hdr,\r
+       IN                              NDIS_BUFFER*                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc )\r
+{\r
+       dhcp_pkt_t                      *p_dhcp;\r
+       dhcp_pkt_t                      *p_ib_dhcp;\r
+       uint8_t                         *p_option, *p_cid = NULL;\r
+       uint8_t                         msg = 0;\r
+       size_t                          len;\r
+       ib_gid_t                        gid;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       if( !buf_len )\r
+       {\r
+               NdisGetNextMdl( p_mdl, &p_mdl );\r
+               if( !p_mdl )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get DHCP buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               NdisQueryMdl( p_mdl, &p_dhcp, &buf_len, NormalPagePriority );\r
+               if( !p_dhcp )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to query DHCP buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               p_dhcp = (dhcp_pkt_t*)(p_udp_hdr + 1);\r
+       }\r
+\r
+       if( buf_len < DHCP_MIN_SIZE )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Buffer not large enough for DHCP packet.\n") );\r
+               return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+       }\r
+\r
+       p_ib_dhcp = &p_desc->p_buf->ip.prot.udp.dhcp;\r
+       cl_memcpy( p_ib_dhcp, p_dhcp, buf_len );\r
+\r
+       /* Now scan through the options looking for the client identifier. */\r
+       p_option = &p_ib_dhcp->options[4];\r
+       while( *p_option != DHCP_OPT_END && p_option < &p_ib_dhcp->options[312] )\r
+       {\r
+               switch( *p_option )\r
+               {\r
+               case DHCP_OPT_PAD:\r
+                       p_option++;\r
+                       break;\r
+\r
+               case DHCP_OPT_MSG:\r
+                       msg = p_option[2];\r
+                       p_option += 3;\r
+                       break;\r
+\r
+               case DHCP_OPT_CLIENT_ID:\r
+                       p_cid = p_option;\r
+                       /* Fall through. */\r
+\r
+               default:\r
+                       /*\r
+                        * All other options have a length byte following the option code.\r
+                        * Offset by the length to get to the next option.\r
+                        */\r
+                       p_option += (p_option[1] + 2);\r
+               }\r
+       }\r
+\r
+       switch( msg )\r
+       {\r
+       /* Client messages */\r
+       case DHCPDISCOVER:\r
+       case DHCPREQUEST:\r
+                       p_ib_dhcp->flags |= DHCP_FLAGS_BROADCAST;\r
+               /* Fall through */\r
+       case DHCPDECLINE:\r
+       case DHCPRELEASE:\r
+       case DHCPINFORM:\r
+               /* Fix up the client identifier option */\r
+               if( p_cid )\r
+               {\r
+                       /* do we need to replace it ?  len eq ETH MAC sz 'and' MAC is mine */\r
+                       if( p_cid[1] == HW_ADDR_LEN+1 && !cl_memcmp( &p_cid[3],\r
+                               &p_port->p_adapter->params.conf_mac.addr, HW_ADDR_LEN ) )\r
+                       {\r
+                               /* Make sure there's room to extend it.  23 is the size of\r
+                                * the CID option for IPoIB.\r
+                                */\r
+                               if( buf_len + 23 - p_cid[1] > sizeof(dhcp_pkt_t) )\r
+                               {\r
+                                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Can't convert CID to IPoIB format.\n") );\r
+                                       return NDIS_STATUS_RESOURCES;\r
+                               }\r
+                               /* Move the existing options down, and add a new CID option */\r
+                               len = p_option - ( p_cid + p_cid[1] + 2 );\r
+                               p_option = p_cid + p_cid[1] + 2;\r
+                               RtlMoveMemory( p_cid, p_option, len );\r
+                               \r
+                               p_cid += len;\r
+                               p_cid[0] = DHCP_OPT_CLIENT_ID;\r
+                               p_cid[1] = 21;\r
+                               p_cid[2] = DHCP_HW_TYPE_IB;\r
+                       }\r
+                       else\r
+                       {\r
+                               p_cid[2] = DHCP_HW_TYPE_IB;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /*\r
+                        * Make sure there's room to extend it.  23 is the size of\r
+                        * the CID option for IPoIB.\r
+                        */\r
+                       if( buf_len + 23 > sizeof(dhcp_pkt_t) )\r
+                       {\r
+                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Can't convert CID to IPoIB format.\n") );\r
+                               return NDIS_STATUS_RESOURCES;\r
+                       }\r
+\r
+                       p_cid = p_option;\r
+                       p_option = p_cid + 23;\r
+                       p_option[0] = DHCP_OPT_END;\r
+                       p_cid[0] = DHCP_OPT_CLIENT_ID;\r
+                       p_cid[1] = 21;\r
+                       p_cid[2] = DHCP_HW_TYPE_IB;\r
+               }\r
+\r
+               CL_ASSERT( p_cid[1] == 21 );\r
+               p_cid[23]= DHCP_OPT_END;\r
+               ib_gid_set_default( &gid, p_port->p_adapter->guids.port_guid.guid );\r
+               cl_memcpy( &p_cid[7], &gid, sizeof(ib_gid_t) );\r
+               cl_memcpy( &p_cid[3], &p_port->ib_mgr.qpn, sizeof(p_port->ib_mgr.qpn) );                \r
+               p_ib_dhcp->htype = DHCP_HW_TYPE_IB;\r
+\r
+               /* update lengths to include any change we made */\r
+               p_desc->p_buf->ip.hdr.length = cl_ntoh16( sizeof(ip_hdr_t) + sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t) );\r
+               p_desc->p_buf->ip.prot.udp.hdr.length = cl_ntoh16( sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t) );\r
+\r
+               /* update crc in ip header */\r
+               //if( !p_port->p_adapter->params.send_chksum_offload )\r
+               //{ //TODO ?\r
+               p_desc->p_buf->ip.hdr.chksum = 0;\r
+               p_desc->p_buf->ip.hdr.chksum = ipchksum((unsigned short*) &p_desc->p_buf->ip.hdr, sizeof(ip_hdr_t));\r
+               //} TODO ??\r
+               break;\r
+\r
+       /* Server messages. */\r
+       case DHCPOFFER:\r
+       case DHCPACK:\r
+       case DHCPNAK:\r
+               /* don't touch server messages */\r
+               break;\r
+\r
+       default:\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Invalide message type.\n") );\r
+               return NDIS_STATUS_INVALID_DATA;\r
+       }\r
+       /* no chksum for udp */\r
+       p_desc->p_buf->ip.prot.udp.hdr.chksum = 0;\r
+       p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( p_desc->p_buf );\r
+       p_desc->send_wr[0].local_ds[1].length = sizeof(ip_hdr_t) +      sizeof(udp_hdr_t) + sizeof(dhcp_pkt_t);\r
+       p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey;\r
+       p_desc->send_wr[0].wr.num_ds = 2;\r
+       p_desc->send_dir = SEND_UD_QP;\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__send_mgr_filter_arp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL*                                            p_mdl,\r
+       IN                              size_t                                          buf_len,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc )\r
+{\r
+       arp_pkt_t                       *p_arp;\r
+       ipoib_arp_pkt_t         *p_ib_arp;\r
+       NDIS_STATUS                     status;\r
+       mac_addr_t                      null_hw = {0};\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+       \r
+       if( !buf_len )\r
+       {\r
+               NdisGetNextMdl( p_mdl, &p_mdl );\r
+               if( !p_mdl )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get ARP buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               NdisQueryMdl( p_mdl, &p_arp, &buf_len, NormalPagePriority );\r
+               if( !p_arp )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get query ARP buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               p_arp = (arp_pkt_t*)(p_eth_hdr + 1);\r
+       }\r
+\r
+       /* Single buffer ARP packet. */\r
+       if( buf_len < sizeof(arp_pkt_t) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Buffer too short for ARP.\n") );\r
+               return NDIS_STATUS_BUFFER_TOO_SHORT;\r
+       }\r
+\r
+       if( p_arp->prot_type != ETH_PROT_TYPE_IP )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Unsupported protocol type.\n") );\r
+               return NDIS_STATUS_INVALID_DATA;\r
+       }\r
+\r
+       /* Allocate our scratch buffer. */\r
+       p_desc->p_buf = (send_buf_t*)\r
+               NdisAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+       if( !p_desc->p_buf )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to query ARP packet buffer.\n") );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+       p_ib_arp = (ipoib_arp_pkt_t*)p_desc->p_buf;\r
+\r
+       /* Convert the ARP payload. */\r
+       p_ib_arp->hw_type = ARP_HW_TYPE_IB;\r
+       p_ib_arp->prot_type = p_arp->prot_type;\r
+       p_ib_arp->hw_size = sizeof(ipoib_hw_addr_t);\r
+       p_ib_arp->prot_size = p_arp->prot_size;\r
+       p_ib_arp->op = p_arp->op;\r
+       \r
+       ipoib_addr_set_qpn( &p_ib_arp->src_hw, p_port->ib_mgr.qpn );\r
+#if 0\r
+\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               ipoib_addr_set_flags( &p_ib_arp->src_hw, IPOIB_CM_FLAG_RC );\r
+       }\r
+#endif\r
+\r
+       ib_gid_set_default( &p_ib_arp->src_hw.gid,\r
+               p_port->p_adapter->guids.port_guid.guid );\r
+       p_ib_arp->src_ip = p_arp->src_ip;\r
+       if( cl_memcmp( &p_arp->dst_hw, &null_hw, sizeof(mac_addr_t) ) )\r
+       {\r
+               /* Get the endpoint referenced by the dst_hw address. */\r
+               net32_t qpn = 0;\r
+               status = __endpt_mgr_get_gid_qpn( p_port, p_arp->dst_hw,\r
+                       &p_ib_arp->dst_hw.gid, &qpn );\r
+               if( status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed lookup of destination HW address\n") );\r
+                       return status;\r
+               }\r
+               ipoib_addr_set_qpn( &p_ib_arp->dst_hw, qpn );\r
+#if 0\r
+               if( p_arp->op == ARP_OP_REP && \r
+                       p_port->p_adapter->params.cm_enabled && \r
+                       p_desc->p_endpt->cm_flag == IPOIB_CM_FLAG_RC )\r
+               {\r
+                       cm_state_t      cm_state;\r
+                       cm_state = \r
+                               ( cm_state_t )InterlockedCompareExchange( (volatile LONG *)&p_desc->p_endpt->conn.state,\r
+                                                               IPOIB_CM_CONNECT, IPOIB_CM_DISCONNECTED );\r
+                       switch( cm_state )\r
+                       {\r
+                       case IPOIB_CM_DISCONNECTED:\r
+                                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                                               ("ARP REPLY pending Endpt[%p] QPN %#x MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+                                               p_desc->p_endpt, \r
+                                               cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->dst_hw )),\r
+                                               p_desc->p_endpt->mac.addr[0], p_desc->p_endpt->mac.addr[1],\r
+                                               p_desc->p_endpt->mac.addr[2], p_desc->p_endpt->mac.addr[3],\r
+                                               p_desc->p_endpt->mac.addr[4], p_desc->p_endpt->mac.addr[5] ) );\r
+                                       ipoib_addr_set_sid( &p_desc->p_endpt->conn.service_id,\r
+                                                                               ipoib_addr_get_qpn( &p_ib_arp->dst_hw ) );\r
+\r
+                                       NdisFreeToNPagedLookasideList(\r
+                                               &p_port->buf_mgr.send_buf_list, p_desc->p_buf );\r
+                                       cl_qlist_insert_tail( &p_port->send_mgr.pending_list,\r
+                                                               IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_buf ) );\r
+                                       NdisInterlockedInsertTailList( &p_port->endpt_mgr.pending_conns, \r
+                                                                                               &p_desc->p_endpt->list_item, \r
+                                                                                               &p_port->endpt_mgr.conn_lock );\r
+                                       cl_event_signal( &p_port->endpt_mgr.event );\r
+                                       return NDIS_STATUS_PENDING;\r
+                       \r
+                       case IPOIB_CM_CONNECT:\r
+                               /* queue ARP REP packet until connected */\r
+                                       NdisFreeToNPagedLookasideList(\r
+                                       &p_port->buf_mgr.send_buf_list, p_desc->p_buf );\r
+                                       cl_qlist_insert_tail( &p_port->send_mgr.pending_list,\r
+                                                               IPOIB_LIST_ITEM_FROM_PACKET( p_desc->p_pkt ) );\r
+                                       return NDIS_STATUS_PENDING;\r
+                       default:\r
+                               break;\r
+                       }\r
+               }\r
+#endif\r
+       }\r
+       else\r
+       {\r
+               cl_memclr( &p_ib_arp->dst_hw, sizeof(ipoib_hw_addr_t) );\r
+       }\r
+       \r
+#if 0 //DBG\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+               (" ARP %s SEND to ENDPT[%p] State: %d flag: %#x, QPN: %#x MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+                       ( p_ib_arp->op == ARP_OP_REP ? "REP": "REQ"),                   p_desc->p_endpt, \r
+                       endpt_cm_get_state( p_desc->p_endpt ),\r
+                       p_desc->p_endpt->cm_flag, \r
+                       cl_ntoh32( ipoib_addr_get_qpn( &p_ib_arp->dst_hw )),\r
+                       p_desc->p_endpt->mac.addr[0], p_desc->p_endpt->mac.addr[1],\r
+                       p_desc->p_endpt->mac.addr[2], p_desc->p_endpt->mac.addr[3],\r
+                       p_desc->p_endpt->mac.addr[4], p_desc->p_endpt->mac.addr[5] ));\r
+       }\r
+#endif\r
+\r
+       p_ib_arp->dst_ip = p_arp->dst_ip;\r
+\r
+       p_desc->send_wr[0].local_ds[1].vaddr = cl_get_physaddr( p_ib_arp );\r
+       p_desc->send_wr[0].local_ds[1].length = sizeof(ipoib_arp_pkt_t);\r
+       p_desc->send_wr[0].local_ds[1].lkey = p_port->ib_mgr.lkey;\r
+       p_desc->send_wr[0].wr.num_ds = 2;\r
+       p_desc->send_wr[0].wr.p_next = NULL;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static inline NDIS_STATUS\r
+__send_mgr_queue(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              eth_hdr_t* const                        p_eth_hdr,\r
+               OUT                     ipoib_endpt_t** const           pp_endpt )\r
+{\r
+       NDIS_STATUS                     status;\r
+\r
+       PERF_DECLARE( GetEndpt );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       /* Check the send queue and pend the request if not empty. */\r
+       if( cl_qlist_count( &p_port->send_mgr.pending_list ) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+                       ("Pending list not empty.\n") );\r
+               return NDIS_STATUS_PENDING;\r
+       }\r
+\r
+       /* Check the send queue and pend the request if not empty. */\r
+       if( p_port->send_mgr.depth == p_port->p_adapter->params.sq_depth )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+                       ("No available WQEs.\n") );\r
+               return NDIS_STATUS_PENDING;\r
+       }\r
+\r
+       cl_perf_start( GetEndpt );\r
+       status = __endpt_mgr_ref( p_port, p_eth_hdr->dst, pp_endpt );\r
+       cl_perf_stop( &p_port->p_adapter->perf, GetEndpt );\r
+\r
+       if( status == NDIS_STATUS_NO_ROUTE_TO_DESTINATION &&\r
+               ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) )\r
+       {\r
+               if( ipoib_port_join_mcast( p_port, p_eth_hdr->dst, \r
+                       IB_MC_REC_STATE_FULL_MEMBER) == IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+                               ("Multicast Mac - trying to join.\n") );\r
+                       return NDIS_STATUS_PENDING;\r
+               }\r
+       }\r
+       else if ( status == NDIS_STATUS_SUCCESS && \r
+                         ETH_IS_MULTICAST( p_eth_hdr->dst.addr ) &&  \r
+                         !ETH_IS_BROADCAST( p_eth_hdr->dst.addr ) )\r
+       {\r
+               CL_ASSERT( (*pp_endpt) );\r
+               CL_ASSERT((*pp_endpt)->h_mcast != NULL);\r
+               (*pp_endpt)->is_in_use = TRUE;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return status;\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+__build_send_desc(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              eth_hdr_t* const                        p_eth_hdr,\r
+       IN                              MDL* const                                      p_mdl,\r
+       IN              const   size_t                                          mdl_len,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc )\r
+{\r
+       NDIS_STATUS                     status;\r
+       int32_t                         hdr_idx;\r
+       uint32_t                        mss;\r
+       //PVOID*                                pp_tmp;\r
+       PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO                      p_checksum_list_info;\r
+       PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO       p_lso_info;\r
+       PERF_DECLARE( SendMgrFilter );\r
+       \r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       /* Format the send descriptor. */\r
+       p_checksum_list_info = NET_BUFFER_LIST_INFO( p_desc->p_netbuf_list,TcpIpChecksumNetBufferListInfo);\r
+       //pp_tmp = &NET_BUFFER_LIST_INFO(p_desc->p_netbuf_list, TcpIpChecksumNetBufferListInfo);\r
+       //p_checksum_list_info =                (   ) ((PULONG)pp_tmp);\r
+       p_lso_info = NET_BUFFER_LIST_INFO( p_desc->p_netbuf_list, TcpLargeSendNetBufferListInfo );\r
+               \r
+       /* Format the send descriptor. */\r
+       hdr_idx = cl_atomic_inc( &p_port->hdr_idx );\r
+       hdr_idx &= (p_port->p_adapter->params.sq_depth - 1);\r
+       ASSERT( hdr_idx < p_port->p_adapter->params.sq_depth );\r
+       p_port->hdr[hdr_idx].type = p_eth_hdr->type;\r
+       p_port->hdr[hdr_idx].resv = 0;\r
+\r
+       p_desc->send_wr[0].local_ds[0].vaddr = cl_get_physaddr( &p_port->hdr[hdr_idx] );\r
+       p_desc->send_wr[0].local_ds[0].length = sizeof(ipoib_hdr_t);\r
+       p_desc->send_wr[0].local_ds[0].lkey = p_port->ib_mgr.lkey;\r
+       p_desc->send_wr[0].wr.send_opt = 0;\r
+\r
+       mss = (p_lso_info->LsoV1Transmit.MSS | p_lso_info->LsoV2Transmit.MSS);\r
+       //TODO: first check params.lso, and thereafter calculate LSO\r
+       if( p_port->p_adapter->params.lso && mss )\r
+\r
+\r
+       {\r
+               ASSERT( mss == (p_lso_info->LsoV1Transmit.MSS & p_lso_info->LsoV2Transmit.MSS));\r
+               ASSERT ( (mss & (1<<20)) == mss);\r
+               status = __build_lso_desc( p_port, p_desc, mss, p_sgl, hdr_idx, p_lso_info );\r
+               if( status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("__build_lso_desc returned 0x%08X.\n", status) );\r
+                       return status;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               uint32_t        i;\r
+               cl_perf_start( SendMgrFilter );\r
+               status = __send_mgr_filter(\r
+               p_port, p_eth_hdr, p_mdl, mdl_len,p_sgl, p_desc );\r
+               cl_perf_stop( &p_port->p_adapter->perf, SendMgrFilter );\r
+               if( status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("__send_mgr_filter returned 0x%08X.\n", status) );\r
+                       return status;\r
+               }\r
+\r
+               if( p_desc->send_dir == SEND_UD_QP )\r
+               {\r
+                       p_desc->send_qp = p_port->ib_mgr.h_qp; // UD QP\r
+                       for( i = 0; i < p_desc->num_wrs; i++ )\r
+                       {\r
+                               p_desc->send_wr[i].wr.dgrm.ud.remote_qp = p_desc->p_endpt->qpn;\r
+                               p_desc->send_wr[i].wr.dgrm.ud.remote_qkey = p_port->ib_mgr.bcast_rec.qkey;\r
+                               p_desc->send_wr[i].wr.dgrm.ud.h_av = p_desc->p_endpt->h_av;\r
+                               p_desc->send_wr[i].wr.dgrm.ud.pkey_index = p_port->pkey_index;\r
+                               p_desc->send_wr[i].wr.dgrm.ud.rsvd = NULL;\r
+                               p_desc->send_wr[i].wr.send_opt = 0;\r
+\r
+                               if( p_port->p_adapter->params.send_chksum_offload && \r
+                                       ( p_checksum_list_info->Transmit.IsIPv4  || \r
+                                       p_checksum_list_info->Transmit.IsIPv6  ))\r
+                               {\r
+                                       // Set transimition checksum offloading \r
+                                       if( p_checksum_list_info->Transmit.IpHeaderChecksum )\r
+                                       {\r
+                                               p_desc->send_wr[i].wr.send_opt |= IB_SEND_OPT_TX_IP_CSUM;\r
+                                       }\r
+                                       if( p_checksum_list_info->Transmit.TcpChecksum )\r
+                                       {\r
+                                               p_desc->send_wr[i].wr.send_opt |= IB_SEND_OPT_TX_TCP_UDP_CSUM;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               else // RC QP\r
+               {\r
+                       CL_ASSERT( p_desc->send_dir == SEND_RC_QP );\r
+                       p_desc->send_qp = p_desc->p_endpt->conn.h_work_qp;\r
+               }\r
+               for( i = 0; i < p_desc->num_wrs; i++ )\r
+               {\r
+                       p_desc->send_wr[i].wr.wr_type = WR_SEND;\r
+                       p_desc->send_wr[i].wr.wr_id = 0;\r
+                       p_desc->send_wr[i].wr.ds_array = &p_desc->send_wr[i].local_ds[0];\r
+                       if( i )\r
+                       {\r
+                               p_desc->send_wr[i-1].wr.p_next = &p_desc->send_wr[i].wr;\r
+                       }\r
+               }\r
+               //TODO p_net_buf or p_buf\r
+//             p_desc->send_wr[p_desc->num_wrs - 1].wr.wr_id = (uintn_t)NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list );\r
+//????         IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("WR_ID was set to NBL 0x%x \n",p_desc->p_netbuf_list ));\r
+               p_desc->send_wr[p_desc->num_wrs - 1].wr.wr_id = (uintn_t)p_desc->p_netbuf_list ;\r
+\r
+               p_desc->send_wr[p_desc->num_wrs - 1].wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
+               p_desc->send_wr[p_desc->num_wrs - 1].wr.p_next = NULL;\r
+       }\r
+\r
+       /* Store context in our reserved area of the packet. */\r
+       IPOIB_PORT_FROM_PACKET( p_desc->p_netbuf_list ) = p_port;\r
+       IPOIB_ENDPT_FROM_PACKET( p_desc->p_netbuf_list ) = p_desc->p_endpt;\r
+       IPOIB_SEND_FROM_NETBUFFER( NET_BUFFER_LIST_FIRST_NB(p_desc->p_netbuf_list ))= p_desc->p_buf;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static NDIS_STATUS\r
+__build_lso_desc(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN      OUT                     ipoib_send_desc_t* const        p_desc,\r
+       IN                              ULONG                                           mss,\r
+       IN                              SCATTER_GATHER_LIST                     *p_sgl,\r
+       IN                              int32_t                                         hdr_idx, \r
+       IN PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO p_lso_info)\r
+{\r
+       NDIS_STATUS                     status;\r
+       LsoData                                                         TheLsoData;\r
+       UINT                                                            IndexOfData = 0;\r
+       \r
+       PNET_BUFFER     FirstBuffer  = NET_BUFFER_LIST_FIRST_NB (p_desc->p_netbuf_list);\r
+       ULONG                   PacketLength = NET_BUFFER_DATA_LENGTH(FirstBuffer);\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+\r
+\r
+       memset(&TheLsoData, 0, sizeof TheLsoData );\r
+       status = GetLsoHeaderSize(\r
+               FirstBuffer, \r
+               &TheLsoData, \r
+               &IndexOfData,\r
+               &p_port->hdr[hdr_idx] );\r
+\r
+       if ((status != NDIS_STATUS_SUCCESS ) || \r
+               (TheLsoData.FullBuffers != TheLsoData.UsedBuffers)) \r
+       {\r
+               ASSERT(FALSE);\r
+\r
+               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("<-- Throwing this packet\n"));\r
+\r
+               if( status == NDIS_STATUS_SUCCESS )\r
+               {\r
+                       status = NDIS_STATUS_INVALID_PACKET;\r
+               }\r
+               return status;\r
+       }\r
+       ASSERT(TheLsoData.LsoHeaderSize> 0);\r
+       // Tell NDIS how much we will send.\r
+       //PktExt->NdisPacketInfo[TcpLargeSendPacketInfo] = UlongToPtr(PacketLength);\r
+       p_lso_info->LsoV1TransmitComplete.TcpPayload = PacketLength;\r
+\r
+       p_desc->send_wr[0].wr.dgrm.ud.mss = mss;\r
+       p_desc->send_wr[0].wr.dgrm.ud.header = TheLsoData.LsoBuffers[0].pData;\r
+       p_desc->send_wr[0].wr.dgrm.ud.hlen = TheLsoData.LsoHeaderSize ;//lso_header_size; \r
+       p_desc->send_wr[0].wr.dgrm.ud.remote_qp = p_desc->p_endpt->qpn;\r
+       p_desc->send_wr[0].wr.dgrm.ud.remote_qkey = p_port->ib_mgr.bcast_rec.qkey;\r
+       p_desc->send_wr[0].wr.dgrm.ud.h_av = p_desc->p_endpt->h_av;\r
+       p_desc->send_wr[0].wr.dgrm.ud.pkey_index = p_port->pkey_index;\r
+       p_desc->send_wr[0].wr.dgrm.ud.rsvd = NULL;\r
+\r
+       //TODO: Should be NBL or p_desc\r
+       p_desc->send_wr[0].wr.wr_id = (uintn_t)p_desc->p_netbuf_list;\r
+       p_desc->send_wr[0].wr.ds_array = p_desc->send_wr[0].local_ds;\r
+       p_desc->send_wr[0].wr.wr_type = WR_LSO;\r
+       p_desc->send_wr[0].wr.send_opt = \r
+               (IB_SEND_OPT_TX_IP_CSUM | IB_SEND_OPT_TX_TCP_UDP_CSUM) | IB_SEND_OPT_SIGNALED;\r
+       \r
+       p_desc->send_wr[0].wr.p_next = NULL;\r
+       p_desc->send_qp = p_port->ib_mgr.h_qp;\r
+       p_desc->send_dir = SEND_UD_QP;\r
+       status = __send_gen(p_port, p_desc, p_sgl, IndexOfData );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return status;\r
+}\r
+\r
+static inline void\r
+__process_failed_send(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_send_desc_t* const        p_desc,\r
+       IN              const   NDIS_STATUS                                     status,\r
+       IN                              ULONG                                           compl_flags)\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       /* Complete the packet. */\r
+       NET_BUFFER_LIST_NEXT_NBL(p_desc->p_netbuf_list) = NULL;\r
+       NET_BUFFER_LIST_STATUS(p_desc->p_netbuf_list) = status;\r
+       NdisMSendNetBufferListsComplete( p_port->p_adapter->h_adapter,\r
+               p_desc->p_netbuf_list, compl_flags );\r
+       ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 );\r
+       /* Deref the endpoint. */\r
+       if( p_desc->p_endpt )\r
+               ipoib_endpt_deref( p_desc->p_endpt );\r
+\r
+       if( p_desc->p_buf )\r
+       {\r
+               NdisFreeToNPagedLookasideList(\r
+                       &p_port->buf_mgr.send_buf_list, p_desc->p_buf );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+// max number of physical fragmented buffers \r
+#define MAX_PHYS_BUF_FRAG_ELEMENTS      0x29\r
+#define MP_FRAG_ELEMENT SCATTER_GATHER_ELEMENT \r
+#define PMP_FRAG_ELEMENT PSCATTER_GATHER_ELEMENT \r
+\r
+\r
+typedef struct _MP_FRAG_LIST {\r
+    ULONG NumberOfElements;\r
+    ULONG_PTR Reserved;\r
+    SCATTER_GATHER_ELEMENT Elements[MAX_PHYS_BUF_FRAG_ELEMENTS];\r
+} MP_FRAG_LIST, *PMP_FRAG_LIST;\r
+\r
+\r
+void \r
+CreateFragList(\r
+    ULONG PhysBufCount,\r
+    PNET_BUFFER NetBuff,\r
+    ULONG PacketLength,\r
+    PMP_FRAG_LIST pFragList\r
+    )\r
+{\r
+//    ETH_ENTER(ETH_SND);\r
+\r
+    ULONG i = 0;\r
+       int j=0;\r
+\r
+    UINT  buf_len = NET_BUFFER_DATA_LENGTH(NetBuff);\r
+    PMDL pMdl = NET_BUFFER_CURRENT_MDL(NetBuff);\r
+\r
+    ULONG CurrentMdlDataOffset = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuff);\r
+    ASSERT(MmGetMdlByteCount(pMdl) >= CurrentMdlDataOffset);\r
+\r
+    \r
+    ASSERT(NetBuff != NULL);\r
+#ifdef DBG\r
+    ASSERT(PhysBufCount <= MAX_PHYS_BUF_FRAG_ELEMENTS);\r
+#else\r
+       UNREFERENCED_PARAMETER(PhysBufCount);\r
+#endif\r
+    \r
+    ASSERT(buf_len > 0);\r
+    UNREFERENCED_PARAMETER(PacketLength);\r
+\r
+\r
+//    ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: NetBuff %p, Length =0x%x\n", NetBuff, buf_len);\r
+\r
+    while ( (pMdl != NULL) && (buf_len != 0) )\r
+    {\r
+        PPFN_NUMBER page_array = MmGetMdlPfnArray(pMdl);\r
+        int MdlBufCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(pMdl), MmGetMdlByteCount(pMdl));\r
+    \r
+        ULONG offset = MmGetMdlByteOffset(pMdl) + CurrentMdlDataOffset ;        \r
+        ULONG MdlBytesCount = MmGetMdlByteCount(pMdl) - CurrentMdlDataOffset;\r
+        CurrentMdlDataOffset = 0;\r
+        \r
+        if( MdlBytesCount == 0 )\r
+        {\r
+            pMdl = pMdl->Next;\r
+            continue;\r
+        }\r
+\r
+        ASSERT( (buf_len > 0) && (MdlBytesCount > 0) );\r
\r
+//        ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: pMdl=%p, MdlBytesCount=x%x, MdlBufCount=0x%x\n", pMdl, MdlBytesCount, MdlBufCount);\r
+\r
+        if (MdlBytesCount > 0)\r
+        {\r
+            if( buf_len > MdlBytesCount)\r
+            {\r
+                buf_len -= MdlBytesCount;    \r
+            }\r
+            else\r
+            {\r
+                MdlBytesCount = buf_len;\r
+                buf_len = 0;                \r
+            }                        \r
+            //\r
+            // In some cases the mdlcount is greater than needed and in the last page\r
+            // there is 0 bytes\r
+            //\r
+            for (j=0; ((j< MdlBufCount) && (MdlBytesCount > 0)); j++) \r
+            {\r
+                ASSERT(MdlBytesCount > 0);\r
+                if (j ==0 ) \r
+                {\r
+                    //\r
+                    // First page\r
+                    //\r
+                    ULONG64 ul64PageNum = page_array[j];\r
+                    pFragList->Elements[i].Address.QuadPart = (ul64PageNum << PAGE_SHIFT)+ offset;\r
+                    if( offset + MdlBytesCount > PAGE_SIZE )\r
+                    {\r
+                        //\r
+                        // the data slides behind the page boundry\r
+                        //\r
+                        ASSERT(PAGE_SIZE > offset);\r
+                        pFragList->Elements[i].Length = PAGE_SIZE - offset;\r
+                        MdlBytesCount -= pFragList->Elements[i].Length;\r
+                    }\r
+                    else\r
+                    {\r
+                        //\r
+                        // All the data is hold in one page\r
+                        //    \r
+                        pFragList->Elements[i].Length = MdlBytesCount;\r
+                        MdlBytesCount = 0;\r
+                    }\r
+\r
+//                    ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: j == 0, MdlBytesCount=x%x, i = %d, element.length=0x%x \n",  MdlBytesCount, i, pFragList->Elements[i].Length);                    \r
+                } \r
+                else \r
+                {\r
+                    if (page_array[j] == (page_array[j-1] + 1))\r
+                    {\r
+                        \r
+                        ULONG size = min(PAGE_SIZE, MdlBytesCount);\r
+                                               i -= 1;\r
+                        pFragList->Elements[i].Length += size;\r
+                        MdlBytesCount -= size;\r
+                    }\r
+                    else \r
+                    {\r
+                        //\r
+                        // Not first page. so the data always start at the begining of the page\r
+                        //\r
+                        ULONG64 ul64PageNum = page_array[j];\r
+                        pFragList->Elements[i].Address.QuadPart = (ul64PageNum << PAGE_SHIFT);\r
+                        pFragList->Elements[i].Length = min(PAGE_SIZE, MdlBytesCount);\r
+                        MdlBytesCount -= pFragList->Elements[i].Length;\r
+                    }\r
+\r
+//                    ETH_PRINT(TRACE_LEVEL_VERBOSE, ETH_SND, "CreateFragList: j != 0, MdlBytesCount=x%x, i = %d, element.length=0x%x \n",  MdlBytesCount, i, pFragList->Elements[i].Length);                    \r
+                }                \r
+                i++;\r
+                ASSERT(i <= MAX_PHYS_BUF_FRAG_ELEMENTS);\r
+            }\r
+        }\r
+\r
+        pMdl = pMdl->Next;\r
+    }\r
+        \r
+    if (buf_len != 0)\r
+    {\r
+        //\r
+        // In some cases the size in MDL isn't equal to the buffer size. In such \r
+        // a case we need to add the rest of packet to last chunk\r
+        //\r
+        ASSERT(i > 0); // To prevent array underflow\r
+        pFragList->Elements[i-1].Length += buf_len;\r
+//        ETH_PRINT(TRACE_LEVEL_ERROR, ETH_SND, "CreateFragList: buf_len != 0, i = %d, element.length=0x%x \n",  i -1, pFragList->Elements[i-1].Length);                    \r
+    }\r
+\r
+    ASSERT(i <= PhysBufCount);\r
+    pFragList->NumberOfElements = i;\r
+\r
+#ifdef DBG\r
+{\r
+    ULONG size = 0;\r
+    for (i  = 0; i <  pFragList->NumberOfElements; ++i)\r
+    {\r
+        size += pFragList->Elements[i].Length;\r
+    }\r
+    ASSERT(size == PacketLength);\r
+}\r
+#endif\r
+\r
+//    ETH_EXIT(ETH_SND);\r
+}\r
+\r
+\r
+\r
+\r
+void\r
+ipoib_port_send(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+    IN  NET_BUFFER_LIST     *p_net_buffer_list,\r
+    IN  ULONG               send_flags)\r
+{\r
+       NDIS_STATUS                     status;\r
+       PNET_BUFFER                     p_netbuf;\r
+       UINT                            buf_cnt = 0;\r
+       //ipoib_send_desc_t     *p_desc;\r
+       ULONG                           send_complete_flags = 0;\r
+       KIRQL                           old_irql;\r
+       PVOID                           p_sgl;\r
+       \r
+       PERF_DECLARE( GetEthHdr );\r
+       PERF_DECLARE( BuildSendDesc );\r
+       PERF_DECLARE( QueuePacket );\r
+       PERF_DECLARE( SendMgrQueue );\r
+       PERF_DECLARE( PostSend );\r
+       PERF_DECLARE( ProcessFailedSends );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+       \r
+       if (NDIS_TEST_SEND_AT_DISPATCH_LEVEL(send_flags))\r
+       {\r
+               //TODO Tzachid: make an assert here to validate your IRQL\r
+               //ASSERT (KeGetCurrentIRQL() == DISPATCH_LEVEL);\r
+               NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
+       } else {\r
+               //ASSERT (KeGetCurrentIRQL() == PASSIVE_LEVEL);\r
+       }\r
+       \r
+       cl_obj_lock( &p_port->obj );\r
+       if( p_port->state != IB_QPS_RTS )\r
+       {\r
+               \r
+               \r
+               cl_obj_unlock( &p_port->obj );\r
+               \r
+               \r
+               NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_FAILURE;\r
+               NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+               ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 );\r
+                       \r
+               NdisMSendNetBufferListsComplete(\r
+                       p_port->p_adapter->h_adapter,\r
+                       p_net_buffer_list,\r
+                       send_complete_flags);  \r
+               \r
+               return;\r
+       }\r
+       cl_obj_unlock( &p_port->obj );\r
+       \r
+       //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+       //                      ("Processing netbuffer list: %x\n", p_net_buffer_list));\r
+       for (p_netbuf = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list);\r
+                p_netbuf != NULL; \r
+                p_netbuf = NET_BUFFER_NEXT_NB(p_netbuf))\r
+       {\r
+               IPOIB_PORT_FROM_PACKET(p_net_buffer_list) = p_port;\r
+               IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_netbuf)  = p_net_buffer_list;\r
+               IPOIB_FROM_QUEUE(p_netbuf) = NULL;\r
+               /*p_desc = &p_port->send_mgr.desc;\r
+               p_desc->p_buf = p_netbuf;\r
+               p_desc->p_endpt = NULL;\r
+               p_desc->p_buf = NULL;\r
+               p_desc->send_qp = NULL;\r
+               p_desc->num_wrs = 1;\r
+               p_desc->send_dir = 0;*/\r
+               \r
+               old_irql = KeGetCurrentIrql();\r
+               if (old_irql < DISPATCH_LEVEL) \r
+               {\r
+                       KeRaiseIrqlToDpcLevel();\r
+               }\r
+               ++buf_cnt;\r
+               //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+               //              ("[%d] Netbuf = %x\n",buf_cnt, p_netbuf) );\r
+               if (cl_is_item_in_qlist( &p_port->send_mgr.pending_list,\r
+                                               IPOIB_LIST_ITEM_FROM_PACKET( p_net_buffer_list ))) {\r
+                               p_sgl = IPOIB_FROM_QUEUE(p_netbuf);     \r
+                               //IPOIB_FROM_QUEUE(p_net_buffer) = (void*)1;\r
+                               ASSERT (p_sgl);                         \r
+                               //IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               //              ("[%d] FROM_QUEUE Netbuf = %x, found SGL = %x\n",buf_cnt, p_netbuf, p_sgl) );\r
+                                status = NDIS_STATUS_SUCCESS;\r
+               } else {\r
+\r
+//#if 0\r
+                       CHAR *pTemp = ExAllocatePoolWithTag(NonPagedPool , p_port->p_adapter->sg_list_size, 'abcd');\r
+                       CL_ASSERT(pTemp != NULL);\r
+                       status = NDIS_STATUS_SUCCESS;\r
+                       p_sgl = pTemp;\r
+                       CreateFragList(NdisQueryNetBufferPhysicalCount(p_netbuf), p_netbuf, NET_BUFFER_DATA_LENGTH(p_netbuf), p_sgl);\r
+                       IPOIB_FROM_QUEUE(p_netbuf) = NULL;\r
+                       /*IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("[%d] Allocation from scratch: Netbuf = %x, found SGL = %x, PhysBufCnt=%ld, NB LEN = %ld, sg_list_size=%ld\n",\r
+                                               buf_cnt, p_netbuf, p_sgl,NdisQueryNetBufferPhysicalCount(p_netbuf) ,\r
+                                               NET_BUFFER_DATA_LENGTH(p_netbuf),p_port->p_adapter->sg_list_size) );\r
+                                               */\r
+                       ipoib_process_sg_list(NULL, NULL, p_sgl, p_netbuf);\r
+                       status = NDIS_STATUS_SUCCESS;\r
+//#endif\r
+#if 0          \r
+                       status = NdisMAllocateNetBufferSGList(\r
+                                                                       p_port->p_adapter->NdisMiniportDmaHandle,\r
+                                                                       p_netbuf,\r
+                                                                       p_netbuf,\r
+                                                                       NDIS_SG_LIST_WRITE_TO_DEVICE,\r
+                                                                       NULL,\r
+                                                                       0);\r
+#endif\r
+               }\r
+               KeLowerIrql (old_irql);\r
+       \r
+               if( status != NDIS_STATUS_SUCCESS )\r
+               {\r
+                       /* fail net buffer list */\r
+                       NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+                       NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_RESOURCES;\r
+                       NdisMSendNetBufferListsComplete(\r
+                               p_port->p_adapter->h_adapter,\r
+                               p_net_buffer_list,\r
+                               send_complete_flags);   \r
+                               break;\r
+               }\r
+               ASSERT(buf_cnt);\r
+               IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(p_net_buffer_list) = (PVOID)(ULONG_PTR)buf_cnt;\r
+       }\r
+       \r
+               /* Post the WR. *\r
+               cl_perf_start( PostSend );\r
+               ib_status =     p_port->p_adapter->p_ifc->post_send( p_desc->send_qp, &p_desc->send_wr[0].wr, &p_wr_failed );\r
+               cl_perf_stop( &p_port->p_adapter->perf, PostSend );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("ib_post_send returned %s\n", \r
+                               p_port->p_adapter->p_ifc->get_err_str( ib_status )) );\r
+                       cl_perf_start( ProcessFailedSends );\r
+                       __process_failed_send( p_port, p_desc, NDIS_STATUS_FAILURE );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, ProcessFailedSends );\r
+                       * Flag the adapter as hung since posting is busted. *\r
+                       p_port->p_adapter->hung = TRUE;\r
+                       continue;\r
+               }\r
+\r
+               cl_atomic_inc( &p_port->send_mgr.depth );\r
+       }\r
+       cl_spinlock_release( &p_port->send_lock );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );*/\r
+}\r
+\r
+\r
+void\r
+ipoib_port_resume(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN boolean_t                                                            b_pending )\r
+{\r
+       NDIS_STATUS                     status;\r
+       cl_list_item_t          *p_item;\r
+       NET_BUFFER                      *p_net_buffer;\r
+       NET_BUFFER_LIST         *p_net_buffer_list;\r
+       //ipoib_send_desc_t     *p_desc;\r
+       KIRQL                           old_irql;\r
+       UINT                            buf_cnt = 0;\r
+       NET_BUFFER_LIST         *p_prev_nbl = NULL;\r
+       PVOID                           p_sgl;\r
+       static PVOID            p_prev_sgl = NULL;\r
+       \r
+       PERF_DECLARE( GetEndpt );\r
+       PERF_DECLARE( BuildSendDesc );\r
+       PERF_DECLARE( ProcessFailedSends );\r
+       PERF_DECLARE( PostSend );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       UNUSED_PARAM(b_pending);\r
+       \r
+       cl_obj_lock( &p_port->obj );\r
+       if( p_port->state != IB_QPS_RTS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+                       ("Invalid state - Aborting.\n") );\r
+               cl_obj_unlock( &p_port->obj );\r
+               return;\r
+       }\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+//TODO NDIS60\r
+////??????????????     cl_spinlock_acquire( &p_port->send_lock );\r
+\r
+       for( p_item = cl_qlist_head( &p_port->send_mgr.pending_list );\r
+               p_item != cl_qlist_end( &p_port->send_mgr.pending_list );\r
+               p_item = cl_qlist_head( &p_port->send_mgr.pending_list ) )\r
+       {\r
+               \r
+               \r
+               /* Check the send queue and pend the request if not empty. */\r
+               if( p_port->send_mgr.depth == p_port->p_adapter->params.sq_depth )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_SEND,\r
+                               ("No available WQEs.\n") );\r
+                       break;\r
+               }\r
+               \r
+               p_net_buffer_list = IPOIB_PACKET_FROM_LIST_ITEM(\r
+                       cl_qlist_remove_head( &p_port->send_mgr.pending_list ) );\r
+               if (p_prev_nbl == p_net_buffer_list) {\r
+//                     IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+       //                      ("TRYING TO PROCESS ONCE AGAIN, EXITING: %x\n", p_net_buffer_list));\r
+                       break; //TODO more sophisticated mechanism to avoid starvation\r
+               }\r
+               old_irql = KeGetCurrentIrql();\r
+               if (old_irql < DISPATCH_LEVEL) \r
+               {\r
+                       KeRaiseIrqlToDpcLevel();\r
+               }\r
+//             IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+       //              ("Processing netbuffer list from queue: %x\n", (UINT) (PVOID) p_net_buffer_list));\r
+               \r
+               for( p_net_buffer = NET_BUFFER_LIST_FIRST_NB(p_net_buffer_list);\r
+                        p_net_buffer != NULL;\r
+                        p_net_buffer = NET_BUFFER_NEXT_NB(p_net_buffer), buf_cnt++)\r
+                               {\r
+\r
+                       \r
+                       p_sgl = IPOIB_FROM_QUEUE(p_net_buffer); \r
+                       //IPOIB_FROM_QUEUE(p_net_buffer) = (void*)1;\r
+                       ASSERT (p_sgl);\r
+                       IPOIB_PORT_FROM_PACKET(p_net_buffer_list) = p_port;\r
+                       IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER(p_net_buffer)  = p_net_buffer_list;\r
+                       /*p_desc = &p_port->send_mgr.desc;\r
+                       p_desc->p_buf = p_net_buffer;\r
+                       p_desc->p_endpt = NULL;\r
+                       p_desc->p_buf = NULL;\r
+                       p_desc->send_qp = NULL;\r
+                       p_desc->num_wrs = 1;\r
+                       p_desc->send_dir = 0;*/\r
+\r
+//                     IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+       //                      ("[%d] Netbuf = %x, p_sgl = %x\n",buf_cnt, p_net_buffer, p_sgl) );\r
+                       ASSERT(p_sgl);\r
+                       if (p_sgl != (void*) 1) {\r
+                               ipoib_process_sg_list(NULL, NULL, p_sgl, p_net_buffer);\r
+                               status = NDIS_STATUS_SUCCESS;\r
+                       }\r
+                       else {\r
+                               ASSERT(FALSE);\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Getting strange flow\n") );\r
+                               NdisMFreeNetBufferSGList(\r
+                                                                       p_port->p_adapter->NdisMiniportDmaHandle,\r
+                                                                       p_sgl,\r
+                                                                       p_net_buffer );\r
+                               status = NdisMAllocateNetBufferSGList(\r
+                                                                       p_port->p_adapter->NdisMiniportDmaHandle,\r
+                                                                       p_net_buffer,\r
+                                                                       p_net_buffer,\r
+                                                                       NDIS_SG_LIST_WRITE_TO_DEVICE,\r
+                                                                       NULL,\r
+                                                                       0 /*p_port->p_adapter->sg_list_size*/ );\r
+                       }\r
+                       p_prev_sgl = p_sgl;             \r
+                       if( status != NDIS_STATUS_SUCCESS )\r
+                       {\r
+                               /* fail net buffer list */\r
+                               NET_BUFFER_LIST_NEXT_NBL(p_net_buffer_list) = NULL;\r
+                               NET_BUFFER_LIST_STATUS(p_net_buffer_list) = NDIS_STATUS_RESOURCES;\r
+                               NdisMSendNetBufferListsComplete(\r
+                                       p_port->p_adapter->h_adapter,\r
+                                       p_net_buffer_list,\r
+                                       0);     \r
+                               break;\r
+                       }\r
+               }\r
+                        \r
+               KeLowerIrql (old_irql);\r
+               \r
+               \r
+               p_prev_nbl = p_net_buffer_list;\r
+               \r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+\r
+\r
+static void\r
+__send_cb(\r
+       IN              const   ib_cq_handle_t                          h_cq,\r
+       IN                              void                                            *cq_context )\r
+{\r
+       ipoib_port_t            *p_port;\r
+       ib_api_status_t         status;\r
+       ib_wc_t                         wc[MAX_SEND_WC], *p_wc, *p_free;\r
+       cl_qlist_t                      done_list;\r
+       NET_BUFFER_LIST         *p_nbl;\r
+       uint32_t                        length;\r
+       ipoib_endpt_t           *p_endpt;\r
+       send_buf_t                      *p_send_buf;\r
+       ip_stat_sel_t           type;\r
+       size_t                          i;\r
+       NET_BUFFER                      *p_netbuffer = NULL;\r
+\r
+       PERF_DECLARE( SendCompBundle );\r
+       PERF_DECLARE( SendCb );\r
+       PERF_DECLARE( PollSend );\r
+       PERF_DECLARE( SendComp );\r
+       PERF_DECLARE( FreeSendBuf );\r
+       PERF_DECLARE( RearmSend );\r
+       PERF_DECLARE( PortResume );\r
+//return;//???????????\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       cl_perf_clr( SendCompBundle );\r
+\r
+       cl_perf_start( SendCb );\r
+\r
+       UNUSED_PARAM( h_cq );\r
+\r
+       cl_qlist_init( &done_list );\r
+\r
+       p_port = (ipoib_port_t*)cq_context;\r
+\r
+       ipoib_port_ref( p_port, ref_send_cb );\r
+\r
+       for( i = 0; i < MAX_SEND_WC; i++ )\r
+               wc[i].p_next = &wc[i + 1];\r
+       wc[MAX_SEND_WC - 1].p_next = NULL;\r
+\r
+       do\r
+       {\r
+               p_free = wc;\r
+               cl_perf_start( PollSend );\r
+               status = p_port->p_adapter->p_ifc->poll_cq( p_port->ib_mgr.h_send_cq, &p_free, &p_wc );\r
+               cl_perf_stop( &p_port->p_adapter->perf, PollSend );\r
+               CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND );\r
+\r
+               while( p_wc )\r
+               {\r
+                       cl_perf_start( SendComp );\r
+                       CL_ASSERT( p_wc->status != IB_WCS_SUCCESS || p_wc->wc_type == IB_WC_SEND );\r
+                       p_nbl = (NET_BUFFER_LIST*)(uintn_t)p_wc->wr_id;\r
+                       //IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_SEND,\r
+                       //("[1]Successfull send completion for NBL=0x%x .\n", (UINT) (PVOID) p_nbl ));\r
+                       CL_ASSERT( p_nbl );\r
+                       CL_ASSERT( IPOIB_PORT_FROM_PACKET( p_nbl ) == p_port );\r
+                       length = 0;\r
+                       p_endpt = IPOIB_ENDPT_FROM_PACKET( p_nbl );\r
+                       p_send_buf = IPOIB_SEND_FROM_NETBUFFER( NET_BUFFER_LIST_FIRST_NB (p_nbl ));\r
+                       \r
+                       switch( p_wc->status )\r
+                       {\r
+                       case IB_WCS_SUCCESS:\r
+                               if( p_endpt->h_mcast )\r
+                               {\r
+                                       if( p_endpt->dgid.multicast.raw_group_id[11] == 0xFF &&\r
+                                               p_endpt->dgid.multicast.raw_group_id[10] == 0xFF &&\r
+                                               p_endpt->dgid.multicast.raw_group_id[12] == 0xFF &&\r
+                                               p_endpt->dgid.multicast.raw_group_id[13] == 0xFF )\r
+                                       {\r
+                                               type = IP_STAT_BCAST_BYTES;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               type = IP_STAT_MCAST_BYTES;\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       type = IP_STAT_UCAST_BYTES;\r
+                               }\r
+                               for (p_netbuffer = NET_BUFFER_LIST_FIRST_NB(p_nbl);\r
+                                        p_netbuffer != NULL;\r
+                                        p_netbuffer = NET_BUFFER_NEXT_NB(p_netbuffer))\r
+                               {\r
+                                        length += NET_BUFFER_DATA_LENGTH(p_netbuffer);\r
+                               }                       \r
+                               ipoib_inc_send_stat( p_port->p_adapter, type, length );\r
+                               //      IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_SEND,\r
+                                       //("Successfull send completion for NBL=0x%x .\n", (UINT) (PVOID) p_nbl) );\r
+                               NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_SUCCESS;\r
+                               IPOIB_DEC_NET_BUFFER_LIST_REF_COUNT(p_nbl);\r
+                               if (IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(p_nbl) == 0)\r
+                                       NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter,\r
+                                                                                               p_nbl,\r
+                                                                                               0);\r
+                               break;\r
+\r
+                       case IB_WCS_WR_FLUSHED_ERR:\r
+                               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_SEND,\r
+                                       ("Flushed send completion.\n") );\r
+                                       ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_DROPPED, 0 );\r
+                               NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_RESET_IN_PROGRESS;\r
+                               NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter,\r
+                                                                                               p_nbl,\r
+                                                                                               0);   \r
+                               break;\r
+\r
+                       default:\r
+                               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                       ("Send failed with %s (vendor specific %#x)\n",\r
+                                       p_port->p_adapter->p_ifc->get_wc_status_str( p_wc->status ),\r
+                                       (int)p_wc->vendor_specific) );\r
+                                       ipoib_inc_send_stat( p_port->p_adapter, IP_STAT_ERROR, 0 );\r
+                               NET_BUFFER_LIST_STATUS(p_nbl) = NDIS_STATUS_FAILURE;\r
+                               NdisMSendNetBufferListsComplete(p_port->p_adapter->h_adapter,\r
+                                                                                               p_nbl,\r
+                                                                                               0);  \r
+                               break;\r
+                       }\r
+                       cl_perf_stop( &p_port->p_adapter->perf, SendComp );\r
+                       /* Dereference the enpoint used for the transfer. */\r
+                       ipoib_endpt_deref( p_endpt );\r
+\r
+                       if( p_send_buf )\r
+                       {\r
+                               cl_perf_start( FreeSendBuf );\r
+                               NdisFreeToNPagedLookasideList( &p_port->buf_mgr.send_buf_list,\r
+                                       p_send_buf );\r
+                       cl_perf_stop( &p_port->p_adapter->perf, FreeSendBuf );\r
+                       }\r
+\r
+                       cl_atomic_dec( &p_port->send_mgr.depth );\r
+\r
+                       p_wc = p_wc->p_next;\r
+                       cl_perf_inc( SendCompBundle );\r
+               }\r
+               /* If we didn't use up every WC, break out. */\r
+       } while( !p_free );\r
+\r
+       /* Rearm the CQ. */\r
+       cl_perf_start( RearmSend );\r
+       status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_send_cq, FALSE );\r
+       cl_perf_stop( &p_port->p_adapter->perf, RearmSend );\r
+       CL_ASSERT( status == IB_SUCCESS );\r
+\r
+       /* Resume any sends awaiting resources. */\r
+       cl_perf_start( PortResume );\r
+       ipoib_port_resume( p_port, TRUE );\r
+       cl_perf_stop( &p_port->p_adapter->perf, PortResume );\r
+       \r
+       ipoib_port_deref( p_port, ref_send_cb );\r
+\r
+       cl_perf_stop( &p_port->p_adapter->perf, SendCb );\r
+       cl_perf_update_ctr( &p_port->p_adapter->perf, SendCompBundle );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+\r
+/******************************************************************************\r
+*\r
+* Endpoint manager implementation\r
+*\r
+******************************************************************************/\r
+static void\r
+__endpt_mgr_construct(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       cl_qmap_init( &p_port->endpt_mgr.mac_endpts );\r
+       cl_qmap_init( &p_port->endpt_mgr.lid_endpts );\r
+       cl_fmap_init( &p_port->endpt_mgr.gid_endpts, __gid_cmp );\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+static void\r
+__endpt_cm_mgr_thread(\r
+IN             void*           p_context );\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_init(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+#if 0\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               cl_fmap_init( &p_port->endpt_mgr.conn_endpts, __gid_cmp );\r
+               \r
+               NdisInitializeListHead( &p_port->endpt_mgr.pending_conns );\r
+               NdisAllocateSpinLock( &p_port->endpt_mgr.conn_lock );\r
+               cl_event_init( &p_port->endpt_mgr.event, FALSE );\r
+       \r
+               NdisInitializeListHead( &p_port->endpt_mgr.remove_conns );\r
+               NdisAllocateSpinLock( &p_port->endpt_mgr.remove_lock );\r
+\r
+               cl_thread_init( &p_port->endpt_mgr.h_thread, \r
+                                               __endpt_cm_mgr_thread,\r
+                                               ( const void *)p_port, \r
+                                               "CmEndPtMgr" );\r
+       }\r
+#endif\r
+       UNUSED_PARAM(p_port);\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+static void\r
+__endpt_cm_mgr_thread(\r
+IN             void*           p_context )\r
+{\r
+       ib_api_status_t ib_status;\r
+       LIST_ENTRY              *p_item;\r
+       ipoib_endpt_t   *p_endpt;\r
+       ipoib_port_t    *p_port =( ipoib_port_t *)p_context;\r
+       \r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, \r
+               ("Starting Port [%d] Endpt CM thread \n", p_port->port_num ) );\r
+\r
+       while( !p_port->endpt_mgr.thread_is_done )\r
+       {\r
+               cl_event_wait_on( &p_port->endpt_mgr.event, EVENT_NO_TIMEOUT, FALSE );\r
+       \r
+               while( ( p_item = NdisInterlockedRemoveHeadList( \r
+                                                               &p_port->endpt_mgr.pending_conns,\r
+                                                               &p_port->endpt_mgr.conn_lock) ) != NULL )\r
+               {\r
+\r
+                       p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, list_item );\r
+                       if( p_port->endpt_mgr.thread_is_done )\r
+                       {\r
+                               endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED );\r
+                               continue;\r
+                       }\r
+\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                               ("Endpt[%p] CONNECT REQ to MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+                               p_endpt,\r
+                               p_endpt->mac.addr[0], p_endpt->mac.addr[1],\r
+                               p_endpt->mac.addr[2], p_endpt->mac.addr[3],\r
+                               p_endpt->mac.addr[4], p_endpt->mac.addr[5] ) );\r
+                       \r
+                       if( !p_endpt->conn.h_send_qp )\r
+                       {\r
+                               ib_status = endpt_cm_create_qp( p_endpt, &p_endpt->conn.h_send_qp );\r
+                               if( ib_status != IB_SUCCESS )\r
+                               {\r
+                                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                               ("Endpt [%p ] CM create QP failed status %#x\n", p_endpt, ib_status ) );\r
+                               }\r
+                               else\r
+                               {\r
+                                       ib_status = ipoib_endpt_connect( p_endpt );\r
+                                       if( ib_status != IB_SUCCESS && ib_status != IB_PENDING )\r
+                                       {\r
+                                               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                                                       ("Endpt [ %p ] conn REQ failed status %#x\n", p_endpt, ib_status ) );\r
+                                       }\r
+                               }\r
+                               if( ib_status != IB_SUCCESS && ib_status != IB_PENDING )\r
+                               {\r
+                                       endpt_cm_set_state( p_endpt, IPOIB_CM_DESTROY );\r
+                                       endpt_cm_flush_recv( p_port, p_endpt );\r
+                                       endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED );\r
+                               }\r
+                       }\r
+\r
+               }//while( p_item != NULL )\r
+\r
+               while( ( p_item = NdisInterlockedRemoveHeadList(\r
+                                                               &p_port->endpt_mgr.remove_conns,\r
+                                                               &p_port->endpt_mgr.remove_lock ) ) != NULL )\r
+               {\r
+                       p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, list_item );\r
+\r
+                       endpt_cm_set_state( p_endpt, IPOIB_CM_DESTROY );\r
+\r
+                       IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,\r
+                               ("\nDESTROYING Endpt[%p]  MAC %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+                               p_endpt,\r
+                               p_endpt->mac.addr[0], p_endpt->mac.addr[1],\r
+                               p_endpt->mac.addr[2], p_endpt->mac.addr[3],\r
+                               p_endpt->mac.addr[4], p_endpt->mac.addr[5] ) );\r
+                       endpt_cm_flush_recv( p_port, p_endpt );\r
+                       endpt_cm_set_state( p_endpt, IPOIB_CM_DISCONNECTED );\r
+                       cl_obj_destroy( &p_endpt->obj );\r
+               }\r
+       }\r
+\r
+       p_port->endpt_mgr.thread_is_done++;\r
+       NdisFreeSpinLock( &p_port->endpt_mgr.conn_lock );\r
+       \r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, \r
+               (" Port [%d] Endpt thread is done\n", p_port->port_num ) );\r
+}\r
+\r
+static void\r
+__endpt_mgr_destroy(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       CL_ASSERT( cl_is_qmap_empty( &p_port->endpt_mgr.mac_endpts ) );\r
+       CL_ASSERT( cl_is_qmap_empty( &p_port->endpt_mgr.lid_endpts ) );\r
+       CL_ASSERT( cl_is_fmap_empty( &p_port->endpt_mgr.gid_endpts ) );\r
+       UNUSED_PARAM(p_port);\r
+#if 0\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               CL_ASSERT( cl_is_fmap_empty( &p_port->endpt_mgr.conn_endpts ) );\r
+       }\r
+#endif\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__endpt_mgr_remove_all(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+       \r
+       cl_obj_lock( &p_port->obj );\r
+       /* Wait for all readers to complete. */\r
+       while( p_port->endpt_rdr )\r
+               ;\r
+       /*\r
+        * We don't need to initiate destruction - this is called only\r
+        * from the __port_destroying function, and destruction cascades\r
+        * to all child objects.  Just clear all the maps.\r
+        */\r
+       cl_qmap_remove_all( &p_port->endpt_mgr.mac_endpts );\r
+       cl_qmap_remove_all( &p_port->endpt_mgr.lid_endpts );\r
+       cl_fmap_remove_all( &p_port->endpt_mgr.gid_endpts );\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+static void\r
+__endpt_mgr_reset_all(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       cl_map_item_t                   *p_item;\r
+       cl_fmap_item_t                  *p_fmap_item;\r
+       ipoib_endpt_t                   *p_endpt;\r
+       cl_qlist_t                              mc_list;\r
+       cl_qlist_t                              conn_list;\r
+       uint32_t                                local_exist = 0;\r
+       NDIS_LINK_STATE                 link_state;\r
+       NDIS_STATUS_INDICATION  status_indication;\r
+\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       cl_qlist_init( &mc_list );\r
+       cl_qlist_init( &conn_list );\r
+//???  cl_obj_lock( &p_port->obj );\r
+       /* Wait for all readers to complete. */\r
+       while( p_port->endpt_rdr )\r
+               ;\r
+\r
+#if 0\r
+                       __endpt_mgr_remove_all(p_port);\r
+#else\r
+                       link_state.Header.Revision = NDIS_LINK_STATE_REVISION_1;\r
+                       link_state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\r
+                       link_state.Header.Size = sizeof(NDIS_LINK_STATE);\r
+                       link_state.MediaConnectState = MediaConnectStateDisconnected;\r
+                       link_state.MediaDuplexState = MediaDuplexStateFull;\r
+                       link_state.XmitLinkSpeed = link_state.RcvLinkSpeed = IPOIB_MEDIA_MAX_SPEED;\r
+\r
+                       IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                                               p_port->p_adapter->h_adapter,\r
+                                                               NDIS_STATUS_LINK_STATE,\r
+                                                               (PVOID)&link_state,\r
+                                                               sizeof(link_state));\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate DISCONNECT!\n") );\r
+                       NdisMIndicateStatusEx(p_port->p_adapter->h_adapter,&status_indication);\r
+                       \r
+                       link_state.MediaConnectState = MediaConnectStateConnected;\r
+                       IPOIB_INIT_NDIS_STATUS_INDICATION(&status_indication,\r
+                                                               p_port->p_adapter->h_adapter,\r
+                                                               NDIS_STATUS_LINK_STATE,\r
+                                                               (PVOID)&link_state,\r
+                                                               sizeof(link_state));\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT, ("Indicate Connect\n") );\r
+                       NdisMIndicateStatusEx(p_port->p_adapter->h_adapter,&status_indication);\r
+\r
+               \r
+                               //      IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                                       //      ("Link DOWN!\n") );\r
+\r
+       if( p_port->p_local_endpt )\r
+       {\r
+               //TODO: CM RESTORE\r
+               //ipoib_port_cancel_listen( p_port, p_port->p_local_endpt );\r
+\r
+               cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+                       &p_port->p_local_endpt->gid_item );\r
+               cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+                       &p_port->p_local_endpt->mac_item );\r
+               cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+                       &p_port->p_local_endpt->lid_item );\r
+               \r
+               cl_qlist_insert_head(\r
+                       &mc_list, &p_port->p_local_endpt->mac_item.pool_item.list_item );\r
+               local_exist = 1;\r
+\r
+               p_port->p_local_endpt = NULL;\r
+       }\r
+\r
+       p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts );\r
+       while( p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+       {\r
+               p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+               p_item = cl_qmap_next( p_item );\r
+               if( p_endpt->h_mcast )\r
+               {\r
+                       /*\r
+                        * We destroy MC endpoints since they will get recreated\r
+                        * when the port comes back up and we rejoin the MC groups.\r
+                        */\r
+                       cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+                               &p_endpt->mac_item );\r
+                       cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+                               &p_endpt->gid_item );\r
+\r
+                       cl_qlist_insert_tail(\r
+                               &mc_list, &p_endpt->mac_item.pool_item.list_item );\r
+               }\r
+               /* destroy connected endpoints if any */\r
+               else if( p_port->p_adapter->params.cm_enabled &&\r
+                                endpt_cm_get_state( p_endpt ) != IPOIB_CM_DISCONNECTED )\r
+               {\r
+                       p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid );\r
+                       if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) )\r
+                       {\r
+                               cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, \r
+                                       &p_endpt->conn_item );\r
+                       }\r
+                       cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+                               &p_endpt->mac_item );\r
+                       cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+                               &p_endpt->gid_item );\r
+\r
+                       cl_qlist_insert_tail(\r
+                               &conn_list, &p_endpt->mac_item.pool_item.list_item );\r
+               }\r
+               if( p_endpt->h_av )\r
+               {\r
+                       /* Destroy the AV for all other endpoints. */\r
+                       p_port->p_adapter->p_ifc->destroy_av( p_endpt->h_av );\r
+                       p_endpt->h_av = NULL;\r
+               }\r
+               \r
+               if( p_endpt->dlid )\r
+               {\r
+                       cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+                               &p_endpt->lid_item );\r
+                       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+                               ("<__endptr_mgr_reset_all: setting p_endpt->dlid to 0\n"));\r
+                       p_endpt->dlid = 0;\r
+               }\r
+               \r
+       }\r
+#endif\r
+//???  cl_obj_unlock( &p_port->obj );\r
+\r
+       //TODO CM\r
+       /*while( cl_qlist_count( &conn_list ) )\r
+       {\r
+               endpt_cm_destroy_conn( p_port,\r
+                       PARENT_STRUCT( cl_qlist_remove_head( &conn_list ),\r
+                       ipoib_endpt_t, mac_item.pool_item.list_item ) );\r
+       }*/\r
+\r
+       if(cl_qlist_count( &mc_list ) - local_exist)\r
+       {\r
+               p_port->mcast_cnt =  (uint32_t)cl_qlist_count( &mc_list ) - local_exist;\r
+       }\r
+       else\r
+       {\r
+               p_port->mcast_cnt = 0;\r
+               KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE );\r
+       }       \r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt - local_exist));\r
+\r
+       /* Destroy all multicast endpoints now that we have released the lock. */\r
+       while( cl_qlist_count( &mc_list ) )\r
+       {\r
+               cl_list_item_t  *p_item;\r
+               p_item = cl_qlist_remove_head( &mc_list );\r
+               p_endpt = PARENT_STRUCT(p_item, ipoib_endpt_t, mac_item.pool_item.list_item);\r
+               cl_obj_destroy( &p_endpt->obj);\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+/*\r
+ * Called when updating an endpoint entry in response to an ARP.\r
+ * Because receive processing is serialized, and holds a reference\r
+ * on the endpoint reader, we wait for all *other* readers to exit before\r
+ * removing the item.\r
+ */\r
+static void\r
+__endpt_mgr_remove(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+#if 0 //CM\r
+       cl_fmap_item_t* p_fmap_item;\r
+#endif \r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       /* This function must be called from the receive path */\r
+       CL_ASSERT(p_port->endpt_rdr > 0);\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+       /* Wait for all readers to complete. */    \r
+       while( p_port->endpt_rdr > 1 )\r
+               ;\r
+\r
+       /* Remove the endpoint from the maps so further requests don't find it. */\r
+       cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts, &p_endpt->mac_item );\r
+       /*\r
+        * The enpoints are *ALWAYS* in both the MAC and GID maps.  They are only\r
+        * in the LID map if the GID has the same subnet prefix as us.\r
+        */\r
+       cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts, &p_endpt->gid_item );\r
+#if 0\r
+\r
+       if( p_port->p_adapter->params.cm_enabled )\r
+       {\r
+               p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid );\r
+               \r
+               if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) )\r
+               {\r
+                       cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, \r
+                               &p_endpt->conn_item );\r
+               }\r
+       }\r
+#endif \r
+       if( p_endpt->dlid )\r
+       {\r
+               cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+                       &p_endpt->lid_item );\r
+       }\r
+\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       //TODO CM\r
+       //endpt_cm_destroy_conn( p_port, p_endpt );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+\r
+NTSTATUS\r
+ipoib_mac_to_gid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ib_gid_t*                                       p_gid )\r
+{\r
+       ipoib_endpt_t*  p_endpt;\r
+       cl_map_item_t   *p_item;\r
+       uint64_t                key = 0;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+\r
+       p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
+       if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed endpoint lookup.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+       *p_gid = p_endpt->dgid;\r
+\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+NTSTATUS\r
+ipoib_mac_to_path(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ib_path_rec_t*                          p_path )\r
+{\r
+       ipoib_endpt_t*  p_endpt;\r
+       cl_map_item_t   *p_item;\r
+       uint64_t                key = 0;\r
+       uint8_t                 sl;\r
+       net32_t                 flow_lbl;\r
+       uint8_t                 hop_limit;\r
+       uint8_t                 pkt_life;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+\r
+       if( p_port->p_local_endpt == NULL )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("No local endpoint.\n") );\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       if( mac.addr[0] == 0 && mac.addr[1] == 0 && mac.addr[2] == 0 &&\r
+               mac.addr[3] == 0 && mac.addr[4] == 0 && mac.addr[5] == 0 )\r
+       {\r
+               p_endpt = p_port->p_local_endpt;\r
+       }\r
+       else\r
+       {\r
+               p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
+               if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+               {\r
+                       cl_obj_unlock( &p_port->obj );\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed endpoint lookup.\n") );\r
+                       return STATUS_INVALID_PARAMETER;\r
+               }\r
+\r
+               p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+       }\r
+\r
+       p_path->service_id = 0;\r
+       p_path->dgid = p_endpt->dgid;\r
+       p_path->sgid = p_port->p_local_endpt->dgid;\r
+       p_path->dlid = p_endpt->dlid;\r
+       p_path->slid = p_port->p_local_endpt->dlid;\r
+\r
+       ib_member_get_sl_flow_hop(\r
+               p_port->ib_mgr.bcast_rec.sl_flow_hop,\r
+               &sl,\r
+               &flow_lbl,\r
+               &hop_limit\r
+               );\r
+       \r
+       if( p_path->slid == p_path->dlid )\r
+               pkt_life = 0;\r
+       else\r
+               pkt_life = p_port->ib_mgr.bcast_rec.pkt_life;\r
+\r
+       ib_path_rec_init_local(\r
+               p_path,\r
+               &p_endpt->dgid,\r
+               &p_port->p_local_endpt->dgid,\r
+               p_endpt->dlid,\r
+               p_port->p_local_endpt->dlid,\r
+               1,\r
+               p_port->ib_mgr.bcast_rec.pkey,\r
+               sl, 0,\r
+               IB_PATH_SELECTOR_EXACTLY, p_port->ib_mgr.bcast_rec.mtu,\r
+               IB_PATH_SELECTOR_EXACTLY, p_port->ib_mgr.bcast_rec.rate,\r
+               IB_PATH_SELECTOR_EXACTLY, pkt_life,\r
+               0 );\r
+\r
+       /* Set global routing information. */\r
+       ib_path_rec_set_hop_flow_raw( p_path, hop_limit, flow_lbl, FALSE );\r
+       p_path->tclass = p_port->ib_mgr.bcast_rec.tclass;\r
\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static inline NDIS_STATUS\r
+__endpt_mgr_ref(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ipoib_endpt_t** const           pp_endpt )\r
+{\r
+       NDIS_STATUS             status;\r
+       cl_map_item_t   *p_item;\r
+       uint64_t                key;\r
+\r
+       PERF_DECLARE( EndptQueue );\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       if( !cl_memcmp( &mac, &p_port->p_adapter->params.conf_mac, sizeof(mac) ) )\r
+       {\r
+               /* Discard loopback traffic. */\r
+               IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_ENDPT,\r
+                       ("Discarding loopback traffic\n") );\r
+               IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+               return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;\r
+       }\r
+\r
+       key = 0;\r
+       cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_ENDPT,\r
+               ("Look for :\t  MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+               mac.addr[0], mac.addr[1], mac.addr[2],\r
+               mac.addr[3], mac.addr[4], mac.addr[5]) );\r
+\r
+       p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
+       if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+                       ("Failed endpoint lookup.\n") );\r
+               return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;\r
+       }\r
+\r
+       *pp_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+       ipoib_endpt_ref( *pp_endpt );\r
+\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       cl_perf_start( EndptQueue );\r
+       status = ipoib_endpt_queue( *pp_endpt );\r
+       cl_perf_stop( &p_port->p_adapter->perf, EndptQueue );\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+               *pp_endpt = NULL;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return status;\r
+}\r
+\r
+\r
+static inline NDIS_STATUS\r
+__endpt_mgr_get_gid_qpn(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ib_gid_t* const                         p_gid,\r
+               OUT                     UNALIGNED net32_t* const        p_qpn )\r
+{\r
+       UNALIGNED\r
+       cl_map_item_t   *p_item;\r
+       ipoib_endpt_t   *p_endpt;\r
+       uint64_t                key;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+\r
+       key = 0;\r
+       cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+       p_item = cl_qmap_get( &p_port->endpt_mgr.mac_endpts, key );\r
+       if( p_item == cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+                       ("Failed endpoint lookup.\n") );\r
+               return NDIS_STATUS_FAILURE;\r
+       }\r
+\r
+       p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+\r
+       *p_gid = p_endpt->dgid;\r
+       *p_qpn = p_endpt->qpn;\r
+\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+static inline ipoib_endpt_t*\r
+__endpt_mgr_get_by_gid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ib_gid_t* const                         p_gid )\r
+{\r
+       cl_fmap_item_t  *p_item;\r
+       ipoib_endpt_t   *p_endpt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       p_item = cl_fmap_get( &p_port->endpt_mgr.gid_endpts, p_gid );\r
+       if( p_item == cl_fmap_end( &p_port->endpt_mgr.gid_endpts ) )\r
+               p_endpt = NULL;\r
+       else\r
+               p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, gid_item );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return p_endpt;\r
+}\r
+\r
+\r
+static ipoib_endpt_t*\r
+__endpt_mgr_get_by_lid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   net16_t                                         lid )\r
+{\r
+       cl_map_item_t   *p_item;\r
+       ipoib_endpt_t   *p_endpt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       p_item = cl_qmap_get( &p_port->endpt_mgr.lid_endpts, lid );\r
+       if( p_item == cl_qmap_end( &p_port->endpt_mgr.lid_endpts ) )\r
+               p_endpt = NULL;\r
+       else\r
+               p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, lid_item );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return p_endpt;\r
+}\r
+\r
+\r
+inline ib_api_status_t\r
+__endpt_mgr_insert_locked(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       ib_api_status_t status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+               ("insert  :\t  MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",\r
+               mac.addr[0], mac.addr[1], mac.addr[2],\r
+               mac.addr[3], mac.addr[4], mac.addr[5]) );\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+       while( p_port->endpt_rdr )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               cl_obj_lock( &p_port->obj );\r
+       }\r
+       /* __endpt_mgr_insert expects *one* reference to be held when being called. */\r
+       cl_atomic_inc( &p_port->endpt_rdr );\r
+       status= __endpt_mgr_insert( p_port, mac, p_endpt );\r
+       cl_atomic_dec( &p_port->endpt_rdr );\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       return status;\r
+}\r
+\r
+\r
+inline ib_api_status_t\r
+__endpt_mgr_insert(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+       IN                              ipoib_endpt_t* const            p_endpt )\r
+{\r
+       uint64_t                key;\r
+       cl_status_t             cl_status;\r
+       cl_map_item_t   *p_qitem;\r
+       cl_fmap_item_t  *p_fitem;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       /* Wait for all accesses to the map to complete. */\r
+       while( p_port->endpt_rdr > 1 )\r
+               ;\r
+\r
+       /* Link the endpoint to the port. */\r
+       cl_status = cl_obj_insert_rel_parent_locked(\r
+               &p_endpt->rel, &p_port->obj, &p_endpt->obj );\r
+\r
+       if( cl_status != CL_SUCCESS )\r
+       {\r
+               cl_obj_destroy( &p_endpt->obj );\r
+               return IB_INVALID_STATE;\r
+       }\r
+\r
+#if DBG\r
+       cl_atomic_inc( &p_port->ref[ref_endpt_track] );\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OBJ,\r
+               ("ref  type %d ref_cnt %d\n", ref_endpt_track, p_port->obj.ref_cnt) );\r
+#endif\r
+\r
+       p_endpt->mac = mac;\r
+       key = 0;\r
+       cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+       p_qitem = cl_qmap_insert(\r
+               &p_port->endpt_mgr.mac_endpts, key, &p_endpt->mac_item );\r
+       CL_ASSERT( p_qitem == &p_endpt->mac_item );\r
+       p_fitem = cl_fmap_insert(\r
+               &p_port->endpt_mgr.gid_endpts, &p_endpt->dgid, &p_endpt->gid_item );\r
+       CL_ASSERT( p_fitem == &p_endpt->gid_item );\r
+       if( p_endpt->dlid )\r
+       {\r
+               p_qitem = cl_qmap_insert(\r
+                       &p_port->endpt_mgr.lid_endpts, p_endpt->dlid, &p_endpt->lid_item );\r
+               CL_ASSERT( p_qitem == &p_endpt->lid_item );\r
+               if (p_qitem != &p_endpt->lid_item) {\r
+                       // Since we failed to insert into the list, make sure it is not removed\r
+                       p_endpt->dlid =0;\r
+               }\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_add_bcast(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_mcast_rec_t                          *p_mcast_rec )\r
+{\r
+       ib_api_status_t status;\r
+       ipoib_endpt_t   *p_endpt;\r
+       mac_addr_t              bcast_mac;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /*\r
+        * Cache the broadcast group properties for creating future mcast groups.\r
+        */\r
+       p_port->ib_mgr.bcast_rec = *p_mcast_rec->p_member_rec;\r
+\r
+       /* Allocate the broadcast endpoint. */\r
+       p_endpt = ipoib_endpt_create( &p_mcast_rec->p_member_rec->mgid,\r
+               0 , CL_HTON32(0x00FFFFFF) );\r
+       if( !p_endpt )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_endpt_create failed.\n") );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+       /* set reference to transport to be used while is not attached to the port */\r
+       p_endpt->is_mcast_listener = TRUE;\r
+       p_endpt->p_ifc = p_port->p_adapter->p_ifc;\r
+       status = ipoib_endpt_set_mcast( p_endpt, p_port->ib_mgr.h_pd,\r
+               p_port->port_num, p_mcast_rec );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               cl_obj_destroy( &p_endpt->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_create_mcast_endpt returned %s\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Add the broadcast endpoint to the endpoint map. */\r
+       cl_memset( &bcast_mac, 0xFF, sizeof(bcast_mac) );\r
+       status = __endpt_mgr_insert_locked( p_port, bcast_mac, p_endpt );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+void\r
+ipoib_port_remove_endpt(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac )\r
+{\r
+       cl_map_item_t   *p_item;\r
+       //TODO CM\r
+//     cl_fmap_item_t  *p_fmap_item;\r
+       ipoib_endpt_t   *p_endpt;\r
+       uint64_t                key;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_ENDPT );\r
+\r
+       key = 0;\r
+       cl_memcpy( &key, &mac, sizeof(mac_addr_t) );\r
+\r
+       /* Remove the endpoint from the maps so further requests don't find it. */\r
+       cl_obj_lock( &p_port->obj );\r
+       /* Wait for all readers to finish */\r
+       while( p_port->endpt_rdr )\r
+               ;\r
+       p_item = cl_qmap_remove( &p_port->endpt_mgr.mac_endpts, key );\r
+       /*\r
+        * Dereference the endpoint.  If the ref count goes to zero, it\r
+        * will get freed.\r
+        */\r
+       if( p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts ) )\r
+       {\r
+               p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+               /*\r
+                * The enpoints are *ALWAYS* in both the MAC and GID maps.  They are only\r
+                * in the LID map if the GID has the same subnet prefix as us.\r
+                */\r
+               cl_fmap_remove_item(\r
+                       &p_port->endpt_mgr.gid_endpts, &p_endpt->gid_item );\r
+#if 0\r
+               if( p_port->p_adapter->params.cm_enabled )\r
+               {\r
+                       p_fmap_item = cl_fmap_get( &p_port->endpt_mgr.conn_endpts, &p_endpt->dgid );\r
+               \r
+                       if( p_fmap_item != cl_fmap_end( &p_port->endpt_mgr.conn_endpts ) )\r
+                       {\r
+                               cl_fmap_remove_item( &p_port->endpt_mgr.conn_endpts, \r
+                                       &p_endpt->conn_item );\r
+                       }\r
+               }\r
+#endif\r
+\r
+               if( p_endpt->dlid )\r
+               {\r
+                       cl_qmap_remove_item(\r
+                               &p_port->endpt_mgr.lid_endpts, &p_endpt->lid_item );\r
+               }\r
+\r
+               cl_obj_unlock( &p_port->obj );\r
+               //TODO CM\r
+               //endpt_cm_destroy_conn( p_port, p_endpt );\r
+\r
+#if DBG\r
+               cl_atomic_dec( &p_port->ref[ref_endpt_track] );\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+                       ("ref type %d ref_cnt %d\n", ref_endpt_track, p_port->obj.ref_cnt) );\r
+#endif\r
+\r
+       }\r
+       else\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_ENDPT );\r
+}\r
+\r
+/*\r
+ * The sequence for port up is as follows:\r
+ *     1. The port goes active.  This allows the adapter to send SA queries\r
+ *     and join the broadcast group (and other groups).\r
+ *\r
+ *     2. The adapter sends an SA query for the broadcast group.\r
+ *\r
+ *     3. Upon completion of the query, the adapter joins the broadcast group.\r
+ */\r
+\r
+\r
+/*\r
+ * Query the SA for the broadcast group.\r
+ */\r
+void\r
+ipoib_port_up(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ib_pnp_port_rec_t* const        p_pnp_rec )\r
+{\r
+       ib_port_info_t          *p_port_info;\r
+       ib_mad_t                        *mad_in         = NULL;\r
+       ib_mad_t                        *mad_out = NULL;\r
+       ib_api_status_t         status  = IB_INSUFFICIENT_MEMORY;\r
+       static int                      cnt     = 0;\r
+       \r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
+                       ("[%d] Entering port_up.\n", ++cnt) ); \r
+       \r
+       cl_obj_lock( &p_port->obj );\r
+       if ( p_port->state == IB_QPS_INIT ) \r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               status = IB_SUCCESS;\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("p_port->state = %d - Aborting.\n", p_port->state) );        \r
+               goto up_done;\r
+       }\r
+       else if ( p_port->state == IB_QPS_RTS )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               cl_obj_lock( &p_port->p_adapter->obj );\r
+               if( p_port->p_adapter->state == IB_PNP_PORT_INIT )\r
+               {\r
+                       p_port->p_adapter->state = IB_PNP_PORT_ACTIVE;\r
+               }\r
+               cl_obj_unlock( &p_port->p_adapter->obj );\r
+               status = IB_SUCCESS;\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Port init is done. p_port->state = %d.\n", p_port->state ) );\r
+               goto up_done;\r
+       }\r
+       p_port->state = IB_QPS_INIT;\r
+       cl_obj_unlock( &p_port->obj );  \r
+\r
+\r
+       /* Wait for all work requests to get flushed. */\r
+       while( p_port->recv_mgr.depth || p_port->send_mgr.depth )\r
+               cl_thread_suspend( 0 );\r
+\r
+       KeResetEvent( &p_port->sa_event );\r
+\r
+       mad_out = (ib_mad_t*)cl_zalloc(256);\r
+       if(! mad_out)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("failed to allocate mad mad_out\n")); \r
+               goto up_done;\r
+       }\r
+       mad_in = (ib_mad_t*)cl_zalloc(256);\r
+       if(! mad_in)\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("failed to allocate mad mad_in\n")); \r
+               goto up_done;\r
+       }\r
+\r
+       mad_in->attr_id = IB_MAD_ATTR_PORT_INFO;\r
+       mad_in->method = IB_MAD_METHOD_GET;\r
+       mad_in->base_ver = 1;\r
+       mad_in->class_ver =1;\r
+       mad_in->mgmt_class = IB_MCLASS_SUBN_LID;\r
+       \r
+       status = p_port->p_adapter->p_ifc->local_mad(\r
+               p_port->ib_mgr.h_ca ,p_port->port_num ,mad_in ,mad_out);\r
+\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               ipoib_set_inactive( p_port->p_adapter );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_local_mad returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               goto up_done;\r
+       }\r
+\r
+       p_port_info = (ib_port_info_t*)(((ib_smp_t*)mad_out)->data);\r
+       p_port->base_lid = p_pnp_rec->p_port_attr->lid;\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Received port info: link width = %d.\n",\r
+                       p_port_info->link_width_active) );\r
+       p_port->ib_mgr.rate =\r
+               ib_port_info_compute_rate( p_port_info );\r
+       \r
+       ipoib_set_rate( p_port->p_adapter,\r
+               p_port_info->link_width_active,\r
+       ib_port_info_get_link_speed_active( p_port_info ) );\r
+\r
+       status = __port_get_bcast( p_port );\r
+       if (status != IB_SUCCESS)\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+               (" __port_get_bcast returned %s\n",p_port->p_adapter->p_ifc->get_err_str( status )));\r
+\r
+up_done:\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               if( status != IB_CANCELED )\r
+               {\r
+                       ipoib_set_inactive( p_port->p_adapter );\r
+                       __endpt_mgr_reset_all( p_port );\r
+               }\r
+               ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+               p_port->state = IB_QPS_ERROR;\r
+               KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+       }\r
+\r
+       if(mad_out)\r
+               cl_free(mad_out);\r
+       if(mad_in)\r
+               cl_free(mad_in);\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__endpt_mgr_add_local(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_port_info_t* const           p_port_info )\r
+{\r
+       ib_api_status_t                 status;\r
+       ib_gid_t                                gid;\r
+       ipoib_endpt_t                   *p_endpt;\r
+       ib_av_attr_t                    av_attr;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       ib_gid_set_default( &gid, p_port->p_adapter->guids.port_guid.guid );\r
+       p_endpt = ipoib_endpt_create(\r
+               &gid, p_port_info->base_lid, p_port->ib_mgr.qpn );\r
+       if( !p_endpt )\r
+       {\r
+               p_port->p_adapter->hung = TRUE;\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to create local endpt\n") );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       cl_memclr( &av_attr, sizeof(ib_av_attr_t) );\r
+       av_attr.port_num = p_port->port_num;\r
+       av_attr.sl = 0;\r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+               (" av_attr.dlid = p_port_info->base_lid = %d\n", cl_ntoh16( p_port_info->base_lid ) ));\r
+       av_attr.dlid = p_port_info->base_lid;\r
+       av_attr.static_rate = p_port->ib_mgr.rate;\r
+       av_attr.path_bits = 0;\r
+       status = p_port->p_adapter->p_ifc->create_av(\r
+               p_port->ib_mgr.h_pd, &av_attr, &p_endpt->h_av );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               cl_obj_destroy( &p_endpt->obj );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_create_av for local endpoint returned %s\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* __endpt_mgr_insert expects *one* reference to be held. */\r
+       cl_atomic_inc( &p_port->endpt_rdr );\r
+       status = __endpt_mgr_insert( p_port, p_port->p_adapter->params.conf_mac, p_endpt );\r
+       cl_atomic_dec( &p_port->endpt_rdr );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__endpt_mgr_insert for local endpoint returned %s\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       p_port->p_local_endpt = p_endpt;\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+\r
+\r
+static ib_api_status_t\r
+__port_get_bcast(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_query_req_t          query;\r
+       ib_user_query_t         info;\r
+       ib_member_rec_t         member_rec;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       info.method = IB_MAD_METHOD_GETTABLE;\r
+       info.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;\r
+       info.attr_size = sizeof(ib_member_rec_t);\r
+       info.comp_mask = IB_MCR_COMPMASK_MGID;\r
+       info.p_attr = &member_rec;\r
+\r
+       /* Query requires only the MGID. */\r
+       cl_memclr( &member_rec, sizeof(ib_member_rec_t) );\r
+       member_rec.mgid = bcast_mgid_template;\r
+\r
+    member_rec.mgid.raw[4] = (uint8_t) (p_port->p_adapter->guids.port_guid.pkey >> 8) ;\r
+       member_rec.mgid.raw[5] = (uint8_t) p_port->p_adapter->guids.port_guid.pkey;\r
+       member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey);\r
+       cl_memclr( &query, sizeof(ib_query_req_t) );\r
+       query.query_type = IB_QUERY_USER_DEFINED;\r
+       query.p_query_input = &info;\r
+       query.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+       query.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
+       query.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
+       query.query_context = p_port;\r
+       query.pfn_query_cb = __bcast_get_cb;\r
+\r
+       /* reference the object for the multicast query. */\r
+       ipoib_port_ref( p_port, ref_get_bcast );\r
+\r
+       status = p_port->p_adapter->p_ifc->query(\r
+               p_port->p_adapter->h_al, &query, &p_port->ib_mgr.h_query );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               ipoib_port_deref( p_port, ref_get_bcast );\r
+               ASSERT(FALSE);\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_query returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+       }\r
+       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_query returned SUCCESS\n"));\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+/* Callback for the MCMemberRecord Get query for the IPv4 broadcast group. */\r
+static void\r
+__bcast_get_cb(\r
+       IN                              ib_query_rec_t                          *p_query_rec )\r
+{\r
+       ipoib_port_t            *p_port;\r
+       ib_member_rec_t         *p_mc_req;\r
+       ib_api_status_t         status;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_port = (ipoib_port_t*)p_query_rec->query_context;\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+       p_port->ib_mgr.h_query = NULL;\r
+\r
+       CL_ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+       if( p_port->state != IB_QPS_INIT )\r
+       {\r
+               status = IB_CANCELED;\r
+               goto done;\r
+       }\r
+       \r
+       status = p_query_rec->status;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+               ("status of request %s\n", \r
+               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+\r
+       switch( status )\r
+       {\r
+       case IB_SUCCESS:\r
+               if( p_query_rec->result_cnt )\r
+               {\r
+                       p_mc_req = (ib_member_rec_t*)\r
+                               ib_get_query_result( p_query_rec->p_result_mad, 0 );\r
+\r
+                       /* Join the broadcast group. */\r
+                       status = __port_join_bcast( p_port, p_mc_req );\r
+                       break;\r
+               }\r
+               /* Fall through. */\r
+\r
+       case IB_REMOTE_ERROR:\r
+               /* SA failed the query.  Broadcast group doesn't exist, create it. */\r
+               status = __port_create_bcast( p_port );\r
+               break;\r
+\r
+       case IB_CANCELED:\r
+               IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Instance destroying - Aborting.\n") );\r
+               break;\r
+\r
+       default:\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_BCAST_GET, 1, p_query_rec->status );\r
+       }\r
+done:\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               if( status != IB_CANCELED )\r
+               {\r
+                       ipoib_set_inactive( p_port->p_adapter );\r
+                       __endpt_mgr_reset_all( p_port );\r
+               }\r
+               p_port->state = IB_QPS_ERROR;\r
+               KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+       }\r
+\r
+       /* Return the response MAD to AL. */\r
+       if( p_query_rec->p_result_mad )\r
+               p_port->p_adapter->p_ifc->put_mad( p_query_rec->p_result_mad );\r
+\r
+       /* Release the reference taken when issuing the member record query. */\r
+       ipoib_port_deref( p_port, ref_bcast_get_cb );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__port_join_bcast(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              ib_member_rec_t* const          p_member_rec )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_mcast_req_t          mcast_req;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /* Check that the rate is realizable for our port. */\r
+       if( p_port->ib_mgr.rate < (p_member_rec->rate & 0x3F) &&\r
+               (g_ipoib.bypass_check_bcast_rate == 0))\r
+       {\r
+               /*\r
+                * The MC group rate is higher than our port's rate.  Log an error\r
+                * and stop.  A port transition will drive the retry.\r
+                */\r
+               IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,\r
+                       ("Unrealizable join due to rate mismatch.\n") );\r
+               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                       EVENT_IPOIB_BCAST_RATE, 2,\r
+                       (uint32_t)(p_member_rec->rate & 0x3F),\r
+                       (uint32_t)p_port->ib_mgr.rate );\r
+               return IB_ERROR;\r
+       }\r
+\r
+       /* Join the broadcast group. */\r
+       cl_memclr( &mcast_req, sizeof(mcast_req) );\r
+       /* Copy the results of the Get to use as parameters. */\r
+       mcast_req.member_rec = *p_member_rec;\r
+       /* We specify our port GID for the join operation. */\r
+       mcast_req.member_rec.port_gid.unicast.prefix = IB_DEFAULT_SUBNET_PREFIX;\r
+       mcast_req.member_rec.port_gid.unicast.interface_id =\r
+               p_port->p_adapter->guids.port_guid.guid;\r
+\r
+       mcast_req.mcast_context = p_port;\r
+       mcast_req.pfn_mcast_cb = __bcast_cb;\r
+       mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
+       mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
+       mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+       mcast_req.pkey_index = p_port->pkey_index;\r
+\r
+       if( ib_member_get_state( mcast_req.member_rec.scope_state ) !=\r
+               IB_MC_REC_STATE_FULL_MEMBER )\r
+       {\r
+               IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,\r
+                       ("Incorrect MC member rec join state in query response.\n") );\r
+               ib_member_set_state( &mcast_req.member_rec.scope_state,\r
+                       IB_MC_REC_STATE_FULL_MEMBER );\r
+       }\r
+\r
+       /* reference the object for the multicast join request. */\r
+       ipoib_port_ref( p_port, ref_join_bcast );\r
+\r
+       status = p_port->p_adapter->p_ifc->join_mcast(\r
+               p_port->ib_mgr.h_qp, &mcast_req );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               ipoib_port_deref( p_port, ref_bcast_join_failed );\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_join_mcast returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__port_create_bcast(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_mcast_req_t          mcast_req;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /* Join the broadcast group. */\r
+       cl_memclr( &mcast_req, sizeof(mcast_req) );\r
+       mcast_req.create = TRUE;\r
+       /*\r
+        * Create requires pkey, qkey, SL, flow label, traffic class, joing state\r
+        * and port GID.\r
+        *\r
+        * We specify the MGID since we don't want the SA to generate it for us.\r
+        */\r
+       mcast_req.member_rec.mgid = bcast_mgid_template;\r
+       mcast_req.member_rec.mgid.raw[4] = (uint8_t) (p_port->p_adapter->guids.port_guid.pkey >> 8); \r
+       mcast_req.member_rec.mgid.raw[5] = (uint8_t) p_port->p_adapter->guids.port_guid.pkey;\r
+       ib_gid_set_default( &mcast_req.member_rec.port_gid,\r
+               p_port->p_adapter->guids.port_guid.guid );\r
+       /*\r
+        * IPOIB spec requires that the QKEY have the MSb set so that the QKEY\r
+        * from the QP is used rather than the QKEY in the send WR.\r
+        */\r
+       mcast_req.member_rec.qkey =\r
+               (uint32_t)(uintn_t)p_port | IB_QP_PRIVILEGED_Q_KEY;\r
+       mcast_req.member_rec.mtu =\r
+               (IB_PATH_SELECTOR_EXACTLY << 6) | IB_MTU_LEN_2048;\r
+\r
+       mcast_req.member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey);\r
+\r
+       mcast_req.member_rec.sl_flow_hop = ib_member_set_sl_flow_hop( 0, 0, 0 );\r
+       mcast_req.member_rec.scope_state =\r
+               ib_member_set_scope_state( 2, IB_MC_REC_STATE_FULL_MEMBER );\r
+\r
+       mcast_req.mcast_context = p_port;\r
+       mcast_req.pfn_mcast_cb = __bcast_cb;\r
+       mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
+       mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
+       mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+       mcast_req.pkey_index = p_port->pkey_index;\r
+\r
+       /* reference the object for the multicast join request. */\r
+       ipoib_port_ref( p_port, ref_join_bcast );\r
+\r
+       status = p_port->p_adapter->p_ifc->join_mcast( p_port->ib_mgr.h_qp, &mcast_req );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               ipoib_port_deref( p_port, ref_bcast_create_failed );\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_join_mcast returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return status;\r
+}\r
+\r
+\r
+void\r
+ipoib_port_down(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t         status;\r
+       ib_qp_mod_t                     qp_mod;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       /*\r
+        * Mark our state.  This causes all callbacks to abort.\r
+        * Note that we hold the receive lock so that we synchronize\r
+        * with reposting.  We must take the receive lock before the\r
+        * object lock since that is the order taken when reposting.\r
+        */\r
+       cl_spinlock_acquire( &p_port->recv_lock );\r
+       cl_obj_lock( &p_port->obj );\r
+       p_port->state = IB_QPS_ERROR;\r
+\r
+       NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+               EVENT_IPOIB_PORT_DOWN, 0 );\r
+\r
+       if( p_port->ib_mgr.h_query )\r
+       {\r
+               p_port->p_adapter->p_ifc->cancel_query(\r
+                       p_port->p_adapter->h_al, p_port->ib_mgr.h_query );\r
+               p_port->ib_mgr.h_query = NULL;\r
+       }\r
+       cl_obj_unlock( &p_port->obj );\r
+       cl_spinlock_release( &p_port->recv_lock );\r
+\r
+       KeWaitForSingleObject(\r
+               &p_port->sa_event, Executive, KernelMode, FALSE, NULL );\r
+\r
+       /* garbage collector timer is not needed when link is down */\r
+       KeCancelTimer(&p_port->gc_timer);\r
+       KeFlushQueuedDpcs();\r
+\r
+       /*\r
+        * Put the QP in the error state.  This removes the need to\r
+        * synchronize with send/receive callbacks.\r
+        */\r
+       CL_ASSERT( p_port->ib_mgr.h_qp );\r
+       cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
+       qp_mod.req_state = IB_QPS_ERROR;\r
+       status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_modify_qp to error state returned %s.\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               p_port->p_adapter->hung = TRUE;\r
+               return;\r
+       }\r
+\r
+       KeResetEvent(&p_port->leave_mcast_event);\r
+\r
+       /* Reset all endpoints so we don't flush our ARP cache. */\r
+       __endpt_mgr_reset_all( p_port );\r
+\r
+       KeWaitForSingleObject(\r
+               &p_port->leave_mcast_event, Executive, KernelMode, FALSE, NULL );\r
+\r
+       __pending_list_destroy(p_port);\r
+       \r
+       cl_obj_lock( &p_port->p_adapter->obj );\r
+       ipoib_dereg_addrs( p_port->p_adapter );\r
+       cl_obj_unlock( &p_port->p_adapter->obj );\r
+       \r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__bcast_cb(\r
+       IN                              ib_mcast_rec_t                          *p_mcast_rec )\r
+{\r
+       ipoib_port_t    *p_port;\r
+       ib_api_status_t status;\r
+       LARGE_INTEGER   gc_due_time;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+\r
+       p_port = (ipoib_port_t*)p_mcast_rec->mcast_context;\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+\r
+       ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+       if( p_port->state != IB_QPS_INIT )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               if( p_mcast_rec->status == IB_SUCCESS )\r
+               {\r
+                       ipoib_port_ref(p_port, ref_leave_mcast);\r
+                       p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+               }\r
+               KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+               ipoib_port_deref( p_port, ref_bcast_inv_state );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Invalid state - Aborting.\n") );\r
+               return;\r
+       }\r
+       status = p_mcast_rec->status;\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Multicast join for broadcast group returned %s.\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( p_mcast_rec->status )) );\r
+               if( status == IB_REMOTE_ERROR )\r
+               {\r
+                       /*\r
+                        * Either:\r
+                        *      - the join failed because the group no longer exists\r
+                        *      - the create failed because the group already exists\r
+                        *\r
+                        * Kick off a new Get query to the SA to restart the join process\r
+                        * from the top.  Note that as an optimization, it would be\r
+                        * possible to distinguish between the join and the create.\r
+                        * If the join fails, try the create.  If the create fails, start\r
+                        * over with the Get.\r
+                        */\r
+                       /* TODO: Assert is a place holder.  Can we ever get here if the\r
+                       state isn't IB_PNP_PORT_ADD or PORT_DOWN or PORT_INIT? */\r
+                       CL_ASSERT( p_port->p_adapter->state == IB_PNP_PORT_ADD ||\r
+                               p_port->p_adapter->state == IB_PNP_PORT_DOWN ||\r
+                               p_port->p_adapter->state == IB_PNP_PORT_INIT );\r
+                       if(++p_port->bc_join_retry_cnt < p_port->p_adapter->params.bc_join_retry)\r
+                       {\r
+                               status = __port_get_bcast( p_port );\r
+                       }\r
+                       else\r
+                       {\r
+                               NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                                       EVENT_IPOIB_BCAST_JOIN, 1, p_mcast_rec->status );\r
+                               p_port->bc_join_retry_cnt = 0;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                               EVENT_IPOIB_BCAST_JOIN, 1, p_mcast_rec->status );\r
+               }\r
+\r
+               cl_obj_unlock( &p_port->obj );\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       ipoib_set_inactive( p_port->p_adapter );\r
+                       __endpt_mgr_reset_all( p_port );\r
+                       ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+                       p_port->state = IB_QPS_ERROR;\r
+                       KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+               }\r
+               ipoib_port_deref( p_port, ref_bcast_req_failed );\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return;\r
+       }\r
+       p_port->bc_join_retry_cnt = 0;\r
+\r
+       while( p_port->endpt_rdr )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               cl_obj_lock( &p_port->obj );\r
+       }\r
+\r
+       if( !p_port->p_local_endpt )\r
+       {\r
+               ib_port_info_t  port_info;\r
+               cl_memclr(&port_info, sizeof(port_info));\r
+               port_info.base_lid = p_port->base_lid;\r
+               status = __endpt_mgr_add_local( p_port, &port_info );\r
+               if( status != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("__endpt_mgr_add_local returned %s\n",\r
+                               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+                       cl_obj_unlock( &p_port->obj );\r
+                       goto err;\r
+               }\r
+       }\r
+\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       status = __endpt_mgr_add_bcast( p_port, p_mcast_rec );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__endpt_mgr_add_bcast returned %s\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               ipoib_port_ref(p_port, ref_leave_mcast);\r
+               status = p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+               CL_ASSERT( status == IB_SUCCESS );\r
+               goto err;\r
+       }\r
+\r
+       /* Get the QP ready for action. */\r
+       status = __ib_mgr_activate( p_port );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__ib_mgr_activate returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+\r
+err:\r
+               /* Flag the adapter as hung. */\r
+               p_port->p_adapter->hung = TRUE;\r
+               ASSERT(p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+               p_port->state = IB_QPS_ERROR;        \r
+               KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+               ipoib_port_deref( p_port, ref_bcast_error );\r
+               IPOIB_EXIT( IPOIB_DBG_INIT );\r
+               return;\r
+       }\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+       /* Only change the state if we're still in INIT. */\r
+       ASSERT( p_port->state == IB_QPS_INIT || p_port->state == IB_QPS_ERROR);\r
+       if (p_port->state == IB_QPS_INIT) {\r
+               p_port->state = IB_QPS_RTS;\r
+       }\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       /* Prepost receives. */\r
+       cl_spinlock_acquire( &p_port->recv_lock );\r
+       __recv_mgr_repost( p_port );\r
+       cl_spinlock_release( &p_port->recv_lock );\r
+\r
+       /* Notify the adapter that we now have an active connection. */\r
+       status = ipoib_set_active( p_port->p_adapter );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               ib_qp_mod_t                     qp_mod;\r
+               ipoib_set_inactive( p_port->p_adapter );\r
+               KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("ipoib_set_active returned %s.\n",p_port->p_adapter->p_ifc->get_err_str( status )));\r
+               cl_spinlock_acquire( &p_port->recv_lock );\r
+               cl_obj_lock( &p_port->obj );\r
+               p_port->state = IB_QPS_ERROR;\r
+               if( p_port->ib_mgr.h_query )\r
+               {\r
+                       p_port->p_adapter->p_ifc->cancel_query(\r
+                               p_port->p_adapter->h_al, p_port->ib_mgr.h_query );\r
+                       p_port->ib_mgr.h_query = NULL;\r
+               }\r
+               cl_obj_unlock( &p_port->obj );\r
+               cl_spinlock_release( &p_port->recv_lock );\r
+\r
+               CL_ASSERT( p_port->ib_mgr.h_qp );\r
+               cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
+               qp_mod.req_state = IB_QPS_ERROR;\r
+               status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod );\r
+               __endpt_mgr_reset_all( p_port );\r
+\r
+               ipoib_port_deref( p_port, ref_join_bcast );\r
+               return;\r
+       }\r
+#if 0 //CM\r
+       if( p_port->p_adapter->params.cm_enabled &&\r
+               !p_port->p_local_endpt->conn.h_cm_listen )\r
+       {\r
+               if( ipoib_port_listen( p_port ) != IB_SUCCESS )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Port CM Listen failed\n" ) );\r
+                       /*keep going with UD only */\r
+                       p_port->p_adapter->params.cm_enabled = FALSE;\r
+\r
+                       NdisWriteErrorLogEntry( p_port->p_adapter->h_adapter,\r
+                               EVENT_IPOIB_CONNECTED_MODE_ERR, 1, 0xbadc0de3 );\r
+               }\r
+       }\r
+#endif\r
+       /* garbage collector timer is needed when link is active */\r
+       gc_due_time.QuadPart = -(int64_t)(((uint64_t)p_port->p_adapter->params.mc_leave_rescan * 2000000) * 10);\r
+       KeSetTimerEx(&p_port->gc_timer,gc_due_time,\r
+                           (LONG)p_port->p_adapter->params.mc_leave_rescan*1000,&p_port->gc_dpc);\r
+\r
+       KeSetEvent( &p_port->sa_event, EVENT_INCREMENT, FALSE );\r
+       ipoib_port_deref( p_port, ref_join_bcast );\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+}\r
+\r
+\r
+static void\r
+__qp_event(\r
+       IN                              ib_async_event_rec_t            *p_event_rec )\r
+{\r
+       UNUSED_PARAM( p_event_rec );\r
+       CL_ASSERT( p_event_rec->context );\r
+       ((ipoib_port_t*)p_event_rec->context)->p_adapter->hung = TRUE;\r
+}\r
+\r
+\r
+static void\r
+__cq_event(\r
+       IN                              ib_async_event_rec_t            *p_event_rec )\r
+{\r
+       UNUSED_PARAM( p_event_rec );\r
+       CL_ASSERT( p_event_rec->context );\r
+       ((ipoib_port_t*)p_event_rec->context)->p_adapter->hung = TRUE;\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+__ib_mgr_activate(\r
+       IN                              ipoib_port_t* const                     p_port )\r
+{\r
+       ib_api_status_t status;\r
+       ib_dgrm_info_t  dgrm_info;\r
+       ib_qp_mod_t             qp_mod;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_INIT );\r
+       /*\r
+        * Move the QP to RESET.  This allows us to reclaim any\r
+        * unflushed receives.\r
+        */\r
+       cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
+       qp_mod.req_state = IB_QPS_RESET;\r
+       status = p_port->p_adapter->p_ifc->modify_qp( p_port->ib_mgr.h_qp, &qp_mod );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_modify_qp returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Move the QP to RTS. */\r
+       dgrm_info.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+       dgrm_info.qkey = p_port->ib_mgr.bcast_rec.qkey;\r
+       dgrm_info.pkey_index = p_port->pkey_index;\r
+       status = p_port->p_adapter->p_ifc->init_dgrm_svc( p_port->ib_mgr.h_qp, &dgrm_info );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_init_dgrm_svc returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* Rearm the CQs. */\r
+       status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_recv_cq, FALSE );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_rearm_cq for recv returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+       status = p_port->p_adapter->p_ifc->rearm_cq( p_port->ib_mgr.h_send_cq, FALSE );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_rearm_cq for send returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_INIT );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+/* Transition to a passive level thread. */\r
+ib_api_status_t\r
+ipoib_port_join_mcast(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                              mac,\r
+       IN              const   uint8_t                                 state)\r
+{\r
+       ib_api_status_t         status;\r
+       ib_mcast_req_t          mcast_req;\r
+       ipoib_endpt_t           *p_endpt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+       switch( __endpt_mgr_ref( p_port, mac, &p_endpt ) )\r
+       {\r
+       case NDIS_STATUS_NO_ROUTE_TO_DESTINATION:\r
+               break;\r
+\r
+       case NDIS_STATUS_SUCCESS:\r
+               ipoib_endpt_deref( p_endpt );\r
+               /* Fall through */\r
+\r
+       case NDIS_STATUS_PENDING:\r
+               return IB_SUCCESS;\r
+       }\r
+\r
+       /*\r
+        * Issue the mcast request, using the parameters of the broadcast group.\r
+        * This allows us to do a create request that should always succeed since\r
+        * the required parameters are known.\r
+        */\r
+       cl_memclr( &mcast_req, sizeof(mcast_req) );\r
+       mcast_req.create = TRUE;\r
+\r
+       /* Copy the settings from the broadcast group. */\r
+       mcast_req.member_rec = p_port->ib_mgr.bcast_rec;\r
+       /* Clear fields that aren't specified in the join */\r
+       mcast_req.member_rec.mlid = 0;\r
+       ib_member_set_state( &mcast_req.member_rec.scope_state,state);\r
+\r
+       if( (mac.addr[0] == 1) && (mac.addr[2] == 0x5E ))\r
+       {\r
+               /*\r
+                * Update the address portion of the MGID with the 28 lower bits of the\r
+                * IP address.  Since we're given a MAC address, we are using \r
+                * 24 lower bits of that network-byte-ordered value (assuming MSb\r
+                * is zero) and 4 lsb bits of the first byte of IP address.\r
+                */\r
+               mcast_req.member_rec.mgid.raw[12] = mac.addr[1];\r
+               mcast_req.member_rec.mgid.raw[13] = mac.addr[3];\r
+               mcast_req.member_rec.mgid.raw[14] = mac.addr[4];\r
+               mcast_req.member_rec.mgid.raw[15] = mac.addr[5];\r
+       }\r
+       else\r
+       {\r
+               /* Handle non IP mutlicast MAC addresses. */\r
+               /* Update the signature to use the lower 2 bytes of the OpenIB OUI. */\r
+               mcast_req.member_rec.mgid.raw[2] = 0x14;\r
+               mcast_req.member_rec.mgid.raw[3] = 0x05;\r
+               /* Now copy the MAC address into the last 6 bytes of the GID. */\r
+               cl_memcpy( &mcast_req.member_rec.mgid.raw[10], mac.addr, 6 );\r
+       }\r
+\r
+       mcast_req.mcast_context = p_port;\r
+       mcast_req.pfn_mcast_cb = __mcast_cb;\r
+       mcast_req.timeout_ms = p_port->p_adapter->params.sa_timeout;\r
+       mcast_req.retry_cnt = p_port->p_adapter->params.sa_retry_cnt;\r
+       mcast_req.port_guid = p_port->p_adapter->guids.port_guid.guid;\r
+       mcast_req.pkey_index = p_port->pkey_index;\r
+       mcast_req.member_rec.pkey = cl_hton16(p_port->p_adapter->guids.port_guid.pkey);\r
+       /*\r
+        * Create the endpoint and insert it in the port.  Since we don't wait for\r
+        * the mcast SA operations to complete before returning from the multicast\r
+        * list set OID asynchronously, it is possible for the mcast entry to be\r
+        * cleared before the SA interaction completes.  In this case, when the\r
+        * mcast callback is invoked, it would not find the corresponding endpoint\r
+        * and would be undone.\r
+        */\r
+       p_endpt = ipoib_endpt_create(\r
+               &mcast_req.member_rec.mgid, 0, CL_HTON32(0x00FFFFFF) );\r
+       if( !p_endpt )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ipoib_endpt_create failed.\n") );\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       status = __endpt_mgr_insert_locked( p_port, mac, p_endpt );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("__endpt_mgr_insert_locked returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               return status;\r
+       }\r
+\r
+       /* reference the object for the multicast join request. */\r
+       ipoib_port_ref( p_port, ref_join_mcast );\r
+\r
+       status = p_port->p_adapter->p_ifc->join_mcast( p_port->ib_mgr.h_qp, &mcast_req );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               ipoib_port_deref( p_port, ref_mcast_join_failed );\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("ib_join_mcast returned %s\n", \r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+       }\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+       return status;\r
+}\r
+\r
+\r
+static void\r
+__mcast_cb(\r
+       IN                              ib_mcast_rec_t                          *p_mcast_rec )\r
+{\r
+       ib_api_status_t         status;\r
+       ipoib_port_t            *p_port;\r
+       cl_fmap_item_t          *p_item;\r
+       ipoib_endpt_t           *p_endpt;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+       p_port = (ipoib_port_t*)p_mcast_rec->mcast_context;\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+       while( p_port->endpt_rdr )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               cl_obj_lock( &p_port->obj );\r
+       }\r
+       if( p_port->state != IB_QPS_RTS )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               if( p_mcast_rec->status == IB_SUCCESS )\r
+\r
+               {\r
+                       ipoib_port_ref(p_port, ref_leave_mcast);\r
+                       p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+               }\r
+               ipoib_port_deref( p_port, ref_mcast_inv_state );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
+                       ("Invalid state - Aborting.\n") );\r
+               return;\r
+       }\r
+\r
+       if( p_mcast_rec->status != IB_SUCCESS )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Multicast join request failed with status %s.\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( p_mcast_rec->status )) );\r
+               /* Flag the adapter as hung. */\r
+               p_port->p_adapter->hung =TRUE;\r
+               ipoib_port_deref( p_port, ref_mcast_req_failed );\r
+               IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+               return;\r
+       }\r
+\r
+       p_item = cl_fmap_get(\r
+               &p_port->endpt_mgr.gid_endpts, &p_mcast_rec->p_member_rec->mgid );\r
+       if( p_item == cl_fmap_end( &p_port->endpt_mgr.gid_endpts ) )\r
+       {\r
+               /*\r
+                * The endpoint must have been flushed while the join request\r
+                * was outstanding.  Just leave the group and return.  This\r
+                * is not an error.\r
+                */\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT(TRACE_LEVEL_WARNING, IPOIB_DBG_ERROR,\r
+                       ("Failed to find endpoint for update.\n") );\r
+\r
+               ipoib_port_ref(p_port, ref_leave_mcast);\r
+               p_port->p_adapter->p_ifc->leave_mcast( p_mcast_rec->h_mcast, __leave_error_mcast_cb );\r
+               ipoib_port_deref( p_port, ref_mcast_no_endpt );\r
+               IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+               return;\r
+       }\r
+\r
+       p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, gid_item );\r
+       p_endpt->p_ifc = p_port->p_adapter->p_ifc;\r
+\r
+       /* Setup the endpoint for use. */\r
+       status = ipoib_endpt_set_mcast(\r
+               p_endpt, p_port->ib_mgr.h_pd, p_port->port_num, p_mcast_rec );\r
+       if( status != IB_SUCCESS )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_MCAST,\r
+                       ("ipoib_endpt_set_mcast returned %s.\n",\r
+                       p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+               /* Flag the adapter as hung. */\r
+               p_port->p_adapter->hung = TRUE;\r
+               ipoib_port_deref( p_port, ref_mcast_av_failed );\r
+               IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+               return;\r
+       }\r
+\r
+       /*\r
+        * The endpoint is already in the GID and MAC maps.\r
+        * mast endpoint are not used in the LID map.\r
+        */\r
+       CL_ASSERT(p_endpt->dlid == 0);\r
+       /* set flag that endpoint is use */\r
+       p_endpt->is_in_use = TRUE;\r
+       cl_obj_unlock( &p_port->obj );\r
+       \r
+       /* Try to send all pending sends. */\r
+       ipoib_port_resume( p_port , FALSE);\r
+\r
+       ipoib_port_deref( p_port, ref_join_mcast );\r
+\r
+       IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+\r
+void\r
+ipoib_leave_mcast_cb(\r
+       IN                              void                            *context )\r
+{\r
+       ipoib_port_t            *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+       p_port = (ipoib_port_t*)context;\r
+\r
+       IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_MCAST,("p_port->mcast_cnt = %d\n", p_port->mcast_cnt));\r
+       \r
+       ipoib_port_deref( p_port, ref_leave_mcast);\r
+       cl_atomic_dec( &p_port->mcast_cnt);\r
+       \r
+       if(0 == p_port->mcast_cnt)\r
+       {\r
+               KeSetEvent( &p_port->leave_mcast_event, EVENT_INCREMENT, FALSE );\r
+       }\r
+       \r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+                       ("Leave mcast callback deref ipoib_port \n") );\r
+       \r
+       IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+\r
+\r
+void\r
+__leave_error_mcast_cb(\r
+       IN                              void                            *context )\r
+{\r
+       ipoib_port_t            *p_port;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_MCAST );\r
+\r
+       p_port = (ipoib_port_t*)context;\r
+\r
+       ipoib_port_deref( p_port, ref_leave_mcast);\r
+       IPOIB_PRINT_EXIT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_MCAST,\r
+                       ("Leave mcast callback deref ipoib_port \n") );\r
+       \r
+       IPOIB_EXIT( IPOIB_DBG_MCAST );\r
+}\r
+\r
+/*++\r
+Routine Description:\r
+    The routine process the packet and returns LSO information\r
+    \r
+Arguments:\r
+    pNetBuffer - a pointer to the first net buffer object of the packet\r
+    TcpHeaderOffset - offset to the begining of the TCP header in the packet\r
+    pLsoData - pointer to LsoData object in which the routine returns the LSO information\r
+    pHeaderSize - pointer to ULONG object in which the header size is returned\r
+    IndexOfData - \r
+             \r
+Return Value:\r
+     NDIS_STATUS   \r
+\r
+NOTE:\r
+    called at DISPATCH level\r
+--*/\r
+\r
+NDIS_STATUS GetLsoHeaderSize(\r
+       IN              PNET_BUFFER             pNetBuffer,\r
+       IN              LsoData                 *pLsoData,\r
+       OUT     UINT                    *IndexOfData,\r
+       IN              ipoib_hdr_t *ipoib_hdr\r
+       )\r
+{\r
+       UINT            CurrLength;\r
+       PUCHAR          pSrc;\r
+       PUCHAR          pCopiedData = pLsoData->coppied_data;\r
+       ip_hdr_t        UNALIGNED  *IpHdr;\r
+       tcp_hdr_t       UNALIGNED *TcpHdr;\r
+       uint16_t        TcpHeaderLen;\r
+       uint16_t        IpHeaderLen;\r
+       uint16_t        IpOffset;\r
+       INT                     FullBuffers = 0;\r
+       PMDL            pMDL;\r
+       NDIS_STATUS     status = NDIS_STATUS_INVALID_PACKET;\r
+       \r
+       \r
+#define IP_OFFSET 14;\r
+       //\r
+       // This Flag indicates the way we gets the headers\r
+       // RegularFlow = we get the headers (ETH+IP+TCP) in the same Buffer \r
+       // in sequence.\r
+       //\r
+       boolean_t                       IsRegularFlow = TRUE;\r
+\r
+       const uint16_t          ETH_OFFSET = IP_OFFSET; \r
+       \r
+       pLsoData->LsoHeaderSize = 0;\r
+       IpOffset = IP_OFFSET; //(uint16_t)pPort->EncapsulationFormat.EncapsulationHeaderSize;\r
+       *IndexOfData = 0;\r
+\r
+       pMDL = NET_BUFFER_CURRENT_MDL(pNetBuffer);\r
+       NdisQueryMdl(pMDL, &pSrc, &CurrLength, NormalPagePriority);\r
+       //NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority );\r
+       if (pSrc == NULL) {\r
+               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error processing packets\n"));\r
+               return status;\r
+       }\r
+       // We start by looking for the ethernet and the IP\r
+       if (CurrLength < ETH_OFFSET) {\r
+               IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+               return status;\r
+       }\r
+       //pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + ETH_OFFSET;\r
+       if (CurrLength == ETH_OFFSET) {        \r
+               ASSERT(FALSE);\r
+               IsRegularFlow = FALSE;        \r
+               memcpy(pCopiedData, pSrc, ETH_OFFSET);\r
+               pCopiedData += ETH_OFFSET;        \r
+               FullBuffers++;\r
+               // First buffer was only ethernet\r
+               pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer);\r
+        NdisQueryMdl(NET_BUFFER_CURRENT_MDL(pNetBuffer), &pSrc, &CurrLength, NormalPagePriority);\r
+               if (pSrc == NULL) {\r
+                       IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+                       return status;\r
+           }\r
+       } else {\r
+               // This is ETH + IP together (at least)\r
+               pLsoData->LsoBuffers[0].pData = pSrc + (ETH_OFFSET - sizeof (ipoib_hdr_t));\r
+               memcpy (pLsoData->LsoBuffers[0].pData, ipoib_hdr, sizeof (ipoib_hdr_t));\r
+               CurrLength -= ETH_OFFSET;\r
+               pSrc = pSrc + ETH_OFFSET;\r
+               pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + sizeof (ipoib_hdr_t);\r
+       }\r
+       // we should now be having at least the size of ethernet data\r
+       if (CurrLength < sizeof (ip_hdr_t)) {\r
+               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+               return status;\r
+       }\r
+       IpHdr = (ip_hdr_t UNALIGNED*)pSrc;\r
+       IpHeaderLen = (uint16_t)IP_HEADER_LENGTH(IpHdr);\r
+       ASSERT(IpHdr->prot == IP_PROT_TCP);\r
+       if (CurrLength < IpHeaderLen) {\r
+               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error processing packets\n"));\r
+               return status;\r
+       }\r
+       pLsoData->LsoHeaderSize = pLsoData->LsoHeaderSize + IpHeaderLen;\r
+       // We now start to find where the TCP header starts\r
+       if (CurrLength == IpHeaderLen) {\r
+               ASSERT(FALSE);\r
+               // two options : \r
+               // if(IsRegularFlow = FALSE) ==> ETH and IP seperated in two buffers\r
+               // if(IsRegularFlow = TRUE ) ==> ETH and IP in the same buffer \r
+               // TCP will start at next buffer\r
+               if(IsRegularFlow){\r
+                       memcpy(pCopiedData, pSrc-ETH_OFFSET ,ETH_OFFSET+IpHeaderLen);\r
+                       pCopiedData += (ETH_OFFSET + IpHeaderLen);\r
+               } else {\r
+                       memcpy(pCopiedData, pSrc,IpHeaderLen);\r
+                       pCopiedData += IpHeaderLen;\r
+               }\r
+\r
+               FullBuffers++;\r
+               IsRegularFlow = FALSE;\r
+               //NdisGetNextBuffer( CurrBuffer, &CurrBuffer);\r
+               //NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority );\r
+               pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer);\r
+               NdisQueryMdl(NET_BUFFER_CURRENT_MDL(pNetBuffer), &pSrc, &CurrLength, NormalPagePriority);\r
+               if (pSrc == NULL) {\r
+                       IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+                       return status;\r
+               }\r
+       } else {\r
+               // if(IsRegularFlow = TRUE ) ==> the ETH and IP and TCP in the same buffer       \r
+               // if(IsRegularFlow = FLASE ) ==> ETH in one buffer , IP+TCP together in the same buffer\r
+               if (IsRegularFlow) {            \r
+                       pLsoData->LsoBuffers[0].Len += IpHeaderLen;\r
+               } else {            \r
+                       memcpy(pCopiedData, pSrc, IpHeaderLen);\r
+                       pCopiedData += IpHeaderLen;\r
+               }\r
+\r
+               CurrLength -= IpHeaderLen;\r
+               pSrc = pSrc + IpHeaderLen;\r
+       }\r
+       if (CurrLength < sizeof (tcp_hdr_t)) {\r
+               IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_ERROR, ("Error porcessing packets\n"));\r
+               return status;\r
+       }\r
+       // We have finaly found the TCP header\r
+       TcpHdr = (tcp_hdr_t UNALIGNED *)pSrc;\r
+       TcpHeaderLen = TCP_HEADER_LENGTH(TcpHdr);\r
+\r
+       //ASSERT(TcpHeaderLen == 20);\r
+       \r
+       if (CurrLength < TcpHeaderLen) {\r
+               //IPOIB_PRINT(TRACE_LEVEL_VERBOSE, ETH, ("Error porcessing packets\n"));\r
+               return status;\r
+       }\r
+       pLsoData->LsoHeaderSize =  pLsoData->LsoHeaderSize + TcpHeaderLen;\r
+       if(IsRegularFlow){\r
+               pLsoData->LsoBuffers[0].Len += TcpHeaderLen;\r
+       }\r
+       else{\r
+               memcpy(pCopiedData, pSrc, TcpHeaderLen);\r
+               pCopiedData += TcpHeaderLen;\r
+       }\r
+       if (CurrLength == TcpHeaderLen) {\r
+               FullBuffers++;\r
+               pLsoData->UsedBuffers = FullBuffers;\r
+               *IndexOfData = FullBuffers ;\r
+       } else {\r
+               pLsoData->UsedBuffers = FullBuffers + 1;\r
+               *IndexOfData = FullBuffers - 1;\r
+       }\r
+       pLsoData->FullBuffers = FullBuffers; \r
+       if (!IsRegularFlow){\r
+               pLsoData->LsoBuffers[0].pData = pLsoData->coppied_data;\r
+               pLsoData->LsoBuffers[0].Len = ETH_OFFSET + IpHeaderLen + TcpHeaderLen;\r
+               ASSERT(pLsoData->LsoBuffers[0].Len <= LSO_MAX_HEADER);\r
+       }\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static void __port_do_mcast_garbage(ipoib_port_t* const        p_port)\r
+{\r
+    const mac_addr_t DEFAULT_MCAST_GROUP = {0x01, 0x00, 0x5E, 0x00, 0x00, 0x01};\r
+       /* Do garbage collecting... */\r
+\r
+       cl_map_item_t   *p_item;\r
+       ipoib_endpt_t   *p_endpt;\r
+       cl_qlist_t              destroy_mc_list;\r
+       uint8_t                 cnt;\r
+       const static GC_MAX_LEAVE_NUM = 80;\r
+\r
+       cl_qlist_init( &destroy_mc_list );\r
+\r
+       cl_obj_lock( &p_port->obj );\r
+       /* Wait for all readers to finish */\r
+       while( p_port->endpt_rdr )\r
+       {\r
+               cl_obj_unlock( &p_port->obj );\r
+               cl_obj_lock( &p_port->obj );\r
+       }\r
+       cnt = 0;\r
+       p_item = cl_qmap_head( &p_port->endpt_mgr.mac_endpts );\r
+       while( (p_item != cl_qmap_end( &p_port->endpt_mgr.mac_endpts )) && (cnt < GC_MAX_LEAVE_NUM))\r
+       {\r
+               p_endpt = PARENT_STRUCT( p_item, ipoib_endpt_t, mac_item );\r
+               p_item = cl_qmap_next( p_item );\r
+\r
+               /* Check if the current endpoint is not a multicast listener */\r
+\r
+               if( p_endpt->h_mcast && \r
+                       (!p_endpt->is_mcast_listener) &&\r
+                       ( cl_memcmp( &p_endpt->mac, &DEFAULT_MCAST_GROUP, sizeof(mac_addr_t) ) &&\r
+                        (!p_endpt->is_in_use) ))\r
+               {\r
+                       cl_qmap_remove_item( &p_port->endpt_mgr.mac_endpts,\r
+                               &p_endpt->mac_item );\r
+                       cl_fmap_remove_item( &p_port->endpt_mgr.gid_endpts,\r
+                               &p_endpt->gid_item );\r
+\r
+                       if( p_endpt->dlid )\r
+                       {\r
+                               cl_qmap_remove_item( &p_port->endpt_mgr.lid_endpts,\r
+                                       &p_endpt->lid_item );\r
+                               p_endpt->dlid = 0;\r
+                       }\r
+\r
+                       cl_qlist_insert_tail(\r
+                               &destroy_mc_list, &p_endpt->mac_item.pool_item.list_item );\r
+                       cnt++;\r
+               }\r
+               else\r
+                       p_endpt->is_in_use = FALSE;\r
+       }\r
+       cl_obj_unlock( &p_port->obj );\r
+\r
+       /* Destroy all multicast endpoints now that we have released the lock. */\r
+       while( cl_qlist_count( &destroy_mc_list ) )\r
+       {\r
+               p_endpt = PARENT_STRUCT( cl_qlist_remove_head( &destroy_mc_list ),\r
+                                                                ipoib_endpt_t, mac_item.pool_item.list_item );\r
+               IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_ENDPT,\r
+                       ("mcast garbage collector: destroying endpoint %02x:%02x:%02x:%02x:%02x:%02x \n", \r
+                                p_endpt->mac.addr[0],\r
+                                p_endpt->mac.addr[1],\r
+                                p_endpt->mac.addr[2],\r
+                                p_endpt->mac.addr[3],\r
+                                p_endpt->mac.addr[4],\r
+                                p_endpt->mac.addr[5]) );\r
+               cl_obj_destroy( &p_endpt->obj );\r
+       }\r
+}\r
+\r
+static void __port_mcast_garbage_dpc(KDPC *p_gc_dpc,void *context,void *s_arg1, void *s_arg2)\r
+{\r
+       ipoib_port_t *p_port = context;\r
+\r
+       UNREFERENCED_PARAMETER(p_gc_dpc);\r
+       UNREFERENCED_PARAMETER(s_arg1);\r
+       UNREFERENCED_PARAMETER(s_arg2);\r
+\r
+       __port_do_mcast_garbage(p_port);\r
+}\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_get_by_gid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ib_gid_t* const                         p_gid )\r
+{\r
+       return __endpt_mgr_get_by_gid( p_port, p_gid );\r
+}\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_get_by_lid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   net16_t                                         lid )\r
+{\r
+       return __endpt_mgr_get_by_lid( p_port, lid );\r
+}\r
+\r
+ib_api_status_t\r
+ipoib_recv_dhcp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t* const            p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst )\r
+{\r
+       return __recv_dhcp(\r
+               p_port, p_ipoib, p_eth, p_src,p_dst );\r
+}\r
+\r
+\r
+void\r
+ipoib_port_cancel_xmit(\r
+       IN                              ipoib_port_t* const             p_port,\r
+       IN                              PVOID                                    cancel_id )\r
+{\r
+       cl_list_item_t          *p_item;\r
+       PNET_BUFFER_LIST                p_nbl;\r
+       PVOID                   nbl_id;\r
+       cl_qlist_t              cancel_list;\r
+       ULONG                   send_complete_flags = 0;\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       cl_qlist_init( &cancel_list );\r
+\r
+       cl_spinlock_acquire( &p_port->send_lock );\r
+\r
+       for( p_item = cl_qlist_head( &p_port->send_mgr.pending_list );\r
+               p_item != cl_qlist_end( &p_port->send_mgr.pending_list );\r
+               p_item = cl_qlist_next( p_item ) )\r
+       {\r
+               p_nbl = IPOIB_PACKET_FROM_LIST_ITEM( p_item );\r
+               nbl_id = NDIS_GET_NET_BUFFER_LIST_CANCEL_ID( p_nbl );\r
+               if( nbl_id == cancel_id )\r
+               {\r
+                       cl_qlist_remove_item( &p_port->send_mgr.pending_list, p_item );\r
+                       NET_BUFFER_LIST_STATUS( p_nbl) = NDIS_STATUS_REQUEST_ABORTED ;\r
+                       cl_qlist_insert_tail( &cancel_list, IPOIB_LIST_ITEM_FROM_PACKET( p_nbl ) );\r
+               }\r
+       }\r
+       cl_spinlock_release( &p_port->send_lock );\r
+\r
+       if( cl_qlist_count( &cancel_list ) )\r
+       {\r
+               while( ( p_item = cl_qlist_remove_head( &cancel_list )) \r
+                                                               != cl_qlist_end( &cancel_list ))\r
+               {\r
+                       p_nbl = IPOIB_PACKET_FROM_LIST_ITEM( p_item );\r
+                       NET_BUFFER_LIST_STATUS( p_nbl) = NDIS_STATUS_SEND_ABORTED;\r
+                       send_complete_flags = 0;\r
+                       if (NDIS_CURRENT_IRQL() == DISPATCH_LEVEL)\r
+                       {\r
+                               NDIS_SET_SEND_COMPLETE_FLAG(send_complete_flags, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);\r
+                       }\r
+                       NdisMSendNetBufferListsComplete( p_port->p_adapter->h_adapter,\r
+                               p_nbl, send_complete_flags );\r
+               }\r
+       }\r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+}\r
+\r
+/* \r
+*  Put all fragments into separate WR and chain together.\r
+*  The last WR will be set to generate CQ Event.\r
+*  lookaside buffer is used for ipoib and ip headers attached to each WR.\r
+*  Buffer will be released on last WR send completion.\r
+*/\r
+#if 0\r
+static NDIS_STATUS\r
+__send_fragments(\r
+IN             ipoib_port_t* const                     p_port,\r
+IN             ipoib_send_desc_t* const        p_desc,\r
+IN             eth_hdr_t* const                        p_eth_hdr,\r
+IN             ip_hdr_t* const                         p_ip_hdr,\r
+IN             uint32_t                                        buf_len,\r
+IN             NDIS_BUFFER*                            p_ndis_buf )\r
+{\r
+       uint32_t        ds_idx = 1;\r
+       uint32_t        wr_idx = 0;\r
+       uint32_t        sgl_idx = 2; //skip eth hdr, ip hdr\r
+       uint32_t        options_len = 0;\r
+       uint8_t*        p_options = NULL;\r
+       uint8_t*        p_buf;\r
+       uint32_t        frag_offset = 0;\r
+       uint32_t        next_sge;\r
+       uint32_t        wr_size = 0;\r
+       uint32_t        ip_hdr_len = IP_HEADER_LENGTH( p_ip_hdr );\r
+       uint32_t        total_ip_len = cl_ntoh16( p_ip_hdr->length );\r
+\r
+       SCATTER_GATHER_LIST             *p_sgl;\r
+\r
+       IPOIB_ENTER( IPOIB_DBG_SEND );\r
+\r
+       if( IP_DONT_FRAGMENT(p_ip_hdr) )\r
+                       return NDIS_STATUS_INVALID_PACKET;\r
+       \r
+       p_sgl = NDIS_PER_PACKET_INFO_FROM_PACKET( p_desc->p_pkt, ScatterGatherListPacketInfo );\r
+       if( !p_sgl )\r
+       {\r
+               ASSERT( p_sgl );\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to get SGL from packet.\n") );\r
+               return NDIS_STATUS_FAILURE;\r
+       }\r
+       if( ( p_sgl->NumberOfElements > MAX_SEND_SGE ||\r
+               p_sgl->Elements[0].Length < sizeof(eth_hdr_t)) )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Too many SG Elements in packet.\n") );\r
+               return NDIS_STATUS_FAILURE;\r
+       }\r
+       p_buf = (uint8_t *)\r
+               ExAllocateFromNPagedLookasideList( &p_port->buf_mgr.send_buf_list );\r
+       if( !p_buf )\r
+       {\r
+               IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Failed to allocate lookaside buffer.\n") );\r
+               return NDIS_STATUS_RESOURCES;\r
+       }\r
+       p_desc->p_buf = (send_buf_t*)p_buf;\r
+\r
+       if( buf_len < ip_hdr_len )\r
+       {       /* ip options in a separate buffer */\r
+               CL_ASSERT( buf_len == sizeof( ip_hdr_t ) );\r
+               NdisGetNextBuffer( p_ndis_buf, &p_ndis_buf );\r
+               if( !p_ndis_buf )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to get IP options buffer.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               NdisQueryBufferSafe( p_ndis_buf, &p_options, &options_len, NormalPagePriority );\r
+               if( !p_options )\r
+               {\r
+                       IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                               ("Failed to query IP options buffer address.\n") );\r
+                       return NDIS_STATUS_FAILURE;\r
+               }\r
+               cl_memcpy( p_buf, p_ip_hdr, sizeof( ip_hdr_t ) );\r
+               if( p_options && options_len )\r
+               { \r
+                       __copy_ip_options( &p_buf[sizeof(ip_hdr_t)], \r
+                                                               p_options, options_len, TRUE );\r
+               }\r
+               wr_size = buf_len + options_len;\r
+               sgl_idx++;\r
+       }\r
+       else\r
+       {       /*options probably in the same buffer */\r
+               cl_memcpy( p_buf, p_ip_hdr, buf_len );\r
+               options_len = ip_hdr_len - sizeof( ip_hdr_t );\r
+               if( options_len )\r
+               {\r
+                       p_options = p_buf + sizeof( ip_hdr_t );\r
+               }\r
+               frag_offset += ( buf_len - ip_hdr_len );\r
+               wr_size = buf_len;\r
+       }\r
+\r
+       p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf );\r
+       p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+       p_desc->send_wr[wr_idx].local_ds[ds_idx].length = wr_size;\r
+       \r
+       /* count how much data can be put into the first WR beside IP header.\r
+        * other protocols headers possibly supplied in subsequent buffers.\r
+        */\r
+       for( sgl_idx; sgl_idx < p_sgl->NumberOfElements; sgl_idx++ )\r
+       {\r
+               next_sge = p_sgl->Elements[sgl_idx].Length;\r
+\r
+               /* add sgl if it can fit into the same WR \r
+               * Note: so far not going to split large SGE between WRs,\r
+               * so first fragment could be a smaller size.\r
+               */\r
+               if( next_sge <= ( p_port->p_adapter->params.payload_mtu - wr_size ) )\r
+               {\r
+                       ++ds_idx;\r
+                       wr_size += next_sge;\r
+                       frag_offset += next_sge;\r
+                       p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = \r
+                                                                       p_sgl->Elements[sgl_idx].Address.QuadPart;\r
+                       p_desc->send_wr[wr_idx].local_ds[ds_idx].length = next_sge;\r
+                       p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+               }\r
+               else\r
+               {\r
+                       /* fix ip hdr for the first fragment and move on */\r
+                       __update_fragment_ip_hdr( (ip_hdr_t* const)p_buf,\r
+                               (uint16_t)wr_size, IP_FRAGMENT_OFFSET(p_ip_hdr), TRUE );\r
+\r
+                       p_desc->send_wr[wr_idx].wr.num_ds = ds_idx + 1;\r
+                       p_buf += ip_hdr_len;\r
+                       p_buf += (( buf_len > ip_hdr_len ) ? ( buf_len - ip_hdr_len ): 0);\r
+                       frag_offset += ( (IP_FRAGMENT_OFFSET(p_ip_hdr)) << 3 );\r
+                       ++wr_idx;\r
+                       ds_idx = 0;\r
+                       break;\r
+               }\r
+       }\r
+       total_ip_len -= wr_size;\r
+       wr_size = 0;\r
+\r
+       for( sgl_idx, wr_idx; sgl_idx < p_sgl->NumberOfElements; sgl_idx++ )\r
+       {\r
+               uint32_t        seg_len;\r
+               uint64_t        next_sgl_addr;\r
+               \r
+               if( wr_idx >= ( MAX_WRS_PER_MSG - 1 ) )\r
+                       return NDIS_STATUS_RESOURCES;\r
+               \r
+               next_sge = p_sgl->Elements[sgl_idx].Length;\r
+               next_sgl_addr = p_sgl->Elements[sgl_idx].Address.QuadPart;\r
+\r
+               while( next_sge )\r
+               {\r
+                       if( ds_idx == 0 )\r
+                       {       /* new ipoib + ip header */\r
+                               ((ipoib_hdr_t*)p_buf)->type = p_eth_hdr->type;\r
+                               ((ipoib_hdr_t*)p_buf)->resv = 0;\r
+                               p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf );\r
+                               p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+                               p_desc->send_wr[wr_idx].local_ds[ds_idx].length = sizeof( ipoib_hdr_t );\r
+                               p_buf += sizeof( ipoib_hdr_t );\r
+                               ++ds_idx;\r
+\r
+                               cl_memcpy( p_buf, p_ip_hdr, sizeof( ip_hdr_t ) );\r
+                               if( p_options && options_len )\r
+                               {\r
+                                       /* copy ip options if needed */\r
+                                       __copy_ip_options( &p_buf[sizeof(ip_hdr_t)], \r
+                                                               p_options, options_len, FALSE );\r
+                               }\r
+                               wr_size = ip_hdr_len;\r
+                       }\r
+                       if( ds_idx == 1 )\r
+                       {\r
+                               p_desc->send_wr[wr_idx].local_ds[ds_idx].length = ip_hdr_len;\r
+                               p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = cl_get_physaddr( p_buf );\r
+                               p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+                               ++ds_idx;\r
+                       }\r
+\r
+                       seg_len = ( next_sge > ( p_port->p_adapter->params.payload_mtu - wr_size ) )?\r
+                               ( p_port->p_adapter->params.payload_mtu - wr_size ) : next_sge;\r
+\r
+                       p_desc->send_wr[wr_idx].local_ds[ds_idx].vaddr = next_sgl_addr;\r
+                       p_desc->send_wr[wr_idx].local_ds[ds_idx].length = seg_len;\r
+                       p_desc->send_wr[wr_idx].local_ds[ds_idx].lkey = p_port->ib_mgr.lkey;\r
+                       ++ds_idx;\r
+                       \r
+                       wr_size += seg_len;\r
+                       total_ip_len -= seg_len;\r
+\r
+                       if( wr_size >= p_port->p_adapter->params.payload_mtu || total_ip_len == 0 )\r
+                       {       /* fix ip hdr for that fragment */\r
+                               __update_fragment_ip_hdr( (ip_hdr_t* const)p_buf, (uint16_t)wr_size,\r
+                                       ((uint16_t)(frag_offset >> 3 )), \r
+                                       (BOOLEAN)(( total_ip_len > 0 ) || IP_MORE_FRAGMENTS( p_ip_hdr)) );\r
+                               p_desc->send_wr[wr_idx].wr.num_ds = ds_idx;\r
+                               if( total_ip_len > 0 )\r
+                               {\r
+                                       ++wr_idx;\r
+                                       frag_offset += (wr_size - ip_hdr_len);\r
+                                       wr_size = 0;\r
+                                       ds_idx = 0;\r
+                                       p_buf += ip_hdr_len;\r
+                               }\r
+                       }\r
+                       next_sge -= seg_len;\r
+                       if( next_sge > 0 )\r
+                       {\r
+                               next_sgl_addr += seg_len;\r
+                       }\r
+               }\r
+       }\r
+       p_desc->num_wrs += wr_idx;\r
+       \r
+       IPOIB_EXIT( IPOIB_DBG_SEND );\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+#endif\r
+\r
+static void\r
+__update_fragment_ip_hdr(\r
+IN             ip_hdr_t* const         p_ip_hdr,\r
+IN             uint16_t                        fragment_size, \r
+IN             uint16_t                        fragment_offset, \r
+IN             BOOLEAN                         more_fragments )\r
+{\r
+       uint16_t*       p_hdr = (uint16_t*)p_ip_hdr;\r
+       p_ip_hdr->length = cl_hton16( fragment_size ); // bytes\r
+       p_ip_hdr->offset = cl_hton16( fragment_offset ); // 8-byte units\r
+       if( more_fragments )\r
+       {\r
+               IP_SET_MORE_FRAGMENTS( p_ip_hdr );\r
+       }\r
+       else\r
+       {\r
+               IP_SET_LAST_FRAGMENT( p_ip_hdr );\r
+       }\r
+       p_ip_hdr->chksum = 0;\r
+       p_ip_hdr->chksum = ipchksum( p_hdr, IP_HEADER_LENGTH(p_ip_hdr) );\r
+}\r
+\r
+static void\r
+__copy_ip_options(\r
+IN             uint8_t*        p_buf,\r
+IN             uint8_t*        p_options,\r
+IN             uint32_t        options_len,\r
+IN             BOOLEAN         copy_all )\r
+{\r
+       uint32_t        option_length;\r
+       uint32_t        total_length = 0;\r
+       uint32_t        copied_length = 0;\r
+       uint8_t*        p_src = p_options;\r
+       uint8_t*        p_dst = p_buf;\r
+\r
+       if( p_options == NULL || options_len == 0 )\r
+               return;\r
+       if( copy_all )\r
+       {\r
+               cl_memcpy( p_dst, p_src, options_len );\r
+               return;\r
+       }\r
+       do\r
+       {\r
+               if( ( *p_src ) == 0 ) // end of options list\r
+               {\r
+                       total_length++;\r
+                       break;\r
+               }\r
+               if( ( *p_src ) == 0x1 ) // no op\r
+               {\r
+                       p_src++;\r
+                       total_length++;\r
+                       continue;\r
+               }\r
+               /*from RFC791: \r
+               * This option may be used between options, for example, to align\r
+        * the beginning of a subsequent option on a 32 bit boundary.\r
+               */\r
+               if( copied_length && (copied_length % 4) )\r
+               {\r
+                       uint32_t align = 4 - (copied_length % 4);\r
+                       cl_memset( p_dst, 0x1, (size_t)align );\r
+                       p_dst += align;\r
+                       copied_length += align;\r
+               }\r
+               option_length = *(p_src + 1);\r
+\r
+               if( *p_src & 0x80 )\r
+               {\r
+                       cl_memcpy( p_dst, p_src, option_length );\r
+                       p_dst += option_length;\r
+                       copied_length += option_length;\r
+               }\r
+               total_length += option_length;\r
+               p_src += option_length;\r
+\r
+       }while( total_length < options_len );\r
+\r
+       CL_ASSERT( total_length == options_len );\r
+       CL_ASSERT( copied_length <= 40 );\r
+\r
+       /* padding the rest */\r
+       if( options_len > copied_length )\r
+       {\r
+               cl_memclr( p_dst, ( options_len - copied_length ) );\r
+       }\r
+       return;\r
+}\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.h b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_port.h
new file mode 100644 (file)
index 0000000..602389b
--- /dev/null
@@ -0,0 +1,827 @@
+/*\r
+ * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
+ * Portions 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: ipoib_port.h 4226 2009-04-06 06:01:03Z xalex $\r
+ */\r
+\r
+\r
+\r
+#ifndef _IPOIB_PORT_H_\r
+#define _IPOIB_PORT_H_\r
+\r
+\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_obj.h>\r
+#include <complib/cl_qmap.h>\r
+#include <complib/cl_fleximap.h>\r
+#include <ip_packet.h>\r
+#include "ipoib_xfr_mgr.h"\r
+#include "ipoib_endpoint.h"\r
+\r
+\r
+/*\r
+ * Define to place receive buffer inline in receive descriptor.\r
+ */\r
+#define IPOIB_INLINE_RECV      1\r
+\r
+/* \r
+ *  Invalid pkey index\r
+ */\r
+#define PKEY_INVALID_INDEX     0xFFFF\r
+\r
+/*\r
+ * Define to control how transfers are done.  When defined as 1, causes\r
+ * packets to be sent using NDIS DMA facilities (getting the SGL from the\r
+ * packet).  When defined as 0, uses the NDIS_BUFFER structures as MDLs\r
+ * to get the physical page mappings of the buffers.\r
+ */\r
+#define IPOIB_USE_DMA  1\r
+\r
+\r
+#define IPOIB_PORT_FROM_PACKET( P )    \\r
+       (((ipoib_port_t**)NET_BUFFER_LIST_MINIPORT_RESERVED(P))[0])\r
+#define IPOIB_ENDPT_FROM_PACKET( P )   \\r
+       (((ipoib_endpt_t**)NET_BUFFER_LIST_MINIPORT_RESERVED(P))[1])\r
+#define IPOIB_RECV_FROM_PACKET( P )    \\r
+       (((ipoib_recv_desc_t**)NET_BUFFER_LIST_MINIPORT_RESERVED(P))[1])\r
+       \r
+//TODO to be renamed: IPOIB_NBL_FROM_LIST_ITEM\r
+#define IPOIB_PACKET_FROM_LIST_ITEM( I ) \\r
+       (PARENT_STRUCT( I, NET_BUFFER_LIST, MiniportReserved ))\r
+#define IPOIB_LIST_ITEM_FROM_PACKET( P ) \\r
+       ((cl_list_item_t*)NET_BUFFER_LIST_MINIPORT_RESERVED(P))\r
+\r
+#define IPOIB_NET_BUFFER_LIST_FROM_NETBUFFER( P )      \\r
+       (((NET_BUFFER_LIST**)NET_BUFFER_MINIPORT_RESERVED(P))[0])\r
+#define IPOIB_FROM_QUEUE( P )  \\r
+       (((void**)NET_BUFFER_MINIPORT_RESERVED(P))[1])\r
+#define IPOIB_SEND_FROM_NETBUFFER( P ) \\r
+       (((send_buf_t**)NET_BUFFER_MINIPORT_RESERVED(P))[2])\r
+\r
+\r
+#define IPOIB_GET_NET_BUFFER_LIST_REF_COUNT(_NetBufferList)    ((_NetBufferList->FirstNetBuffer)->MiniportReserved[3])\r
+#define IPOIB_DEC_NET_BUFFER_LIST_REF_COUNT(_NetBufferList)    (*(PULONG)&(_NetBufferList->FirstNetBuffer)->MiniportReserved[3])--\r
+\r
+\r
+typedef struct _ipoib_ib_mgr\r
+{\r
+       ib_ca_handle_t                  h_ca;\r
+       ib_pd_handle_t                  h_pd;\r
+       ib_cq_handle_t                  h_recv_cq;\r
+       ib_cq_handle_t                  h_send_cq;\r
+       ib_qp_handle_t                  h_qp;\r
+       ib_query_handle_t               h_query;\r
+       ib_srq_handle_t                 h_srq;\r
+       net32_t                                 qpn;\r
+\r
+       ib_mr_handle_t                  h_mr;\r
+       net32_t                                 lkey;\r
+\r
+       uint8_t                                 rate;\r
+       ib_member_rec_t                 bcast_rec;\r
+\r
+}      ipoib_ib_mgr_t;\r
+/*\r
+* FIELDS\r
+*      h_ca\r
+*              CA handle for all IB resources.\r
+*\r
+*      h_pd\r
+*              PD handle for all IB resources.\r
+*\r
+*      h_recv_cq\r
+*              Recv CQ handle.\r
+*\r
+*      h_send_cq\r
+*              Send CQ handle.\r
+*\r
+*      h_qp\r
+*              QP handle for data transfers.\r
+*\r
+*      h_query\r
+*              Query handle for cancelling SA queries.\r
+*\r
+*      h_mr\r
+*              Registration handle for all of physical memory.  Used for\r
+*              send/receive buffers to simplify growing the receive pool.\r
+*\r
+*      lkey\r
+*              LKey for the memory region.\r
+*\r
+*      bcast_rec\r
+*              Cached information about the broadcast group, used to specify\r
+*              parameters used to join other multicast groups.\r
+*********/\r
+\r
+\r
+#include <complib/cl_packon.h>\r
+/****s* IPoIB Driver/ipoib_hdr_t\r
+* NAME\r
+*      ipoib_hdr_t\r
+*\r
+* DESCRIPTION\r
+*      IPoIB packet header.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ipoib_hdr\r
+{\r
+       net16_t                 type;\r
+       net16_t                 resv;\r
+\r
+}      PACK_SUFFIX ipoib_hdr_t;\r
+/*\r
+* FIELDS\r
+*      type\r
+*              Protocol type.\r
+*\r
+*      resv\r
+*              Reserved portion of IPoIB header.\r
+*********/\r
+\r
+typedef struct _ipoib_arp_pkt\r
+{\r
+       net16_t                 hw_type;\r
+       net16_t                 prot_type;\r
+       uint8_t                 hw_size;\r
+       uint8_t                 prot_size;\r
+       net16_t                 op;\r
+       ipoib_hw_addr_t src_hw;\r
+       net32_t                 src_ip;\r
+       ipoib_hw_addr_t dst_hw;\r
+       net32_t                 dst_ip;\r
+\r
+}      PACK_SUFFIX ipoib_arp_pkt_t;\r
+\r
+\r
+/****s* IPoIB Driver/ipoib_pkt_t\r
+* NAME\r
+*      ipoib_pkt_t\r
+*\r
+* DESCRIPTION\r
+*      Represents an IPoIB packet with no GRH.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ipoib_pkt\r
+{\r
+       ipoib_hdr_t             hdr;\r
+       union _payload\r
+       {\r
+               uint8_t                 data[MAX_UD_PAYLOAD_MTU];\r
+               ipoib_arp_pkt_t arp;\r
+               ip_pkt_t                ip;\r
+\r
+       }       PACK_SUFFIX type;\r
+\r
+}      PACK_SUFFIX ipoib_pkt_t;\r
+/*\r
+* FIELDS\r
+*      hdr\r
+*              IPoIB header.\r
+*\r
+*      type\r
+*              Union for different types of payloads.\r
+*\r
+*      type.data\r
+*              raw packet.\r
+*\r
+*      type.ib_arp\r
+*              IPoIB ARP packet.\r
+*\r
+*      type.arp\r
+*              Ethernet ARP packet.\r
+*\r
+*      type.ip\r
+*              IP packet.\r
+*********/\r
+\r
+\r
+/****s* IPoIB Driver/recv_buf_t\r
+* NAME\r
+*      recv_buf_t\r
+*\r
+* DESCRIPTION\r
+*      Represents a receive buffer, including the ethernet header\r
+*      used to indicate the receive to the OS.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef union _recv_buf\r
+{\r
+       struct _recv_buf_type_eth\r
+       {\r
+               uint8_t                 pad[sizeof(ib_grh_t) +\r
+                                                       sizeof(ipoib_hdr_t) -\r
+                                                       sizeof(eth_hdr_t)];\r
+               eth_pkt_t               pkt;    /* data starts at sizeof(grh)+sizeof(eth_hdr) */\r
+\r
+       }       PACK_SUFFIX eth;\r
+\r
+       struct _recv_buf_type_ib\r
+       {\r
+               ib_grh_t                grh;    /* Must be same offset as lcl_rt.ib.pkt */\r
+               ipoib_pkt_t             pkt;    /* data starts at 10+grh+4 */\r
+\r
+       }       PACK_SUFFIX ib;\r
+\r
+}      PACK_SUFFIX recv_buf_t;\r
+/*\r
+* FIELDS\r
+*      eth.pkt\r
+*              Ethernet packet, used to indicate the receive to the OS.\r
+*\r
+*      ib.grh\r
+*              GRH for a globally routed received packet.\r
+*\r
+*      ib.pkt\r
+*              IPOIB packet representing a globally routed received packet.\r
+*\r
+* NOTES\r
+*      When posting the work request, the address of ib.grh is used.\r
+*\r
+*      TODO: Do we need a pad to offset the header so that the data ends up\r
+*      aligned on a pointer boundary?\r
+*********/\r
+\r
+/****s* IPoIB Driver/send_buf_t\r
+* NAME\r
+*      send_buf_t\r
+*\r
+* DESCRIPTION\r
+*      Represents a send buffer, used to convert packets to IPoIB format.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef union _send_buf\r
+{\r
+       uint8_t                 data[MAX_UD_PAYLOAD_MTU];\r
+       ipoib_arp_pkt_t arp;\r
+       ip_pkt_t                ip;\r
+\r
+}      PACK_SUFFIX send_buf_t;\r
+/*\r
+* FIELDS\r
+*      data\r
+*              IP/ARP packet.\r
+*\r
+* NOTES\r
+*      TODO: Do we need a pad to offset the header so that the data ends up\r
+*      aligned on a pointer boundary?\r
+*********/\r
+#include <complib/cl_packoff.h>\r
+\r
+\r
+typedef struct _ipoib_buf_mgr\r
+{\r
+       cl_qpool_t                      recv_pool;\r
+\r
+       NDIS_HANDLE                     h_packet_pool;\r
+       NDIS_HANDLE                     h_buffer_pool;\r
+\r
+       NPAGED_LOOKASIDE_LIST   send_buf_list;\r
+       NDIS_HANDLE                     h_send_pkt_pool;\r
+       NDIS_HANDLE                     h_send_buf_pool;\r
+\r
+}      ipoib_buf_mgr_t;\r
+/*\r
+* FIELDS\r
+*      recv_pool\r
+*              Pool of ipoib_recv_desc_t structures.\r
+*\r
+*      h_packet_pool\r
+*              NDIS packet pool, used to indicate receives to NDIS.\r
+*\r
+*      h_buffer_pool\r
+*              NDIS buffer pool, used to indicate receives to NDIS.\r
+*\r
+*      send_buf_list\r
+*              Lookaside list for dynamically allocating send buffers for send\r
+*              that require copies (ARP, DHCP, and any with more physical pages\r
+*              than can fit in the local data segments).\r
+*********/\r
+\r
+\r
+typedef enum _ipoib_pkt_type\r
+{\r
+       PKT_TYPE_UCAST,\r
+       PKT_TYPE_BCAST,\r
+       PKT_TYPE_MCAST,\r
+       PKT_TYPE_CM_UCAST\r
+\r
+}      ipoib_pkt_type_t;\r
+\r
+typedef struct _ipoib_cm_desc\r
+{\r
+       cl_pool_item_t                          item;   /* Must be first. */\r
+       uint32_t                                        len;\r
+       ipoib_pkt_type_t                        type;\r
+       ib_recv_wr_t                            wr;\r
+       ib_local_ds_t                           local_ds[2];\r
+       cl_list_item_t                          list_item;\r
+       uint8_t*                                        p_alloc_buf;\r
+       uint8_t*                                        p_buf;\r
+       uint32_t                                        alloc_buf_size;\r
+       uint32_t                                        buf_size;\r
+       net32_t                                         lkey;\r
+       ib_mr_handle_t                          h_mr;\r
+       NDIS_TCP_IP_CHECKSUM_PACKET_INFO        ndis_csum;\r
+\r
+}      ipoib_cm_desc_t;\r
+\r
+typedef struct _ipoib_recv_desc\r
+{\r
+       cl_pool_item_t          item;   /* Must be first. */\r
+       uint32_t                        len;\r
+       ipoib_pkt_type_t        type;\r
+       ib_recv_wr_t            wr;\r
+       ib_local_ds_t           local_ds[2];\r
+       NDIS_TCP_IP_CHECKSUM_PACKET_INFO        ndis_csum;\r
+#if IPOIB_INLINE_RECV\r
+       recv_buf_t                      buf;\r
+#else\r
+       recv_buf_t                      *p_buf;\r
+#endif\r
+\r
+}      ipoib_recv_desc_t;\r
+/*\r
+* FIELDS\r
+*      item\r
+*              Pool item for storing descriptors in a pool.\r
+*\r
+*      len\r
+*              Length to indicate to NDIS.  This is different than the length of the\r
+*              received data as some data is IPoIB specific and filtered out.\r
+*\r
+*      type\r
+*              Type of packet, used in filtering received packets against the packet\r
+*              filter.  Also used to update stats.\r
+*\r
+*      wr\r
+*              Receive work request.\r
+*\r
+*      local_ds\r
+*              Local data segments.  The second segment is only used if a buffer\r
+*              spans physical pages.\r
+*\r
+*      buf\r
+*              Buffer for the receive.\r
+*\r
+* NOTES\r
+*      The pool item is always first to allow casting form a cl_pool_item_t or\r
+*      cl_list_item_t to the descriptor.\r
+*********/\r
+typedef struct __ipoib_send_wr\r
+{\r
+       ib_send_wr_t            wr;\r
+       ib_local_ds_t           local_ds[MAX_SEND_SGE]; /* Must be last. */\r
+} ipoib_send_wr_t;\r
+\r
+typedef enum __send_dir\r
+{\r
+       SEND_UD_QP = 1,\r
+       SEND_RC_QP = 2\r
+} send_dir_t;\r
+\r
+typedef struct _ipoib_send_desc\r
+{\r
+       PNET_BUFFER_LIST    p_netbuf_list;\r
+       ipoib_endpt_t           *p_endpt;\r
+       send_buf_t                      *p_buf;\r
+       ib_qp_handle_t          send_qp;\r
+       send_dir_t                      send_dir;\r
+       uint32_t                        num_wrs;\r
+       ipoib_send_wr_t         send_wr[MAX_WRS_PER_MSG];\r
+\r
+}      ipoib_send_desc_t;\r
+/*\r
+* FIELDS\r
+*      p_pkt\r
+*              Pointer to the NDIS_PACKET associated with the send operation.\r
+*\r
+*      p_endpt\r
+*              Endpoint for this send.\r
+*\r
+*      p_buf\r
+*              Buffer for the send, if allocated.\r
+*\r
+*      wr\r
+*              Send work request.\r
+*\r
+*      pkt_hdr\r
+*              IPoIB packet header, pointed to by the first local datasegment.\r
+*\r
+*      local_ds\r
+*              Local data segment array.  Placed last to allow allocating beyond the\r
+*              end of the descriptor for additional datasegments.\r
+*\r
+* NOTES\r
+*      The pool item is always first to allow casting form a cl_pool_item_t or\r
+*      cl_list_item_t to the descriptor.\r
+*********/\r
+\r
+\r
+typedef struct _ipoib_recv_mgr\r
+{\r
+       int32_t                 depth;\r
+\r
+       NET_BUFFER_LIST         **recv_pkt_array;\r
+\r
+       cl_qlist_t              done_list;\r
+\r
+}      ipoib_recv_mgr_t;\r
+/*\r
+* FIELDS\r
+*      depth\r
+*              Current number of WRs posted.\r
+*\r
+*      p_head\r
+*              Pointer to work completion in descriptor at the head of the QP.\r
+*\r
+*      p_tail\r
+*              Pointer to the work completion in the descriptor at the tail of the QP.\r
+*\r
+*      recv_pkt_array\r
+*              Array of pointers to NDIS_PACKET used to indicate receives.\r
+*\r
+*      done_list\r
+*              List of receive descriptors that need to be indicated to NDIS.\r
+*********/\r
+\r
+\r
+typedef struct _ipoib_send_mgr\r
+{\r
+       atomic32_t              depth;\r
+       cl_qlist_t              pending_list;\r
+       ipoib_send_desc_t desc;\r
+\r
+}      ipoib_send_mgr_t;\r
+/*\r
+* FIELDS\r
+*      depth\r
+*              Current number of WRs posted, used to queue pending requests.\r
+*\r
+*      pending_list\r
+*              List of NDIS_PACKET structures that are awaiting available WRs to send.\r
+*********/\r
+\r
+\r
+typedef struct _ipoib_endpt_mgr\r
+{\r
+       cl_qmap_t                               mac_endpts;\r
+       cl_fmap_t                               gid_endpts;\r
+       cl_qmap_t                               lid_endpts;\r
+       cl_fmap_t                               conn_endpts;\r
+       LIST_ENTRY                      pending_conns;\r
+       LIST_ENTRY                              remove_conns;\r
+       NDIS_SPIN_LOCK                  conn_lock;\r
+       NDIS_SPIN_LOCK                  remove_lock;\r
+       cl_thread_t                             h_thread;\r
+       cl_event_t                              event;\r
+       uint32_t                                thread_is_done;\r
+}      ipoib_endpt_mgr_t;\r
+/*\r
+* FIELDS\r
+*      mac_endpts\r
+*              Map of enpoints, keyed by MAC address.\r
+*\r
+*      gid_endpts\r
+*              Map of enpoints, keyed by GID.\r
+*\r
+*      lid_endpts\r
+*              Map of enpoints, keyed by LID.  Only enpoints on the same subnet\r
+*              are inserted in the LID map.\r
+*\r
+*      conn_endpts\r
+*              Map of connected endpts, keyed by remote gid.\r
+*********/\r
+\r
+\r
+typedef struct _ipoib_port\r
+{\r
+       cl_obj_t                                obj;\r
+       cl_obj_rel_t                    rel;\r
+\r
+       ib_qp_state_t                   state;\r
+\r
+       cl_spinlock_t                   recv_lock;\r
+       cl_spinlock_t                   send_lock;\r
+\r
+       struct _ipoib_adapter   *p_adapter;\r
+       uint8_t                                 port_num;\r
+\r
+       KEVENT                                  sa_event;\r
+\r
+       atomic32_t                              mcast_cnt;\r
+       KEVENT                                  leave_mcast_event;\r
+       \r
+       ipoib_ib_mgr_t                  ib_mgr;\r
+\r
+       ipoib_buf_mgr_t                 buf_mgr;\r
+\r
+       ipoib_recv_mgr_t                recv_mgr;\r
+       ipoib_send_mgr_t                send_mgr;\r
+\r
+       KDPC                                    recv_dpc;\r
+\r
+       ipoib_endpt_mgr_t               endpt_mgr;\r
+\r
+       endpt_buf_mgr_t                 cm_buf_mgr;\r
+       endpt_recv_mgr_t                cm_recv_mgr;\r
+\r
+       ipoib_endpt_t                   *p_local_endpt;\r
+       ib_ca_attr_t                    *p_ca_attrs;\r
+#if DBG\r
+       atomic32_t                              ref[ref_array_size];\r
+#endif\r
+\r
+       atomic32_t                              endpt_rdr;\r
+\r
+       atomic32_t                              hdr_idx;\r
+       uint16_t                                pkey_index;\r
+       KDPC                                    gc_dpc;\r
+       KTIMER                                  gc_timer;\r
+       uint32_t                                bc_join_retry_cnt;\r
+       ib_net16_t                              base_lid;\r
+       ipoib_hdr_t                             hdr[1]; /* Must be last! */\r
+\r
+}      ipoib_port_t;\r
+/*\r
+* FIELDS\r
+*      obj\r
+*              Complib object for reference counting, relationships,\r
+*              and destruction synchronization.\r
+*\r
+*      rel\r
+*              Relationship to associate the port with the adapter.\r
+*\r
+*      state\r
+*              State of the port object.  Tracks QP state fairly closely.\r
+*\r
+*      recv_lock\r
+*              Spinlock to protect receive operations.\r
+*\r
+*      send_lock\r
+*              Spinlock to protect send operations.\r
+*\r
+*      p_adapter\r
+*              Parent adapter.  Used to get AL handle.\r
+*\r
+*      port_num\r
+*              Port number of this adapter.\r
+*\r
+*      ib_mgr\r
+*              IB resource manager.\r
+*\r
+*      recv_mgr\r
+*              Receive manager.\r
+*\r
+*      send_mgr\r
+*              Send manager.\r
+*\r
+*      endpt_mgr\r
+*              Endpoint manager.\r
+*********/\r
+typedef struct _sgl_context\r
+{\r
+       MDL                                     *p_mdl;\r
+       NET_BUFFER_LIST         *p_netbuffer_list;\r
+       ipoib_port_t            *p_port;\r
+}sgl_context_t;\r
+\r
+ib_api_status_t\r
+ipoib_create_port(\r
+       IN                              struct _ipoib_adapter* const    p_adapter,\r
+       IN                              ib_pnp_port_rec_t* const        p_pnp_rec,\r
+               OUT                     ipoib_port_t** const            pp_port );\r
+\r
+void\r
+ipoib_port_destroy(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+void\r
+ipoib_port_up(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ib_pnp_port_rec_t* const        p_pnp_rec );\r
+\r
+void\r
+ipoib_port_down(\r
+       IN                              ipoib_port_t* const                     p_port );\r
+\r
+ib_api_status_t\r
+ipoib_port_join_mcast(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                              mac,\r
+       IN              const   uint8_t                                 state );\r
+\r
+\r
+void\r
+ipoib_leave_mcast_cb(\r
+       IN                              void                            *context );\r
+\r
+\r
+void\r
+ipoib_port_remove_endpt(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac );\r
+\r
+void\r
+ipoib_port_send(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN                              NET_BUFFER_LIST                         *net_buffer_list,\r
+       IN                              ULONG                                           send_flags );\r
+\r
+void\r
+ipoib_return_net_buffer_list(\r
+       IN                              NDIS_HANDLE                                     adapter_context,\r
+       IN                              PNET_BUFFER_LIST                        p_netbuffer_lists,\r
+       IN                              ULONG                                           return_flags);\r
+\r
+void\r
+ipoib_port_resume(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN boolean_t                                                            b_pending );\r
+\r
+NTSTATUS\r
+ipoib_mac_to_gid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ib_gid_t*                                       p_gid );\r
+\r
+NTSTATUS\r
+ipoib_mac_to_path(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   mac_addr_t                                      mac,\r
+               OUT                     ib_path_rec_t*                          p_path );\r
+\r
+void \r
+ipoib_process_sg_list(\r
+    IN  PDEVICE_OBJECT          pDO,\r
+    IN  PVOID                   pIrp,\r
+    IN  PSCATTER_GATHER_LIST    pSGList,\r
+    IN  PVOID                   Context);\r
+    \r
+inline void ipoib_port_ref(\r
+       IN                              ipoib_port_t *                          p_port, \r
+       IN                              int                                             type);\r
+\r
+inline void ipoib_port_deref(\r
+       IN                              ipoib_port_t *                          p_port,\r
+       IN                              int                                             type);\r
+\r
+#if 0\r
+// This function is only used to monitor send failures\r
+static inline VOID NdisMSendCompleteX(\r
+       IN NDIS_HANDLE  MiniportAdapterHandle,\r
+       IN PNDIS_PACKET  Packet,\r
+       IN NDIS_STATUS  Status\r
+       ) {\r
+       if (Status != NDIS_STATUS_SUCCESS) {\r
+               IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
+                       ("Sending status other than Success to NDIS\n"));\r
+       }\r
+       NdisMSendComplete(MiniportAdapterHandle,Packet,Status);\r
+}\r
+#else\r
+//#define NdisMSendCompleteX NdisMSendComplete\r
+#endif\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_get_by_gid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ib_gid_t* const                         p_gid );\r
+\r
+ipoib_endpt_t*\r
+ipoib_endpt_get_by_lid(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   net16_t                                         lid );\r
+\r
+ib_api_status_t\r
+ipoib_port_srq_init(\r
+       IN              ipoib_port_t* const             p_port );\r
+\r
+void\r
+ipoib_port_srq_destroy( \r
+       IN              ipoib_port_t* const             p_port );\r
+\r
+#if 0 //CM\r
+ib_api_status_t\r
+ipoib_port_listen(\r
+        IN             ipoib_port_t* const             p_port );\r
+\r
+ib_api_status_t\r
+ipoib_port_cancel_listen(\r
+       IN              ipoib_port_t*   const   p_port,\r
+       IN              ipoib_endpt_t* const    p_endpt ) {\r
+       UNUSED_PARAM(p_port);\r
+       UNUSED_PARAM(p_endpt);\r
+       return IB_SUCCESS;\r
+}\r
+#endif \r
+\r
+ib_api_status_t\r
+endpt_cm_buf_mgr_init(\r
+       IN              ipoib_port_t* const                     p_port );\r
+\r
+void\r
+endpt_cm_buf_mgr_destroy(\r
+       IN              ipoib_port_t* const             p_port );\r
+\r
+void\r
+endpt_cm_buf_mgr_reset(\r
+       IN              ipoib_port_t* const             p_port );\r
+\r
+void\r
+endpt_cm_buf_mgr_put_recv(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr,\r
+       IN              ipoib_cm_desc_t* const          p_desc );\r
+\r
+void\r
+endpt_cm_buf_mgr_put_recv_list(\r
+       IN              endpt_buf_mgr_t * const         p_buf_mgr,\r
+       IN              cl_qlist_t* const                       p_list );\r
+\r
+uint32_t\r
+endpt_cm_recv_mgr_build_pkt_array(\r
+       IN              ipoib_port_t* const                     p_port,\r
+       IN              ipoib_endpt_t* const            p_endpt,\r
+       IN              cl_qlist_t* const                       p_done_list,\r
+       IN OUT  uint32_t*                                       p_bytes_recv );\r
+\r
+ib_api_status_t\r
+endpt_cm_post_recv(\r
+       IN              ipoib_port_t* const                     p_port );\r
+\r
+/*void\r
+endpt_cm_destroy_conn(\r
+       IN              ipoib_port_t* const                     p_port,\r
+       IN              ipoib_endpt_t* const            p_endpt );\r
+*/\r
+void\r
+endpt_cm_disconnect(\r
+       IN              ipoib_port_t*   const           p_port,\r
+       IN              ipoib_endpt_t*  const           p_endpt );\r
+void\r
+endpt_cm_flush_recv(\r
+       IN                              ipoib_port_t* const             p_port,\r
+       IN                              ipoib_endpt_t* const    p_endpt );\r
+\r
+ib_api_status_t\r
+ipoib_recv_dhcp(\r
+       IN                              ipoib_port_t* const                     p_port,\r
+       IN              const   ipoib_pkt_t* const                      p_ipoib,\r
+               OUT                     eth_pkt_t* const                        p_eth,\r
+       IN                              ipoib_endpt_t* const            p_src,\r
+       IN                              ipoib_endpt_t* const            p_dst );\r
+\r
+void\r
+ipoib_port_cancel_xmit(\r
+       IN                              ipoib_port_t* const             p_port,\r
+       IN                              PVOID                                    cancel_id );\r
+\r
+static inline uint32_t\r
+__port_attr_to_mtu_size(uint32_t value)\r
+{\r
+       switch (value) \r
+       {\r
+       default:\r
+       case IB_MTU_LEN_2048:\r
+               return 2048;\r
+       case IB_MTU_LEN_4096:\r
+               return 4096;\r
+       case IB_MTU_LEN_1024:\r
+               return 1024;\r
+       case IB_MTU_LEN_512:\r
+               return  512;\r
+       case IB_MTU_LEN_256:\r
+               return  256;\r
+       }\r
+}\r
+#endif /* _IPOIB_PORT_H_ */\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_xfr_mgr.c b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_xfr_mgr.c
new file mode 100644 (file)
index 0000000..ce0650f
--- /dev/null
@@ -0,0 +1,74 @@
+/*\r
+ * Copyright (c) 2008 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: ipoib_xfr_mgr.c 3459 2008-11-12 16:48:21Z tzachid $\r
+ */\r
+\r
+\r
+#include "ipoib_xfr_mgr.h"\r
+#if defined(EVENT_TRACING)\r
+#ifdef offsetof\r
+#undef offsetof\r
+#endif\r
+#include "ipoib_xfr_mgr.tmh"\r
+#endif\r
+\r
+\r
+const ipoib_guid2mac_translation_t guid2mac_table[] = {\r
+       {0x30, 0x48, 0xE7},\r
+       {0x05, 0xAD, 0xE7},\r
+       {0x18, 0x8B, 0xE7},\r
+       {0x1A, 0x4B, 0xE7},\r
+       {0x17, 0x08, 0xE7},\r
+       {0x1E, 0x0B, 0xE7},\r
+\r
+       {0x03, 0xBA, 0xE7},\r
+       {0x05, 0xAD, 0xE7},\r
+       {0x0D, 0x9D, 0xE7},\r
+       {0x11, 0x0A, 0xE7},\r
+       {0x11, 0x85, 0xE7},\r
+       {0x12, 0x79, 0xE7},\r
+       {0x13, 0x21, 0xE7},\r
+       {0x14, 0x38, 0xE7},\r
+       {0x16, 0x35, 0xE7},\r
+       {0x17, 0x08, 0xE7},\r
+       {0x17, 0xA4, 0xE7},\r
+       {0x18, 0x8B, 0xE7},\r
+       {0x18, 0xFE, 0xE7},\r
+       {0x19, 0xBB, 0xE7},\r
+       {0x1A, 0x4B, 0xE7},\r
+       {0x1B, 0x78, 0xE7},\r
+       {0x1E, 0x0B, 0xE7},\r
+       {0x22, 0x64, 0xE7},\r
+       {0x23, 0x7D, 0xE7},\r
+       {0x30, 0x48, 0xE7},\r
+       {0x80, 0x5F, 0xE7},\r
+\r
+       {0x00, 0x00, 0x00},\r
+};\r
+\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_xfr_mgr.h b/trunk/ulp/ipoib_NDIS6_CM/kernel/ipoib_xfr_mgr.h
new file mode 100644 (file)
index 0000000..9e38b60
--- /dev/null
@@ -0,0 +1,513 @@
+/*\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: ipoib_xfr_mgr.h 3719 2009-01-07 12:31:52Z reuven $\r
+ */\r
+\r
+\r
+#ifndef _IPOIB_XFR_MGR_H_\r
+#define _IPOIB_XFR_MGR_H_\r
+\r
+\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_types.h>\r
+#include <complib/cl_qpool.h>\r
+#include <complib/cl_spinlock.h>\r
+#include <complib/cl_qlist.h>\r
+#include <complib/cl_qpool.h>\r
+#include <complib/cl_list.h>\r
+\r
+\r
+#include "ipoib_driver.h"\r
+#include "ip_stats.h"\r
+#include <ip_packet.h>\r
+\r
+\r
+#include <complib/cl_packon.h>\r
+/****s* IPoIB Driver/ipoib_hw_addr_t\r
+* NAME\r
+*   ipoib_hw_addr_t\r
+*\r
+* DESCRIPTION\r
+*   The ipoib_hw_addr_t structure defines an IPoIB compatible hardware\r
+*   address.  Values in this structure are stored in network order.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ipoib_hw_addr\r
+{\r
+       uint32_t        flags_qpn;\r
+       ib_gid_t        gid;\r
+\r
+}      PACK_SUFFIX ipoib_hw_addr_t;\r
+/*\r
+* FIELDS\r
+*      flags_qpn\r
+*              Flags and queue pair number.  Use ipoib_addr_get_flags,\r
+*              ipoib_addr_set_flags, ipoib_addr_set_qpn, and ipoib_addr_get_qpn\r
+*              to manipulate the contents.\r
+*\r
+*      gid\r
+*              IB GID value.\r
+*\r
+* SEE ALSO\r
+*      IPoIB, ipoib_addr_get_flags, ipoib_addr_set_flags, ipoib_addr_set_qpn,\r
+*      ipoib_addr_get_qpn\r
+*********/\r
+#include <complib/cl_packoff.h>\r
+\r
+/****s* IPoIB Driver/ipoib_guid2mac_translation_t\r
+* NAME\r
+*   ipoib_guid2mac_translation_t\r
+*\r
+* DESCRIPTION\r
+*   The ipoib_guid2mac_translation_t structure defines a GUID to MAC translation.\r
+*   The structure holds map between known OUI to an appropriate GUID mask.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ipoib_guid2mac_translation_\r
+{\r
+       uint8_t second_byte;\r
+       uint8_t third_byte;\r
+       uint8_t guid_mask;\r
+       \r
+}      ipoib_guid2mac_translation_t;\r
+/*\r
+* FIELDS\r
+*      second_byte\r
+*              second byte of OUI (located in lower three bytes of GUID).\r
+*\r
+*      third_byte\r
+*              third byte of OUI (located in lower three bytes of GUID).\r
+*\r
+*      guid_mask\r
+*              GUID mask that will be used to generate MAC from the GUID.      \r
+*\r
+* SEE ALSO\r
+*      IPoIB, ipoib_mac_from_guid_mask\r
+*********/\r
+\r
+extern const ipoib_guid2mac_translation_t guid2mac_table[];\r
+\r
+#ifdef __cplusplus\r
+extern "C"\r
+{\r
+#endif\r
+\r
+\r
+/*\r
+ * Address accessors\r
+ */\r
+\r
+static inline uint8_t\r
+ipoib_addr_get_flags(\r
+       IN              const   ipoib_hw_addr_t* const          p_addr )\r
+{\r
+       return (uint8_t)( p_addr->flags_qpn & 0x000000ff);\r
+}\r
+\r
+static inline void\r
+ipoib_addr_set_flags(\r
+       IN                              ipoib_hw_addr_t* const          p_addr,\r
+       IN              const   uint8_t                                         flags )\r
+{\r
+       p_addr->flags_qpn &= ( 0xFFFFFF00 );\r
+       p_addr->flags_qpn |= ( flags );\r
+}\r
+\r
+static inline net32_t\r
+ipoib_addr_get_qpn(\r
+       IN              const   ipoib_hw_addr_t* const          p_addr )\r
+{\r
+       return( ( p_addr->flags_qpn ) & 0xffffff00 );\r
+}\r
+\r
+static inline void\r
+ipoib_addr_set_qpn(\r
+       IN                              ipoib_hw_addr_t* const          p_addr,\r
+       IN              const   net32_t                                         qpn )\r
+{\r
+       p_addr->flags_qpn &= ( 0x000000FF );\r
+       p_addr->flags_qpn |= qpn ;\r
+}\r
+\r
+static inline void\r
+ipoib_addr_set_sid(\r
+       IN      net64_t* const          p_sid,\r
+       IN      const   net32_t         qpn )\r
+{\r
+       *p_sid = qpn;\r
+       *p_sid <<= 32;\r
+       *p_sid |= IPOIB_CM_FLAG_SVCID;\r
+}\r
+\r
+/****f* IPOIB/ipoib_mac_from_sst_guid\r
+* NAME\r
+*      ipoib_mac_from_sst_guid\r
+*\r
+* DESCRIPTION\r
+*      Generates an ethernet MAC address given a SilverStorm port GUID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_api_status_t\r
+ipoib_mac_from_sst_guid(\r
+       IN              const   net64_t                                         port_guid,\r
+               OUT                     mac_addr_t* const                       p_mac_addr )\r
+{\r
+       const uint8_t   *p_guid = (const uint8_t*)&port_guid;\r
+       uint32_t                low24;\r
+\r
+       /* Port guid is in network byte order.  OUI is in lower 3 bytes. */\r
+       ASSERT( p_guid[0] == 0x00 && p_guid[1] == 0x06 && p_guid[2] == 0x6a );\r
+\r
+       /*\r
+        * We end up using only the lower 23-bits of the GUID.  Trap that\r
+        * the 24th (bit 23) through 27th (bit 26) bit aren't set.\r
+        */\r
+       if( port_guid & CL_HTON64( 0x0000000007800000 ) )\r
+               return IB_INVALID_GUID;\r
+\r
+       low24 = 0x00FFF000 -\r
+               ((((uint32_t)cl_ntoh64( port_guid ) & 0x00FFFFFF) - 0x101) * 2);\r
+       low24 -= p_guid[3]; /* minus port number */\r
+\r
+       p_mac_addr->addr[0] = p_guid[0];\r
+       p_mac_addr->addr[1] = p_guid[1];\r
+       p_mac_addr->addr[2] = p_guid[2];\r
+       p_mac_addr->addr[3] = (uint8_t)(low24 >> 16);\r
+       p_mac_addr->addr[4] = (uint8_t)(low24 >> 8);\r
+       p_mac_addr->addr[5] = (uint8_t)low24;\r
+       \r
+       return IB_SUCCESS;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      port_guid\r
+*              The port GUID, in network byte order, for which to generate a\r
+*              MAC address.\r
+*\r
+*      p_mac_addr\r
+*              Pointer to a mac address in which to store the results.\r
+*\r
+* RETURN VALUES\r
+*      IB_SUCCESS\r
+*              The MAC address was successfully converted.\r
+*\r
+*      IB_INVALID_GUID\r
+*              The port GUID provided was not a known GUID format.\r
+*\r
+* NOTES\r
+*      The algorithm to convert portGuid to MAC address is as per DN0074, and\r
+*      assumes a 2 port HCA.\r
+*\r
+* SEE ALSO\r
+*      IPOIB\r
+*********/\r
+\r
+\r
+/****f* IPOIB/ipoib_mac_from_mlx_guid\r
+* NAME\r
+*      ipoib_mac_from_mlx_guid\r
+*\r
+* DESCRIPTION\r
+*      Generates an ethernet MAC address given a Mellanox port GUID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_api_status_t\r
+ipoib_mac_from_mlx_guid(\r
+       IN              const   net64_t                                         port_guid,\r
+               OUT                     mac_addr_t* const                       p_mac_addr )\r
+{\r
+       const uint8_t   *p_guid = (const uint8_t*)&port_guid;\r
+       uint32_t                low24;\r
+       net16_t                 guid_middle;\r
+\r
+       /* Port guid is in network byte order.  OUI is in lower 3 bytes. */\r
+       ASSERT( p_guid[0] == 0x00 && p_guid[1] == 0x02 && p_guid[2] == 0xc9 );\r
+\r
+       guid_middle = (net16_t)((port_guid & CL_HTON64( 0x000000ffff000000 )) >>24);\r
+\r
+       if (guid_middle == 2) {\r
+                       p_mac_addr->addr[0] = 0;\r
+       } else if (guid_middle == 3) {\r
+                       p_mac_addr->addr[0] = 2;\r
+       } else {\r
+               return IB_INVALID_GUID;\r
+       }\r
+       low24 = ((uint32_t)cl_ntoh64( port_guid ) & 0x00FFFFFF);\r
+\r
+       p_mac_addr->addr[1] = p_guid[1];\r
+       p_mac_addr->addr[2] = p_guid[2];\r
+       p_mac_addr->addr[3] = (uint8_t)(low24 >> 16);\r
+       p_mac_addr->addr[4] = (uint8_t)(low24 >> 8);\r
+       p_mac_addr->addr[5] = (uint8_t)low24;\r
+       \r
+       return IB_SUCCESS;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      port_guid\r
+*              The port GUID, in network byte order, for which to generate a\r
+*              MAC address.\r
+*\r
+*      p_mac_addr\r
+*              Pointer to a mac address in which to store the results.\r
+*\r
+* RETURN VALUES\r
+*      IB_SUCCESS\r
+*              The MAC address was successfully converted.\r
+*\r
+*      IB_INVALID_GUID\r
+*              The port GUID provided was not a known GUID format.\r
+*\r
+*********/\r
+\r
+\r
+/****f* IPOIB/ipoib_mac_from_voltaire_guid\r
+* NAME\r
+*      ipoib_mac_from_voltaire_guid\r
+*\r
+* DESCRIPTION\r
+*      Generates an ethernet MAC address given a Voltaire port GUID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_api_status_t\r
+ipoib_mac_from_voltaire_guid(\r
+       IN              const   net64_t                                         port_guid,\r
+               OUT                     mac_addr_t* const                       p_mac_addr )\r
+{\r
+       const uint8_t   *p_guid = (const uint8_t*)&port_guid;\r
+\r
+       /* Port guid is in network byte order.  OUI is in lower 3 bytes. */\r
+       ASSERT( p_guid[0] == 0x00 && p_guid[1] == 0x08 && p_guid[2] == 0xf1 );\r
+\r
+       p_mac_addr->addr[0] = p_guid[0];\r
+       p_mac_addr->addr[1] = p_guid[1];\r
+       p_mac_addr->addr[2] = p_guid[2];\r
+       p_mac_addr->addr[3] = p_guid[4] ^ p_guid[6];\r
+       p_mac_addr->addr[4] = p_guid[5] ^ p_guid[7];\r
+       p_mac_addr->addr[5] = p_guid[5] + p_guid[6] + p_guid[7];\r
+\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+/****f* IPOIB/ipoib_mac_from_guid_mask\r
+* NAME\r
+*      ipoib_mac_from_guid_mask\r
+*\r
+* DESCRIPTION\r
+*      Generates an ethernet MAC address given general port GUID and a bitwise mask\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_api_status_t\r
+ipoib_mac_from_guid_mask(\r
+       IN              const   uint8_t                                         *p_guid,\r
+       IN                              uint32_t                                        guid_mask,\r
+               OUT                     mac_addr_t* const                       p_mac_addr )\r
+{\r
+       static const mac_addr_size =  HW_ADDR_LEN;\r
+       uint8_t i;\r
+       int digit_counter = 0;\r
+\r
+       // All non-zero bits of guid_mask indicates the number of an appropriate\r
+       // byte in port_guid, that will be used in MAC address construction\r
+       for (i = 7; guid_mask; guid_mask >>= 1, --i )\r
+       {\r
+               if( guid_mask & 1 )\r
+               {\r
+                       ++digit_counter;\r
+                       if( digit_counter > mac_addr_size )\r
+                       {\r
+                               //to avoid negative index\r
+                               return IB_INVALID_GUID_MASK;\r
+                       }\r
+                       p_mac_addr->addr[mac_addr_size - digit_counter] = p_guid [i];\r
+               }\r
+       }\r
+\r
+       // check for the mask validity: it should have 6 non-zero bits\r
+       if( digit_counter != mac_addr_size )\r
+               return IB_INVALID_GUID_MASK;\r
+\r
+       return IB_SUCCESS;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      port_guid\r
+*              The port GUID, in network byte order, for which to generate a\r
+*              MAC address.\r
+*\r
+*      guid_mask\r
+*              Each BIT in the mask indicates whether to include the appropriate BYTE\r
+*              to the MAC address. Bit 0 corresponds to the less significant BYTE , i.e.\r
+*              highest index in the MAC array\r
+*\r
+*      p_mac_addr\r
+*              Pointer to a mac address in which to store the results.\r
+*\r
+* RETURN VALUES\r
+*      IB_SUCCESS\r
+*              The MAC address was successfully converted.\r
+*\r
+*      IB_INVALID_GUID\r
+*              The port GUID provided was not a known GUID format.\r
+*\r
+* SEE ALSO\r
+*      IPOIB\r
+*********/\r
+\r
+\r
+/****f* IPOIB/ipoib_mac_from_guid\r
+* NAME\r
+*      ipoib_mac_from_guid\r
+*\r
+* DESCRIPTION\r
+*      Generates an ethernet MAC address given a port GUID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_api_status_t\r
+ipoib_mac_from_guid(\r
+       IN              const   net64_t                                         port_guid,\r
+       IN                              uint32_t                                        guid_mask,\r
+               OUT                     mac_addr_t* const                       p_mac_addr\r
+               )\r
+{\r
+       ib_api_status_t status = IB_INVALID_GUID;\r
+       const uint8_t   *p_guid = (const uint8_t*)&port_guid;\r
+       uint32_t                laa, idx = 0;\r
+\r
+       /* Port guid is in network byte order.  OUI is in lower 3 bytes. */\r
+       if( p_guid[0] == 0 )\r
+       {\r
+               if( p_guid[1] == 0x02 && p_guid[2] == 0xc9 )\r
+               {\r
+                       status = ipoib_mac_from_mlx_guid( port_guid, p_mac_addr );\r
+               }\r
+               else if( p_guid[1] == 0x08 && p_guid[2] == 0xf1 )\r
+               {\r
+                       status = ipoib_mac_from_voltaire_guid( port_guid, p_mac_addr );\r
+               }\r
+               else if( p_guid[1] == 0x06 && p_guid[2] == 0x6a )\r
+               {\r
+                       status = ipoib_mac_from_sst_guid( port_guid, p_mac_addr );\r
+               }\r
+               else\r
+               {\r
+                       while( guid2mac_table[idx].second_byte != 0x00 ||\r
+                                  guid2mac_table[idx].third_byte != 0x00 )\r
+                       {\r
+                               if( p_guid[1] == guid2mac_table[idx].second_byte &&\r
+                                       p_guid[2] == guid2mac_table[idx].third_byte )\r
+                               {\r
+                                       status = ipoib_mac_from_guid_mask(p_guid, guid2mac_table[idx].guid_mask,\r
+                                                                                                               p_mac_addr);\r
+                                       break;\r
+                               }\r
+                               ++idx;\r
+                       }\r
+               }\r
+\r
+               if( status == IB_SUCCESS )\r
+                       return status;\r
+       }\r
+\r
+       if( guid_mask )\r
+               return ipoib_mac_from_guid_mask( p_guid, guid_mask, p_mac_addr );\r
+\r
+       /* Value of zero is reserved. */\r
+       laa = cl_atomic_inc( &g_ipoib.laa_idx );\r
+\r
+       if( !laa )\r
+               return IB_INVALID_GUID;\r
+\r
+       p_mac_addr->addr[0] = 2; /* LAA bit */\r
+       p_mac_addr->addr[1] = 0;\r
+       p_mac_addr->addr[2] = (uint8_t)(laa >> 24);\r
+       p_mac_addr->addr[3] = (uint8_t)(laa >> 16);\r
+       p_mac_addr->addr[4] = (uint8_t)(laa >> 8);\r
+       p_mac_addr->addr[5] = (uint8_t)laa;\r
+       \r
+       return IB_SUCCESS;\r
+}\r
+/*\r
+* PARAMETERS\r
+*      port_guid\r
+*              The port GUID, in network byte order, for which to generate a\r
+*              MAC address.\r
+*\r
+*      p_mac_addr\r
+*              Pointer to a mac address in which to store the results.\r
+*\r
+* RETURN VALUES\r
+*      IB_SUCCESS\r
+*              The MAC address was successfully converted.\r
+*\r
+*      IB_INVALID_GUID\r
+*              The port GUID provided was not a known GUID format.\r
+*\r
+* NOTES\r
+*      Creates a locally administered address using a global incrementing counter.\r
+*\r
+* SEE ALSO\r
+*      IPOIB\r
+*********/\r
+\r
+\r
+/****f* IPOIB/ipoib_is_voltaire_router_gid\r
+* NAME\r
+*      ipoib_is_voltaire_router_gid\r
+*\r
+* DESCRIPTION\r
+*      Checks whether the GID belongs to Voltaire IP router\r
+*\r
+* SYNOPSIS\r
+*/\r
+boolean_t\r
+static inline\r
+ipoib_is_voltaire_router_gid(\r
+       IN              const   ib_gid_t                                        *p_gid )\r
+{\r
+       static const uint8_t VOLTAIRE_GUID_PREFIX[] = {0, 0x08, 0xf1, 0, 0x1};\r
+\r
+       return !cl_memcmp( &p_gid->unicast.interface_id, VOLTAIRE_GUID_PREFIX,\r
+               sizeof(VOLTAIRE_GUID_PREFIX) );\r
+}\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* _IPOIB_XFR_MGR_H_ */\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/makefile b/trunk/ulp/ipoib_NDIS6_CM/kernel/makefile
new file mode 100644 (file)
index 0000000..bffacaa
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the OpenIB Windows project.\r
+#\r
+\r
+!INCLUDE ..\..\..\inc\openib.def\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/makefile.inc b/trunk/ulp/ipoib_NDIS6_CM/kernel/makefile.inc
new file mode 100644 (file)
index 0000000..4f29f50
--- /dev/null
@@ -0,0 +1,17 @@
+\r
+# Transform .inx file to .inf file adding date + major,min & svn.version stamp\r
+# Output .inf file is copied to the $(INF_TARGET) folder (commonly where .sys file resides).\r
+\r
+_LNG=$(LANGUAGE)\r
+\r
+!IF !DEFINED(_INX)\r
+_INX=.\r
+!ENDIF\r
+\r
+STAMP=stampinf -a $(_BUILDARCH)\r
+\r
+!INCLUDE mod_ver.def\r
+\r
+$(INF_TARGET) : $(_INX)\$(INF_NAME).inx\r
+    copy $(_INX)\$(@B).inx $@\r
+    $(STAMP) -f $@ -d * -v $(IB_MAJORVERSION).$(IB_MINORVERSION).$(IB_BUILDVERSION).$(OPENIB_REV)\r
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/netipoib.inx b/trunk/ulp/ipoib_NDIS6_CM/kernel/netipoib.inx
new file mode 100644 (file)
index 0000000..ca3126b
--- /dev/null
@@ -0,0 +1,295 @@
+; OpenFabrics Alliance Internet Protocol over InfiniBand Adapter\r
+; Copyright 2005 SilverStorm Technologies all Rights Reserved.\r
+; Copyright 2006 Mellanox Technologies all Rights Reserved.\r
+\r
+[Version]\r
+Signature   = "$Windows NT$"\r
+Class       = Net\r
+ClassGUID   = {4d36e972-e325-11ce-bfc1-08002be10318}\r
+Provider    = %MTL%\r
+DriverVer=06/11/2008,1.0.0000.1207\r
+CatalogFile=ipoib.cat\r
+\r
+[Manufacturer]\r
+%MTL%       = MTL,ntx86,ntamd64,ntia64\r
+\r
+[ControlFlags]\r
+ExcludeFromSelect = IBA\IPoIB\r
+\r
+[MTL]\r
+; empty since we don't support W9x/Me\r
+\r
+[MTL.ntx86]\r
+%IpoibDesc%      = Ipoib.DDInstall,    IBA\IPoIB   ; Internet Protocol over InfiniBand Adapter\r
+%IpoibDescP%     = Ipoib.DDInstall,    IBA\IPoIBP  ; Internet Protocol over InfiniBand Adapter with partition key\r
+\r
+[MTL.ntamd64]\r
+%IpoibDesc%      = Ipoib.DDInstall,    IBA\IPoIB   ; Internet Protocol over InfiniBand Adapter\r
+%IpoibDescP%     = Ipoib.DDInstall,    IBA\IPoIBP  ; Internet Protocol over InfiniBand Adapter with partition key\r
+\r
+[MTL.ntia64]\r
+%IpoibDesc%      = Ipoib.DDInstall,    IBA\IPoIB   ; Internet Protocol over InfiniBand Adapter\r
+%IpoibDescP%     = Ipoib.DDInstall,    IBA\IPoIBP  ; Internet Protocol over InfiniBand Adapter with partition key\r
+\r
+[Ipoib.DDInstall.ntx86]\r
+Characteristics = 0x81 ; NCF_HAS_UI | NCF_VIRTUAL\r
+AddReg          = IpoibAddReg\r
+CopyFiles       = IpoibCopyFiles\r
+CopyFiles       = WsdCopyFiles\r
+CopyFiles       = NdCopyFiles\r
+*IfType         = 6            ; IF_TYPE_ETHERNET_CSMACD \r
+*MediaType      = 0            ; NdisMedium802_3\r
+*PhysicalMediaType = 14                ; NdisPhysicalMedium802_3\r
+\r
+[Ipoib.DDInstall.ntamd64]\r
+Characteristics = 0x81 ; NCF_HAS_UI | NCF_VIRTUAL\r
+AddReg          = IpoibAddReg\r
+CopyFiles       = IpoibCopyFiles\r
+CopyFiles       = WsdCopyFiles\r
+CopyFiles       = NdCopyFiles\r
+CopyFiles       = WOW64CopyFiles\r
+*IfType         = 6            ; IF_TYPE_ETHERNET_CSMACD \r
+*MediaType      = 0            ; NdisMedium802_3\r
+*PhysicalMediaType = 14                ; NdisPhysicalMedium802_3\r
+\r
+[Ipoib.DDInstall.ntia64]\r
+Characteristics = 0x81 ; NCF_HAS_UI | NCF_VIRTUAL\r
+AddReg          = IpoibAddReg\r
+CopyFiles       = IpoibCopyFiles\r
+CopyFiles       = WsdCopyFiles\r
+CopyFiles       = NdCopyFiles\r
+CopyFiles       = WOW64CopyFiles\r
+*IfType         = 6            ; IF_TYPE_ETHERNET_CSMACD \r
+*MediaType      = 0            ; NdisMedium802_3\r
+*PhysicalMediaType = 14                ; NdisPhysicalMedium802_3\r
+\r
+[Ipoib.DDInstall.ntx86.Services]\r
+AddService = ipoib, 2, IpoibService, IpoibEventLog\r
+\r
+[Ipoib.DDInstall.ntamd64.Services]\r
+AddService = ipoib, 2, IpoibService, IpoibEventLog\r
+\r
+[Ipoib.DDInstall.ntia64.Services]\r
+AddService = ipoib, 2, IpoibService, IpoibEventLog\r
+\r
+[IpoibAddReg]\r
+HKR, ,RDMACapable, %REG_DWORD%, 1\r
+HKR, Ndi,                       Service,    0, "ipoib"\r
+HKR, Ndi\Interfaces,            UpperRange, 0, "ndis5"\r
+HKR, Ndi\Interfaces,            LowerRange, 0, "ethernet"\r
+\r
+HKR, Ndi\Params\RqDepth,               ParamDesc,      0, %RQ_DEPTH_STR%\r
+HKR, Ndi\Params\RqDepth,               Type,           0, "dword"\r
+HKR, Ndi\Params\RqDepth,               Default,        0, "512"\r
+HKR, Ndi\Params\RqDepth,               Optional,       0, "0"\r
+HKR, Ndi\Params\RqDepth,               Min,            0, "128"\r
+HKR, Ndi\Params\RqDepth,               Max,            0, "1024"\r
+HKR, Ndi\Params\RqDepth,               Step,           0, "128"\r
+\r
+HKR, Ndi\Params\RqLowWatermark,        ParamDesc,      0, %RQ_WATERMARK_STR%\r
+HKR, Ndi\Params\RqLowWatermark,        Type,           0, "dword"\r
+HKR, Ndi\Params\RqLowWatermark,        Default,        0, "4"\r
+HKR, Ndi\Params\RqLowWatermark,        Optional,       0, "0"\r
+HKR, Ndi\Params\RqLowWatermark,        Min,            0, "2"\r
+HKR, Ndi\Params\RqLowWatermark,        Max,            0, "8"\r
+HKR, Ndi\Params\RqLowWatermark,        Step,           0, "1"\r
+\r
+HKR, Ndi\Params\SqDepth,               ParamDesc,      0, %SQ_DEPTH_STR%\r
+HKR, Ndi\Params\SqDepth,               Type,           0, "dword"\r
+HKR, Ndi\Params\SqDepth,               Default,        0, "512"\r
+HKR, Ndi\Params\SqDepth,               Optional,       0, "0"\r
+HKR, Ndi\Params\SqDepth,               Min,            0, "128"\r
+HKR, Ndi\Params\SqDepth,               Max,            0, "1024"\r
+HKR, Ndi\Params\SqDepth,               Step,           0, "128"\r
+\r
+HKR, Ndi\Params\SendChksum,            ParamDesc,      0, %SQ_CSUM_STR%\r
+HKR, Ndi\Params\SendChksum,            Type,           0, "enum"\r
+HKR, Ndi\Params\SendChksum,            Default,        0, "1"\r
+HKR, Ndi\Params\SendChksum,            Optional,       0, "0"\r
+HKR, Ndi\Params\SendChksum\enum,       "0",    0, %DISABLED_STR%\r
+HKR, Ndi\Params\SendChksum\enum,       "1",    0, %ENABLED_IF_STR%\r
+HKR, Ndi\Params\SendChksum\enum,       "2",    0, %BYPASS_STR%\r
+\r
+HKR, Ndi\Params\RecvChksum,            ParamDesc,      0, %RQ_CSUM_STR%\r
+HKR, Ndi\Params\RecvChksum,            Type,           0, "enum"\r
+HKR, Ndi\Params\RecvChksum,            Default,        0, "1"\r
+HKR, Ndi\Params\RecvChksum,            Optional,       0, "0"\r
+HKR, Ndi\Params\RecvChksum\enum,       "0",    0, %DISABLED_STR%\r
+HKR, Ndi\Params\RecvChksum\enum,       "1",    0, %ENABLED_IF_STR%\r
+HKR, Ndi\Params\RecvChksum\enum,       "2",    0, %BYPASS_STR%\r
+\r
+HKR, Ndi\Params\lso,           ParamDesc,      0, %LSO_STR%\r
+HKR, Ndi\Params\lso,           Type,           0, "enum"\r
+HKR, Ndi\Params\lso,           Default,        0, "0"\r
+HKR, Ndi\Params\lso,           Optional,       0, "0"\r
+HKR, Ndi\Params\lso\enum,      "0",    0, %DISABLED_STR%\r
+HKR, Ndi\Params\lso\enum,      "1",    0, %ENABLED_STR%\r
+\r
+\r
+HKR, Ndi\Params\SaTimeout,             ParamDesc,      0, %SA_QUERY_TO_STR%\r
+HKR, Ndi\Params\SaTimeout,             Type,           0, "dword"\r
+HKR, Ndi\Params\SaTimeout,             Default,        0, "1000"\r
+HKR, Ndi\Params\SaTimeout,             Optional,       0, "0"\r
+HKR, Ndi\Params\SaTimeout,             Min,            0, "500"\r
+HKR, Ndi\Params\SaTimeout,             Step,           0, "250"\r
+\r
+HKR, Ndi\Params\SaRetries,             ParamDesc,      0, %SA_QUERY_RETRY_STR%\r
+HKR, Ndi\Params\SaRetries,             Type,           0, "dword"\r
+HKR, Ndi\Params\SaRetries,             Default,        0, "10"\r
+HKR, Ndi\Params\SaRetries,             Optional,       0, "0"\r
+HKR, Ndi\Params\SaRetries,             Min,            0, "1"\r
+\r
+HKR, Ndi\Params\RecvRatio,             ParamDesc,      0, %RECV_RATIO_STR%\r
+HKR, Ndi\Params\RecvRatio,             Type,           0, "dword"\r
+HKR, Ndi\Params\RecvRatio,             Default,        0, "1"\r
+HKR, Ndi\Params\RecvRatio,             Optional,       0, "0"\r
+HKR, Ndi\Params\RecvRatio,             Min,            0, "1"\r
+HKR, Ndi\Params\RecvRatio,             Max,            0, "10"\r
+\r
+HKR, Ndi\Params\PayloadMtu,            ParamDesc,      0, %MTU_STR%\r
+HKR, Ndi\Params\PayloadMtu,            Type,           0, "dword"\r
+HKR, Ndi\Params\PayloadMtu,            Default,        0, "2044"\r
+HKR, Ndi\Params\PayloadMtu,            Min,            0, "512"\r
+HKR, Ndi\Params\PayloadMtu,            Max,            0, "4092"\r
+\r
+HKR, Ndi\Params\MCLeaveRescan,         ParamDesc,      0, %MC_RESCAN_STR%\r
+HKR, Ndi\Params\MCLeaveRescan,         Type,           0, "dword"\r
+HKR, Ndi\Params\MCLeaveRescan,         Default,        0, "260"\r
+HKR, Ndi\Params\MCLeaveRescan,         Optional,       0, "0"\r
+HKR, Ndi\Params\MCLeaveRescan,         Min,            0, "1"\r
+HKR, Ndi\Params\MCLeaveRescan,         Max,            0, "3600"\r
+\r
+HKR, Ndi\Params\GUIDMask,              ParamDesc,      0, %GUID_MASK_STR%\r
+HKR, Ndi\Params\GUIDMask,              Type,           0, "dword"\r
+HKR, Ndi\Params\GUIDMask,              Default,        0, "0"\r
+HKR, Ndi\Params\GUIDMask,              Optional,       0, "0"\r
+HKR, Ndi\Params\GUIDMask,              Min,            0, "0"\r
+HKR, Ndi\Params\GUIDMask,              Max,            0, "252"\r
+\r
+HKR, Ndi\Params\BCJoinRetry,           ParamDesc,      0, %BC_JOIN_RETRY_STR%\r
+HKR, Ndi\Params\BCJoinRetry,           Type,           0, "dword"\r
+HKR, Ndi\Params\BCJoinRetry,           Default,        0, "50"\r
+HKR, Ndi\Params\BCJoinRetry,           Optional,       0, "0"\r
+HKR, Ndi\Params\BCJoinRetry,           Min,            0, "0"\r
+HKR, Ndi\Params\BCJoinRetry,           Max,            0, "1000"\r
+\r
+HKR, Ndi\Params\CmEnabled,             ParamDesc,      0, %CONNECTED_MODE_STR%\r
+HKR, Ndi\Params\CmEnabled,             Type,           0, "enum"\r
+HKR, Ndi\Params\CmEnabled,             Default,        0, "0"\r
+HKR, Ndi\Params\CmEnabled,             Optional,       0, "0"\r
+HKR, Ndi\Params\CmEnabled\enum,        "0",    0,      %DISABLED_STR%\r
+HKR, Ndi\Params\CmEnabled\enum,        "1",    0,      %ENABLED_STR%\r
+\r
+HKR, Ndi\Params\CmPayloadMtu,          ParamDesc,      0, %CONNECTED_MODE_MTU_STR%\r
+HKR, Ndi\Params\CmPayloadMtu,          Type,           0, "dword"\r
+HKR, Ndi\Params\CmPayloadMtu,          Default,        0, "65520"\r
+HKR, Ndi\Params\CmPayloadMtu,          Min,            0, "512"\r
+HKR, Ndi\Params\CmPayloadMtu,          Max,            0, "65520"\r
+\r
+[IpoibService]\r
+DisplayName     = %IpoibServiceDispName%\r
+ServiceType     = 1 ;%SERVICE_KERNEL_DRIVER%\r
+StartType       = 3 ;%SERVICE_DEMAND_START%\r
+ErrorControl    = 1 ;%SERVICE_ERROR_NORMAL%\r
+ServiceBinary   = %12%\ipoib.sys\r
+LoadOrderGroup  = NDIS\r
+AddReg          = Ipoib.ParamsReg\r
+\r
+[Ipoib.ParamsReg]\r
+HKR,"Parameters","DebugLevel",%REG_DWORD_NO_CLOBBER%,0x00000002\r
+HKR,"Parameters","DebugFlags",%REG_DWORD_NO_CLOBBER%,0x00000fff\r
+HKR,"Parameters","bypass_check_bcast_rate",%REG_DWORD_NO_CLOBBER%,0x00000000\r
+\r
+[IpoibEventLog]\r
+AddReg = IpoibAddEventLogReg\r
+\r
+[IpoibAddEventLogReg]\r
+HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\netevent.dll;%%SystemRoot%%\System32\drivers\ipoib.sys"\r
+HKR, , TypesSupported,   0x00010001, 7\r
+\r
+\r
+[IpoibCopyFiles]\r
+ipoib.sys,,,2\r
+\r
+[WsdCopyFiles]\r
+ibwsd.dll,,,0x00000002\r
+\r
+[NdCopyFiles]\r
+ibndprov.dll,,,0x00000002\r
+ndinstall.exe,,,0x00000002\r
+\r
+[WOW64CopyFiles]\r
+ibwsd.dll,ibwsd32.dll,,0x00000002\r
+ibndprov.dll,ibndprov32.dll,,0x00000002\r
+\r
+[SourceDisksNames.x86]\r
+1 = %IcsDisk1%,,,""\r
+\r
+[SourceDisksNames.amd64]\r
+1 = %IcsDisk1%,,,""\r
+\r
+[SourceDisksNames.ia64]\r
+1 = %IcsDisk1%,,,""\r
+\r
+[SourceDisksFiles.x86]\r
+ipoib.sys = 1\r
+ibwsd.dll = 1\r
+ibndprov.dll = 1\r
+ndinstall.exe = 1\r
+\r
+[SourceDisksFiles.amd64]\r
+ipoib.sys = 1\r
+ibwsd.dll = 1\r
+ibwsd32.dll = 1\r
+ibndprov.dll = 1\r
+ibndprov32.dll = 1\r
+ndinstall.exe = 1\r
+\r
+[SourceDisksFiles.ia64]\r
+ipoib.sys = 1\r
+ibwsd.dll = 1\r
+ibwsd32.dll = 1\r
+ibndprov.dll = 1\r
+ibndprov32.dll = 1\r
+ndinstall.exe = 1\r
+\r
+[DestinationDirs]\r
+IpoibCopyFiles    = %DIRID_DRIVERS%\r
+WsdCopyFiles      = %DIRID_SYSTEM%\r
+NdCopyFiles       = %DIRID_SYSTEM%\r
+WOW64CopyFiles    = %DIRID_SYSTEM_X86%\r
+DefaultDestDir    = %DIRID_SYSTEM%\r
+\r
+[Strings]\r
+OPENIB               = "OpenFabrics Alliance"\r
+MTL                     = "Mellanox Technologies Ltd."\r
+IpoibDesc            = "Mellanox IPoIB Adapter"\r
+IpoibDescP           = "Mellanox IPoIB Adapter Partition"\r
+IpoibServiceDispName = "IPoIB"\r
+IcsDisk1             = "Mellanox IPoIB Disk #1"\r
+DIRID_SYSTEM         = 11\r
+DIRID_DRIVERS        = 12\r
+DIRID_SYSTEM_X86     = 16425\r
+REG_DWORD            = 0x00010001\r
+REG_DWORD_NO_CLOBBER = 0x00010003\r
+\r
+RQ_DEPTH_STR           = "Receive Queue depth"\r
+RQ_WATERMARK_STR       = "Receive Queue Low Watermark"\r
+SQ_DEPTH_STR           = "Send Queue Depth"\r
+SQ_CSUM_STR            = "Send Checksum Offload"\r
+RQ_CSUM_STR            = "Recv Checksum Offload"\r
+LSO_STR                        = "Large Send Offload"\r
+SA_QUERY_TO_STR                = "SA Query Timeout (ms)"\r
+SA_QUERY_RETRY_STR     = "SA Query Retry Count"\r
+RECV_RATIO_STR         = "Receive Pool Ratio"\r
+MTU_STR                        = "Payload Mtu size"\r
+MC_RESCAN_STR          = "MC leave rescan (sec)"\r
+GUID_MASK_STR          = "GUID bitwise mask"\r
+BC_JOIN_RETRY_STR   = "Number of retries connecting to bc"\r
+\r
+ENABLED_IF_STR         = "Enabled (if supported by HW)"\r
+ENABLED_STR            = "Enabled"\r
+DISABLED_STR           = "Disabled"\r
+BYPASS_STR             = "Bypass"\r
+CONNECTED_MODE_STR     = "Connected mode"\r
+CONNECTED_MODE_MTU_STR = "Connected Mode Payload Mtu size"
\ No newline at end of file
diff --git a/trunk/ulp/ipoib_NDIS6_CM/kernel/offload.h b/trunk/ulp/ipoib_NDIS6_CM/kernel/offload.h
new file mode 100644 (file)
index 0000000..de696c6
--- /dev/null
@@ -0,0 +1,47 @@
+/*++\r
\r
+Copyright (c) 2005-2008 Mellanox Technologies. All rights reserved.\r
+\r
+Module Name:\r
+    offload.h\r
+\r
+Abstract:\r
+    Task offloading header file\r
+\r
+Revision History:\r
+\r
+Notes:\r
+\r
+--*/\r
+\r
+//\r
+//  Define the maximum size of large TCP packets the driver can offload.\r
+//  This sample driver uses shared memory to map the large packets, \r
+//  LARGE_SEND_OFFLOAD_SIZE is useless in this case, so we just define \r
+//  it as NIC_MAX_PACKET_SIZE. But shipping drivers should define\r
+//  LARGE_SEND_OFFLOAD_SIZE if they support LSO, and use it as \r
+//  MaximumPhysicalMapping  when they call NdisMInitializeScatterGatherDma \r
+//  if they use ScatterGather method. If the drivers don't support\r
+//  LSO, then MaximumPhysicalMapping is NIC_MAX_PACKET_SIZE.\r
+//\r
+\r
+#define LSO_MAX_HEADER 136\r
+#define LARGE_SEND_OFFLOAD_SIZE 60000 \r
+\r
+// This struct is being used in order to pass data about the GSO buffers if they\r
+// are present\r
+typedef struct LsoBuffer_ {\r
+    PUCHAR pData;\r
+    UINT Len;\r
+} LsoBuffer;\r
+\r
+typedef struct LsoData_ {\r
+    LsoBuffer LsoBuffers[1];\r
+    UINT UsedBuffers;\r
+    UINT FullBuffers;\r
+    UINT LsoHeaderSize;\r
+    UINT IndexOfData;\r
+    UCHAR coppied_data[LSO_MAX_HEADER];\r
+} LsoData;\r
+\r
+\r