[VNIC] Initial checkin of VNIC code. Not yet fully functional.
authorftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Fri, 6 Oct 2006 20:26:00 +0000 (20:26 +0000)
committerftillier <ftillier@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Fri, 6 Oct 2006 20:26:00 +0000 (20:26 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@515 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

24 files changed:
ulp/dirs
ulp/inic/dirs [new file with mode: 0644]
ulp/inic/kernel/SOURCES [new file with mode: 0644]
ulp/inic/kernel/inic.rc [new file with mode: 0644]
ulp/inic/kernel/makefile [new file with mode: 0644]
ulp/inic/kernel/netvnic.inf [new file with mode: 0644]
ulp/inic/kernel/vnic_adapter.c [new file with mode: 0644]
ulp/inic/kernel/vnic_adapter.h [new file with mode: 0644]
ulp/inic/kernel/vnic_config.h [new file with mode: 0644]
ulp/inic/kernel/vnic_control.c [new file with mode: 0644]
ulp/inic/kernel/vnic_control.h [new file with mode: 0644]
ulp/inic/kernel/vnic_controlpkt.h [new file with mode: 0644]
ulp/inic/kernel/vnic_data.c [new file with mode: 0644]
ulp/inic/kernel/vnic_data.h [new file with mode: 0644]
ulp/inic/kernel/vnic_debug.h [new file with mode: 0644]
ulp/inic/kernel/vnic_driver.c [new file with mode: 0644]
ulp/inic/kernel/vnic_driver.h [new file with mode: 0644]
ulp/inic/kernel/vnic_ib.c [new file with mode: 0644]
ulp/inic/kernel/vnic_ib.h [new file with mode: 0644]
ulp/inic/kernel/vnic_netpath.c [new file with mode: 0644]
ulp/inic/kernel/vnic_trailer.h [new file with mode: 0644]
ulp/inic/kernel/vnic_util.h [new file with mode: 0644]
ulp/inic/kernel/vnic_viport.c [new file with mode: 0644]
ulp/inic/kernel/vnic_viport.h [new file with mode: 0644]

index 87be055..e5ba0c8 100644 (file)
--- a/ulp/dirs
+++ b/ulp/dirs
@@ -3,4 +3,5 @@ DIRS=\
        dapl    \\r
        ipoib   \\r
        srp             \\r
-       wsd\r
+       wsd             \\r
+       inic\r
diff --git a/ulp/inic/dirs b/ulp/inic/dirs
new file mode 100644 (file)
index 0000000..ed41dcf
--- /dev/null
@@ -0,0 +1,2 @@
+DIRS=\\r
+       kernel\r
diff --git a/ulp/inic/kernel/SOURCES b/ulp/inic/kernel/SOURCES
new file mode 100644 (file)
index 0000000..d56ea8c
--- /dev/null
@@ -0,0 +1,75 @@
+########################################################################\r
+#\r
+#  Copyright(c) Infinicon Systems All rights reserved.\r
+#\r
+########################################################################\r
+\r
+\r
+# The TARGETNAME.  This is name of the item being built (without the\r
+#  extension.  \r
+TARGETNAME=vnic\r
+\r
+########################################################################\r
+# The path where all binaries are built.  \r
+#\r
+TARGETPATH=..\..\..\bin\kernel\obj$(BUILD_ALT_DIR)\r
+\r
+########################################################################\r
+# The type of item that is being built.  This is manditory.\r
+# Value         Meaning\r
+# DYNLINK       - A DLL.\r
+# DRIVER        - A kernel device driver.\r
+# EXPORT_DRIVER - A kernel device driver with exports.\r
+# PROGRAM       - A windows executable.\r
+# PROGLIB       - A windows library.\r
+# MINPORT       - A miniport driver.\r
+# GDI_DRIVER    - A video driver.\r
+# LIBRARY       - A library \r
+TARGETTYPE=MINIPORT\r
+\r
+########################################################################\r
+# The type of driver being built.  This affects the include paths.\r
+# Comment out for non-WDM drivers.\r
+#DRIVERTYPE=WDM\r
+\r
+#\r
+########################################################################\r
+# All the source files in this project.  \r
+#\r
+SOURCES=       inic.rc \\r
+                       vnic_driver.c \\r
+                       vnic_adapter.c  \\r
+                       vnic_ib.c       \\r
+                       vnic_control.c  \\r
+                       vnic_data.c     \\r
+                       vnic_netpath.c  \\r
+                       vnic_viport.c \\r
+\r
+\r
+\r
+\r
+INCLUDES=..;..\..\..\inc;..\..\..\inc\kernel;\r
+\r
+C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER -DNDIS_WDM=1 \\r
+       -DDEPRECATE_DDK_FUNCTIONS -DNDIS51_MINIPORT -DNEED_CL_OBJ -DBINARY_COMPATIBLE=0\r
+\r
+TARGETLIBS= \\r
+       $(DDK_LIB_PATH)\ntoskrnl.lib \\r
+       $(DDK_LIB_PATH)\hal.lib         \\r
+       $(DDK_LIB_PATH)\ndis.lib        \\r
+       $(TARGETPATH)\*\complib.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
+########################################################################\r
+# Set the warning levels to maximum.\r
+MSC_WARNING_LEVEL= /W4\r
+#\r
+\r
+\r
diff --git a/ulp/inic/kernel/inic.rc b/ulp/inic/kernel/inic.rc
new file mode 100644 (file)
index 0000000..66c5b30
--- /dev/null
@@ -0,0 +1,47 @@
+/*\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$\r
+ */\r
+\r
+\r
+#include <ics_ver.h>\r
+\r
+#define VER_FILETYPE                           VFT_DRV\r
+#define VER_FILESUBTYPE                                VFT2_DRV_NETWORK\r
+\r
+#ifdef _DEBUG_\r
+#define VER_FILEDESCRIPTION_STR                "Virtual Nic NDIS Miniport (Debug)"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR                "Virtual Nic NDIS Miniport"\r
+#endif\r
+\r
+#define VER_INTERNALNAME_STR           "vnic.sys"\r
+#define VER_ORIGINALFILENAME_STR       "vnic.sys"\r
+\r
+#include <common.ver>\r
diff --git a/ulp/inic/kernel/makefile b/ulp/inic/kernel/makefile
new file mode 100644 (file)
index 0000000..9c985f5
--- /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 Windows NT DDK\r
+#\r
+\r
+!INCLUDE $(NTMAKEENV)\makefile.def\r
diff --git a/ulp/inic/kernel/netvnic.inf b/ulp/inic/kernel/netvnic.inf
new file mode 100644 (file)
index 0000000..a4f72d3
--- /dev/null
@@ -0,0 +1,146 @@
+; SilverStorm Technologies Ethernet over Infiniband NIC.\r
+; Copyright 2006 SilverStorm Technologies all Rights Reserved.\r
+\r
+[Version]\r
+Signature="$Windows NT$"\r
+Class=Net\r
+ClassGUID={4d36e972-e325-11ce-bfc1-08002be10318}\r
+Provider=%Inf_Provider%\r
+DriverVer=01/12/2006,3.0.0039.0\r
+\r
+[ControlFlags]\r
+ExcludeFromSelect = IBA\V00066aP00000030\r
+\r
+; ================= Device Install section =====================\r
+\r
+[DestinationDirs]\r
+DefaultDestDir=12\r
+\r
+[SourceDisksNames.x86]\r
+1=%DiskId%,,,\x86\r
+\r
+[SourceDisksNames.amd64]\r
+1=%DiskId%,,,\amd64\r
+\r
+[SourceDisksNames.ia64]\r
+1=%DiskId%,,,\ia64\r
+\r
+[SourceDisksFiles]\r
+vnic.sys=1\r
+\r
+[Manufacturer]\r
+%Inf_Provider% = VNIC.DeviceSection,ntx86,ntamd64,ntia64\r
+\r
+[VNIC.DeviceSection]\r
+; empty since we don't support W9x/Me\r
+\r
+[VNIC.DeviceSection.ntx86]\r
+%VNIC.DeviceDesc% = VNIC.DDInstall,IBA\V00066aP00000030S00066as00000030v0001, \\r
+                                                               IBA\V00066aP00000030S00066as00000030, \\r
+                                                               IBA\V00066aP00000030v0001, \\r
+                                                               IBA\V00066aP00000030\r
+\r
+[VNIC.DeviceSection.ntamd64]\r
+%VNIC.DeviceDesc% = VNIC.DDInstall,IBA\V00066aP00000030S00066as00000030v0001, \\r
+                                                               IBA\V00066aP00000030S00066as00000030, \\r
+                                                               IBA\V00066aP00000030v0001, \\r
+                                                               IBA\V00066aP00000030\r
+\r
+[VNIC.DeviceSection.ntia64]\r
+%VNIC.DeviceDesc% = VNIC.DDInstall,IBA\V00066aP00000030S00066as00000030v0001, \\r
+                                                               IBA\V00066aP00000030S00066as00000030, \\r
+                                                               IBA\V00066aP00000030v0001, \\r
+                                                               IBA\V00066aP00000030\r
+\r
+[VNIC.DDInstall.ntx86]\r
+Characteristics = %CHARACTERISTICS%\r
+AddReg = VNIC.AddReg\r
+CopyFiles = VNIC.CopyFiles\r
+\r
+[VNIC.DDInstall.ntamd64]\r
+Characteristics = %CHARACTERISTICS%\r
+AddReg = VNIC.AddReg\r
+CopyFiles = VNIC.CopyFiles\r
+\r
+[VNIC.DDInstall.ntia64]\r
+Characteristics = %CHARACTERISTICS%\r
+AddReg = VNIC.AddReg\r
+CopyFiles = VNIC.CopyFiles\r
+\r
+[VNIC.DDInstall.ntx86.Services]\r
+AddService = vnic,%SPSVCINST_ASSOCSERVICE%,VNIC.ServiceInstall,VNIC.EventLogInstall\r
+\r
+[VNIC.DDInstall.ntamd64.Services]\r
+AddService = vnic,%SPSVCINST_ASSOCSERVICE%,VNIC.ServiceInstall,VNIC.EventLogInstall\r
+\r
+[VNIC.DDInstall.ntia64.Services]\r
+AddService = vnic,%SPSVCINST_ASSOCSERVICE%,VNIC.ServiceInstall,VNIC.EventLogInstall\r
+\r
+[VNIC.CopyFiles]\r
+vnic.sys\r
+\r
+[VNIC.AddReg]\r
+HKR, Ndi,                       Service,    0, "ipoib"\r
+HKR, Ndi\Interfaces,            UpperRange, 0, "ndis5"\r
+HKR, Ndi\Interfaces,            LowerRange, 0, "ethernet"\r
+\r
+\r
+; ============= Service Install section ==============\r
+\r
+[VNIC.ServiceInstall]\r
+DisplayName     = %VNIC.ServiceDesc%\r
+ServiceType     = %SERVICE_KERNEL_DRIVER%\r
+StartType       = %SERVICE_DEMAND_START%\r
+ErrorControl    = %SERVICE_ERROR_NORMAL%\r
+ServiceBinary   = %12%\vnic.sys\r
+LoadOrderGroup  = NDIS\r
+AddReg          = VNIC.ParamsReg\r
+\r
+[VNIC.ParamsReg]\r
+HKR,"Params\PnpInterface",%InternalBus%,%REG_DWORD%,1\r
+HKR,"Params\PnpInterface",%PNPBus%,%REG_DWORD%,1\r
+\r
+HKR, Params,   MinMtu,,                                        "1500"\r
+HKR, Params,   MaxMtu,,                                        "9500"\r
+HKR, Params,   MinHostPoolSz,,                         "64"\r
+HKR, Params,   HostRecvPoolEntries,,           "256"\r
+HKR, Params,   MinEiocPoolSz,,                         "64"\r
+HKR, Params,   MaxEiocPoolSz,,                         "256"\r
+HKR, Params,   MinHostKickTimeout,,            "50"\r
+HKR, Params,   MaxHostKickTimeout,,            "200"\r
+HKR, Params,   MinHostKickEntries,,            "1"\r
+HKR, Params,   MaxHostKickEntries,,            "64"\r
+HKR, Params,   MinHostKickBytes,,                      "0"\r
+HKR, Params,   MaxHostKickBytes,,                      "5000"\r
+HKR, Params,   MinHostUpdateSz,,                       "8"\r
+HKR, Params,   MaxHostUpdateSz,,                       "32"\r
+HKR, Params,   MinEiocUpdateSz,,                       "8"\r
+HKR, Params,   MaxEiocUpdateSz,,                       "32"\r
+HKR, Params,   UseRxCsum,                              %REG_DWORD%,1\r
+HKR, Params,   UseTxCsum,                              %REG_DWORD%,1\r
+\r
+[VNIC.EventLogInstall]\r
+AddReg = VNIC.EventLogAddReg\r
+\r
+[VNIC.EventLogAddReg]\r
+HKR,,EventMessageFile,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\netevent.dll"\r
+HKR,,TypesSupported,%REG_DWORD%,7\r
+\r
+[Strings]\r
+NetClassGuid = "{4d36e972-e325-11ce-bfc1-08002be10318}"\r
+Inf_Provider = "SilverStorm Technologies"\r
+VNIC.DeviceDesc = "Ethernet over InfiniBand Virtual NIC"\r
+VNIC.ServiceDesc = "Virtual NIC"\r
+DiskId = "SilverStorm Ethernet over InfiniBand Virtual NIC installation disk"\r
+InternalBus                            = 0\r
+PNPBus                                 = 15\r
+SPSVCINST_NULL                 = 0x0\r
+SPSVCINST_ASSOCSERVICE = 0x00000002\r
+SERVICE_KERNEL_DRIVER  = 1\r
+SERVICE_DEMAND_START   = 3\r
+SERVICE_ERROR_NORMAL   = 1\r
+REG_DWORD                              = 0x00010001\r
+REG_DWORD_NO_CLOBBER   = 0x00010003\r
+REG_EXPAND_SZ                  = 0x00020000\r
+CHARACTERISTICS                        = 0x81 ; NCF_VIRTUAL | NCF_HAS_UI\r
+\r
diff --git a/ulp/inic/kernel/vnic_adapter.c b/ulp/inic/kernel/vnic_adapter.c
new file mode 100644 (file)
index 0000000..624a6b1
--- /dev/null
@@ -0,0 +1,1007 @@
+/*\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$\r
+ */\r
+\r
+#include <iba/ib_al.h>\r
+#include <iba/ioc_ifc.h>\r
+#include <complib/cl_bus_ifc.h>\r
+#include "vnic_adapter.h"\r
+\r
+//#include "vnic_driver.h"\r
+\r
+extern struct _vnic_globals    g_vnic;\r
+\r
+NDIS_STATUS\r
+vnic_get_adapter_params(\r
+       IN                              NDIS_HANDLE                             h_handle,\r
+       OUT                             vnic_params_t* const    p_params );\r
+\r
+NDIS_STATUS\r
+vnic_get_adapter_interface(\r
+       IN                              NDIS_HANDLE                     h_handle,\r
+       IN                              vnic_adapter_t          *p_adapter);\r
+\r
+static ib_api_status_t\r
+__path_record_add(\r
+       IN                              vnic_adapter_t          *p_adapter,\r
+       IN                              ib_path_rec_t           *p_path_rec );\r
+\r
+static ib_api_status_t\r
+__path_record_remove(\r
+       IN                              vnic_adapter_t          *p_adapter,\r
+       IN                              ib_path_rec_t           *p_path_rec );\r
+\r
+static BOOLEAN\r
+__path_records_match(\r
+       IN                              ib_path_rec_t           *p_path1,\r
+       IN                              ib_path_rec_t           *p_path2 );\r
+\r
+static void\r
+__path_records_cleanup(\r
+       IN         vnic_adapter_t       *p_adapter );\r
+\r
+static ib_api_status_t\r
+_vnic_get_ca_info(\r
+                       IN              vnic_adapter_t          *p_adapter );\r
+\r
+static inline uint8_t\r
+_get_ioc_num_from_iocguid(\r
+                       IN              ib_net64_t              *p_iocguid );\r
+\r
+static BOOLEAN\r
+__sid_valid(\r
+               IN              vnic_adapter_t          *p_adapter,\r
+               IN              ib_net64_t                      sid );\r
+\r
+static void\r
+_vnic_viport_free(\r
+               IN       vnic_adapter_t* const          p_adapter );\r
+\r
+ib_api_status_t\r
+vnic_create_adapter(\r
+       IN              NDIS_HANDLE                     h_handle,\r
+       OUT             vnic_adapter_t**        const pp_adapter)\r
+{\r
+       NDIS_STATUS                     status;\r
+       ib_api_status_t         ib_status;\r
+       vnic_adapter_t          *p_adapter;\r
+       KIRQL                           irql;\r
+\r
+       VNIC_ENTER( VNIC_DBG_ADAPTER );\r
+\r
+       status = NdisAllocateMemoryWithTag( &p_adapter, sizeof(vnic_adapter_t), 'pada');\r
+\r
+       if ( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               VNIC_TRACE_EXIT(VNIC_DBG_ERROR,("Failed to allocate adapter\n"));\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       NdisZeroMemory( p_adapter, sizeof(vnic_adapter_t) );\r
+\r
+       NdisAllocateSpinLock( &p_adapter->lock );\r
+\r
+       status = vnic_get_adapter_params( h_handle, &p_adapter->params );\r
+\r
+       if ( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       (" vnic_get_adapter_params failed with status %d\n", status));\r
+               NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
+               return IB_INVALID_PARAMETER;\r
+       }\r
+\r
+       status = vnic_get_adapter_interface( h_handle, p_adapter );\r
+       if ( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("failed status %x\n", status ) );\r
+               NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
+               return IB_INVALID_PARAMETER;\r
+       }\r
+\r
+       /*Open AL */\r
+       ib_status = p_adapter->ifc.open_al( &p_adapter->h_al );\r
+       if ( ib_status != IB_SUCCESS )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("ib_open_al returned %s\n", p_adapter->ifc.get_err_str( ib_status )) );\r
+               NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
+               return ib_status;\r
+       }\r
+\r
+       /* ca is opened here */\r
+       ib_status = _vnic_get_ca_info( p_adapter );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               VNIC_TRACE ( VNIC_DBG_ERROR,\r
+                       ("_get_ca_info return status %s\n", p_adapter->ifc.get_err_str( ib_status )) );\r
+               NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
+               return ib_status;\r
+       }\r
+\r
+       KeAcquireSpinLock( &g_vnic.lock, &irql );\r
+       InsertTailList( &g_vnic.adapter_list, &p_adapter->list_entry );\r
+       InterlockedIncrement( &g_vnic.adapters );\r
+       KeReleaseSpinLock( &g_vnic.lock, irql );\r
+\r
+       p_adapter->h_handle = h_handle;\r
+       *pp_adapter = p_adapter;\r
+\r
+       VNIC_EXIT( VNIC_DBG_ADAPTER );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+vnic_destroy_adapter(\r
+        IN      vnic_adapter_t         *p_adapter)\r
+{\r
+       ib_api_status_t ib_status = IB_SUCCESS;\r
+       KIRQL                   irql;\r
+\r
+       VNIC_ENTER( VNIC_DBG_ADAPTER );\r
+\r
+       ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
+\r
+       KeAcquireSpinLock( &g_vnic.lock, &irql );\r
+       RemoveEntryList( &p_adapter->list_entry );\r
+       InterlockedDecrement( &g_vnic.adapters );\r
+       KeReleaseSpinLock( &g_vnic.lock, irql );\r
+\r
+       if( p_adapter->h_pnp )\r
+       {\r
+               ib_status =\r
+                       p_adapter->ifc.dereg_pnp( p_adapter->h_pnp, ib_sync_destroy );\r
+       }\r
+\r
+       vnic_viport_cleanup( p_adapter );\r
+\r
+       if ( p_adapter->ca.region.h_mr )\r
+       {\r
+               ib_status = p_adapter->ifc.dereg_mr(p_adapter->ca.region.h_mr );\r
+               ASSERT( ib_status == IB_SUCCESS );\r
+       }\r
+\r
+       if( p_adapter->ca.hPd )\r
+       {\r
+               ib_status = p_adapter->ifc.dealloc_pd( p_adapter->ca.hPd, NULL );\r
+               ASSERT( ib_status == IB_SUCCESS );\r
+       }\r
+\r
+       if ( p_adapter->h_ca )\r
+       {\r
+               ib_status = p_adapter->ifc.close_ca( p_adapter->h_ca, NULL );\r
+               ASSERT( ib_status == IB_SUCCESS );\r
+       }\r
+\r
+       if ( p_adapter->h_al )\r
+       {\r
+               ib_status = p_adapter->ifc.close_al( p_adapter->h_al );\r
+               ASSERT( ib_status == IB_SUCCESS );\r
+       }\r
+\r
+       if ( p_adapter->p_svc_entries )\r
+               cl_free ( p_adapter->p_svc_entries );\r
+\r
+       NdisFreeSpinLock( &p_adapter->lock );\r
+       NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
+\r
+       VNIC_EXIT( VNIC_DBG_ADAPTER );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+_vnic_get_ca_info(\r
+                       IN                      vnic_adapter_t          *p_adapter )\r
+{\r
+       ib_api_status_t         ib_status = IB_SUCCESS;\r
+       ib_al_ifc_t                     *p_ifc  = &p_adapter->ifc;\r
+       uint32_t                        attr_size;\r
+       ib_ca_attr_t            *p_ca_attrs;\r
+       uint32_t                        num;\r
+       uint64_t        start_addr      = 0;\r
+\r
+       ib_status = p_ifc->open_ca( p_adapter->h_al,\r
+                                                               p_adapter->ifc_data.ca_guid,\r
+                                                               ib_asyncEvent,\r
+                                                               p_adapter,\r
+                                                               &p_adapter->h_ca );\r
+\r
+       if ( ib_status != IB_SUCCESS )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("Failed to open hca\n") );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       ib_status = p_ifc->query_ca( p_adapter->h_ca, NULL , &attr_size );\r
+       if( ib_status != IB_INSUFFICIENT_MEMORY )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("ib_query_ca failed status %s\n",\r
+                       p_ifc->get_err_str( ib_status )) );\r
+               return IB_INSUFFICIENT_RESOURCES;\r
+       }\r
+\r
+       ASSERT( attr_size );\r
+\r
+       p_ca_attrs = cl_zalloc( attr_size );\r
+       if ( p_ca_attrs == NULL )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("Allocate %d bytes failed for Channel adapter\n", attr_size ));\r
+               return IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       ib_status = p_ifc->query_ca( p_adapter->h_ca, p_ca_attrs , &attr_size );\r
+       if ( ib_status != IB_SUCCESS )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("Query failed for channel adapter\n") );\r
+               cl_free ( p_ca_attrs );\r
+               return  ib_status;\r
+       }\r
+\r
+       p_adapter->ca.numPorts = p_ca_attrs->num_ports;\r
+       if( p_adapter->ca.numPorts > VNIC_CA_MAX_PORTS )\r
+               p_adapter->ca.numPorts = VNIC_CA_MAX_PORTS;\r
+\r
+       for( num = 0; num < p_adapter->ca.numPorts; num++ )\r
+               p_adapter->ca.portGuids[num] = p_ca_attrs->p_port_attr[num].port_guid;\r
+\r
+       p_adapter->ca.caGuid = p_adapter->ifc_data.ca_guid;\r
+\r
+       cl_free ( p_ca_attrs );\r
+\r
+       ib_status = p_adapter->ifc.alloc_pd( p_adapter->h_ca,\r
+               IB_PDT_NORMAL, p_adapter, &p_adapter->ca.hPd );\r
+       if ( ib_status != IB_SUCCESS )\r
+       {\r
+               VNIC_TRACE_EXIT ( VNIC_DBG_ERROR,\r
+                       ("alloc PD failed status %s(%d)\n",\r
+                       p_adapter->ifc.get_err_str(ib_status), ib_status ));\r
+               return ib_status;\r
+       }\r
+\r
+       if ( ( ib_status = ibregion_physInit( p_adapter,\r
+                                                        &p_adapter->ca.region,\r
+                                                        p_adapter->ca.hPd,\r
+                                                        &start_addr,\r
+                                                        MAX_PHYS_MEMORY ) ) != IB_SUCCESS )\r
+       {\r
+               VNIC_TRACE_EXIT ( VNIC_DBG_ERROR,\r
+                       ("phys region init failed status %s(%d)\n",\r
+                       p_adapter->ifc.get_err_str(ib_status), ib_status ));\r
+\r
+               p_adapter->ifc.dealloc_pd( p_adapter->ca.hPd, NULL );\r
+       }\r
+\r
+       return ib_status;\r
+}\r
+\r
+static BOOLEAN\r
+_vnic_params_sanity_check(vnic_params_t *p_params)\r
+{\r
+        DEFAULT_PARAM( p_params->MaxAddressEntries, MAX_ADDRESS_ENTRIES );\r
+        DEFAULT_PARAM( p_params->MinAddressEntries, MIN_ADDRESS_ENTRIES );\r
+     \r
+               DEFAULT_PARAM( p_params->ViportStatsInterval, VIPORT_STATS_INTERVAL );\r
+        DEFAULT_PARAM( p_params->ViportHbInterval, VIPORT_HEARTBEAT_INTERVAL );\r
+        DEFAULT_PARAM( p_params->ViportHbTimeout, VIPORT_HEARTBEAT_TIMEOUT );\r
+       \r
+               DEFAULT_PARAM( p_params->ControlRspTimeout, CONTROL_RSP_TIMEOUT );\r
+        DEFAULT_PARAM( p_params->ControlReqRetryCount, CONTROL_REQ_RETRY_COUNT );\r
+       \r
+               DEFAULT_PARAM( p_params->RetryCount, RETRY_COUNT );\r
+        DEFAULT_PARAM( p_params->MinRnrTimer, MIN_RNR_TIMER );\r
+       \r
+               DEFAULT_PARAM( p_params->MaxViportsPerNetpath, MAX_VIPORTS_PER_NETPATH );\r
+        DEFAULT_PARAM( p_params->DefaultViportsPerNetpath, DEFAULT_VIPORTS_PER_NETPATH );\r
+\r
+               DEFAULT_PARAM( p_params->DefaultPkey, DEFAULT_PKEY );\r
+        DEFAULT_PARAM( p_params->NotifyBundleSz, NOTIFY_BUNDLE_SZ );\r
+               DEFAULT_PARAM( p_params->DefaultNoPathTimeout, DEFAULT_NO_PATH_TIMEOUT );\r
+        DEFAULT_PARAM( p_params->DefaultPrimaryConnectTimeout, DEFAULT_PRI_CON_TIMEOUT );\r
+        DEFAULT_PARAM( p_params->DefaultPrimaryReconnectTimeout, DEFAULT_PRI_RECON_TIMEOUT );\r
+        DEFAULT_PARAM( p_params->DefaultPrimarySwitchTimeout, DEFAULT_PRI_SWITCH_TIMEOUT );\r
+               DEFAULT_PARAM( p_params->DefaultPreferPrimary, DEFAULT_PREFER_PRIMARY );\r
+\r
+        U32_RANGE( p_params->MaxAddressEntries );\r
+        U32_RANGE( p_params->MinAddressEntries );\r
+               RANGE_CHECK( p_params->MinMtu, MIN_MTU, MAX_MTU );\r
+        RANGE_CHECK( p_params->MaxMtu, MIN_MTU, MAX_MTU );\r
+        U32_RANGE( p_params->HostRecvPoolEntries );\r
+        U32_RANGE( p_params->MinHostPoolSz );\r
+        U32_RANGE( p_params->MinEiocPoolSz );\r
+        U32_RANGE( p_params->MaxEiocPoolSz );\r
+        U32_ZERO_RANGE( p_params->MinHostKickTimeout );\r
+        U32_ZERO_RANGE( p_params->MaxHostKickTimeout );\r
+        U32_ZERO_RANGE( p_params->MinHostKickEntries );\r
+        U32_ZERO_RANGE( p_params->MaxHostKickEntries );\r
+        U32_ZERO_RANGE( p_params->MinHostKickBytes );\r
+        U32_ZERO_RANGE( p_params->MaxHostKickBytes );\r
+        U32_RANGE( p_params->MinHostUpdateSz );\r
+        U32_RANGE( p_params->MaxHostUpdateSz );\r
+        U32_RANGE( p_params->MinEiocUpdateSz );\r
+        U32_RANGE( p_params->MaxEiocUpdateSz );\r
+        U8_RANGE( p_params->NotifyBundleSz );\r
+        U32_ZERO_RANGE( p_params->ViportStatsInterval );\r
+        U32_ZERO_RANGE( p_params->ViportHbInterval );\r
+        U32_ZERO_RANGE( p_params->ViportHbTimeout );\r
+        U32_RANGE( p_params->ControlRspTimeout );\r
+        U8_RANGE( p_params->ControlReqRetryCount );\r
+        ZERO_RANGE_CHECK( p_params->RetryCount, 0, 7 );\r
+        ZERO_RANGE_CHECK( p_params->MinRnrTimer, 0, 31 );\r
+        U32_RANGE( p_params->DefaultViportsPerNetpath );\r
+        U8_RANGE( p_params->MaxViportsPerNetpath );\r
+        U16_ZERO_RANGE( p_params->DefaultPkey );\r
+        U32_RANGE( p_params->DefaultNoPathTimeout );\r
+        U32_RANGE( p_params->DefaultPrimaryConnectTimeout );\r
+        U32_RANGE( p_params->DefaultPrimaryReconnectTimeout );\r
+        U32_RANGE( p_params->DefaultPrimarySwitchTimeout );\r
+        BOOLEAN_RANGE( p_params->DefaultPreferPrimary );\r
+        BOOLEAN_RANGE( p_params->UseRxCsum );\r
+        BOOLEAN_RANGE( p_params->UseTxCsum );\r
+\r
+        LESS_THAN_OR_EQUAL( p_params->MinAddressEntries, p_params->MaxAddressEntries );\r
+        LESS_THAN_OR_EQUAL( p_params->MinMtu, p_params->MaxMtu );\r
+        LESS_THAN_OR_EQUAL( p_params->MinHostPoolSz, p_params->HostRecvPoolEntries );\r
+        POWER_OF_2( p_params->HostRecvPoolEntries );\r
+        POWER_OF_2( p_params->MinHostPoolSz );\r
+        POWER_OF_2( p_params->NotifyBundleSz );\r
+        LESS_THAN( p_params->NotifyBundleSz, p_params->MinEiocPoolSz );\r
+        LESS_THAN_OR_EQUAL( p_params->MinEiocPoolSz, p_params->MaxEiocPoolSz );\r
+        POWER_OF_2( p_params->MinEiocPoolSz );\r
+        POWER_OF_2( p_params->MaxEiocPoolSz );\r
+        LESS_THAN_OR_EQUAL( p_params->MinHostKickTimeout, p_params->MaxHostKickTimeout );\r
+        LESS_THAN_OR_EQUAL( p_params->MinHostKickEntries, p_params->MaxHostKickEntries );\r
+        LESS_THAN_OR_EQUAL( p_params->MinHostKickBytes, p_params->MaxHostKickBytes );\r
+        LESS_THAN_OR_EQUAL( p_params->MinHostUpdateSz, p_params->MaxHostUpdateSz );\r
+        POWER_OF_2( p_params->MinHostUpdateSz );\r
+        POWER_OF_2( p_params->MaxHostUpdateSz );\r
+        LESS_THAN( p_params->MinHostUpdateSz, p_params->MinHostPoolSz );\r
+        LESS_THAN( p_params->MaxHostUpdateSz, p_params->HostRecvPoolEntries );\r
+        LESS_THAN_OR_EQUAL( p_params->MinEiocUpdateSz, p_params->MaxEiocUpdateSz );\r
+        POWER_OF_2( p_params->MinEiocUpdateSz );\r
+        POWER_OF_2( p_params->MaxEiocUpdateSz );\r
+        LESS_THAN( p_params->MinEiocUpdateSz, p_params->MinEiocPoolSz );\r
+        LESS_THAN( p_params->MaxEiocUpdateSz, p_params->MaxEiocPoolSz );\r
+        LESS_THAN_OR_EQUAL( p_params->DefaultViportsPerNetpath, p_params->MaxViportsPerNetpath );\r
+\r
+        return TRUE;\r
+\r
+}\r
+NDIS_STATUS\r
+vnic_get_adapter_params(\r
+       IN                      NDIS_HANDLE                             h_handle,\r
+       OUT                     vnic_params_t* const    p_params )\r
+{\r
+       NDIS_STATUS                                             status;\r
+       NDIS_HANDLE                                             h_config;\r
+       NDIS_CONFIGURATION_PARAMETER    *p_reg_prm;\r
+       //NDIS_STRING                                           keyword;\r
+\r
+       VNIC_ENTER( VNIC_DBG_ADAPTER );\r
+\r
+       CL_ASSERT(p_params );\r
+\r
+       /* prepare params for default initialization */\r
+       cl_memset( p_params, 0xff, sizeof (vnic_params_t) );\r
+\r
+       NdisOpenConfiguration( &status, &h_config, h_handle );\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+                       ("NdisOpenConfiguration returned 0x%.8x\n", status) );\r
+               return status;\r
+       }\r
+\r
+       status = NDIS_STATUS_FAILURE;\r
+       p_reg_prm = NULL;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"DebugFlags" );\r
+\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+       //if( status == NDIS_STATUS_SUCCESS )\r
+       //              g_vnic_dbg_lvl = p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MinMtu" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MinMtu = ( status != NDIS_STATUS_SUCCESS ) ? MIN_MTU:\r
+                                               p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MaxMtu" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MaxMtu =( status != NDIS_STATUS_SUCCESS )? MAX_MTU:\r
+                                               p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"UseRxCsum" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->UseRxCsum = ( status != NDIS_STATUS_SUCCESS ) ?\r
+               TRUE : ( p_reg_prm->ParameterData.IntegerData )? TRUE : FALSE;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"UseTxCsum" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       /* turn it on by default, if not present */\r
+       p_params->UseTxCsum = ( status != NDIS_STATUS_SUCCESS ) ?\r
+               TRUE : ( p_reg_prm->ParameterData.IntegerData )? TRUE : FALSE;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MinEiocUpdateSz" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MinEiocUpdateSz = ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       MIN_EIOC_UPDATE_SZ : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MaxEiocUpdateSz" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MaxEiocUpdateSz = ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       MAX_EIOC_UPDATE_SZ : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MinHostUpdateSz" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MinHostUpdateSz = ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       MIN_HOST_UPDATE_SZ : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MaxHostUpdateSz" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MaxHostUpdateSz = ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       MAX_HOST_UPDATE_SZ : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MinHostKickBytes" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MinHostKickBytes = ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       MIN_HOST_KICK_BYTES : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MaxHostKickBytes" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MaxHostKickBytes = ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       MAX_HOST_KICK_BYTES : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MinHostKickEntries" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MinHostKickEntries =  ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       MIN_HOST_KICK_ENTRIES : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MaxHostKickEntries" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MaxHostKickEntries =  ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       MAX_HOST_KICK_ENTRIES : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MinHostKickTimeout" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MinHostKickTimeout =  ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       MIN_HOST_KICK_TIMEOUT : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MaxHostKickTimeout" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MaxHostKickTimeout =  ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       MAX_HOST_KICK_TIMEOUT : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MinEiocPoolSz" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MinEiocPoolSz =  ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       MIN_EIOC_POOL_SZ : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MaxEiocPoolSz" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MaxEiocPoolSz =  ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       MAX_EIOC_POOL_SZ : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"MinHostPoolSz" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->MinHostPoolSz =  ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       MIN_HOST_POOL_SZ : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       //RtlInitUnicodeString( &keyword, L"HostRecvPoolEntries" );\r
+       //NdisReadConfiguration(\r
+       //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
+\r
+       p_params->HostRecvPoolEntries =  ( status != NDIS_STATUS_SUCCESS ) ?\r
+                       HOST_RECV_POOL_ENTRIES : p_reg_prm->ParameterData.IntegerData;\r
+\r
+       NdisCloseConfiguration( h_config );\r
+\r
+       status = ( _vnic_params_sanity_check(p_params)?\r
+                               NDIS_STATUS_SUCCESS: NDIS_STATUS_FAILURE );\r
+\r
+       VNIC_EXIT( VNIC_DBG_ADAPTER );\r
+       return status;\r
+}\r
+\r
+ib_api_status_t\r
+vnic_viport_allocate(\r
+       IN                      vnic_adapter_t* const           p_adapter,\r
+       IN OUT          viport_t**              const           pp_viport )\r
+{\r
+       viport_t        *p_viport;\r
+       NDIS_STATUS      status;\r
+       VNIC_ENTER( VNIC_DBG_ADAPTER );\r
+\r
+       NdisAcquireSpinLock( &p_adapter->lock );\r
+       status = NdisAllocateMemoryWithTag( &p_viport, sizeof(viport_t), 'trop' );\r
+\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               NdisReleaseSpinLock( &p_adapter->lock );\r
+               VNIC_TRACE_EXIT(VNIC_DBG_ERROR,\r
+                               ( "Failed allocating Viport structure\n" ));\r
+               return IB_ERROR;\r
+       }\r
+\r
+       NdisZeroMemory( p_viport, sizeof(viport_t) );\r
+\r
+       KeInitializeSpinLock( &p_viport->lock );\r
+       InitializeListHead( &p_viport->listPtrs );\r
+       cl_qlist_init( &p_viport->send_pending_list );\r
+\r
+       KeInitializeEvent( &p_viport->conn_event, SynchronizationEvent, FALSE );\r
+\r
+       p_viport->p_adapter = p_adapter;\r
+\r
+       viport_get_adapter_name( p_viport );\r
+\r
+       viport_config_defaults ( p_viport );\r
+       VNIC_TRACE( VNIC_DBG_PNP, ("Configure Viport default values\n") );\r
+\r
+       control_construct( &p_viport->control, p_viport );\r
+       data_construct( &p_viport->data, p_viport );\r
+\r
+       *pp_viport = p_viport;\r
+\r
+       NdisReleaseSpinLock( &p_adapter->lock );\r
+       VNIC_EXIT( VNIC_DBG_ADAPTER );\r
+       return IB_SUCCESS;\r
+}\r
+static void\r
+_vnic_viport_free(\r
+       IN       vnic_adapter_t* const          p_adapter )\r
+{\r
+       viport_t        *p_viport = p_adapter->p_viport;\r
+       VNIC_ENTER( VNIC_DBG_ADAPTER );\r
+\r
+       if ( p_viport )\r
+       {\r
+               p_adapter->p_viport = NULL;\r
+               NdisFreeMemory( p_viport, sizeof(viport_t), 0 );\r
+       }\r
+       p_adapter->state = INIC_UNINITIALIZED;\r
+\r
+       VNIC_EXIT( VNIC_DBG_ADAPTER );\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+vnic_set_mcast(\r
+       IN                              vnic_adapter_t* const           p_adapter,\r
+       IN                              mac_addr_t* const                       p_mac_array,\r
+       IN              const   uint8_t                                         mc_count )\r
+{\r
+       NDIS_STATUS     status;\r
+\r
+       VNIC_ENTER( VNIC_DBG_MCAST );\r
+\r
+       /* Copy the MC address list into the adapter. */\r
+       if( mc_count )\r
+       {\r
+               RtlCopyMemory(\r
+                       p_adapter->mcast_array, p_mac_array, mc_count * MAC_ADDR_LEN );\r
+       }\r
+       p_adapter->mc_count = mc_count;\r
+\r
+       if( !p_adapter->p_currentPath->pViport )\r
+               return NDIS_STATUS_SUCCESS;\r
+\r
+       p_adapter->pending_set = TRUE;\r
+       status = viport_setMulticast( p_adapter->p_currentPath->pViport );\r
+       if( status != NDIS_STATUS_PENDING )\r
+       {\r
+               p_adapter->pending_set = FALSE;\r
+       }\r
+\r
+       VNIC_EXIT( VNIC_DBG_MCAST );\r
+       return status;\r
+}\r
+\r
+\r
+static BOOLEAN\r
+__path_records_match(\r
+       IN                      ib_path_rec_t           *p_path1,\r
+       IN                      ib_path_rec_t           *p_path2 )\r
+{\r
+       if ( p_path1->dgid.unicast.prefix != p_path2->dgid.unicast.prefix )\r
+               return FALSE;\r
+       if ( p_path1->dgid.unicast.interface_id != p_path2->dgid.unicast.interface_id )\r
+               return FALSE;\r
+       if ( p_path1->dlid != p_path2->dlid )\r
+               return FALSE;\r
+       if ( p_path1->pkey != p_path2->pkey )\r
+               return FALSE;\r
+       if ( p_path1->rate != p_path2->rate )\r
+               return FALSE;\r
+\r
+       return TRUE;\r
+}\r
+\r
+static BOOLEAN\r
+__sid_valid(\r
+               IN              vnic_adapter_t          *p_adapter,\r
+               IN              ib_net64_t                      sid )\r
+{\r
+       vnic_sid_t      svc_id;\r
+       svc_id.as_uint64 = sid;\r
+       if( ( svc_id.s.base_id & 0x10 ) != 0x10 )\r
+               return FALSE;\r
+       if( svc_id.s.oui[0] != 0x00 &&\r
+               svc_id.s.oui[1] != 0x06 &&\r
+               svc_id.s.oui[2] != 0x6a )\r
+               return FALSE;\r
+       if ( svc_id.s.type != CONTROL_SID &&\r
+                svc_id.s.type != DATA_SID )\r
+                return FALSE;\r
+       if ( svc_id.s.ioc_num   != _get_ioc_num_from_iocguid( &p_adapter->ifc_data.guid ) )\r
+               return FALSE;\r
+       return TRUE;\r
+}\r
+static inline uint8_t\r
+_get_ioc_num_from_iocguid(\r
+                 IN ib_net64_t         *p_iocguid )\r
+{\r
+       return ( (vnic_ioc_guid_t *)p_iocguid)->s.ioc_num;\r
+}\r
+\r
+static ib_api_status_t\r
+__path_record_add(\r
+       IN                              vnic_adapter_t          *p_adapter,\r
+       IN                              ib_path_rec_t           *p_path_rec )\r
+{\r
+\r
+       NdisAcquireSpinLock( &p_adapter->lock );\r
+\r
+       if ( !__path_records_match( &p_adapter->path_record.path_rec, p_path_rec ) )\r
+       {\r
+                       p_adapter->path_record.path_rec = *p_path_rec;\r
+                       p_adapter->path_record.num_entries++;\r
+       }\r
+\r
+       NdisReleaseSpinLock( &p_adapter->lock );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+static ib_api_status_t\r
+__path_record_remove(\r
+               IN                      vnic_adapter_t          *p_adapter,\r
+               IN                      ib_path_rec_t           *p_path_rec )\r
+{\r
+\r
+       NdisAcquireSpinLock( &p_adapter->lock );\r
+\r
+       if ( __path_records_match( &p_adapter->path_record.path_rec, p_path_rec ) )\r
+       {\r
+               --p_adapter->path_record.num_entries;\r
+               cl_memclr( &p_adapter->path_record.path_rec, sizeof( ib_path_rec_t ));\r
+       }\r
+\r
+       NdisReleaseSpinLock( &p_adapter->lock );\r
+       return IB_SUCCESS;\r
+}\r
+\r
+static void\r
+__path_records_cleanup(\r
+                  vnic_adapter_t       *p_adapter )\r
+{\r
+\r
+       NdisAcquireSpinLock( &p_adapter->lock );\r
+\r
+       cl_memclr( &p_adapter->path_record.path_rec, sizeof( ib_path_rec_t ));\r
+       p_adapter->path_record.num_entries = 0;\r
+\r
+       NdisReleaseSpinLock( &p_adapter->lock );\r
+       return;\r
+}\r
+ib_api_status_t\r
+__vnic_pnp_cb(\r
+       IN              ib_pnp_rec_t                *p_pnp_rec )\r
+{\r
+       ib_api_status_t                 ib_status = IB_SUCCESS;\r
+       ib_pnp_ioc_rec_t                *p_ioc_rec;\r
+       ib_pnp_ioc_path_rec_t   *p_ioc_path;\r
+\r
+       vnic_adapter_t * __ptr64 p_adapter = (vnic_adapter_t * __ptr64)p_pnp_rec->pnp_context;\r
+       \r
+       VNIC_ENTER( VNIC_DBG_PNP );\r
+\r
+       CL_ASSERT( p_adapter );\r
+\r
+       switch( p_pnp_rec->pnp_event )\r
+       {\r
+               case IB_PNP_IOC_ADD:\r
+                       p_ioc_rec = (ib_pnp_ioc_rec_t*)p_pnp_rec;\r
+\r
+                       VNIC_TRACE( VNIC_DBG_PNP, ("IB_PNP_IOC_ADD for %s.\n", p_ioc_rec->info.profile.id_string) );\r
+\r
+                       if( p_adapter->ifc_data.ca_guid != p_ioc_rec->ca_guid )\r
+                       {\r
+                               VNIC_TRACE_EXIT( VNIC_DBG_WARN, ("Invalid CA GUID.\n") );\r
+                               ib_status = IB_INVALID_GUID;\r
+                               break;\r
+                       }\r
+                       if( p_adapter->ifc_data.guid != p_ioc_rec->info.profile.ioc_guid )\r
+                       {\r
+                               VNIC_TRACE_EXIT( VNIC_DBG_WARN, ("Invalid IOC GUID.\n") );\r
+                               ib_status = IB_INVALID_GUID;\r
+                               break;\r
+                       }\r
+                       /* get ioc profile data */\r
+                       NdisAcquireSpinLock( &p_adapter->lock );\r
+               \r
+                       InterlockedExchange( (volatile LONG*)&p_adapter->pnp_state, IB_PNP_IOC_ADD );\r
+               \r
+                       p_adapter->ioc_info = p_ioc_rec->info;\r
+                       p_adapter->num_svc_entries = p_ioc_rec->info.profile.num_svc_entries;\r
+               \r
+                       CL_ASSERT(p_adapter->num_svc_entries >= 2 );\r
+\r
+                       if( !__sid_valid( p_adapter, p_ioc_rec->svc_entry_array[0].id ) )\r
+                       {\r
+                               NdisReleaseSpinLock( &p_adapter->lock );\r
+\r
+                               VNIC_TRACE_EXIT( VNIC_DBG_WARN,\r
+                                       ("Invalid Service ID %#I64x\n",p_ioc_rec->svc_entry_array[0].id ) );\r
+\r
+                               ib_status = IB_INVALID_GUID; // should it be set INVALID_SERVICE_TYPE ?\r
+                               break;\r
+                       }\r
+\r
+                       p_adapter->p_svc_entries =\r
+                                       cl_zalloc( sizeof(ib_svc_entry_t) *\r
+                                       p_adapter->ioc_info.profile.num_svc_entries );\r
+\r
+                       if( p_adapter->p_svc_entries == NULL )\r
+                       {\r
+                               NdisReleaseSpinLock( &p_adapter->lock );\r
+\r
+                               VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("Insufficient Memory.\n") );\r
+                               ib_status = IB_INSUFFICIENT_MEMORY;\r
+                               break;\r
+                       }\r
+\r
+                       cl_memcpy( p_adapter->p_svc_entries,\r
+                                               p_ioc_rec->svc_entry_array,\r
+                                               sizeof(ib_svc_entry_t) * p_adapter->ioc_info.profile.num_svc_entries);\r
+\r
+                       VNIC_TRACE( VNIC_DBG_PNP,\r
+                               ("Found %d Service Entries.\n", p_adapter->ioc_info.profile.num_svc_entries));\r
+                       NdisReleaseSpinLock( &p_adapter->lock );\r
+                       break;\r
+\r
+               case IB_PNP_IOC_REMOVE:\r
+                       CL_ASSERT( p_pnp_rec->guid == p_adapter->ifc_data.guid );\r
+               \r
+                       p_ioc_rec = (ib_pnp_ioc_rec_t*)p_pnp_rec;\r
+\r
+                       InterlockedExchange( (volatile LONG*)&p_adapter->pnp_state, IB_PNP_IOC_REMOVE );\r
+               \r
+                       VNIC_TRACE( VNIC_DBG_PNP, ("IB_PNP_IOC_REMOVE for %s.\n",\r
+                                                       p_adapter->ioc_info.profile.id_string) );\r
+               \r
+                       NdisMIndicateStatus( p_adapter->h_handle,\r
+                                       NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );\r
+                               NdisMIndicateStatusComplete( p_adapter->h_handle );\r
+                       vnic_viport_cleanup( p_adapter );\r
+                       break;\r
+\r
+               case IB_PNP_IOC_PATH_ADD:\r
+                       /* path for our IOC ? */\r
+                       if ( p_pnp_rec->guid != p_adapter->ifc_data.guid )\r
+                       {\r
+                               VNIC_TRACE( VNIC_DBG_PNP,\r
+                                       ("Getting path for wrong IOC\n") );\r
+                               ib_status = IB_INVALID_GUID;\r
+                               break;\r
+                       }\r
+                       p_ioc_path = (ib_pnp_ioc_path_rec_t*)p_pnp_rec;\r
+\r
+                       if( p_adapter->state != INIC_UNINITIALIZED )\r
+                               break;\r
+\r
+                       ib_status = __path_record_add( p_adapter, &p_ioc_path->path );\r
+                       if ( ib_status != IB_SUCCESS )\r
+                       {\r
+                               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                                       ("Failed to add path record\n") );\r
+                               break;\r
+                       }\r
+\r
+                       netpath_init( &p_adapter->primaryPath, p_adapter );\r
+                       p_adapter->p_currentPath = &p_adapter->primaryPath;\r
+\r
+                       ib_status = vnic_viport_allocate( p_adapter, &p_adapter->p_viport );\r
+\r
+                       if( ib_status != IB_SUCCESS )\r
+                       {\r
+                               VNIC_TRACE ( VNIC_DBG_ERROR,\r
+                                                       ("Failed status %s\n", p_adapter->ifc.get_err_str( ib_status )) );\r
+                               _vnic_viport_free( p_adapter );\r
+                               return ib_status;\r
+                       }\r
+               \r
+                       netpath_addPath( p_adapter->p_currentPath, p_adapter->p_viport );\r
+                       viport_setPath( p_adapter->p_viport,\r
+                                                       &p_adapter->path_record.path_rec,\r
+                                                       &p_adapter->ioc_info.profile.ioc_guid );\r
+               \r
+                       ib_status = viport_control_connect( p_adapter->p_viport );\r
+                       if( ib_status != IB_SUCCESS )\r
+                       {\r
+                               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                                               ("Control path connect failed status s%\n",\r
+                                                                               p_adapter->ifc.get_err_str( ib_status )) );\r
+                               vnic_viport_cleanup( p_adapter );\r
+                               break;\r
+                       }\r
+\r
+                       ib_status = viport_data_connect( p_adapter->p_viport );\r
+                       if( ib_status != IB_SUCCESS )\r
+                       {\r
+                               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                                       ("Data path connect failed status %s\n",\r
+                                       p_adapter->ifc.get_err_str( ib_status )) );\r
+                               vnic_viport_cleanup( p_adapter );\r
+                               break;\r
+                       }\r
+\r
+                       p_adapter->state = INIC_REGISTERED;\r
+                       break;\r
+\r
+               case IB_PNP_IOC_PATH_REMOVE:\r
+                       p_ioc_path = (ib_pnp_ioc_path_rec_t*)p_pnp_rec;\r
+\r
+                       VNIC_TRACE( VNIC_DBG_PNP,\r
+                               ("IB_PNP_IOC_PATH_REMOVE (slid:%d dlid:%d) for %s.\n",\r
+                               ntoh16( p_ioc_path->path.slid ),\r
+                               ntoh16( p_ioc_path->path.dlid ),\r
+                               p_adapter->ioc_info.profile.id_string));\r
+\r
+                       ib_status = __path_record_remove( p_adapter, &p_ioc_path->path );\r
+               \r
+                       if ( ib_status != IB_SUCCESS )\r
+                       {\r
+                               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                                       ("Failed to remove path record\n") );\r
+                       }\r
+                       break;\r
+\r
+               default:\r
+                       VNIC_TRACE( VNIC_DBG_PNP,\r
+                               (" Received unhandled PnP event %#x\n", p_pnp_rec->pnp_event ) );\r
+                       break;\r
+       }\r
+\r
+       VNIC_EXIT( VNIC_DBG_PNP );\r
+       return ib_status;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+vnic_get_adapter_interface(\r
+       IN      NDIS_HANDLE                     h_handle,\r
+       IN      vnic_adapter_t          *p_adapter)\r
+{\r
+\r
+       NTSTATUS                        status;\r
+       ib_al_ifc_data_t        data;\r
+       IO_STACK_LOCATION       io_stack;\r
+       DEVICE_OBJECT           *p_pdo;\r
+\r
+       VNIC_ENTER( VNIC_DBG_ADAPTER );\r
+\r
+       NdisMGetDeviceProperty( h_handle, &p_pdo, NULL, NULL, NULL, NULL );\r
+\r
+       data.size = sizeof(ioc_ifc_data_t);\r
+       data.type = &GUID_IOC_INTERFACE_DATA;\r
+       data.version = IOC_INTERFACE_DATA_VERSION;\r
+       data.p_data = &p_adapter->ifc_data;\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 = (INTERFACE*)&p_adapter->ifc;\r
+       io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data;\r
+       io_stack.Parameters.QueryInterface.InterfaceType = &GUID_IB_AL_INTERFACE;\r
+\r
+       status = cl_fwd_query_ifc( p_pdo, &io_stack );\r
+\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+                       ("Query interface for VNIC interface returned %08x.\n", status) );\r
+               return status;\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
+       p_adapter->ifc.wdm.InterfaceDereference(\r
+               p_adapter->ifc.wdm.Context );\r
+\r
+       VNIC_EXIT( VNIC_DBG_ADAPTER );\r
+\r
+       return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+void\r
+vnic_viport_cleanup(\r
+               IN      vnic_adapter_t          *p_adapter )\r
+{\r
+       VNIC_ENTER( VNIC_DBG_ADAPTER );\r
+\r
+       if ( p_adapter->p_viport )\r
+               viport_cleanup(p_adapter->p_viport );\r
+       p_adapter->p_viport = NULL;\r
+\r
+       VNIC_EXIT( VNIC_DBG_ADAPTER );\r
+}\r
diff --git a/ulp/inic/kernel/vnic_adapter.h b/ulp/inic/kernel/vnic_adapter.h
new file mode 100644 (file)
index 0000000..dcb0b25
--- /dev/null
@@ -0,0 +1,216 @@
+/*\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$\r
+ */\r
+\r
+#if !defined _VNIC_ADAPTER_H_\r
+#define _VNIC_ADAPTER_H_\r
+\r
+#include <complib/comp_lib.h>\r
+#include <iba/ib_al.h>\r
+#include <initguid.h>\r
+#include <ip_packet.h>\r
+#include "vnic_ib.h"\r
+#include "vnic_controlpkt.h"\r
+#include "vnic_config.h"\r
+#include "vnic_control.h"\r
+#include "vnic_data.h"\r
+#include "vnic_viport.h"\r
+#include <iba/ioc_ifc.h>\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
+\r
+}      pending_oid_t;\r
+\r
+typedef struct _ipv4_address_item\r
+{\r
+       union _net_address_item_address\r
+       {\r
+               ULONG                   as_ulong;\r
+               UCHAR                   as_bytes[4];\r
+       }       address;\r
+\r
+}      ipv4_address_item_t;\r
+\r
+typedef struct _vnic_params {\r
+       uint32_t        MaxAddressEntries;\r
+       uint32_t        MinAddressEntries;\r
+       uint32_t        MinMtu;\r
+       uint32_t        MaxMtu;\r
+       uint32_t        HostRecvPoolEntries;\r
+       uint32_t        MinHostPoolSz;\r
+       uint32_t        MinEiocPoolSz;\r
+       uint32_t        MaxEiocPoolSz;\r
+       uint32_t        MinHostKickTimeout;\r
+       uint32_t        MaxHostKickTimeout;\r
+       uint32_t        MinHostKickEntries;\r
+       uint32_t        MaxHostKickEntries;\r
+       uint32_t        MinHostKickBytes;\r
+       uint32_t        MaxHostKickBytes;\r
+       uint32_t        MinHostUpdateSz;\r
+       uint32_t        MaxHostUpdateSz;\r
+       uint32_t        MinEiocUpdateSz;\r
+       uint32_t        MaxEiocUpdateSz;\r
+       uint32_t        NotifyBundleSz;\r
+       uint32_t        ViportStatsInterval;\r
+       uint32_t        ViportHbInterval;\r
+       uint32_t        ViportHbTimeout;\r
+       uint32_t        ControlRspTimeout;\r
+       uint32_t        ControlReqRetryCount;\r
+       uint32_t        RetryCount;\r
+       uint32_t        MinRnrTimer;\r
+       uint32_t        MaxViportsPerNetpath;\r
+       uint32_t        DefaultViportsPerNetpath;\r
+       uint32_t        DefaultPkey;\r
+       uint32_t        DefaultNoPathTimeout;\r
+       uint32_t        DefaultPrimaryConnectTimeout;\r
+       uint32_t        DefaultPrimaryReconnectTimeout;\r
+       uint32_t        DefaultPrimarySwitchTimeout;\r
+       uint32_t        DefaultPreferPrimary;\r
+       uint32_t        UseRxCsum;\r
+       uint32_t        UseTxCsum;\r
+       mac_addr_t      conf_mac;\r
+}      vnic_params_t;\r
+\r
+\r
+typedef struct _vnic_adapter {\r
+       LIST_ENTRY                              list_entry;\r
+       NDIS_HANDLE                             h_handle;\r
+       PDRIVER_OBJECT                  p_drv_obj;\r
+//     cl_obj_t                                obj;\r
+       NDIS_SPIN_LOCK                  lock;\r
+       ib_al_ifc_t                             ifc;\r
+       ioc_ifc_data_t                  ifc_data;\r
+       ib_ioc_info_t                   ioc_info;\r
+       vnic_path_record_t              path_record;\r
+       ib_al_handle_t                  h_al;\r
+       ib_ca_handle_t                  h_ca;\r
+       ib_pnp_handle_t                 h_pnp;\r
+       ib_pnp_event_t                  pnp_state;\r
+       IbCa_t                                  ca;\r
+       struct _viport                  *p_viport;\r
+       InicState_t                             state;\r
+       struct Netpath                  primaryPath;\r
+       struct Netpath                  secondaryPath;\r
+       struct Netpath                  *p_currentPath;\r
+       vnic_params_t                   params;\r
+       int                                             open;\r
+       int                                             macSet;\r
+       int                                             mc_count;\r
+       mac_addr_t                              mcast_array[MAX_MCAST];\r
+       LONG                                    xmitStarted;\r
+       LONG                                    carrier;\r
+       uint32_t                                packet_filter;\r
+       BOOLEAN                                 hung;\r
+       BOOLEAN                                 pending_set;\r
+       BOOLEAN                                 pending_query;\r
+       pending_oid_t                   query_oid;\r
+       pending_oid_t                   set_oid;\r
+       uint8_t                                 num_svc_entries;\r
+       ib_svc_entry_t                  *p_svc_entries;\r
+       char                                    name[65];\r
+       InicNPEvent_t                   np_event[INICNP_NUM_EVENTS];\r
+#ifdef VNIC_STATISTIC\r
+       struct {\r
+               uint64_t                        startTime;\r
+               uint64_t                        connTime;\r
+               uint64_t                        disconnRef;     /* Intermediate time */\r
+               uint64_t                        disconnTime;\r
+               uint32_t                        disconnNum;\r
+               uint64_t                        xmitTime;\r
+               uint32_t                        xmitNum;\r
+               uint32_t                        xmitFail;\r
+               uint64_t                        recvTime;\r
+               uint32_t                        recvNum;\r
+               uint64_t                        xmitRef;        /* Intermediate time */\r
+               uint64_t                        xmitOffTime;\r
+               uint32_t                        xmitOffNum;\r
+               uint64_t                        carrierRef;     /* Intermediate time */\r
+               uint64_t                        carrierOffTime;\r
+               uint32_t                        carrierOffNum;\r
+       }   statistics;\r
+#endif /* VNIC_STATISTIC */\r
+\r
+} vnic_adapter_t;\r
+\r
+ib_api_status_t\r
+vnic_create_adapter(\r
+       IN              NDIS_HANDLE                     h_handle,\r
+       OUT             vnic_adapter_t**        const pp_adapter);\r
+\r
+void\r
+vnic_destroy_adapter(\r
+       IN              vnic_adapter_t*         p_adapter);\r
+\r
+ib_api_status_t\r
+vnic_construct_adapter(\r
+       IN              vnic_adapter_t          *p_adapter);\r
+\r
+NDIS_STATUS\r
+vnic_set_mcast(\r
+       IN                              vnic_adapter_t* const           p_adapter,\r
+       IN                              mac_addr_t* const                       p_mac_array,\r
+       IN              const   uint8_t                                         mc_count );\r
+\r
+ib_api_status_t\r
+vnic_viport_allocate(\r
+       IN                      vnic_adapter_t* const           p_adapter,\r
+       IN OUT          viport_t**              const           pp_viport );\r
+\r
+void\r
+vnic_viport_cleanup(\r
+       IN                      vnic_adapter_t                  *p_adapter );\r
+\r
+void\r
+vnic_resume_set_oids(\r
+       IN                              vnic_adapter_t* const           p_adapter );\r
+\r
+void\r
+vnic_resume_oids(\r
+       IN                              vnic_adapter_t* const           p_adapter );\r
+\r
+ib_api_status_t\r
+__vnic_pnp_cb(\r
+       IN                      ib_pnp_rec_t                    *p_pnp_rec );\r
+\r
+ib_api_status_t\r
+ibregion_physInit(\r
+       IN                      struct _vnic_adapter*           p_adapter,\r
+               OUT             IbRegion_t                                      *pRegion,\r
+       IN                      ib_pd_handle_t                          hPd,\r
+       IN                      uint64_t                                        *p_vaddr,\r
+       IN                      uint64_t                                        len );\r
+\r
+#endif /* !defined _VNIC_ADAPTER_H_ */\r
diff --git a/ulp/inic/kernel/vnic_config.h b/ulp/inic/kernel/vnic_config.h
new file mode 100644 (file)
index 0000000..9a054ca
--- /dev/null
@@ -0,0 +1,238 @@
+#ifndef _VNIC_CONFIG_H_\r
+#define _VNIC_CONFIG_H_\r
+\r
+#include "vnic_util.h"\r
+/* These are hard, compile time limits.\r
+ * Lower runtime overrides may be in effect\r
+ */\r
+#define INIC_CLASS_SUBCLASS 0x2000066A\r
+#define INIC_PROTOCOL       0\r
+#define INIC_PROT_VERSION   1\r
+\r
+#define INIC_MAJORVERSION 1\r
+#define INIC_MINORVERSION 1\r
+\r
+#define MAX_ADDRESS_ENTRIES             64   /* max entries to negotiate with remote */\r
+#define MIN_ADDRESS_ENTRIES             16   /* min entries remote can return to us that we agree with */\r
+#define MAX_ADDR_ARRAY                  32   /* address array we can handle. for now */\r
+#define MIN_MTU                         1500 /* Minimum Negotiated payload size */\r
+#define MAX_MTU                         9500 /*  max Jumbo frame payload size */\r
+#define ETH_VLAN_HLEN                   18   /* ethernet header with VLAN tag */\r
+\r
+#define HOST_RECV_POOL_ENTRIES          512  /* TBD: Abritrary */\r
+#define MIN_HOST_POOL_SZ                64   /* TBD: Abritrary */\r
+#define MIN_EIOC_POOL_SZ                64   /* TBD: Abritrary */\r
+#define MAX_EIOC_POOL_SZ                256  /* TBD: Abritrary */\r
+\r
+#define MIN_HOST_KICK_TIMEOUT           10   /* TBD: Arbitrary */\r
+#define MAX_HOST_KICK_TIMEOUT           100  /* In uSec */\r
+\r
+#define MIN_HOST_KICK_ENTRIES           1    /* TBD: Arbitrary */\r
+#define MAX_HOST_KICK_ENTRIES           128  /* TBD: Arbitrary */\r
+\r
+#define MIN_HOST_KICK_BYTES             0\r
+#define MAX_HOST_KICK_BYTES             5000\r
+\r
+#define MIN_HOST_UPDATE_SZ              8    /* TBD: Arbitrary */\r
+#define MAX_HOST_UPDATE_SZ              32   /* TBD: Arbitrary */\r
+#define MIN_EIOC_UPDATE_SZ              8    /* TBD: Arbitrary */\r
+#define MAX_EIOC_UPDATE_SZ              32   /* TBD: Arbitrary */\r
+\r
+#define NOTIFY_BUNDLE_SZ                32\r
+\r
+#define MAX_PARAM_VALUE                 0x40000000\r
+\r
+#define DEFAULT_VIPORTS_PER_NETPATH     1\r
+#define MAX_VIPORTS_PER_NETPATH         1\r
+\r
+#define INIC_USE_RX_CSUM                TRUE\r
+#define INIC_USE_TX_CSUM                TRUE\r
+#define DEFAULT_NO_PATH_TIMEOUT         10000 /* TBD: Arbitrary */\r
+#define DEFAULT_PRI_CON_TIMEOUT         10000 /* TBD: Arbitrary */\r
+#define DEFAULT_PRI_RECON_TIMEOUT       10000 /* TBD: Arbitrary */\r
+#define DEFAULT_PRI_SWITCH_TIMEOUT      10000 /* TBD: Arbitrary */\r
+#define DEFAULT_PREFER_PRIMARY          TRUE\r
+\r
+/* timeouts: !! all data defined in milliseconds,\r
+   some later will be converted to microseconds */\r
+#define VIPORT_STATS_INTERVAL           5000   /* 5 sec */\r
+#define VIPORT_HEARTBEAT_INTERVAL       2000 /* 2 seconds */\r
+#define VIPORT_HEARTBEAT_TIMEOUT        64000 /* 64 sec  */\r
+#define CONTROL_RSP_TIMEOUT             2000  /* 2 sec */\r
+\r
+#define _100NS_IN_1MS                                  (10000)\r
+inline uint64_t\r
+get_time_stamp_ms( void )\r
+{\r
+       return( (KeQueryInterruptTime() / _100NS_IN_1MS ) );\r
+}\r
+\r
+/* InfiniBand Connection Parameters */\r
+#define CONTROL_REQ_RETRY_COUNT         4\r
+#define RETRY_COUNT                     3\r
+#define MIN_RNR_TIMER                   22       /* 20 ms */\r
+#define DEFAULT_PKEY                    0    /* Pkey table index */\r
+\r
+/* phys memory size to register with HCA*/\r
+#define MEM_REG_SIZE    0xFFFFFFFFFFFFFFFF\r
+\r
+/* link speed in 100 bits/sec units */\r
+#define LINK_SPEED_1GBIT_x100BPS       10000000\r
+#define LINK_SPEED_10GBIT_x100BPS      100000000\r
+    /* VEx does not report it's link speed, so set it 1Gb/s so far */\r
+#define DEFAULT_LINK_SPEED_x100BPS     LINK_SPEED_1GBIT_x100BPS\r
+\r
+#define DEFAULT_PARAM(x,y)     if(x == MAXU32) { \\r
+                                                               x = y; }\r
+#define POWER_OF_2(x) if (!IsPowerOf2(x)) { \\r
+                VNIC_TRACE( VNIC_DBG_WARN, (" %s (%d) must be a power of 2\n",#x,x) ); \\r
+                x = SetMinPowerOf2(x); \\r
+        }\r
+#define LESS_THAN(lo, hi) if (lo >= hi) { \\r
+                VNIC_TRACE( VNIC_DBG_ERROR, (" %s (%d) must be less than %s (%d)\n",#lo,lo,#hi,hi) ); \\r
+                lo = hi >> 1; \\r
+        }\r
+#define LESS_THAN_OR_EQUAL(lo, hi) if (lo > hi) { \\r
+                VNIC_TRACE( VNIC_DBG_WARN, (" %s (%d) cannot be greater than %s (%d)\n",#lo,lo,#hi,hi) ); \\r
+                lo = hi; \\r
+        }\r
+#define RANGE_CHECK(x, min, max) if ((x < min) || (x > max)) { \\r
+                VNIC_TRACE( VNIC_DBG_WARN, (" %s (%d) must be between %d and %d\n",#x,x,min,max) ); \\r
+                if (x < min)  \\r
+                                       x = min;  \\r
+                               else          \\r
+                                       x = max;  \\r
+        }\r
+#define ZERO_RANGE_CHECK(x, min, max) if (x > max) { \\r
+                VNIC_TRACE( VNIC_DBG_WARN, (" %s (%d) must be between %d and %d\n",#x,x,min,max) ); \\r
+                x = max; \\r
+        }\r
+\r
+#define BOOLEAN_RANGE(x)  ZERO_RANGE_CHECK(x, 0, 1)\r
+#define U32_ZERO_RANGE(x) ZERO_RANGE_CHECK(x, 0, 0x7FFFFFFF)\r
+#define U32_RANGE(x)      RANGE_CHECK(x, 1, 0x7FFFFFFF)\r
+#define U16_ZERO_RANGE(x) ZERO_RANGE_CHECK(x, 0, 0xFFFF)\r
+#define U16_RANGE(x)      RANGE_CHECK(x, 1, 0xFFFF)\r
+#define U8_ZERO_RANGE(x)  ZERO_RANGE_CHECK(x, 0, 0xFF)\r
+#define U8_RANGE(x)       RANGE_CHECK(x, 1, 0xFF)\r
+\r
+\r
+typedef struct {\r
+        uint64_t ioc_guid;\r
+        uint64_t portGuid;\r
+        uint64_t port;\r
+        uint64_t hca;\r
+        uint64_t instance;\r
+        char  ioc_string[65];\r
+        char  ioc_guid_set;\r
+        char  ioc_string_set;\r
+} PathParam_t;\r
+\r
+typedef struct _vnic_globals {\r
+       NDIS_HANDLE             ndis_handle; // ndis wrapper handle\r
+       volatile LONG   dev_reg;     // dev register counter\r
+       volatile LONG   adapters;    // created adapters counter\r
+       KSPIN_LOCK              lock;\r
+       LIST_ENTRY              adapter_list;\r
+       uint8_t                 host_name[IB_NODE_DESCRIPTION_SIZE + 1];\r
+} vnic_globals_t;\r
+/*\r
+struct members:\r
+       lock:\r
+               take this lock before access to adapter_list\r
+       adapter_list:\r
+                head of list of virtual adapters initialized by driver\r
+*/\r
+\r
+typedef struct IbConfig {\r
+        ib_path_rec_t       pathInfo;\r
+        uint64_t                 sid;\r
+        Inic_ConnectionData_t connData;\r
+        uint32_t                 retryCount;\r
+        uint32_t                 rnrRetryCount;\r
+        uint8_t                  minRnrTimer;\r
+        uint32_t                 numSends;\r
+        uint32_t                 numRecvs;\r
+        uint32_t                 recvScatter; /* 1 */\r
+        uint32_t                 sendGather;  /* 1 or 2 */\r
+        uint32_t                 overrides;\r
+} IbConfig_t;\r
+\r
+typedef struct ControlConfig {\r
+        IbConfig_t ibConfig;\r
+        uint32_t      numRecvs;\r
+        uint8_t       inicInstance;\r
+        uint16_t      maxAddressEntries;\r
+        uint16_t      minAddressEntries;\r
+        uint32_t      rspTimeout;\r
+        uint8_t       reqRetryCount;\r
+        uint32_t      overrides;\r
+} ControlConfig_t;\r
+\r
+typedef struct DataConfig {\r
+        IbConfig_t            ibConfig;\r
+        uint64_t                 pathId;\r
+        uint32_t                 numRecvs;\r
+        uint32_t                 hostRecvPoolEntries;\r
+        Inic_RecvPoolConfig_t hostMin;\r
+        Inic_RecvPoolConfig_t hostMax;\r
+        Inic_RecvPoolConfig_t eiocMin;\r
+        Inic_RecvPoolConfig_t eiocMax;\r
+        uint32_t                 notifyBundle;\r
+        uint32_t                 overrides;\r
+} DataConfig_t;\r
+\r
+typedef struct ViportConfig {\r
+        struct _viport  *pViport;\r
+        ControlConfig_t controlConfig;\r
+        DataConfig_t    dataConfig;\r
+        uint32_t           hca;\r
+        uint32_t           port;\r
+        uint32_t           statsInterval;\r
+        uint32_t           hbInterval; /* heartbeat interval */\r
+        uint32_t           hbTimeout;  /* heartbeat timeout */\r
+        uint64_t           portGuid;\r
+        uint64_t           guid;\r
+        size_t          pathIdx;\r
+        char            ioc_string[65];\r
+\r
+#define HB_INTERVAL_OVERRIDE 0x1\r
+#define GUID_OVERRIDE        0x2\r
+#define STRING_OVERRIDE      0x4\r
+#define HCA_OVERRIDE         0x8\r
+#define PORT_OVERRIDE        0x10\r
+#define PORTGUID_OVERRIDE    0x20\r
+        uint32_t           overrides;\r
+} ViportConfig_t;\r
+\r
+/*\r
+ * primaryConnectTimeout   - If the secondary connects first, how long do we\r
+ *                         give the primary?\r
+ * primaryReconnectTimeout - Same as above, but used when recovering when\r
+ *                         both paths fail\r
+ * primaryReconnectTimeout - How long do we wait before switching to the\r
+ *                         primary when it comes back?\r
+ */\r
+#define IFNAMSIZ 65\r
+typedef struct InicConfig {\r
+        //struct Inic *pInic;\r
+        char        name[IFNAMSIZ];\r
+        uint32_t       noPathTimeout;\r
+        uint32_t       primaryConnectTimeout;\r
+        uint32_t       primaryReconnectTimeout;\r
+        uint32_t       primarySwitchTimeout;\r
+        int         preferPrimary;\r
+        BOOLEAN     useRxCsum;\r
+        BOOLEAN     useTxCsum;\r
+#define USE_RX_CSUM_OVERRIDE 0x1\r
+#define USE_TX_CSUM_OVERRIDE 0x2\r
+        uint32_t       overrides;\r
+} InicConfig_t;\r
+\r
+typedef enum {\r
+       INIC_UNINITIALIZED,\r
+       INIC_REGISTERED,\r
+} InicState_t;\r
+\r
+#endif /* _VNIC_CONFIG_H_ */\r
+\r
diff --git a/ulp/inic/kernel/vnic_control.c b/ulp/inic/kernel/vnic_control.c
new file mode 100644 (file)
index 0000000..9ca242f
--- /dev/null
@@ -0,0 +1,1980 @@
+/*\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$\r
+ */\r
+\r
+#include "vnic_adapter.h"\r
+\r
+static void\r
+control_recv( Control_t *pControl, RecvIo_t *pRecvIo );\r
+\r
+static void\r
+control_recvComplete(\r
+               IN              Io_t            *pIo );\r
+\r
+static ib_api_status_t\r
+control_send( Control_t *pControl );\r
+\r
+static void\r
+control_sendComplete( Io_t *pIo );\r
+static void\r
+control_timeout( void * context );\r
+\r
+static void\r
+control_timer( Control_t *pControl, int timeout );\r
+\r
+static void\r
+control_timerStop( Control_t *pControl );\r
+\r
+static void\r
+control_initHdr( Control_t *pControl, uint8_t cmd );\r
+\r
+static RecvIo_t *\r
+control_getRsp( Control_t *pControl );\r
+\r
+static void\r
+copyRecvPoolConfig( Inic_RecvPoolConfig_t *pSrc,\r
+                                       Inic_RecvPoolConfig_t *pDst );\r
+\r
+static BOOLEAN\r
+checkRecvPoolConfigValue(\r
+               IN              void            *pSrc,\r
+               IN              void            *pDst,\r
+               IN              void            *pMax,\r
+               IN              void            *pMin,\r
+               IN              char            *name );\r
+\r
+static BOOLEAN  checkRecvPoolConfig(\r
+                                       Inic_RecvPoolConfig_t *pSrc,\r
+                                       Inic_RecvPoolConfig_t *pDst,\r
+                                       Inic_RecvPoolConfig_t *pMax,\r
+                                       Inic_RecvPoolConfig_t *pMin);\r
+\r
+static void\r
+__control_logControlPacket(\r
+                                       Inic_ControlPacket_t *pPkt );\r
+\r
+static inline char*\r
+control_ifcfg_name( Control_t *pControl )\r
+{\r
+       if (! pControl)\r
+               return "NCtl";\r
+       return (pControl->p_viport->p_adapter->name );\r
+}\r
+\r
+\r
+void\r
+control_construct(\r
+       IN              Control_t                       *pControl,\r
+       IN              viport_t                        *pViport )\r
+{\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       cl_memclr(pControl, sizeof(Control_t));\r
+\r
+       pControl->p_viport = pViport;\r
+\r
+       pControl->reqOutstanding = FALSE;\r
+       pControl->seqNum         = 0;\r
+\r
+       pControl->pResponse      = NULL;\r
+       pControl->pInfo          = NULL;\r
+\r
+       pControl->p_viport->addrs_query_done = TRUE;\r
+\r
+       InitializeListHead(&pControl->failureList);\r
+       KeInitializeSpinLock(&pControl->ioLock);\r
+\r
+       cl_timer_construct( &pControl->timer );\r
+\r
+       ibqp_construct( &pControl->qp, pViport );\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+}\r
+\r
+\r
+ib_api_status_t\r
+control_init(\r
+       IN              Control_t                       *pControl,\r
+       IN              viport_t                        *pViport,\r
+       IN              ControlConfig_t         *pConfig,\r
+       IN              uint64_t                        guid )\r
+{\r
+       ib_api_status_t                 ib_status;\r
+       ib_pd_handle_t                  hPd;\r
+       Inic_ControlPacket_t    *pkt;\r
+       Io_t                                    *pIo;\r
+       int                                             sz;\r
+       unsigned int                    i;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       pControl->p_conf  = pConfig;\r
+\r
+       hPd = pViport->p_adapter->ca.hPd;\r
+\r
+       cl_timer_init( &pControl->timer, control_timeout, pControl );\r
+\r
+       ib_status = ibqp_init(\r
+               &pControl->qp, guid, &pConfig->ibConfig );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("%s: ibqp_init returned %s\n",\r
+                       pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
+               goto failure;\r
+       }\r
+\r
+       sz = (sizeof(RecvIo_t) * pConfig->numRecvs ) +\r
+               (sizeof(Inic_ControlPacket_t) * (pConfig->numRecvs + 1));\r
+\r
+       pControl->pLocalStorage = cl_zalloc( sz );\r
+\r
+       if ( pControl->pLocalStorage == NULL )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+                       ("%s: Failed allocating space for local storage\n",\r
+                                       control_ifcfg_name(pControl)) );\r
+\r
+               ibqp_cleanup(&pControl->qp);\r
+               ib_status = IB_INSUFFICIENT_MEMORY;\r
+               goto failure;\r
+       }\r
+\r
+       pControl->pRecvIos = (RecvIo_t *)pControl->pLocalStorage;\r
+\r
+       pkt = (Inic_ControlPacket_t *)(pControl->pLocalStorage +\r
+                            sizeof(SendIo_t) * pConfig->numRecvs);\r
+\r
+       sz = sizeof(Inic_ControlPacket_t) * (pConfig->numRecvs + 1);\r
+\r
+       ib_status = ibregion_init( pViport, &pControl->region, hPd,\r
+               pkt, sz, IB_AC_LOCAL_WRITE );\r
+       if ( ib_status != IB_SUCCESS )\r
+       {\r
+               /* NOTE: I'm allowing recvs into the send buffer as well\r
+                * as the receive buffers. I'm doing this to combine them\r
+                * into a single region, and conserve a region.\r
+                */\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR|VNIC_DBG_CTRL,\r
+                                       ("%s: Failed setting up control space region\n",\r
+                                                                       control_ifcfg_name(pControl)) );\r
+               ibqp_cleanup( &pControl->qp );\r
+               cl_free( pControl->pLocalStorage );\r
+               goto failure;\r
+       }\r
+       pIo                                             = &pControl->sendIo.io;\r
+       pIo->pViport                    = pViport;\r
+       pIo->pRoutine                   = control_sendComplete;\r
+\r
+       pIo->wrq.p_next                 = NULL;\r
+       pIo->wrq.wr_type                = WR_SEND;\r
+       pIo->wrq.send_opt               = IB_SEND_OPT_SIGNALED;\r
+       pIo->wrq.wr_id                  = (uint64_t)(pIo);\r
+       pIo->wrq.num_ds                 = 1;\r
+       pIo->wrq.ds_array               = &pControl->sendIo.dsList;\r
+       pIo->wrq.ds_array[0].length     = sizeof(Inic_ControlPacket_t);\r
+       pIo->wrq.ds_array[0].lkey  = pControl->region.lkey;\r
+       pIo->wrq.ds_array[0].vaddr = (uint64_t)(pkt++);\r
+\r
+       for (i = 0; i < pConfig->numRecvs; i++ )\r
+       {\r
+               pIo                                             = &pControl->pRecvIos[i].io;\r
+               pIo->pViport                    = pViport;\r
+               pIo->pRoutine                   = control_recvComplete;\r
+\r
+               pIo->r_wrq.wr_id                                = (uint64_t)(pIo);\r
+               pIo->r_wrq.p_next                               = NULL;\r
+               pIo->r_wrq.num_ds                               = 1;\r
+               pIo->r_wrq.ds_array                             = &pControl->pRecvIos[i].dsList;\r
+               pIo->r_wrq.ds_array[0].length   = sizeof(Inic_ControlPacket_t);\r
+               pIo->r_wrq.ds_array[0].vaddr    = (uint64_t)(pkt++);\r
+               pIo->r_wrq.ds_array[0].lkey             = pControl->region.lkey;\r
+       \r
+               if ( ibqp_postRecv( &pControl->qp, pIo ) != IB_SUCCESS )\r
+               {\r
+                       control_cleanup( pControl );\r
+                       ib_status = IB_ERROR;\r
+                       goto failure;\r
+               }\r
+       }\r
+\r
+failure:\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return ib_status;\r
+}\r
+\r
+\r
+void\r
+control_cleanup(\r
+       IN                      Control_t       *pControl )\r
+{\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       control_timerStop( pControl );\r
+       ibqp_detach( &pControl->qp );\r
+       ibqp_cleanup( &pControl->qp );\r
+       ibregion_cleanup( pControl->p_viport, &pControl->region );\r
+\r
+       if ( pControl->pLocalStorage )\r
+       {\r
+               cl_free( pControl->pLocalStorage );\r
+               pControl->pLocalStorage = NULL;\r
+       }\r
+\r
+       cl_timer_destroy( &pControl->timer );\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return;\r
+}\r
+\r
+void\r
+control_processAsync(\r
+               IN                      Control_t               *pControl )\r
+{\r
+       RecvIo_t                                *pRecvIo;\r
+       Inic_ControlPacket_t    *pPkt;\r
+       LIST_ENTRY                              *p_list_entry;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       pRecvIo = InterlockedExchangePointer( &pControl->pInfo, NULL );\r
+\r
+       if ( pRecvIo != NULL )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_CTRL | VNIC_DBG_INFO,\r
+                               ("%s: processing info packet\n",\r
+                                               control_ifcfg_name(pControl)) );\r
+       \r
+               pPkt = control_packet( pRecvIo );\r
+\r
+               if ( pPkt->hdr.pktCmd == CMD_REPORT_STATUS )\r
+               {\r
+                       switch( ntoh32(pPkt->cmd.reportStatus.statusNumber) )\r
+                       {\r
+                       case INIC_STATUS_LINK_UP:\r
+                               VNIC_TRACE( VNIC_DBG_CTRL | VNIC_DBG_INFO,\r
+                                                       ("%s: Link Up\n",\r
+                                                                       control_ifcfg_name(pControl)) );\r
+\r
+                               viport_linkUp( pControl->p_viport );\r
+                               break;\r
+\r
+                       case INIC_STATUS_LINK_DOWN:\r
+                               VNIC_TRACE( VNIC_DBG_CTRL | VNIC_DBG_INFO,\r
+                                                       ("%s: Link Down\n",\r
+                                                                       control_ifcfg_name(pControl)) );\r
+\r
+                               viport_linkDown( pControl->p_viport );\r
+                               break;\r
+\r
+                       default:\r
+                               VNIC_TRACE( VNIC_DBG_CTRL | VNIC_DBG_ERROR,\r
+                                               ("%s: Asynchronous status received from EIOC\n",\r
+                                                                       control_ifcfg_name(pControl)) );\r
+                               __control_logControlPacket( pPkt );\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if (  pPkt->hdr.pktCmd != CMD_REPORT_STATUS ||\r
+                         pPkt->cmd.reportStatus.isFatal )\r
+               {\r
+                       viport_failure( pControl->p_viport );\r
+               }\r
+\r
+               control_recv( pControl, pRecvIo );\r
+       }\r
+\r
+       while ( !IsListEmpty( &pControl->failureList ) )\r
+       {\r
+\r
+               VNIC_TRACE( VNIC_DBG_CTRL | VNIC_DBG_INFO,\r
+                                       ("%s: processing error packet\n",\r
+                                                               control_ifcfg_name(pControl)) );\r
+\r
+               p_list_entry = ExInterlockedRemoveHeadList( &pControl->failureList, &pControl->ioLock );\r
+               pRecvIo = (RecvIo_t *)p_list_entry;\r
+               pPkt = control_packet( pRecvIo );\r
+\r
+               VNIC_TRACE( VNIC_DBG_CTRL | VNIC_DBG_INFO,\r
+                                       ("%s: Asynchronous error received from EIOC\n",\r
+                                                               control_ifcfg_name(pControl)) );\r
+       \r
+               __control_logControlPacket( pPkt );\r
+\r
+               if ( ( pPkt->hdr.pktType != TYPE_ERR ) ||\r
+                        ( pPkt->hdr.pktCmd != CMD_REPORT_STATUS ) ||\r
+                    ( pPkt->cmd.reportStatus.isFatal ) )\r
+               {\r
+                       viport_failure( pControl->p_viport );\r
+               }\r
+\r
+               control_recv( pControl, pRecvIo );\r
+       }\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+}\r
+\r
+\r
+ib_api_status_t\r
+control_initInicReq(\r
+       IN                      Control_t                *pControl )\r
+{\r
+       ControlConfig_t                 *p_conf = pControl->p_conf;\r
+       Inic_ControlPacket_t    *pPkt;\r
+       Inic_CmdInitInicReq_t   *pInitInicReq;\r
+       ib_api_status_t                 ib_status;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       control_initHdr( pControl, CMD_INIT_INIC );\r
+\r
+       pPkt                           = control_packet( &pControl->sendIo );\r
+       pInitInicReq                   = &pPkt->cmd.initInicReq;\r
+       pInitInicReq->inicMajorVersion = hton16( INIC_MAJORVERSION );\r
+       pInitInicReq->inicMinorVersion = hton16( INIC_MINORVERSION );\r
+       pInitInicReq->inicInstance = p_conf->inicInstance;\r
+       pInitInicReq->numDataPaths = 1;\r
+       pInitInicReq->numAddressEntries = hton16( p_conf->maxAddressEntries );\r
+\r
+       ib_status = control_send( pControl );\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return ib_status;\r
+}\r
+\r
+\r
+BOOLEAN\r
+control_initInicRsp(\r
+               IN              Control_t               *pControl,\r
+               IN              uint32_t                *pFeatures,\r
+               IN              uint8_t                 *pMacAddress,\r
+               IN              uint16_t                *pNumAddrs,\r
+               IN              uint16_t                *pVlan )\r
+{\r
+       RecvIo_t              *pRecvIo;\r
+       ControlConfig_t       *p_conf = pControl->p_conf;\r
+       Inic_ControlPacket_t  *pPkt;\r
+       Inic_CmdInitInicRsp_t *pInitInicRsp;\r
+       uint8_t               numDataPaths,\r
+                             numLanSwitches;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       pRecvIo = control_getRsp( pControl );\r
+       if (!pRecvIo)\r
+               return FALSE;\r
+\r
+       pPkt = control_packet( pRecvIo );\r
+\r
+       if ( pPkt->hdr.pktCmd != CMD_INIT_INIC )\r
+       {\r
+       \r
+               VNIC_TRACE( VNIC_DBG_CTRL | VNIC_DBG_ERROR,\r
+                                       ("%s: Sent control request:\n",\r
+                                               control_ifcfg_name(pControl)) );\r
+\r
+               __control_logControlPacket( control_lastReq( pControl ) );\r
+\r
+               VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR,\r
+                                       ("%s: Received control response:\n",\r
+                                                       control_ifcfg_name(pControl)) );\r
+       \r
+               __control_logControlPacket( pPkt );\r
+               goto failure;\r
+       }\r
+       pInitInicRsp     = &pPkt->cmd.initInicRsp;\r
+       pControl->majVer = ntoh16( pInitInicRsp->inicMajorVersion );\r
+       pControl->minVer = ntoh16( pInitInicRsp->inicMinorVersion );\r
+       numDataPaths     = pInitInicRsp->numDataPaths;\r
+       numLanSwitches   = pInitInicRsp->numLanSwitches;\r
+       *pFeatures       = ntoh32( pInitInicRsp->featuresSupported );\r
+       *pNumAddrs       = ntoh16( pInitInicRsp->numAddressEntries );\r
+\r
+       if ( ( pControl->majVer > INIC_MAJORVERSION ) ||\r
+                (( pControl->majVer == INIC_MAJORVERSION ) &&\r
+             ( pControl->minVer > INIC_MINORVERSION )) )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR,\r
+                               ("%s: Unsupported version\n",\r
+                                               control_ifcfg_name(pControl)) );\r
+               goto failure;\r
+       }\r
+\r
+       if ( numDataPaths != 1 )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR,\r
+                                       ("%s: EIOC returned too many datapaths\n",\r
+                                                       control_ifcfg_name(pControl)) );\r
+               goto failure;\r
+       }\r
+\r
+       if ( *pNumAddrs > p_conf->maxAddressEntries )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR,\r
+                               ("%s: EIOC returned more Address entries than requested\n",\r
+                                               control_ifcfg_name(pControl)) );\r
+               goto failure;\r
+       }\r
+       if ( *pNumAddrs < p_conf->minAddressEntries )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR,\r
+                                       ("%s: Not enough address entries\n",\r
+                                                       control_ifcfg_name(pControl)) );\r
+               goto failure;\r
+       }\r
+       if ( numLanSwitches < 1 )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR,\r
+                                       ("%s: EIOC returned no lan switches\n",\r
+                                                       control_ifcfg_name(pControl)) );\r
+               goto failure;\r
+       }\r
+       if ( numLanSwitches > 1 )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_CTRL | VNIC_DBG_ERROR,\r
+                                       ("%s: EIOC returned multiple lan switches\n",\r
+                                                       control_ifcfg_name(pControl)) );\r
+               goto failure;\r
+       }\r
+\r
+       pControl->lanSwitch.lanSwitchNum =\r
+               pInitInicRsp->lanSwitch[0].lanSwitchNum ;\r
+       pControl->lanSwitch.numEnetPorts =\r
+               pInitInicRsp->lanSwitch[0].numEnetPorts ;\r
+       pControl->lanSwitch.defaultVlan =\r
+               ntoh16( pInitInicRsp->lanSwitch[0].defaultVlan );\r
+       *pVlan = pControl->lanSwitch.defaultVlan;\r
+       cl_memcpy( pControl->lanSwitch.hwMacAddress,\r
+                               pInitInicRsp->lanSwitch[0].hwMacAddress, MAC_ADDR_LEN );\r
+       cl_memcpy( pMacAddress,\r
+                               pInitInicRsp->lanSwitch[0].hwMacAddress, MAC_ADDR_LEN);\r
+\r
+       control_recv( pControl, pRecvIo );\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return TRUE;\r
+failure:\r
+       viport_failure( pControl->p_viport );\r
+       return FALSE;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+control_configDataPathReq(\r
+               IN              Control_t                               *pControl,\r
+               IN              uint64_t                                pathId,\r
+               IN              Inic_RecvPoolConfig_t   *pHost,\r
+               IN              Inic_RecvPoolConfig_t   *pEioc )\r
+{\r
+       Inic_ControlPacket_t            *pPkt;\r
+       Inic_CmdConfigDataPath_t        *pConfigDataPath;\r
+       ib_api_status_t                         ib_status;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       control_initHdr( pControl, CMD_CONFIG_DATA_PATH );\r
+\r
+       pPkt                            = control_packet( &pControl->sendIo );\r
+       pConfigDataPath                 = &pPkt->cmd.configDataPathReq;\r
+       NdisZeroMemory( pConfigDataPath, sizeof( Inic_CmdConfigDataPath_t ) );\r
+       pConfigDataPath->dataPath       = 0;\r
+       pConfigDataPath->pathIdentifier = pathId;\r
+       copyRecvPoolConfig( pHost, &pConfigDataPath->hostRecvPoolConfig );\r
+       copyRecvPoolConfig( pEioc, &pConfigDataPath->eiocRecvPoolConfig );\r
+\r
+       ib_status = control_send( pControl );\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return ib_status;\r
+}\r
+\r
+\r
+BOOLEAN\r
+control_configDataPathRsp(\r
+               IN              Control_t                               *pControl,\r
+               IN              Inic_RecvPoolConfig_t   *pHost,\r
+               IN              Inic_RecvPoolConfig_t   *pEioc,\r
+               IN              Inic_RecvPoolConfig_t   *pMaxHost,\r
+               IN              Inic_RecvPoolConfig_t   *pMaxEioc,\r
+               IN              Inic_RecvPoolConfig_t   *pMinHost,\r
+               IN              Inic_RecvPoolConfig_t   *pMinEioc )\r
+{\r
+       RecvIo_t                 *pRecvIo;\r
+       Inic_ControlPacket_t     *pPkt;\r
+       Inic_CmdConfigDataPath_t *pConfigDataPath;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       pRecvIo = control_getRsp( pControl );\r
+       if ( !pRecvIo )\r
+               return FALSE;\r
+\r
+       pPkt = control_packet( pRecvIo );\r
+\r
+       if ( pPkt->hdr.pktCmd != CMD_CONFIG_DATA_PATH )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("%s: Sent control request:\n",\r
+                                       control_ifcfg_name(pControl)) );\r
+\r
+               __control_logControlPacket( control_lastReq( pControl ) );\r
+\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("%s: Received control response:\n",\r
+                                               control_ifcfg_name( pControl )) );\r
+       \r
+               __control_logControlPacket( pPkt );\r
+               goto failure;\r
+       }\r
+\r
+       pConfigDataPath = &pPkt->cmd.configDataPathRsp;\r
+\r
+       if ( pConfigDataPath->dataPath  != 0 )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("%s: Received CMD_CONFIG_DATA_PATH response for wrong data path: %u\n",\r
+                                       control_ifcfg_name( pControl ), pConfigDataPath->dataPath) );\r
+               goto failure;\r
+       }\r
+\r
+       if ( !checkRecvPoolConfig(&pConfigDataPath->hostRecvPoolConfig,\r
+                                pHost, pMaxHost, pMinHost )\r
+               || !checkRecvPoolConfig(&pConfigDataPath->eiocRecvPoolConfig,\r
+                               pEioc, pMaxEioc, pMinEioc))\r
+       {\r
+               goto failure;\r
+       }\r
+\r
+       control_recv( pControl, pRecvIo );\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return TRUE;\r
+failure:\r
+       viport_failure( pControl->p_viport );\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return FALSE;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+control_exchangePoolsReq(\r
+               IN                      Control_t               *pControl,\r
+               IN                      uint64_t                 addr,\r
+               IN                      uint32_t                rkey )\r
+{\r
+       Inic_CmdExchangePools_t *pExchangePools;\r
+       Inic_ControlPacket_t    *pPkt;\r
+       ib_api_status_t                 ib_status;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       control_initHdr(pControl, CMD_EXCHANGE_POOLS );\r
+\r
+       pPkt                     = control_packet( &pControl->sendIo );\r
+       pExchangePools           = &pPkt->cmd.exchangePoolsReq;\r
+       NdisZeroMemory( pExchangePools, sizeof( Inic_CmdExchangePools_t ) );\r
+       pExchangePools->dataPath =      0;\r
+       pExchangePools->poolRKey = rkey;\r
+       pExchangePools->poolAddr = hton64( addr );\r
+\r
+       ib_status = control_send( pControl );\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return ib_status;\r
+}\r
+\r
+\r
+BOOLEAN\r
+control_exchangePoolsRsp(\r
+               IN                      Control_t                       *pControl,\r
+               IN      OUT             uint64_t                        *pAddr,\r
+               IN      OUT             uint32_t                        *pRkey )\r
+{\r
+       RecvIo_t                *pRecvIo;\r
+       Inic_ControlPacket_t    *pPkt;\r
+       Inic_CmdExchangePools_t *pExchangePools;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       pRecvIo = control_getRsp( pControl );\r
+       if ( !pRecvIo )\r
+               return FALSE;\r
+\r
+       pPkt = control_packet( pRecvIo );\r
+\r
+       if ( pPkt->hdr.pktCmd != CMD_EXCHANGE_POOLS )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("%s: Sent control request:\n",\r
+                                       control_ifcfg_name(pControl)) );\r
+\r
+               __control_logControlPacket( control_lastReq(pControl ) );\r
+\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("%s: Received control response:\n",\r
+                                       control_ifcfg_name(pControl)) );\r
+       \r
+               __control_logControlPacket( pPkt );\r
+               goto failure;\r
+       }\r
+\r
+       pExchangePools = &pPkt->cmd.exchangePoolsRsp;\r
+       *pRkey         = pExchangePools->poolRKey;\r
+       *pAddr         = ntoh64( pExchangePools->poolAddr );\r
+\r
+       if ( hton32( pExchangePools->dataPath ) != 0 )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+                       ("%s: Received CMD_EXCHANGE_POOLS response for wrong data path: %u\n",\r
+                                       control_ifcfg_name(pControl), pExchangePools->dataPath ) );\r
+               goto failure;\r
+       }\r
+\r
+       control_recv( pControl, pRecvIo );\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return TRUE;\r
+\r
+failure:\r
+       viport_failure( pControl->p_viport );\r
+       return FALSE;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+control_configLinkReq(\r
+               IN              Control_t               *pControl,\r
+               IN              uint8_t                 flags,\r
+               IN              uint16_t                 mtu )\r
+{\r
+       Inic_CmdConfigLink_t    *pConfigLinkReq;\r
+       Inic_ControlPacket_t    *pPkt;\r
+       ib_api_status_t                 ib_status;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       control_initHdr( pControl, CMD_CONFIG_LINK );\r
+\r
+       pPkt                         = control_packet( &pControl->sendIo );\r
+       pConfigLinkReq               = &pPkt->cmd.configLinkReq;\r
+       NdisZeroMemory( pConfigLinkReq, sizeof( Inic_CmdConfigLink_t ) );\r
+       pConfigLinkReq->lanSwitchNum = pControl->lanSwitch.lanSwitchNum;\r
+       pConfigLinkReq->cmdFlags     = INIC_FLAG_SET_MTU;\r
+\r
+       if ( flags & INIC_FLAG_ENABLE_NIC )\r
+       {\r
+               pConfigLinkReq->cmdFlags |= INIC_FLAG_ENABLE_NIC;\r
+       }\r
+       else\r
+       {\r
+               pConfigLinkReq->cmdFlags |= INIC_FLAG_DISABLE_NIC;\r
+       }\r
+\r
+       if (flags & INIC_FLAG_ENABLE_MCAST_ALL )\r
+       {\r
+               pConfigLinkReq->cmdFlags |= INIC_FLAG_ENABLE_MCAST_ALL;\r
+       }\r
+       else\r
+       {\r
+               pConfigLinkReq->cmdFlags |= INIC_FLAG_DISABLE_MCAST_ALL;\r
+       }\r
+       if (flags & INIC_FLAG_ENABLE_PROMISC )\r
+       {\r
+               pConfigLinkReq->cmdFlags |= INIC_FLAG_ENABLE_PROMISC;\r
+               /* The EIOU doesn't really do PROMISC mode.\r
+                * If PROMISC is set, it only receives unicast packets\r
+                * I also have to set MCAST_ALL if I want real\r
+                * PROMISC mode.\r
+                */\r
+               pConfigLinkReq->cmdFlags &= ~INIC_FLAG_DISABLE_MCAST_ALL;\r
+               pConfigLinkReq->cmdFlags |= INIC_FLAG_ENABLE_MCAST_ALL;\r
+       }\r
+       else\r
+       {\r
+               pConfigLinkReq->cmdFlags |= INIC_FLAG_DISABLE_PROMISC;\r
+       }\r
+       pConfigLinkReq->mtuSize      = hton16( mtu );\r
+\r
+       ib_status = control_send( pControl );\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return ib_status;\r
+}\r
+\r
+\r
+BOOLEAN\r
+control_configLinkRsp(\r
+               IN                      Control_t               *pControl,\r
+               IN      OUT             uint8_t         *pFlags,\r
+               IN      OUT             uint16_t                *pMtu )\r
+{\r
+       RecvIo_t             *pRecvIo;\r
+       Inic_ControlPacket_t *pPkt;\r
+       Inic_CmdConfigLink_t *pConfigLinkRsp;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       pRecvIo = control_getRsp( pControl );\r
+       if ( !pRecvIo )\r
+               return FALSE;\r
+\r
+       pPkt = control_packet( pRecvIo );\r
+       if ( pPkt->hdr.pktCmd != CMD_CONFIG_LINK )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("%s: Sent control request:\n",\r
+                               control_ifcfg_name( pControl )) );\r
+\r
+               __control_logControlPacket( control_lastReq( pControl ) );\r
+\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("%s: Received control response:\n",\r
+                                       control_ifcfg_name( pControl ))  );\r
+       \r
+               __control_logControlPacket( pPkt );\r
+               goto failure;\r
+       }\r
+\r
+       pConfigLinkRsp = &pPkt->cmd.configLinkRsp;\r
+\r
+       *pFlags = pConfigLinkRsp->cmdFlags;\r
+       *pMtu   = ntoh16( pConfigLinkRsp->mtuSize );\r
+\r
+       control_recv( pControl, pRecvIo );\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return TRUE;\r
+\r
+failure:\r
+       viport_failure( pControl->p_viport );\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return FALSE;\r
+}\r
+\r
+/* control_configAddrsReq:\r
+ * Return values:\r
+ *          -1: failure\r
+ *           0: incomplete (successful operation, but more address\r
+ *              table entries to be updated)\r
+ *           1: complete\r
+ */\r
+ib_api_status_t\r
+control_configAddrsReq(\r
+       IN                              Control_t                       *pControl,\r
+       IN                              Inic_AddressOp_t        *pAddrs,\r
+       IN                              uint16_t                        num,\r
+               OUT                     int32_t                         *pAddrQueryDone )\r
+{\r
+       Inic_CmdConfigAddresses_t       *pConfigAddrsReq;\r
+       Inic_ControlPacket_t            *pPkt;\r
+       uint16_t                                        i;\r
+       uint8_t                                         j;\r
+       ib_api_status_t                         ib_status;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       control_initHdr( pControl, CMD_CONFIG_ADDRESSES );\r
+\r
+       pPkt                          = control_packet( &pControl->sendIo );\r
+       pConfigAddrsReq               = &pPkt->cmd.configAddressesReq;\r
+       NdisZeroMemory( pConfigAddrsReq, sizeof( Inic_CmdConfigAddresses_t ) );\r
+       pConfigAddrsReq->lanSwitchNum = pControl->lanSwitch.lanSwitchNum;\r
+\r
+       for ( i=0, j = 0; ( i < num ) && ( j < 16 ); i++ )\r
+       {\r
+               if ( !pAddrs[i].operation )\r
+                       continue;\r
+\r
+               pConfigAddrsReq->listAddressOps[j].index     = hton16(i);\r
+               pConfigAddrsReq->listAddressOps[j].operation = INIC_OP_SET_ENTRY;\r
+               pConfigAddrsReq->listAddressOps[j].valid = pAddrs[i].valid;\r
+       \r
+               cl_memcpy( pConfigAddrsReq->listAddressOps[j].address,\r
+                       pAddrs[i].address, MAC_ADDR_LEN );\r
+               pConfigAddrsReq->listAddressOps[j].vlan = hton16( pAddrs[i].vlan );\r
+               pAddrs[i].operation = 0;\r
+               j++;\r
+       }\r
+       pConfigAddrsReq->numAddressOps = j;\r
+\r
+       for ( ; i < num; i++ )\r
+       {\r
+               if ( pAddrs[i].operation )\r
+                       break;\r
+       }\r
+       *pAddrQueryDone = (i == num);\r
+\r
+       ib_status = control_send( pControl );\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return ib_status;\r
+}\r
+\r
+\r
+BOOLEAN\r
+control_configAddrsRsp(\r
+               IN              Control_t               *pControl )\r
+{\r
+       RecvIo_t                  *pRecvIo;\r
+       Inic_ControlPacket_t      *pPkt;\r
+       Inic_CmdConfigAddresses_t *pConfigAddrsRsp;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       pRecvIo = control_getRsp( pControl );\r
+       if ( !pRecvIo )\r
+               return FALSE;\r
+\r
+       pPkt = control_packet( pRecvIo );\r
+       if ( pPkt->hdr.pktCmd != CMD_CONFIG_ADDRESSES )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("%s: Sent control request:\n",\r
+                               control_ifcfg_name( pControl )) );\r
+\r
+               __control_logControlPacket( control_lastReq( pControl ) );\r
+\r
+               VNIC_TRACE_EXIT(VNIC_DBG_ERROR,\r
+                       ("%s: Received control response:\n",\r
+                               control_ifcfg_name( pControl )) );\r
+\r
+               __control_logControlPacket( pPkt );\r
+       \r
+               goto failure;\r
+       }\r
+\r
+       pConfigAddrsRsp = &pPkt->cmd.configAddressesRsp;\r
+\r
+       control_recv( pControl, pRecvIo );\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return TRUE;\r
+\r
+failure:\r
+       viport_failure( pControl->p_viport );\r
+       return FALSE;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+control_reportStatisticsReq(\r
+               IN              Control_t               *pControl )\r
+{\r
+       Inic_ControlPacket_t                    *pPkt;\r
+       Inic_CmdReportStatisticsReq_t   *pReportStatisticsReq;\r
+       ib_api_status_t                                 ib_status;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       control_initHdr( pControl, CMD_REPORT_STATISTICS );\r
+\r
+       pPkt                               = control_packet( &pControl->sendIo );\r
+       pReportStatisticsReq               = &pPkt->cmd.reportStatisticsReq;\r
+       pReportStatisticsReq->lanSwitchNum = pControl->lanSwitch.lanSwitchNum;\r
+\r
+       ib_status = control_send( pControl );\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return ib_status;\r
+}\r
+\r
+\r
+BOOLEAN\r
+control_reportStatisticsRsp(\r
+               IN              Control_t                                               *pControl,\r
+               IN              Inic_CmdReportStatisticsRsp_t   *pStats )\r
+{\r
+       RecvIo_t                      *pRecvIo;\r
+       Inic_ControlPacket_t          *pPkt;\r
+       Inic_CmdReportStatisticsRsp_t *pRepStatRsp;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       pRecvIo = control_getRsp( pControl );\r
+       if (!pRecvIo)\r
+               return FALSE;\r
+\r
+       pPkt = control_packet( pRecvIo );\r
+       if ( pPkt->hdr.pktCmd != CMD_REPORT_STATISTICS )\r
+       {\r
+               VNIC_TRACE(VNIC_DBG_ERROR,\r
+                       ("%s: Sent control request:\n",\r
+                                       control_ifcfg_name( pControl )) );\r
+\r
+               __control_logControlPacket( control_lastReq( pControl ) );\r
+\r
+               VNIC_TRACE_EXIT(VNIC_DBG_ERROR,\r
+                       ("%s: Received control response:\n",\r
+                               control_ifcfg_name( pControl ) ) );\r
+\r
+               __control_logControlPacket( pPkt );\r
+       \r
+               goto failure;\r
+       }\r
+\r
+       pRepStatRsp                 = &pPkt->cmd.reportStatisticsRsp;\r
+       pStats->ifInBroadcastPkts   = ntoh64(pRepStatRsp->ifInBroadcastPkts);\r
+       pStats->ifInMulticastPkts   = ntoh64(pRepStatRsp->ifInMulticastPkts);\r
+       pStats->ifInOctets          = ntoh64(pRepStatRsp->ifInOctets);\r
+       pStats->ifInUcastPkts       = ntoh64(pRepStatRsp->ifInUcastPkts);\r
+       pStats->ifInNUcastPkts      = ntoh64(pRepStatRsp->ifInNUcastPkts);\r
+       pStats->ifInUnderrun        = ntoh64(pRepStatRsp->ifInUnderrun);\r
+       pStats->ifInErrors          = ntoh64(pRepStatRsp->ifInErrors);\r
+       pStats->ifOutErrors         = ntoh64(pRepStatRsp->ifOutErrors);\r
+       pStats->ifOutOctets         = ntoh64(pRepStatRsp->ifOutOctets);\r
+       pStats->ifOutUcastPkts      = ntoh64(pRepStatRsp->ifOutUcastPkts);\r
+       pStats->ifOutMulticastPkts  = ntoh64(pRepStatRsp->ifOutMulticastPkts);\r
+       pStats->ifOutBroadcastPkts  = ntoh64(pRepStatRsp->ifOutBroadcastPkts);\r
+       pStats->ifOutNUcastPkts     = ntoh64(pRepStatRsp->ifOutNUcastPkts);\r
+       pStats->ifOutOk             = ntoh64(pRepStatRsp->ifOutOk);\r
+       pStats->ifInOk              = ntoh64(pRepStatRsp->ifInOk);\r
+       pStats->ifOutUcastBytes     = ntoh64(pRepStatRsp->ifOutUcastBytes);\r
+       pStats->ifOutMulticastBytes = ntoh64(pRepStatRsp->ifOutMulticastBytes);\r
+       pStats->ifOutBroadcastBytes = ntoh64(pRepStatRsp->ifOutBroadcastBytes);\r
+       pStats->ifInUcastBytes      = ntoh64(pRepStatRsp->ifInUcastBytes);\r
+       pStats->ifInMulticastBytes  = ntoh64(pRepStatRsp->ifInMulticastBytes);\r
+       pStats->ifInBroadcastBytes  = ntoh64(pRepStatRsp->ifInBroadcastBytes);\r
+       pStats->ethernetStatus      = ntoh64(pRepStatRsp->ethernetStatus);\r
+\r
+       control_recv(pControl, pRecvIo);\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return TRUE;\r
+failure:\r
+       viport_failure( pControl->p_viport );\r
+       return FALSE;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+control_resetReq(\r
+       IN              Control_t               *pControl )\r
+{\r
+       ib_api_status_t         ib_status;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       control_initHdr( pControl, CMD_RESET );\r
+       ib_status = control_send( pControl );\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return ib_status;\r
+}\r
+\r
+BOOLEAN\r
+control_resetRsp(\r
+               IN              Control_t               *pControl )\r
+{\r
+       RecvIo_t                      *pRecvIo;\r
+       Inic_ControlPacket_t          *pPkt;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       pRecvIo = control_getRsp( pControl );\r
+       if ( !pRecvIo ) return FALSE;\r
+\r
+       pPkt = control_packet( pRecvIo );\r
+\r
+       if ( pPkt->hdr.pktCmd != CMD_RESET )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("%s: Sent control request:\n",\r
+                               control_ifcfg_name( pControl )) );\r
+\r
+               __control_logControlPacket( control_lastReq( pControl ) );\r
+       \r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("%s: Received control response:\n",\r
+                               control_ifcfg_name( pControl )) );\r
+\r
+               __control_logControlPacket( pPkt );\r
+\r
+               goto failure;\r
+       }\r
+\r
+       control_recv( pControl, pRecvIo );\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return TRUE;\r
+failure:\r
+       viport_failure( pControl->p_viport );\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return FALSE;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+control_heartbeatReq(\r
+               IN              Control_t       *pControl,\r
+               IN              uint32_t        hbInterval )\r
+{\r
+       Inic_ControlPacket_t    *pPkt;\r
+       Inic_CmdHeartbeat_t             *pHeartbeatReq;\r
+       ib_api_status_t                 ib_status;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       control_initHdr(pControl, CMD_HEARTBEAT);\r
+\r
+       pPkt                      = control_packet(&pControl->sendIo);\r
+       pHeartbeatReq             = &pPkt->cmd.heartbeatReq;\r
+\r
+       /* pass timeout for the target in microseconds */\r
+       pHeartbeatReq->hbInterval = hton32( hbInterval*1000 );\r
+\r
+       ib_status = control_send( pControl );\r
+       ASSERT( ib_status == IB_SUCCESS );\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return ib_status;\r
+}\r
+\r
+BOOLEAN\r
+control_heartbeatRsp(\r
+               IN              Control_t               *pControl )\r
+{\r
+       RecvIo_t             *pRecvIo;\r
+       Inic_ControlPacket_t *pPkt;\r
+       Inic_CmdHeartbeat_t  *pHeartbeatRsp;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       pRecvIo = control_getRsp( pControl );\r
+\r
+       if (!pRecvIo)\r
+               return FALSE;\r
+\r
+       pPkt = control_packet(pRecvIo);\r
+\r
+       if ( pPkt->hdr.pktCmd != CMD_HEARTBEAT )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                               ("%s: Sent control request:\n",\r
+                                       control_ifcfg_name(pControl)) );\r
+       \r
+               __control_logControlPacket( control_lastReq(pControl) );\r
+       \r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("%s: Received control response:\n",\r
+                                       control_ifcfg_name(pControl)) );\r
+       \r
+               __control_logControlPacket( pPkt );\r
+               goto failure;\r
+       }\r
+\r
+       pHeartbeatRsp = &pPkt->cmd.heartbeatRsp;\r
+\r
+       control_recv( pControl, pRecvIo );\r
+       VNIC_EXIT ( VNIC_DBG_CTRL );\r
+       return TRUE;\r
+\r
+failure:\r
+       viport_failure( pControl->p_viport );\r
+       VNIC_EXIT ( VNIC_DBG_CTRL );\r
+       return FALSE;\r
+}\r
+\r
+static void\r
+control_recv(\r
+               IN              Control_t               *pControl,\r
+               IN              RecvIo_t                *pRecvIo )\r
+{\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       if ( ibqp_postRecv( &pControl->qp, &pRecvIo->io ) != IB_SUCCESS )\r
+               viport_failure( pControl->p_viport );\r
+\r
+       VNIC_EXIT ( VNIC_DBG_CTRL );\r
+}\r
+\r
+\r
+static void\r
+control_recvComplete(\r
+               IN              Io_t            *pIo )\r
+{\r
+       RecvIo_t             *pRecvIo = (RecvIo_t *)pIo;\r
+       RecvIo_t             *pLastRecvIo;\r
+       BOOLEAN                         status = FALSE;\r
+       Control_t            *pControl = &pIo->pViport->control;\r
+       viport_t                        *p_viport = pIo->pViport;\r
+       Inic_ControlPacket_t *pPkt = control_packet(pRecvIo);\r
+       Inic_ControlHeader_t *pCHdr = &pPkt->hdr;\r
+\r
+       switch ( pCHdr->pktType )\r
+       {\r
+               case TYPE_INFO:\r
+                       pLastRecvIo = InterlockedExchangePointer( &pControl->pInfo, pRecvIo );\r
+\r
+                       control_processAsync( pControl );\r
+\r
+                       if ( pLastRecvIo )\r
+                       {\r
+                               control_recv( pControl, pLastRecvIo );\r
+                       }\r
+                       return;\r
+\r
+               case TYPE_RSP:\r
+                       break;\r
+\r
+               default:\r
+                       //TODO: Should we ever reach this?  Who processes the list entries?\r
+                       ASSERT( pCHdr->pktType == TYPE_INFO || pCHdr->pktType == TYPE_RSP );\r
+                       ExInterlockedInsertTailList( &pRecvIo->io.listPtrs,\r
+                                                                                &pControl->failureList,\r
+                                                                                &pControl->ioLock );\r
+                       return;\r
+       }\r
+\r
+       if( (pCHdr->pktSeqNum != pControl->seqNum) ||\r
+               !InterlockedExchange( (volatile LONG*)&pControl->rspExpected, FALSE ) )\r
+       {\r
+               return;\r
+       }\r
+\r
+       InterlockedExchangePointer( &pControl->pResponse, pRecvIo );\r
+\r
+       switch ( pCHdr->pktCmd )\r
+       {\r
+       case CMD_INIT_INIC:\r
+               status = control_initInicRsp( pControl,\r
+                       &p_viport->featuresSupported,\r
+                       p_viport->hwMacAddress,\r
+                       &p_viport->numMacAddresses,\r
+                       &p_viport->defaultVlan );\r
+               if( status )\r
+               {\r
+                       InterlockedExchange(\r
+                               (volatile LONG*)&p_viport->linkState,\r
+                               (LONG)LINK_INITINICRSP );\r
+               }\r
+               InterlockedOr( &p_viport->updates, SYNC_QUERY );\r
+               break;\r
+\r
+       case CMD_CONFIG_DATA_PATH:\r
+               status = control_configDataPathRsp( &p_viport->control,\r
+                       data_hostPool( &p_viport->data ),\r
+                       data_eiocPool( &p_viport->data ),\r
+                       data_hostPoolMax( &p_viport->data ),\r
+                       data_eiocPoolMax( &p_viport->data ),\r
+                       data_hostPoolMin( &p_viport->data ),\r
+                       data_eiocPoolMin( &p_viport->data ));\r
+               if( status )\r
+               {\r
+                       InterlockedExchange(\r
+                               (volatile LONG*)&p_viport->linkState,\r
+                               (LONG)LINK_CONFIGDATAPATHRSP );\r
+               }\r
+               InterlockedOr( &p_viport->updates, SYNC_QUERY );\r
+               break;\r
+\r
+       case CMD_EXCHANGE_POOLS:\r
+               status = control_exchangePoolsRsp( &p_viport->control,\r
+                       data_remotePoolAddr( &p_viport->data ),\r
+                       data_remotePoolRkey( &p_viport->data ) );\r
+               if( status )\r
+               {\r
+                       InterlockedExchange(\r
+                               (volatile LONG*)&p_viport->linkState,\r
+                               (LONG)LINK_XCHGPOOLRSP );\r
+               }\r
+               InterlockedOr( &p_viport->updates, SYNC_QUERY );\r
+               break;\r
+\r
+               /* process other responses */\r
+       case CMD_CONFIG_LINK:\r
+               status = control_configLinkRsp( &p_viport->control,\r
+                       &p_viport->flags,\r
+                       &p_viport->mtu );\r
+               if( status )\r
+               {\r
+                       InterlockedExchange(\r
+                               (volatile LONG*)&p_viport->linkState,\r
+                               (LONG)LINK_CONFIGLINKRSP );\r
+\r
+                       if( p_viport->flags & INIC_FLAG_ENABLE_NIC )\r
+                       {\r
+                               InterlockedExchange( &p_viport->p_netpath->carrier, TRUE );\r
+                       }\r
+                       else\r
+                       {\r
+                               InterlockedExchange( &p_viport->p_netpath->carrier, FALSE );\r
+                       }\r
+                       InterlockedAnd( &p_viport->updates, ~NEED_LINK_CONFIG );\r
+               }\r
+               break;\r
+\r
+       case CMD_HEARTBEAT:\r
+               status = control_heartbeatRsp( pControl );\r
+               if( status &&\r
+                       !p_viport->errored &&\r
+                       !p_viport->disconnect )\r
+               {\r
+                       status = FALSE;\r
+                       viport_timer( p_viport, p_viport->port_config.hbInterval );\r
+               }\r
+               // Don't signal any waiting thread or start processing other updates.\r
+               return;\r
+\r
+       case CMD_CONFIG_ADDRESSES:\r
+               status = control_configAddrsRsp( pControl );\r
+               if( status == TRUE )\r
+               {\r
+                       if(     pControl->p_viport->addrs_query_done == 0 )\r
+                       {\r
+                               // need more entries to send\r
+                               // TODO: Handle a send failure.\r
+                               control_configAddrsReq( pControl,\r
+                                       pControl->p_viport->macAddresses,\r
+                                       pControl->p_viport->numMacAddresses,\r
+                                       &pControl->p_viport->addrs_query_done );\r
+                               // Don't signal any waiting thread or start processing other updates.\r
+                               return;\r
+                       }\r
+\r
+                       InterlockedAnd( &p_viport->updates, ~NEED_ADDRESS_CONFIG );\r
+                       InterlockedExchange( (volatile LONG*)&p_viport->linkState,\r
+                               (LONG)LINK_CONFIGADDRSRSP );\r
+               }\r
+               break;\r
+\r
+       case CMD_REPORT_STATISTICS:\r
+               status = control_reportStatisticsRsp( pControl, &p_viport->stats );\r
+               if ( status )\r
+               {\r
+                       if( p_viport->stats.ethernetStatus > 0 )\r
+                       {\r
+                               viport_linkUp( p_viport );\r
+                       }\r
+                       else\r
+                       {\r
+                               viport_linkDown( p_viport );\r
+                       }\r
+               }\r
+               InterlockedAnd( &p_viport->updates, ~NEED_STATS );\r
+               break;\r
+\r
+       case CMD_RESET:\r
+               status = control_resetRsp( pControl );\r
+               if( status )\r
+               {\r
+                       status = FALSE;\r
+                       InterlockedExchange(\r
+                               (volatile LONG*)&p_viport->linkState,\r
+                               (LONG)LINK_RESETRSP );\r
+               }\r
+               break;\r
+\r
+       default:\r
+               break;\r
+       }\r
+\r
+       if( _viport_process_query( p_viport, FALSE ) == STATUS_SUCCESS )\r
+       {\r
+               /* Complete any pending set OID. */\r
+               vnic_resume_set_oids( p_viport->p_adapter );\r
+       }\r
+\r
+       if(     InterlockedAnd( &p_viport->updates, ~SYNC_QUERY ) & SYNC_QUERY )\r
+               cl_event_signal( &p_viport->conn_event );\r
+}\r
+\r
+\r
+static ib_api_status_t\r
+control_send(\r
+       IN              Control_t               *pControl )\r
+{\r
+       ib_api_status_t ib_status;\r
+       Inic_ControlPacket_t *pPkt = control_packet(&pControl->sendIo);\r
+\r
+       VNIC_ENTER ( VNIC_DBG_CTRL );\r
+\r
+       ASSERT( !pControl->reqOutstanding );\r
+       if ( InterlockedCompareExchange( (volatile LONG*)&pControl->reqOutstanding,\r
+                                                                       TRUE, FALSE ) == TRUE )\r
+       {\r
+               /* IF WE HIT THIS WE ARE HOSED!!!\r
+                * by the time we detect this error, the send buffer has been\r
+                * overwritten, and if we retry we will send garbage data.\r
+                */\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+                       ("IB Send never completed\n" ) );\r
+               viport_failure( pControl->p_viport );\r
+               return IB_ERROR;\r
+       }\r
+\r
+#ifdef _DEBUG_\r
+       __control_logControlPacket( pPkt );\r
+#endif\r
+\r
+       InterlockedExchange( (volatile LONG*)&pControl->rspExpected,\r
+                                                                               (LONG)pPkt->hdr.pktCmd );\r
+\r
+       control_timer( pControl, pControl->p_conf->rspTimeout );\r
+\r
+#ifdef VNIC_STATISTIC\r
+       pControl->statistics.requestTime = cl_get_time_stamp();\r
+#endif /* VNIC_STATISTIC */\r
+\r
+       ib_status = ibqp_postSend( &pControl->qp, &pControl->sendIo.io );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               InterlockedExchange((volatile LONG*)&pControl->reqOutstanding, FALSE );\r
+\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                       ("%s: Failed to post send\n", control_ifcfg_name(pControl)) );\r
+               viport_failure( pControl->p_viport );\r
+       }\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return ib_status;\r
+}\r
+\r
+\r
+static void\r
+control_sendComplete(\r
+               IN              Io_t            *pIo )\r
+{\r
+       Control_t *pControl = &pIo->pViport->control;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       InterlockedExchange((volatile LONG*)&pControl->reqOutstanding, FALSE );\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return;\r
+}\r
+\r
+static void\r
+control_timeout(\r
+               IN              void    *p_context )\r
+{\r
+       Control_t *pControl;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       pControl = (Control_t *)p_context;\r
+\r
+       InterlockedExchange( (LONG *)&pControl->timerstate, (LONG)TIMER_EXPIRED );\r
+\r
+       InterlockedExchange( (volatile LONG*)&pControl->rspExpected, FALSE );\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return;\r
+}\r
+\r
+static void\r
+control_timer(\r
+               IN              Control_t       *pControl,\r
+               IN              int                     timeout )\r
+{\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       InterlockedExchange( (LONG *)&pControl->timerstate, (LONG)TIMER_ACTIVE );\r
+\r
+       cl_timer_start(&pControl->timer, timeout);\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return;\r
+}\r
+\r
+static void\r
+control_timerStop(\r
+               IN                      Control_t       *pControl )\r
+{\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+\r
+       if ( ( InterlockedExchange( (LONG *)&pControl->timerstate,\r
+                                                                               (LONG)TIMER_IDLE )) == TIMER_ACTIVE )\r
+       {\r
+               cl_timer_stop( &pControl->timer );\r
+       }\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+       return;\r
+}\r
+\r
+static void\r
+control_initHdr(\r
+               IN              Control_t *             pControl,\r
+               IN              uint8_t                 cmd )\r
+{\r
+       ControlConfig_t      *p_conf;\r
+       Inic_ControlPacket_t *pPkt;\r
+       Inic_ControlHeader_t *pHdr;\r
+\r
+       VNIC_ENTER( VNIC_DBG_CTRL );\r
+\r
+       p_conf = pControl->p_conf;\r
+\r
+       pPkt = control_packet( &pControl->sendIo );\r
+       pHdr = &pPkt->hdr;\r
+\r
+       pHdr->pktType = TYPE_REQ;\r
+       pHdr->pktCmd = cmd;\r
+       pHdr->pktSeqNum = ++pControl->seqNum;\r
+       pControl->reqRetryCounter = 0;\r
+       pHdr->pktRetryCount = 0;\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+}\r
+\r
+static RecvIo_t*\r
+control_getRsp(\r
+               IN                      Control_t               *pControl )\r
+{\r
+       RecvIo_t                *pRecvIo;\r
+\r
+       VNIC_ENTER ( VNIC_DBG_CTRL );\r
+\r
+       pRecvIo = InterlockedExchangePointer( &pControl->pResponse, NULL );\r
+\r
+       if ( pRecvIo != NULL )\r
+       {\r
+               control_timerStop(pControl);\r
+               return pRecvIo;\r
+       }\r
+\r
+       if ( ( pControl->timerstate =\r
+                               InterlockedCompareExchange( (LONG *)&pControl->timerstate,\r
+                               (LONG)TIMER_IDLE, (LONG)TIMER_EXPIRED )) == TIMER_EXPIRED )\r
+       {\r
+               Inic_ControlPacket_t *pPkt = control_packet( &pControl->sendIo );\r
+               Inic_ControlHeader_t *pHdr = &pPkt->hdr;\r
+\r
+               VNIC_TRACE( VNIC_DBG_CTRL| VNIC_DBG_ERROR,\r
+                               ("%s: No response received from EIOC\n",\r
+                                               control_ifcfg_name(pControl)) );\r
+#ifdef VNIC_STATISTIC\r
+               pControl->statistics.timeoutNum++;\r
+#endif /* VNIC_STATISTIC */\r
+\r
+               pControl->reqRetryCounter++;\r
+\r
+               if ( pControl->reqRetryCounter >= pControl->p_conf->reqRetryCount )\r
+               {\r
+                       VNIC_TRACE( VNIC_DBG_CTRL| VNIC_DBG_ERROR,\r
+                               ("%s: Control packet retry exceeded\n",\r
+                                               control_ifcfg_name(pControl)) );\r
+                       viport_failure(pControl->p_viport );\r
+               }\r
+               else\r
+               {\r
+                       pHdr->pktRetryCount = pControl->reqRetryCounter;\r
+                       control_send( pControl );\r
+               }\r
+       }\r
+       return NULL;\r
+}\r
+\r
+static void\r
+copyRecvPoolConfig(\r
+               IN                      Inic_RecvPoolConfig_t           *pSrc,\r
+               IN OUT          Inic_RecvPoolConfig_t           *pDst )\r
+{\r
+\r
+       pDst->sizeRecvPoolEntry            = hton32(pSrc->sizeRecvPoolEntry);\r
+       pDst->numRecvPoolEntries           = hton32(pSrc->numRecvPoolEntries);\r
+       pDst->timeoutBeforeKick            = hton32(pSrc->timeoutBeforeKick);\r
+       pDst->numRecvPoolEntriesBeforeKick = hton32(pSrc->numRecvPoolEntriesBeforeKick);\r
+       pDst->numRecvPoolBytesBeforeKick   = hton32(pSrc->numRecvPoolBytesBeforeKick);\r
+       pDst->freeRecvPoolEntriesPerUpdate = hton32(pSrc->freeRecvPoolEntriesPerUpdate);\r
+       return;\r
+}\r
+\r
+static BOOLEAN\r
+checkRecvPoolConfigValue(\r
+               IN              void            *pSrc,\r
+               IN              void            *pDst,\r
+               IN              void            *pMax,\r
+               IN              void            *pMin,\r
+               IN              char            *name )\r
+{\r
+       uint32_t value;\r
+       uint32_t *p_src = (uint32_t *)pSrc;\r
+       uint32_t *p_dst = (uint32_t *)pDst;\r
+       uint32_t *p_min = (uint32_t *)pMin;\r
+       uint32_t *p_max = (uint32_t *)pMax;\r
+\r
+       UNREFERENCED_PARAMETER( name );\r
+\r
+       value = ntoh32( *p_src );\r
+\r
+       if (value > *p_max )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_CTRL| VNIC_DBG_ERROR,\r
+                                       ("Value %s too large\n", name) );\r
+               return FALSE;\r
+       }\r
+       else if (value < *p_min )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_CTRL| VNIC_DBG_ERROR,\r
+                               ("Value %s too small\n", name) );\r
+               return FALSE;\r
+       }\r
+\r
+       *p_dst = value;\r
+       return TRUE;\r
+}\r
+\r
+static BOOLEAN\r
+checkRecvPoolConfig(\r
+               IN              Inic_RecvPoolConfig_t           *pSrc,\r
+               IN              Inic_RecvPoolConfig_t           *pDst,\r
+               IN              Inic_RecvPoolConfig_t           *pMax,\r
+               IN              Inic_RecvPoolConfig_t           *pMin )\r
+{\r
+       if (!checkRecvPoolConfigValue(&pSrc->sizeRecvPoolEntry, &pDst->sizeRecvPoolEntry,\r
+           &pMax->sizeRecvPoolEntry, &pMin->sizeRecvPoolEntry, "sizeRecvPoolEntry")\r
+       || !checkRecvPoolConfigValue(&pSrc->numRecvPoolEntries, &pDst->numRecvPoolEntries,\r
+           &pMax->numRecvPoolEntries, &pMin->numRecvPoolEntries, "numRecvPoolEntries")\r
+       || !checkRecvPoolConfigValue(&pSrc->timeoutBeforeKick, &pDst->timeoutBeforeKick,\r
+           &pMax->timeoutBeforeKick, &pMin->timeoutBeforeKick, "timeoutBeforeKick")\r
+       || !checkRecvPoolConfigValue(&pSrc->numRecvPoolEntriesBeforeKick,\r
+           &pDst->numRecvPoolEntriesBeforeKick, &pMax->numRecvPoolEntriesBeforeKick,\r
+           &pMin->numRecvPoolEntriesBeforeKick, "numRecvPoolEntriesBeforeKick")\r
+       || !checkRecvPoolConfigValue(&pSrc->numRecvPoolBytesBeforeKick,\r
+           &pDst->numRecvPoolBytesBeforeKick, &pMax->numRecvPoolBytesBeforeKick,\r
+           &pMin->numRecvPoolBytesBeforeKick, "numRecvPoolBytesBeforeKick")\r
+       || !checkRecvPoolConfigValue(&pSrc->freeRecvPoolEntriesPerUpdate,\r
+           &pDst->freeRecvPoolEntriesPerUpdate, &pMax->freeRecvPoolEntriesPerUpdate,\r
+           &pMin->freeRecvPoolEntriesPerUpdate, "freeRecvPoolEntriesPerUpdate"))\r
+               return FALSE;\r
+\r
+       if ( !IsPowerOf2( pDst->numRecvPoolEntries ) )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_CTRL| VNIC_DBG_ERROR,\r
+                       ("numRecvPoolEntries (%d) must be power of 2\n",\r
+                                       pDst->numRecvPoolEntries) );\r
+               return FALSE;\r
+       }\r
+       if ( !IsPowerOf2( pDst->freeRecvPoolEntriesPerUpdate ) )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_CTRL| VNIC_DBG_ERROR,\r
+                       ("freeRecvPoolEntriesPerUpdate (%d) must be power of 2\n",\r
+                                       pDst->freeRecvPoolEntriesPerUpdate) );\r
+               return FALSE;\r
+       }\r
+       if ( pDst->freeRecvPoolEntriesPerUpdate >= pDst->numRecvPoolEntries )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_CTRL| VNIC_DBG_ERROR,\r
+                       ("freeRecvPoolEntriesPerUpdate (%d) must be less than numRecvPoolEntries (%d)\n",\r
+                       pDst->freeRecvPoolEntriesPerUpdate, pDst->numRecvPoolEntries) );\r
+                       return FALSE;\r
+       }\r
+       if ( pDst->numRecvPoolEntriesBeforeKick >= pDst->numRecvPoolEntries )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_CTRL| VNIC_DBG_ERROR,\r
+                       ("numRecvPoolEntriesBeforeKick (%d) must be less than numRecvPoolEntries (%d)\n",\r
+                               pDst->numRecvPoolEntriesBeforeKick, pDst->numRecvPoolEntries) );\r
+                       return FALSE;\r
+       }\r
+\r
+       return TRUE;\r
+}\r
+\r
+static void\r
+__control_logControlPacket(\r
+                       IN              Inic_ControlPacket_t            *pPkt )\r
+{\r
+       char *type;\r
+       int i;\r
+\r
+       switch( pPkt->hdr.pktType  )\r
+       {\r
+       case TYPE_INFO:\r
+               type = "TYPE_INFO";\r
+               break;\r
+       case TYPE_REQ:\r
+               type = "TYPE_REQ";\r
+               break;\r
+       case TYPE_RSP:\r
+               type = "TYPE_RSP";\r
+               break;\r
+       case TYPE_ERR:\r
+               type = "TYPE_ERR";\r
+               break;\r
+       default:\r
+               type = "UNKNOWN";\r
+       }\r
+       switch( pPkt->hdr.pktCmd  )\r
+       {\r
+       case CMD_INIT_INIC:\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("ControlPacket: pktType = %s, pktCmd = CMD_INIT_INIC\n", type ) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL| VNIC_DBG_INFO,\r
+                       ("               pktSeqNum = %u, pktRetryCount = %u\n",\r
+                                                               pPkt->hdr.pktSeqNum,\r
+                                                               pPkt->hdr.pktRetryCount) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               inicMajorVersion = %u, inicMinorVersion = %u\n",\r
+                                                               ntoh16(pPkt->cmd.initInicReq.inicMajorVersion),\r
+                                                               ntoh16(pPkt->cmd.initInicReq.inicMinorVersion)) );\r
+               if (pPkt->hdr.pktType == TYPE_REQ)\r
+               {\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("               inicInstance = %u, numDataPaths = %u\n",\r
+                              pPkt->cmd.initInicReq.inicInstance,\r
+                              pPkt->cmd.initInicReq.numDataPaths) );\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT| VNIC_DBG_INFO,\r
+                               ("               numAddressEntries = %u\n",\r
+                                                               ntoh16(pPkt->cmd.initInicReq.numAddressEntries)) );\r
+               }\r
+               else\r
+               {\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("               numLanSwitches = %u, numDataPaths = %u\n",\r
+                                                               pPkt->cmd.initInicRsp.numLanSwitches,\r
+                                                               pPkt->cmd.initInicRsp.numDataPaths) );\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("               numAddressEntries = %u, featuresSupported = %08x\n",\r
+                                                               ntoh16(pPkt->cmd.initInicRsp.numAddressEntries),\r
+                                                               ntoh32(pPkt->cmd.initInicRsp.featuresSupported)) );\r
+                       if (pPkt->cmd.initInicRsp.numLanSwitches != 0)\r
+                       {\r
+                               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("lanSwitch[0]  lanSwitchNum = %u, numEnetPorts = %08x\n",\r
+                                      pPkt->cmd.initInicRsp.lanSwitch[0].lanSwitchNum,\r
+                                      pPkt->cmd.initInicRsp.lanSwitch[0].numEnetPorts) );\r
+                               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                                       ("               defaultVlan = %u, hwMacAddress = %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+                                                               ntoh16(pPkt->cmd.initInicRsp.lanSwitch[0].defaultVlan),\r
+                                                               pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[0],\r
+                                                               pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[1],\r
+                                                               pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[2],\r
+                                                               pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[3],\r
+                                                               pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[4],\r
+                                                               pPkt->cmd.initInicRsp.lanSwitch[0].hwMacAddress[5]) );\r
+                       }\r
+               }\r
+               break;\r
+       case CMD_CONFIG_DATA_PATH:\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ( "ControlPacket: pktType = %s, pktCmd = CMD_CONFIG_DATA_PATH\n", type) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               pktSeqNum = %u, pktRetryCount = %u\n",\r
+                                                               pPkt->hdr.pktSeqNum,\r
+                                                               pPkt->hdr.pktRetryCount) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               pathIdentifier = %"PRIx64", dataPath = %u\n",\r
+                                                       pPkt->cmd.configDataPathReq.pathIdentifier,\r
+                                                       pPkt->cmd.configDataPathReq.dataPath) );\r
+       \r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("Host Config    sizeRecvPoolEntry = %u, numRecvPoolEntries = %u\n",\r
+                                       ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.sizeRecvPoolEntry),\r
+                                       ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.numRecvPoolEntries)) );\r
+       \r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               timeoutBeforeKick = %u, numRecvPoolEntriesBeforeKick = %u\n",\r
+                                       ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.timeoutBeforeKick),\r
+                                       ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.numRecvPoolEntriesBeforeKick)) );\r
+       \r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               numRecvPoolBytesBeforeKick = %u, freeRecvPoolEntriesPerUpdate = %u\n",\r
+                      ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.numRecvPoolBytesBeforeKick),\r
+                      ntoh32(pPkt->cmd.configDataPathReq.hostRecvPoolConfig.freeRecvPoolEntriesPerUpdate)) );\r
+\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("Eioc Config    sizeRecvPoolEntry = %u, numRecvPoolEntries = %u\n",\r
+                      ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.sizeRecvPoolEntry),\r
+                      ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.numRecvPoolEntries)) );\r
+\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               timeoutBeforeKick = %u, numRecvPoolEntriesBeforeKick = %u\n",\r
+                      ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.timeoutBeforeKick),\r
+                      ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.numRecvPoolEntriesBeforeKick)) );\r
+\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               numRecvPoolBytesBeforeKick = %u, freeRecvPoolEntriesPerUpdate = %u\n",\r
+                      ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.numRecvPoolBytesBeforeKick),\r
+                      ntoh32(pPkt->cmd.configDataPathReq.eiocRecvPoolConfig.freeRecvPoolEntriesPerUpdate)) );\r
+               break;\r
+       case CMD_EXCHANGE_POOLS:\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("ControlPacket: pktType = %s, pktCmd = CMD_EXCHANGE_POOLS\n", type ) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               pktSeqNum = %u, pktRetryCount = %u\n",\r
+                                                       pPkt->hdr.pktSeqNum,\r
+                                                       pPkt->hdr.pktRetryCount) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               datapath = %u\n",\r
+                                               pPkt->cmd.exchangePoolsReq.dataPath) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               poolRKey = %08x poolAddr = %"PRIx64"\n",\r
+                                               ntoh32(pPkt->cmd.exchangePoolsReq.poolRKey),\r
+                                               ntoh64(pPkt->cmd.exchangePoolsReq.poolAddr)) );\r
+               break;\r
+       case CMD_CONFIG_ADDRESSES:\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ( "ControlPacket: pktType = %s, pktCmd = CMD_CONFIG_ADDRESSES\n", type ) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               pktSeqNum = %u, pktRetryCount = %u\n",\r
+                                                       pPkt->hdr.pktSeqNum,\r
+                                                       pPkt->hdr.pktRetryCount) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               numAddressOps = %x, lanSwitchNum = %d\n",\r
+                                                       pPkt->cmd.configAddressesReq.numAddressOps,\r
+                                                       pPkt->cmd.configAddressesReq.lanSwitchNum) );\r
+               for (i = 0; ( i < pPkt->cmd.configAddressesReq.numAddressOps) && (i < 16); i++)\r
+               {\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("               listAddressOps[%u].index = %u\n",\r
+                                       i, ntoh16(pPkt->cmd.configAddressesReq.listAddressOps[i].index)) );\r
+                      \r
+                       switch(pPkt->cmd.configAddressesReq.listAddressOps[i].operation)\r
+                       {\r
+                       case INIC_OP_GET_ENTRY:\r
+                               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                                       ("               listAddressOps[%u].operation = INIC_OP_GET_ENTRY\n", i) );\r
+                               break;\r
+                       case INIC_OP_SET_ENTRY:\r
+                               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                                       ("               listAddressOps[%u].operation = INIC_OP_SET_ENTRY\n", i) );\r
+                               break;\r
+                       default:\r
+                               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                                       ("               listAddressOps[%u].operation = UNKNOWN(%d)\n",\r
+                                      i, pPkt->cmd.configAddressesReq.listAddressOps[i].operation) );\r
+                               break;\r
+                       }\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("               listAddressOps[%u].valid = %u\n",\r
+                              i, pPkt->cmd.configAddressesReq.listAddressOps[i].valid) );\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("               listAddressOps[%u].address = %02x:%02x:%02x:%02x:%02x:%02x\n", i,\r
+                                       pPkt->cmd.configAddressesReq.listAddressOps[i].address[0],\r
+                                       pPkt->cmd.configAddressesReq.listAddressOps[i].address[1],\r
+                                       pPkt->cmd.configAddressesReq.listAddressOps[i].address[2],\r
+                                       pPkt->cmd.configAddressesReq.listAddressOps[i].address[3],\r
+                                       pPkt->cmd.configAddressesReq.listAddressOps[i].address[4],\r
+                                       pPkt->cmd.configAddressesReq.listAddressOps[i].address[5]) );\r
+\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("               listAddressOps[%u].vlan = %u\n",\r
+                              i, ntoh16(pPkt->cmd.configAddressesReq.listAddressOps[i].vlan)) );\r
+               }\r
+               break;\r
+       case CMD_CONFIG_LINK:\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("ControlPacket: pktType = %s, pktCmd = CMD_CONFIG_LINK\n", type) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               pktSeqNum = %u, pktRetryCount = %u\n",\r
+                      pPkt->hdr.pktSeqNum,\r
+                      pPkt->hdr.pktRetryCount) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               cmdFlags = %x\n",\r
+                      pPkt->cmd.configLinkReq.cmdFlags) );\r
+\r
+               if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_ENABLE_NIC )\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("                       INIC_FLAG_ENABLE_NIC\n") );\r
+\r
+               if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_DISABLE_NIC )\r
+       \r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("                       INIC_FLAG_DISABLE_NIC\n") );\r
+\r
+               if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_ENABLE_MCAST_ALL )\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("                       INIC_FLAG_ENABLE_MCAST_ALL\n") );\r
+\r
+               if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_DISABLE_MCAST_ALL )\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("                       INIC_FLAG_DISABLE_MCAST_ALL\n") );\r
+\r
+               if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_ENABLE_PROMISC )\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("                       INIC_FLAG_ENABLE_PROMISC\n") );\r
+       \r
+               if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_DISABLE_PROMISC )\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("                       INIC_FLAG_DISABLE_PROMISC\n") );\r
+               if ( pPkt->cmd.configLinkReq.cmdFlags & INIC_FLAG_SET_MTU )\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("                       INIC_FLAG_SET_MTU\n") );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("               lanSwitchNum = %x, mtuSize = %d\n",\r
+                                               pPkt->cmd.configLinkReq.lanSwitchNum,\r
+                                               ntoh16(pPkt->cmd.configLinkReq.mtuSize)) );\r
+               if ( pPkt->hdr.pktType == TYPE_RSP )\r
+               {\r
+                       VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                               ("               defaultVlan = %u, hwMacAddress = %02x:%02x:%02x:%02x:%02x:%02x\n",\r
+                               ntoh16(pPkt->cmd.configLinkReq.defaultVlan),\r
+                               pPkt->cmd.configLinkReq.hwMacAddress[0],\r
+                               pPkt->cmd.configLinkReq.hwMacAddress[1],\r
+                               pPkt->cmd.configLinkReq.hwMacAddress[2],\r
+                               pPkt->cmd.configLinkReq.hwMacAddress[3],\r
+                               pPkt->cmd.configLinkReq.hwMacAddress[4],\r
+                               pPkt->cmd.configLinkReq.hwMacAddress[5]) );\r
+               }\r
+               break;\r
+       case CMD_REPORT_STATISTICS:\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("ControlPacket: pktType = %s, pktCmd = CMD_REPORT_STATISTICS\n", type ) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               pktSeqNum = %u, pktRetryCount = %u\n",\r
+                       pPkt->hdr.pktSeqNum,\r
+                       pPkt->hdr.pktRetryCount) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               lanSwitchNum = %u\n",\r
+                       pPkt->cmd.reportStatisticsReq.lanSwitchNum) );\r
+\r
+               if (pPkt->hdr.pktType == TYPE_REQ)\r
+                       break;\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               ifInBroadcastPkts = %"PRIu64,\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifInBroadcastPkts)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       (" ifInMulticastPkts = %"PRIu64"\n",\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifInMulticastPkts)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               ifInOctets = %"PRIu64,\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifInOctets)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       (" ifInUcastPkts = %"PRIu64"\n",\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifInUcastPkts)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               ifInNUcastPkts = %"PRIu64,\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifInNUcastPkts)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       (" ifInUnderrun = %"PRIu64"\n",\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifInUnderrun)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               ifInErrors = %"PRIu64,\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifInErrors)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       (" ifOutErrors = %"PRIu64"\n",\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutErrors)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               ifOutOctets = %"PRIu64,\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutOctets)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       (" ifOutUcastPkts = %"PRIu64"\n",\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutUcastPkts)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               ifOutMulticastPkts = %"PRIu64,\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutMulticastPkts)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       (" ifOutBroadcastPkts = %"PRIu64"\n",\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutBroadcastPkts)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               ifOutNUcastPkts = %"PRIu64,\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutNUcastPkts)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       (" ifOutOk = %"PRIu64"\n",\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutOk)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               ifInOk = %"PRIu64,\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifInOk)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       (" ifOutUcastBytes = %"PRIu64"\n",\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutUcastBytes)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               ifOutMulticastBytes = %"PRIu64,\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutMulticastBytes)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       (" ifOutBroadcastBytes = %"PRIu64"\n",\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifOutBroadcastBytes)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               ifInUcastBytes = %"PRIu64,\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifInUcastBytes)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       (" ifInMulticastBytes = %"PRIu64"\n",\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifInMulticastBytes)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               ifInBroadcastBytes = %"PRIu64,\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ifInBroadcastBytes)) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       (" ethernetStatus = %"PRIu64"\n",\r
+                       ntoh64(pPkt->cmd.reportStatisticsRsp.ethernetStatus)) );\r
+               break;\r
+       case CMD_CLEAR_STATISTICS:\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("ControlPacket: pktType = %s, pktCmd = CMD_CLEAR_STATISTICS\n", type ) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               pktSeqNum = %u, pktRetryCount = %u\n",\r
+                       pPkt->hdr.pktSeqNum,\r
+                       pPkt->hdr.pktRetryCount) );\r
+               break;\r
+       case CMD_REPORT_STATUS:\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("ControlPacket: pktType = %s, pktCmd = CMD_REPORT_STATUS\n",\r
+                       type) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               pktSeqNum = %u, pktRetryCount = %u\n",\r
+                       pPkt->hdr.pktSeqNum,\r
+                       pPkt->hdr.pktRetryCount) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               lanSwitchNum = %u, isFatal = %u\n",\r
+                       pPkt->cmd.reportStatus.lanSwitchNum,\r
+                       pPkt->cmd.reportStatus.isFatal) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               statusNumber = %u, statusInfo = %u\n",\r
+                       ntoh32(pPkt->cmd.reportStatus.statusNumber),\r
+                       ntoh32(pPkt->cmd.reportStatus.statusInfo)) );\r
+               pPkt->cmd.reportStatus.fileName[31] = '\0';\r
+               pPkt->cmd.reportStatus.routine[31] = '\0';\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               filename = %s, routine = %s\n",\r
+                       pPkt->cmd.reportStatus.fileName,\r
+                       pPkt->cmd.reportStatus.routine) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               lineNum = %u, errorParameter = %u\n",\r
+                       ntoh32(pPkt->cmd.reportStatus.lineNum),\r
+                       ntoh32(pPkt->cmd.reportStatus.errorParameter)) );\r
+               pPkt->cmd.reportStatus.descText[127] = '\0';\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               descText = %s\n",\r
+                       pPkt->cmd.reportStatus.descText) );\r
+               break;\r
+       case CMD_RESET:\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("ControlPacket: pktType = %s, pktCmd = CMD_RESET\n", type ) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               pktSeqNum = %u, pktRetryCount = %u\n",\r
+                       pPkt->hdr.pktSeqNum,\r
+                       pPkt->hdr.pktRetryCount) );\r
+               break;\r
+       case CMD_HEARTBEAT:\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("ControlPacket: pktType = %s, pktCmd = CMD_HEARTBEAT\n", type ) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               pktSeqNum = %u, pktRetryCount = %u\n",\r
+                       pPkt->hdr.pktSeqNum,\r
+                       pPkt->hdr.pktRetryCount) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               hbInterval = %d\n",\r
+                       ntoh32(pPkt->cmd.heartbeatReq.hbInterval)) );\r
+               break;\r
+       default:\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("ControlPacket: pktType = %s, pktCmd = UNKNOWN (%u)\n",\r
+                       type,pPkt->hdr.pktCmd) );\r
+               VNIC_PRINT( VNIC_DBG_CTRL_PKT | VNIC_DBG_INFO,\r
+                       ("               pktSeqNum = %u, pktRetryCount = %u\n",\r
+                       pPkt->hdr.pktSeqNum,\r
+                       pPkt->hdr.pktRetryCount) );\r
+               break;\r
+       }\r
+       return;\r
+}\r
diff --git a/ulp/inic/kernel/vnic_control.h b/ulp/inic/kernel/vnic_control.h
new file mode 100644 (file)
index 0000000..f6c2ce3
--- /dev/null
@@ -0,0 +1,123 @@
+/*\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$\r
+ */\r
+\r
+#ifndef _VNIC_CONTROL_H_\r
+#define _VNIC_CONTROL_H_\r
+\r
+#include "vnic_controlpkt.h"\r
+#include "vnic_util.h"\r
+\r
+typedef enum {\r
+       TIMER_IDLE,\r
+       TIMER_ACTIVE,\r
+       TIMER_EXPIRED\r
+}timerstate_t;\r
+\r
+typedef struct Control {\r
+       struct _viport       *p_viport;\r
+       struct ControlConfig *p_conf;\r
+       IbRegion_t           region;\r
+       IbQp_t              qp;\r
+       uint8_t              *pLocalStorage;\r
+       uint16_t             majVer;\r
+       uint16_t                         minVer;\r
+       Inic_LanSwitchAttributes_t lanSwitch;\r
+       SendIo_t             sendIo;\r
+       RecvIo_t             *pRecvIos;\r
+\r
+       timerstate_t            timerstate;\r
+       cl_timer_t                      timer;\r
+       uint8_t                         reqRetryCounter;\r
+       uint8_t                         seqNum;\r
+       uint32_t                        reqOutstanding;\r
+       uint32_t                        rspExpected;\r
+       RecvIo_t                        *pResponse;\r
+       RecvIo_t                        *pInfo;\r
+       LIST_ENTRY                      failureList;\r
+       KSPIN_LOCK                      ioLock;\r
+\r
+#ifdef VNIC_STATISTIC\r
+       struct {\r
+               uint64_t     requestTime; /* Intermediate value */\r
+               uint64_t     responseTime;\r
+               uint32_t     responseNum;\r
+               uint64_t     responseMax;\r
+               uint64_t     responseMin;\r
+               uint32_t     timeoutNum;\r
+       } statistics;\r
+#endif /* VNIC_STATISTIC */\r
+} Control_t;\r
+\r
+void\r
+control_construct(\r
+       IN              Control_t                       *pControl,\r
+       IN              struct _viport          *pViport );\r
+\r
+ib_api_status_t control_init(Control_t *pControl, struct _viport *pViport,\r
+                     struct ControlConfig *p_conf, uint64_t guid);\r
+void    control_cleanup(Control_t *pControl);\r
+void    control_processAsync(Control_t *pControl);\r
+ib_api_status_t control_initInicReq(Control_t *pControl);\r
+BOOLEAN control_initInicRsp(Control_t *pControl, uint32_t *pFeatures,\r
+                           uint8_t *pMacAddress, uint16_t *pNumAddrs, uint16_t *pVlan);\r
+ib_api_status_t control_configDataPathReq(Control_t *pControl, uint64_t pathId,\r
+                                  struct Inic_RecvPoolConfig *pHost,\r
+                                 struct Inic_RecvPoolConfig *pEioc);\r
+BOOLEAN control_configDataPathRsp(Control_t *pControl,\r
+                                  struct Inic_RecvPoolConfig *pHost,\r
+                                 struct Inic_RecvPoolConfig *pEioc,\r
+                                  struct Inic_RecvPoolConfig *pMaxHost,\r
+                                 struct Inic_RecvPoolConfig *pMaxEioc,\r
+                                  struct Inic_RecvPoolConfig *pMinHost,\r
+                                 struct Inic_RecvPoolConfig *pMinEioc);\r
+ib_api_status_t control_exchangePoolsReq(Control_t *pControl, uint64_t addr, uint32_t rkey);\r
+BOOLEAN control_exchangePoolsRsp(Control_t *pControl, uint64_t *pAddr,\r
+                                uint32_t *pRkey);\r
+ib_api_status_t control_configLinkReq(Control_t *pControl, uint8_t flags, uint16_t mtu);\r
+BOOLEAN control_configLinkRsp(Control_t *pControl, uint8_t *pFlags, uint16_t *pMtu);\r
+ib_api_status_t control_configAddrsReq(Control_t *pControl, Inic_AddressOp_t *pAddrs,\r
+                              uint16_t num, int32_t *pAddrQueryDone);\r
+BOOLEAN control_configAddrsRsp(Control_t *pControl);\r
+ib_api_status_t control_reportStatisticsReq(Control_t *pControl);\r
+BOOLEAN control_reportStatisticsRsp(Control_t *pControl,\r
+                                   struct Inic_CmdReportStatisticsRsp *pStats);\r
+ib_api_status_t control_resetReq( Control_t *pControl );\r
+BOOLEAN control_resetRsp(Control_t *pControl);\r
+ib_api_status_t control_heartbeatReq(Control_t *pControl, uint32_t hbInterval);\r
+BOOLEAN control_heartbeatRsp(Control_t *pControl);\r
+\r
+#define control_packet(pIo) (Inic_ControlPacket_t *)(LONG_PTR)((pIo)->dsList.vaddr )\r
+#define control_lastReq(pControl) control_packet(&(pControl)->sendIo)\r
+#define control_features(pControl) (pControl)->featuresSupported\r
+#define control_getMacAddress(pControl,addr) \\r
+        memcpy(addr,(pControl)->lanSwitch.hwMacAddress,MAC_ADDR_LEN)\r
+\r
+#endif /* _VNIC_CONTROL_H_ */\r
diff --git a/ulp/inic/kernel/vnic_controlpkt.h b/ulp/inic/kernel/vnic_controlpkt.h
new file mode 100644 (file)
index 0000000..378d792
--- /dev/null
@@ -0,0 +1,284 @@
+/*\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$\r
+ */\r
+\r
+#ifndef _VNIC_CONTROLPKT_H_\r
+#define _VNIC_CONTROLPKT_H_\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct Inic_ConnectionData {\r
+       uint64_t        pathId;\r
+       uint8_t         inicInstance;\r
+       uint8_t         pathNum;\r
+       uint8_t         nodename[65];\r
+       uint8_t         reserved;\r
+       uint32_t        featuresSupported;\r
+} Inic_ConnectionData_t;\r
+       \r
+typedef struct Inic_ControlHeader {\r
+       uint8_t         pktType;\r
+       uint8_t         pktCmd;\r
+       uint8_t         pktSeqNum;\r
+       uint8_t         pktRetryCount;\r
+       uint32_t        reserved;       /* for 64-bit alignmnet */\r
+} Inic_ControlHeader_t;\r
+\r
+/* ptkType values */\r
+#define TYPE_INFO      0\r
+#define TYPE_REQ       1\r
+#define TYPE_RSP       2\r
+#define TYPE_ERR       3\r
+\r
+/* ptkCmd values */\r
+#define CMD_INIT_INIC                  1\r
+#define CMD_CONFIG_DATA_PATH   2\r
+#define CMD_EXCHANGE_POOLS             3\r
+#define CMD_CONFIG_ADDRESSES   4\r
+#define CMD_CONFIG_LINK                        5\r
+#define CMD_REPORT_STATISTICS  6\r
+#define CMD_CLEAR_STATISTICS   7\r
+#define CMD_REPORT_STATUS              8\r
+#define CMD_RESET                              9\r
+#define CMD_HEARTBEAT                  10\r
+\r
+#define MAC_ADDR_LEN                   HW_ADDR_LEN\r
+\r
+/* pktCmd CMD_INIT_INIC, pktType TYPE_REQ data format */\r
+typedef struct Inic_CmdInitInicReq {\r
+       uint16_t        inicMajorVersion;\r
+       uint16_t        inicMinorVersion;\r
+       uint8_t         inicInstance;\r
+       uint8_t         numDataPaths;\r
+       uint16_t        numAddressEntries;\r
+} Inic_CmdInitInicReq_t;\r
+\r
+/* pktCmd CMD_INIT_INIC, pktType TYPE_RSP subdata format */\r
+typedef struct Inic_LanSwitchAttributes {\r
+       uint8_t         lanSwitchNum;\r
+       uint8_t         numEnetPorts;\r
+       uint16_t        defaultVlan;\r
+       uint8_t         hwMacAddress[MAC_ADDR_LEN];\r
+} Inic_LanSwitchAttributes_t;\r
+\r
+/* pktCmd CMD_INIT_INIC, pktType TYPE_RSP data format */\r
+typedef struct Inic_CmdInitInicRsp {\r
+       uint16_t        inicMajorVersion;\r
+       uint16_t        inicMinorVersion;\r
+       uint8_t         numLanSwitches;\r
+       uint8_t         numDataPaths;\r
+       uint16_t        numAddressEntries;\r
+       uint32_t        featuresSupported;\r
+       Inic_LanSwitchAttributes_t lanSwitch[1];\r
+} Inic_CmdInitInicRsp_t;\r
+\r
+/* featuresSupported values */\r
+#define INIC_FEAT_IPV4_HEADERS                 0x00000001\r
+#define INIC_FEAT_IPV6_HEADERS                 0x00000002\r
+#define INIC_FEAT_IPV4_CSUM_RX                 0x00000004\r
+#define INIC_FEAT_IPV4_CSUM_TX                 0x00000008\r
+#define INIC_FEAT_TCP_CSUM_RX                  0x00000010\r
+#define INIC_FEAT_TCP_CSUM_TX                  0x00000020\r
+#define INIC_FEAT_UDP_CSUM_RX                  0x00000040\r
+#define INIC_FEAT_UDP_CSUM_TX                  0x00000080\r
+#define INIC_FEAT_TCP_SEGMENT                  0x00000100\r
+#define INIC_FEAT_IPV4_IPSEC_OFFLOAD   0x00000200\r
+#define INIC_FEAT_IPV6_IPSEC_OFFLOAD   0x00000400\r
+#define INIC_FEAT_FCS_PROPAGATE                        0x00000800\r
+#define INIC_FEAT_PF_KICK                              0x00001000\r
+#define INIC_FEAT_PF_FORCE_ROUTE               0x00002000\r
+#define INIC_FEAT_CHASH_OFFLOAD                        0x00004000\r
+#define INIC_FEAT_RDMA_IMMED                   0x00008000 \r
+#define INIC_FEAT_IGNORE_VLAN                  0x00010000\r
+\r
+/* pktCmd CMD_CONFIG_DATA_PATH subdata format */\r
+typedef struct  Inic_RecvPoolConfig {\r
+       uint32_t        sizeRecvPoolEntry;\r
+       uint32_t        numRecvPoolEntries;\r
+       uint32_t        timeoutBeforeKick;\r
+       uint32_t        numRecvPoolEntriesBeforeKick;\r
+       uint32_t        numRecvPoolBytesBeforeKick;\r
+       uint32_t        freeRecvPoolEntriesPerUpdate;\r
+} Inic_RecvPoolConfig_t;\r
+\r
+/* pktCmd CMD_CONFIG_DATA_PATH data format */\r
+typedef struct Inic_CmdConfigDataPath {\r
+       uint64_t        pathIdentifier;\r
+       uint8_t         dataPath;\r
+       uint8_t         reserved[3];\r
+       Inic_RecvPoolConfig_t  hostRecvPoolConfig;\r
+       Inic_RecvPoolConfig_t  eiocRecvPoolConfig;\r
+} Inic_CmdConfigDataPath_t;\r
+\r
+/* pktCmd CMD_EXCHANGE_POOLS data format */\r
+typedef struct Inic_CmdExchangePools {\r
+       uint8_t dataPath;\r
+       uint8_t reserved[3];\r
+       uint32_t        poolRKey;\r
+       uint64_t        poolAddr;\r
+} Inic_CmdExchangePools_t;\r
+\r
+/* pktCmd CMD_CONFIG_ADDRESSES subdata format */\r
+typedef struct Inic_AddressOp {\r
+       uint16_t        index;\r
+       uint8_t operation;\r
+       uint8_t valid;\r
+       uint8_t address[6];\r
+       uint16_t        vlan;\r
+} Inic_AddressOp_t;\r
+\r
+/* operation values */\r
+#define INIC_OP_SET_ENTRY      0x01\r
+#define INIC_OP_GET_ENTRY      0x02\r
+\r
+/* pktCmd CMD_CONFIG_ADDRESSES data format */\r
+typedef struct Inic_CmdConfigAddresses {\r
+       uint8_t numAddressOps;\r
+       uint8_t lanSwitchNum;\r
+       Inic_AddressOp_t        listAddressOps[1];\r
+} Inic_CmdConfigAddresses_t;\r
+\r
+/* CMD_CONFIG_LINK data format */\r
+typedef struct Inic_CmdConfigLink {\r
+       uint8_t cmdFlags;\r
+       uint8_t lanSwitchNum;\r
+       uint16_t   mtuSize;\r
+       uint16_t        defaultVlan;\r
+       uint8_t hwMacAddress[6];\r
+} Inic_CmdConfigLink_t;\r
+\r
+/* cmdFlags values */\r
+#define INIC_FLAG_ENABLE_NIC           0x01\r
+#define INIC_FLAG_DISABLE_NIC          0x02\r
+#define INIC_FLAG_ENABLE_MCAST_ALL     0x04\r
+#define INIC_FLAG_DISABLE_MCAST_ALL    0x08\r
+#define INIC_FLAG_ENABLE_PROMISC       0x10\r
+#define INIC_FLAG_DISABLE_PROMISC      0x20\r
+#define INIC_FLAG_SET_MTU                      0x40\r
+\r
+/* pktCmd CMD_REPORT_STATISTICS, pktType TYPE_REQ data format */\r
+typedef struct Inic_CmdReportStatisticsReq {\r
+       uint8_t lanSwitchNum;\r
+} Inic_CmdReportStatisticsReq_t;\r
+\r
+/* pktCmd CMD_REPORT_STATISTICS, pktType TYPE_RSP data format */\r
+typedef struct Inic_CmdReportStatisticsRsp {\r
+       uint8_t lanSwitchNum;\r
+       uint8_t reserved[7]; /* for 64-bit alignment */\r
+       uint64_t        ifInBroadcastPkts;\r
+       uint64_t        ifInMulticastPkts;\r
+       uint64_t        ifInOctets;\r
+       uint64_t        ifInUcastPkts;\r
+       uint64_t        ifInNUcastPkts; /* ifInBroadcastPkts + ifInMulticastPkts */\r
+       uint64_t        ifInUnderrun; /* (OID_GEN_RCV_NO_BUFFER) */\r
+       uint64_t        ifInErrors; /* (OID_GEN_RCV_ERROR) */\r
+       uint64_t        ifOutErrors; /* (OID_GEN_XMIT_ERROR) */\r
+       uint64_t        ifOutOctets;\r
+       uint64_t        ifOutUcastPkts;\r
+       uint64_t        ifOutMulticastPkts;\r
+       uint64_t        ifOutBroadcastPkts;\r
+       uint64_t        ifOutNUcastPkts; /* ifOutBroadcastPkts + ifOutMulticastPkts */\r
+       uint64_t        ifOutOk; /* ifOutNUcastPkts + ifOutUcastPkts (OID_GEN_XMIT_OK)*/\r
+       uint64_t        ifInOk; /* ifInNUcastPkts + ifInUcastPkts (OID_GEN_RCV_OK) */\r
+       uint64_t        ifOutUcastBytes; /* (OID_GEN_DIRECTED_BYTES_XMT) */\r
+       uint64_t        ifOutMulticastBytes; /* (OID_GEN_MULTICAST_BYTES_XMT) */\r
+       uint64_t        ifOutBroadcastBytes; /* (OID_GEN_BROADCAST_BYTES_XMT) */\r
+       uint64_t        ifInUcastBytes; /* (OID_GEN_DIRECTED_BYTES_RCV) */\r
+       uint64_t        ifInMulticastBytes; /* (OID_GEN_MULTICAST_BYTES_RCV) */\r
+       uint64_t        ifInBroadcastBytes; /* (OID_GEN_BROADCAST_BYTES_RCV) */\r
+       uint64_t        ethernetStatus; /* OID_GEN_MEDIA_CONNECT_STATUS) */\r
+} Inic_CmdReportStatisticsRsp_t;\r
+\r
+/* pktCmd CMD_CLEAR_STATISTICS data format */\r
+typedef struct Inic_CmdClearStatistics {\r
+       uint8_t lanSwitchNum;\r
+} Inic_CmdClearStatistics_t;\r
+\r
+/* pktCmd CMD_REPORT_STATUS data format */\r
+typedef struct Inic_CmdReportStatus {\r
+       uint8_t lanSwitchNum;\r
+       uint8_t isFatal;\r
+       uint8_t reserved[2]; /* for 32-bit alignment */\r
+       uint32_t        statusNumber;\r
+       uint32_t        statusInfo;\r
+       uint8_t         fileName[32];\r
+       uint8_t routine[32];\r
+       uint32_t        lineNum;\r
+       uint32_t        errorParameter;\r
+       uint8_t descText[128];\r
+} Inic_CmdReportStatus_t;\r
+\r
+/* pktCmd CMD_HEARTBEAT data format */\r
+typedef struct Inic_CmdHeartbeat {\r
+       uint32_t        hbInterval;\r
+} Inic_CmdHeartbeat_t;\r
+\r
+#define INIC_STATUS_LINK_UP                            1\r
+#define INIC_STATUS_LINK_DOWN                  2\r
+#define INIC_STATUS_ENET_AGGREGATION_CHANGE    3\r
+#define INIC_STATUS_EIOC_SHUTDOWN              4\r
+#define INIC_STATUS_CONTROL_ERROR              5\r
+#define INIC_STATUS_EIOC_ERROR                 6\r
+\r
+#define INIC_MAX_CONTROLPKTSZ  256\r
+#define INIC_MAX_CONTROLDATASZ \\r
+               (INIC_MAX_CONTROLPKTSZ - sizeof(Inic_ControlHeader_t))\r
+\r
+typedef struct Inic_ControlPacket {\r
+       Inic_ControlHeader_t hdr;\r
+       union {\r
+               Inic_CmdInitInicReq_t initInicReq;\r
+               Inic_CmdInitInicRsp_t initInicRsp;\r
+               Inic_CmdConfigDataPath_t configDataPathReq;\r
+               Inic_CmdConfigDataPath_t configDataPathRsp;\r
+               Inic_CmdExchangePools_t exchangePoolsReq;\r
+               Inic_CmdExchangePools_t exchangePoolsRsp;\r
+               Inic_CmdConfigAddresses_t configAddressesReq;\r
+               Inic_CmdConfigAddresses_t configAddressesRsp;\r
+               Inic_CmdConfigLink_t configLinkReq;\r
+               Inic_CmdConfigLink_t configLinkRsp;\r
+               Inic_CmdReportStatisticsReq_t reportStatisticsReq;\r
+               Inic_CmdReportStatisticsRsp_t reportStatisticsRsp;\r
+               Inic_CmdClearStatistics_t clearStatisticsReq;\r
+               Inic_CmdClearStatistics_t clearStatisticsRsp;\r
+               Inic_CmdReportStatus_t reportStatus;\r
+               Inic_CmdHeartbeat_t heartbeatReq;\r
+               Inic_CmdHeartbeat_t heartbeatRsp;\r
+               char cmdData[INIC_MAX_CONTROLDATASZ];\r
+       } cmd;\r
+} Inic_ControlPacket_t;\r
+/*\r
+typedef struct _mac_addr\r
+{\r
+       uint8_t         addr[MAC_ADDR_LEN];\r
+}      PACK_SUFFIX mac_addr_t;\r
+*/\r
+#include <complib/cl_packoff.h>\r
+\r
+#endif /* _VNIC_CONTROLPKT_H_ */
\ No newline at end of file
diff --git a/ulp/inic/kernel/vnic_data.c b/ulp/inic/kernel/vnic_data.c
new file mode 100644 (file)
index 0000000..66f6037
--- /dev/null
@@ -0,0 +1,1383 @@
+/*\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$\r
+ */\r
+#include <complib/comp_lib.h>\r
+#include "vnic_driver.h"\r
+\r
+static void    data_postRecvs(Data_t *pData);\r
+static void    _data_receivedKick(Io_t *pIo);\r
+static void    _data_xmitComplete(Io_t *pIo);\r
+static void    data_sendKickMessage(Data_t *pData);\r
+static void    _data_kickTimeoutHandler( void *context );\r
+static BOOLEAN data_allocXmitBuffer(Data_t *pData,\r
+                                       BufferPoolEntry_t **ppBpe, RdmaIo_t **ppRdmaIo, BOOLEAN *pLast);\r
+static void    data_checkXmitBuffers(Data_t *pData);\r
+static void    data_rdmaPacket(Data_t *pData, BufferPoolEntry_t *pBpe, RdmaIo_t *pRdmaIo);\r
+\r
+static NDIS_PACKET *\r
+_data_recv_to_ndis_pkt( Data_t *pData, RdmaDest_t *pRdmaDest );\r
+\r
+static void\r
+_data_allocBuffers(\r
+                                       Data_t          *pData,\r
+                                       BOOLEAN         initialAllocation );\r
+\r
+static void\r
+_data_addFreeBuffer(\r
+                                       Data_t          *pData,\r
+                                       int                     index,\r
+                                       RdmaDest_t      *pRdmaDest );\r
+\r
+static uint32_t\r
+_data_incomingRecv(\r
+                                       Data_t          *pData );\r
+\r
+static void   \r
+_data_sendFreeRecvBuffers(\r
+                                       Data_t          *pData );\r
+\r
+static uint8_t\r
+_tx_chksum_flags(\r
+ IN            NDIS_PACKET* const              p_packet );\r
+\r
+\r
+static void\r
+_get_first_buffer(\r
+               IN              NDIS_PACKET             *p_packet,\r
+               IN OUT  NDIS_BUFFER             **pp_buf_desc,\r
+               OUT             void                    **pp_buf,\r
+               OUT             ULONG                   *p_packet_sz );\r
+\r
+static void\r
+_data_return_recv(\r
+         IN    NDIS_PACKET             *p_packet );\r
+\r
+static void\r
+_data_kickTimer_start(\r
+                 IN    Data_t          *pData,\r
+                 IN    uint32_t        microseconds );\r
+\r
+static void\r
+_data_kickTimer_stop(\r
+                 IN    Data_t          *pData );\r
+\r
+#define LOCAL_IO(x) PTR64((x))\r
+\r
+#define INBOUND_COPY\r
+\r
+#ifdef VNIC_STATISTIC\r
+int64_t recvRef;\r
+#endif /* VNIC_STATISTIC */\r
+\r
+void\r
+data_construct(\r
+       IN              Data_t                  *pData,\r
+       IN              viport_t                *pViport )\r
+{\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       RtlZeroMemory( pData, sizeof(*pData) );\r
+\r
+       pData->p_viport = pViport;\r
+       pData->p_phy_region = &pViport->p_adapter->ca.region;\r
+       InitializeListHead( &pData->recvIos );\r
+       KeInitializeSpinLock ( &pData->recvIosLock );\r
+       KeInitializeSpinLock ( &pData->xmitBufLock );\r
+       cl_timer_construct( &pData->kickTimer );\r
+\r
+       ibqp_construct( &pData->qp, pViport );\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+}\r
+\r
+\r
+ib_api_status_t\r
+data_init(\r
+       IN              Data_t                  *pData,\r
+       IN              DataConfig_t    *p_conf,\r
+       IN              uint64_t                guid )\r
+{\r
+       ib_api_status_t ib_status;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       ASSERT( pData->p_viport != NULL );\r
+       pData->p_conf = p_conf;\r
+\r
+       cl_timer_init( &pData->kickTimer, _data_kickTimeoutHandler, pData );\r
+\r
+       ib_status = ibqp_init(&pData->qp, guid, &p_conf->ibConfig );\r
+       if( ib_status != IB_SUCCESS )\r
+               VNIC_TRACE( VNIC_DBG_ERROR, ("data ibqp_init failed\n") );\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+       return ib_status;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+data_connect(\r
+               IN              Data_t          *pData )\r
+{\r
+       NDIS_STATUS                     status;\r
+       ib_api_status_t         ib_status;\r
+       XmitPool_t        *pXmitPool = &pData->xmitPool;\r
+       RecvPool_t        *pRecvPool = &pData->recvPool;\r
+       RecvIo_t          *pRecvIo;\r
+       SendIo_t          *pSendIo;\r
+       RdmaIo_t          *pRdmaIo;\r
+       RdmaDest_t        *pRdmaDest;\r
+       uint8_t           *pRegionData;\r
+       int               sz, regionSz;\r
+       unsigned int      i, j;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       pRecvPool->poolSz           = pData->p_conf->hostRecvPoolEntries;\r
+       pRecvPool->eiocPoolSz       = pData->hostPoolParms.numRecvPoolEntries;\r
+\r
+       if ( pRecvPool->poolSz > pRecvPool->eiocPoolSz )\r
+       {\r
+               pRecvPool->poolSz = pData->hostPoolParms.numRecvPoolEntries;\r
+       }\r
+       pRecvPool->szFreeBundle     =\r
+                       pData->hostPoolParms.freeRecvPoolEntriesPerUpdate;\r
+       pRecvPool->numFreeBufs      = 0;\r
+       pRecvPool->numPostedBufs    = 0;\r
+       pRecvPool->nextFullBuf      = 0;\r
+       pRecvPool->nextFreeBuf      = 0;\r
+       pRecvPool->kickOnFree       = FALSE;\r
+       pRecvPool->bufferSz         = pData->hostPoolParms.sizeRecvPoolEntry;\r
+\r
+       pXmitPool->bufferSz         = pData->eiocPoolParms.sizeRecvPoolEntry;\r
+       pXmitPool->poolSz           = pData->eiocPoolParms.numRecvPoolEntries;\r
+       pXmitPool->notifyCount      = 0;\r
+       pXmitPool->notifyBundle     = pData->p_conf->notifyBundle;\r
+       pXmitPool->nextXmitPool     = 0;\r
+\r
+#if TRUE // LIMIT_OUTSTANDING_SENDS\r
+       pXmitPool->numXmitBufs      = pXmitPool->notifyBundle * 2;\r
+#else /* !LIMIT_OUTSTANDING_SENDS */\r
+       pXmitPool->numXmitBufs      = pXmitPool->poolSz;\r
+#endif /* LIMIT_OUTSTANDING_SENDS */\r
+\r
+       pXmitPool->nextXmitBuf      = 0;\r
+       pXmitPool->lastCompBuf      = pXmitPool->numXmitBufs - 1;\r
+       pXmitPool->kickCount        = 0;\r
+       pXmitPool->kickByteCount    = 0;\r
+       pXmitPool->sendKicks        =\r
+               (BOOLEAN)(( pData->eiocPoolParms.numRecvPoolEntriesBeforeKick != 0 )\r
+               || ( pData->eiocPoolParms.numRecvPoolBytesBeforeKick != 0 ));\r
+       pXmitPool->kickBundle       =\r
+               pData->eiocPoolParms.numRecvPoolEntriesBeforeKick;\r
+       pXmitPool->kickByteBundle   =\r
+               pData->eiocPoolParms.numRecvPoolBytesBeforeKick;\r
+       pXmitPool->needBuffers      = TRUE;\r
+\r
+       sz  = sizeof(RdmaDest_t) * pRecvPool->poolSz;\r
+       sz += sizeof(RecvIo_t) * pData->p_conf->numRecvs;\r
+       sz += sizeof(RdmaIo_t) * pXmitPool->numXmitBufs;\r
+\r
+       regionSz  = 4 * pData->p_conf->numRecvs;\r
+       regionSz += sizeof(BufferPoolEntry_t) * pRecvPool->eiocPoolSz;\r
+       regionSz += sizeof(BufferPoolEntry_t) * pXmitPool->poolSz;\r
+       sz       += regionSz;\r
+\r
+       status = NdisAllocateMemoryWithTag( &pData->pLocalStorage,\r
+                                                                               (UINT)sz,\r
+                                                                               'grtS' );\r
+       if ( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+                       ("Failed allocating %d bytes local storage\n", sz ) );\r
+               ib_status = IB_INSUFFICIENT_MEMORY;\r
+               goto err1;\r
+       }\r
+\r
+       NdisZeroMemory( pData->pLocalStorage, sz );\r
+       pData->localStorageSz = sz;\r
+\r
+       pRecvPool->pRecvBufs = (RdmaDest_t *)pData->pLocalStorage;\r
+       sz                   = sizeof(RdmaDest_t) * pRecvPool->poolSz;\r
+       pRecvIo              = (RecvIo_t *)(pData->pLocalStorage + sz);\r
+       sz                  += sizeof(RecvIo_t) * pData->p_conf->numRecvs;\r
+\r
+       pXmitPool->pXmitBufs = (RdmaIo_t *)(pData->pLocalStorage + sz);\r
+       sz                  += sizeof(RdmaIo_t) * pXmitPool->numXmitBufs;\r
+\r
+       pRegionData          = pData->pLocalStorage + sz;\r
+       sz                  += 4 * pData->p_conf->numRecvs;\r
+\r
+       pRecvPool->bufPool   = (BufferPoolEntry_t *)(pData->pLocalStorage + sz);\r
+       sz                  += sizeof(BufferPoolEntry_t) * pRecvPool->eiocPoolSz;\r
+       pXmitPool->bufPool   = (BufferPoolEntry_t *)(pData->pLocalStorage + sz);\r
+\r
+       ib_status = ibregion_init( pData->p_viport, &pData->region,\r
+               pData->p_viport->p_adapter->ca.hPd, pRegionData, regionSz,\r
+               ( IB_AC_LOCAL_WRITE | IB_AC_RDMA_WRITE ) );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("ib_region_init failed\n") );\r
+               goto err2;\r
+       }\r
+\r
+       pRdmaIo = &pData->freeBufsIo;\r
+       pRdmaIo->io.pViport          = pData->p_viport;\r
+       pRdmaIo->io.pRoutine         = NULL;\r
+       pRdmaIo->io.wrq.p_next       = NULL;\r
+       pRdmaIo->io.wrq.wr_type      = WR_RDMA_WRITE;\r
+       pRdmaIo->io.wrq.wr_id        = PTR64( pRdmaIo );\r
+       pRdmaIo->io.wrq.num_ds       = 1;\r
+       pRdmaIo->io.wrq.ds_array     = pRdmaIo->dsList;\r
+       pRdmaIo->dsList[0].lkey      = pData->region.lkey;\r
+       pRdmaIo->io.wrq.send_opt     = IB_SEND_OPT_SIGNALED;\r
+\r
+       pSendIo = &pData->kickIo;\r
+       pSendIo->io.pViport          = pData->p_viport;\r
+       pSendIo->io.pRoutine         = NULL;\r
+       pSendIo->io.wrq.p_next       = NULL;\r
+       pSendIo->io.wrq.wr_type      = WR_SEND;\r
+       pSendIo->io.wrq.wr_id        = PTR64( pSendIo );\r
+       pSendIo->io.wrq.num_ds       = 1;\r
+       pSendIo->io.wrq.ds_array     = &pSendIo->dsList;\r
+\r
+       pSendIo->io.wrq.send_opt     = IB_SEND_OPT_SIGNALED;\r
+\r
+       pSendIo->dsList.length       = 0;\r
+       pSendIo->dsList.vaddr        = PTR64( pRegionData );\r
+       pSendIo->dsList.lkey         = pData->region.lkey;\r
+\r
+       for ( i = 0; i < pData->p_conf->numRecvs; i++ )\r
+       {\r
+               pRecvIo[i].io.pViport         = pData->p_viport;\r
+               pRecvIo[i].io.pRoutine        = _data_receivedKick;\r
+               pRecvIo[i].io.r_wrq.wr_id     = PTR64( &pRecvIo[i].io );\r
+               pRecvIo[i].io.r_wrq.p_next    = NULL;\r
+               pRecvIo[i].io.r_wrq.num_ds    = 1;\r
+               pRecvIo[i].io.r_wrq.ds_array  = &pRecvIo[i].dsList;\r
+               pRecvIo[i].dsList.length      = 4;\r
+               pRecvIo[i].dsList.vaddr       = PTR64( pRegionData );\r
+               pRecvIo[i].dsList.lkey        = pData->region.lkey;\r
+       \r
+               ExInterlockedInsertTailList( &pData->recvIos, &pRecvIo[i].io.listPtrs, &pData->recvIosLock );\r
+        /* Do not need to move pointer since the receive info\r
+         * is not read.  Note, we could reduce the amount\r
+         * of memory allocated and the size of the region.\r
+                * pRegionData                  += 4;\r
+         * */\r
+       }\r
+\r
+       sz = pRecvPool->poolSz * pRecvPool->bufferSz;\r
+       status = NdisAllocateMemoryWithTag(&pData->p_recv_bufs,\r
+                                                                               sz, 'fubr');\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               ib_status = IB_INSUFFICIENT_MEMORY;\r
+               goto err3;\r
+       }\r
+       NdisZeroMemory( pData->p_recv_bufs, sz );\r
+\r
+       pData->recv_bufs_sz = sz;\r
+\r
+       ib_status = ibregion_init( pData->p_viport, &pData->rbuf_region,\r
+               pData->p_viport->p_adapter->ca.hPd, pData->p_recv_bufs, sz,\r
+               (IB_AC_LOCAL_WRITE | IB_AC_RDMA_WRITE) );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               goto err4;\r
+       }\r
+\r
+       NdisAllocatePacketPool( &status,\r
+                                                       &pData->h_recv_pkt_pool,\r
+                                                       pRecvPool->poolSz,\r
+                                                       PROTOCOL_RESERVED_SIZE_IN_PACKET );\r
+\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+                       ("Allocate packet pool failed status %#x\n", status ));\r
+               ib_status = IB_INSUFFICIENT_MEMORY;\r
+               goto err5;\r
+       }\r
+\r
+       NdisAllocateBufferPool(\r
+               &status, &pData->h_recv_buf_pool, pRecvPool->poolSz );\r
+\r
+       if( status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+                       ("Allocate packet pool failed status %#x\n", status ));\r
+               ib_status = IB_INSUFFICIENT_MEMORY;\r
+               goto err6;\r
+       }\r
+       pData->recvPool.recv_pkt_array =\r
+               cl_zalloc( sizeof(NDIS_PACKET*)* pRecvPool->poolSz );\r
+       if( !pData->recvPool.recv_pkt_array )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+                               ("Allocate packet array failed\n" ) );\r
+               ib_status = IB_INSUFFICIENT_MEMORY;\r
+               goto err7;\r
+       }\r
+\r
+       InitializeListHead( &pRecvPool->availRecvBufs );\r
+\r
+       for ( i = 0; i < pRecvPool->poolSz; i++ )\r
+       {\r
+               /* Allocate a region for each possible receive\r
+                * buffer. Make sure each is large enough for\r
+                * the maximum packet size, but initially point\r
+                * each to a random piece of memory. As buffers\r
+                * are allocated, the region will be modified to\r
+                * reflect the memory space of the actual buffers.\r
+                */\r
+               pRdmaDest = &pRecvPool->pRecvBufs[i];\r
+               pRdmaDest->data = pData->p_recv_bufs + (i * pRecvPool->bufferSz );\r
+               pRdmaDest->region = pData->rbuf_region;\r
+               InsertTailList( &pRecvPool->availRecvBufs, &pRdmaDest->listPtrs );\r
+       }\r
+\r
+       for ( i = 0; i < pXmitPool->numXmitBufs; i++ )\r
+       {\r
+               pRdmaIo = &pXmitPool->pXmitBufs[i];\r
+               pRdmaIo->index               = (uint16_t)i;\r
+               pRdmaIo->io.pViport          = pData->p_viport;\r
+               pRdmaIo->io.pRoutine         = _data_xmitComplete;\r
+               pRdmaIo->io.wrq.p_next       = NULL;\r
+               pRdmaIo->io.wrq.wr_type      = WR_RDMA_WRITE;\r
+               pRdmaIo->io.wrq.wr_id        = PTR64(pRdmaIo);\r
+               pRdmaIo->io.wrq.num_ds       = MAX_NUM_SGE; // will set actual number when transmit\r
+               pRdmaIo->io.wrq.ds_array     = pRdmaIo->dsList;\r
+               pRdmaIo->p_trailer                      =  (ViportTrailer_t *)&pRdmaIo->data[0];\r
+               for( j = 0; j < MAX_NUM_SGE; j++ )\r
+               {\r
+                       pRdmaIo->dsList[j].lkey      = pData->p_phy_region->lkey;\r
+               }\r
+       }\r
+\r
+       pXmitPool->rdmaRKey      = pData->region.rkey;\r
+       pXmitPool->rdmaAddr      = PTR64( pXmitPool->bufPool );\r
+\r
+       data_postRecvs( pData );\r
+\r
+       ib_status = ibqp_connect( &pData->qp );\r
+       if( ib_status != IB_SUCCESS )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR, ("ibqp_connect returned %s\n",\r
+                       pData->p_viport->p_adapter->ifc.get_err_str( ib_status )) );\r
+err7:\r
+               NdisFreeBufferPool( pData->h_recv_buf_pool );\r
+err6:\r
+               NdisFreePacketPool( pData->h_recv_pkt_pool );\r
+err5:\r
+               ibregion_cleanup( pData->p_viport, &pData->rbuf_region );\r
+err4:\r
+               NdisFreeMemory( pData->p_recv_bufs, pData->recv_bufs_sz, 0 );\r
+               pData->p_recv_bufs = NULL;\r
+err3:\r
+               ibregion_cleanup(pData->p_viport, &pData->region );\r
+err2:\r
+               NdisFreeMemory( pData->pLocalStorage, pData->localStorageSz, 0 );\r
+               pData->pLocalStorage = NULL;\r
+err1:\r
+               pRecvPool->poolSz = 0;\r
+       }\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+       return ib_status;\r
+}\r
+\r
+\r
+void\r
+data_connected(\r
+               IN              Data_t          *pData )\r
+{\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       pData->freeBufsIo.io.wrq.remote_ops.rkey =\r
+                                                       pData->recvPool.eiocRdmaRkey;\r
+\r
+       _data_allocBuffers(pData, TRUE);\r
+       _data_sendFreeRecvBuffers(pData);\r
+       pData->connected = TRUE;\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+       return;\r
+}\r
+\r
+void\r
+data_disconnect(\r
+               IN              Data_t          *pData )\r
+{\r
+       RecvPool_t *pRecvPool = &pData->recvPool;\r
+       viport_t        *p_viport = pData->p_viport;\r
+       NDIS_PACKET             *p_packet;\r
+       cl_list_item_t  *p_list_item;\r
+       unsigned int        i;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       pData->connected = FALSE;\r
+       _data_kickTimer_stop ( pData );\r
+\r
+       ibqp_detach( &pData->qp );\r
+\r
+       ibregion_cleanup( pData->p_viport, &pData->rbuf_region );\r
+       ibregion_cleanup( pData->p_viport, &pData->region );\r
+\r
+       for ( i = 0; i < pRecvPool->poolSz; i++ )\r
+       {\r
+               p_packet = pRecvPool->pRecvBufs[i].p_packet;\r
+               pRecvPool->pRecvBufs[i].p_packet = NULL;\r
+\r
+               if ( p_packet != NULL )\r
+               {\r
+                       _data_return_recv( p_packet );\r
+               }\r
+       }\r
+       /* clear pending queue if any */\r
+       if( cl_qlist_count( &p_viport->send_pending_list ) )\r
+       {\r
+               for( p_list_item = cl_qlist_remove_head( &p_viport->send_pending_list );\r
+                       p_list_item != cl_qlist_end( &p_viport->send_pending_list );\r
+                       p_list_item = cl_qlist_remove_head( &p_viport->send_pending_list ) )\r
+               {\r
+                       p_packet = VNIC_PACKET_FROM_LIST_ITEM( p_list_item );\r
+                       NdisMSendComplete( pData->p_viport->p_adapter->h_handle,\r
+                                                               p_packet, NDIS_STATUS_RESET_IN_PROGRESS );\r
+               }\r
+       }\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+       return;\r
+}\r
+\r
+BOOLEAN\r
+data_xmitPacket(\r
+               IN              Data_t                          *pData,\r
+               IN              NDIS_PACKET* const      p_packet )\r
+{\r
+       XmitPool_t              *p_xmitPool = &pData->xmitPool;\r
+       RdmaIo_t                *pRdmaIo;\r
+       BufferPoolEntry_t *pBpe;\r
+       BOOLEAN                 last;\r
+       uint8_t                 *p_buf;\r
+       uint32_t                buf_len;\r
+       NDIS_BUFFER             *p_buf_desc;\r
+       eth_hdr_t*              p_eth_hdr;\r
+       int                             pad;\r
+       SCATTER_GATHER_LIST             *p_sgl;\r
+       uint32_t                i;\r
+       PHYSICAL_ADDRESS phy_addr;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       if( !data_allocXmitBuffer( pData, &pBpe, &pRdmaIo, &last ) )\r
+       {\r
+               return FALSE;\r
+       }\r
+       p_sgl = NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet,\r
+                                                                                       ScatterGatherListPacketInfo );\r
+       if ( p_sgl == NULL )\r
+       {\r
+               return FALSE;\r
+       }\r
+\r
+       NdisGetFirstBufferFromPacketSafe( p_packet,\r
+                                                                       &p_buf_desc,\r
+                                                                       &p_buf,\r
+                                                                       &buf_len,\r
+                                                                       &pRdmaIo->packet_sz,\r
+                                                                       NormalPagePriority );\r
+\r
+       if( pRdmaIo->packet_sz > p_xmitPool->bufferSz )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+                       ("Outbound packet too large, size = %d\n", pRdmaIo->packet_sz ) );\r
+               return FALSE;\r
+       }\r
+\r
+       if ( p_sgl->NumberOfElements > (ULONG)MAX_NUM_SGE - 1 )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_DATA | VNIC_DBG_INFO,\r
+                       (" Xmit packet exceeded SGE limit - %d\n",\r
+                                                                               p_sgl->NumberOfElements ) );\r
+               return FALSE;\r
+       }\r
+\r
+       for( i=0; i < p_sgl->NumberOfElements; i++ )\r
+       {\r
+               pRdmaIo->dsList[i].vaddr = p_sgl->Elements[i].Address.QuadPart;\r
+               pRdmaIo->dsList[i].length = p_sgl->Elements[i].Length;\r
+       }\r
+\r
+       pRdmaIo->len = (uint32_t)ROUNDUPP2(\r
+               max(60, pRdmaIo->packet_sz), VIPORT_TRAILER_ALIGNMENT );\r
+       pad = pRdmaIo->len - pRdmaIo->packet_sz;\r
+\r
+       p_eth_hdr = (eth_hdr_t *)p_buf;\r
+\r
+       pRdmaIo->p_trailer = (ViportTrailer_t *)&pRdmaIo->data[pad];\r
+       cl_memclr( pRdmaIo->data, pad + sizeof( ViportTrailer_t ) );\r
+       cl_memcpy( pRdmaIo->p_trailer->destMacAddr, p_eth_hdr->dst.addr, MAC_ADDR_LEN );\r
+\r
+       pRdmaIo->p_trailer->dataLength =\r
+                                       hton16( (uint16_t)max( 60, pRdmaIo->packet_sz ) );\r
+\r
+       NdisGetNextBuffer( p_buf_desc, &p_buf_desc );\r
+\r
+       /* should handle VLAN tag */\r
+       if( pRdmaIo->packet_sz > 16 )\r
+       {\r
+               if(     p_eth_hdr->type == hton16(0x8100) )\r
+               {\r
+                       if( p_sgl->Elements[0].Length > sizeof(eth_hdr_t) )\r
+                       {\r
+                               pRdmaIo->p_trailer->vLan = *(uint16_t *)((uint8_t *)p_eth_hdr + 14 );\r
+                               pRdmaIo->p_trailer->pktFlags |= PF_VLAN_INSERT;\r
+                       }\r
+                       else\r
+                       {\r
+                               if( p_buf_desc )\r
+                               {\r
+                                       NdisQueryBufferSafe( p_buf_desc, &p_buf, &buf_len, NormalPagePriority );\r
+\r
+                                       pad = sizeof(eth_hdr_t) - p_sgl->Elements[0].Length;\r
+                                       pRdmaIo->p_trailer->vLan = *(uint16_t *)(p_buf + pad + 2);\r
+                                       pRdmaIo->p_trailer->pktFlags |= PF_VLAN_INSERT;\r
+                               }\r
+                       }\r
+               }\r
+               else if( p_eth_hdr->type == ETH_PROT_TYPE_IP &&\r
+                               !( p_eth_hdr->dst.addr[0] & 0x01 ) )\r
+               {\r
+                       if( p_buf_desc )\r
+                       {\r
+                               NdisQueryBufferSafe( p_buf_desc, &p_buf, &buf_len, NormalPagePriority );\r
+\r
+                               if( ((ip_pkt_t*)p_buf)->hdr.prot == IP_PROT_UDP ||\r
+                                       ((ip_pkt_t*)p_buf)->hdr.prot == IP_PROT_TCP )\r
+                               {\r
+                                       /* use socket src port + dest port to generate hash value\r
+                                       * for link aggregation distribution function.\r
+                                       */\r
+                                       pRdmaIo->p_trailer->connectionHashAndValid = 0x40 |\r
+                                               ((uint8_t)((ip_pkt_t*)p_buf)->prot.tcp.src_port +\r
+                                               (uint8_t)((ip_pkt_t*)p_buf)->prot.tcp.dst_port ) & 0x3f;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       pRdmaIo->p_trailer->txChksumFlags = _tx_chksum_flags( p_packet );\r
+       pRdmaIo->p_trailer->connectionHashAndValid |= CHV_VALID;\r
+\r
+       if( last )\r
+               pRdmaIo->p_trailer->pktFlags |= PF_KICK;\r
+\r
+       /* fill last data segment with trailer and pad */\r
+       phy_addr = MmGetPhysicalAddress( pRdmaIo->data );\r
+\r
+       pRdmaIo->dsList[p_sgl->NumberOfElements].vaddr = phy_addr.QuadPart;\r
+       pRdmaIo->dsList[p_sgl->NumberOfElements].length = pRdmaIo->len -\r
+                                                                                                         pRdmaIo->packet_sz +\r
+                                                                                                         sizeof( ViportTrailer_t );\r
+       //pRdmaIo->io.wrq.ds_array = pRdmaIo->dsList;\r
+    pRdmaIo->io.wrq.num_ds =p_sgl->NumberOfElements + 1;\r
+\r
+       data_rdmaPacket( pData, pBpe, pRdmaIo );\r
+\r
+       if( p_xmitPool->sendKicks )\r
+       {\r
+               /* EIOC needs kicks to inform it of sent packets */\r
+\r
+               p_xmitPool->kickCount++;\r
+               p_xmitPool->kickByteCount += pRdmaIo->packet_sz;\r
+               if( ( p_xmitPool->kickCount >= p_xmitPool->kickBundle )\r
+                        || ( p_xmitPool->kickByteCount >= p_xmitPool->kickByteBundle ) )\r
+               {\r
+                       data_sendKickMessage( pData );\r
+               }\r
+               else if( p_xmitPool->kickCount == 1 )\r
+               {\r
+                       _data_kickTimer_start( pData, pData->eiocPoolParms.timeoutBeforeKick );\r
+               }\r
+       }\r
+       return TRUE;\r
+}\r
+static uint8_t\r
+_tx_chksum_flags(\r
+                 IN    NDIS_PACKET* const              p_packet )\r
+\r
+{\r
+       NDIS_TCP_IP_CHECKSUM_PACKET_INFO        *p_packet_info;\r
+       ULONG                                                           packet_info;\r
+       uint8_t                 txChksumFlags = 0;\r
+\r
+       if( NDIS_PROTOCOL_ID_TCP_IP == NDIS_GET_PACKET_PROTOCOL_TYPE(p_packet) )\r
+       {\r
+               packet_info = PtrToUlong( NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo));\r
+               p_packet_info = ( NDIS_TCP_IP_CHECKSUM_PACKET_INFO *)&packet_info;\r
+\r
+               if( p_packet_info &&\r
+                       p_packet_info->Transmit.NdisPacketChecksumV4 )\r
+               {\r
+                       txChksumFlags = TX_CHKSUM_FLAGS_CHECKSUM_V4\r
+                       | ( p_packet_info->Transmit.NdisPacketIpChecksum ? TX_CHKSUM_FLAGS_IP_CHECKSUM: 0 )\r
+                       | ( p_packet_info->Transmit.NdisPacketTcpChecksum ? TX_CHKSUM_FLAGS_TCP_CHECKSUM: 0 )\r
+                       | ( p_packet_info->Transmit.NdisPacketUdpChecksum ? TX_CHKSUM_FLAGS_UDP_CHECKSUM: 0 );\r
+               }\r
+       }\r
+       \r
+       VNIC_TRACE( VNIC_DBG_DATA | VNIC_DBG_INFO ,\r
+                               ("txChksumFlags = %d: V4 %c, V6 %c, IP %c, TCP %c, UDP %c\n",\r
+                               txChksumFlags,\r
+                               ((txChksumFlags & TX_CHKSUM_FLAGS_CHECKSUM_V4 )? '+': '-'),\r
+                               ((txChksumFlags & TX_CHKSUM_FLAGS_CHECKSUM_V6 )? '+': '-'),\r
+                               ((txChksumFlags & TX_CHKSUM_FLAGS_IP_CHECKSUM )? '+': '-'),\r
+                               ((txChksumFlags & TX_CHKSUM_FLAGS_TCP_CHECKSUM )? '+': '-'),\r
+                               ((txChksumFlags & TX_CHKSUM_FLAGS_UDP_CHECKSUM )? '+': '-') ));\r
+\r
+       return txChksumFlags;\r
+}\r
+\r
+static void\r
+_get_first_buffer(\r
+               IN              NDIS_PACKET             *p_packet,\r
+               IN OUT  NDIS_BUFFER             **pp_buf_desc,\r
+               OUT             void                    **pp_buf,\r
+               OUT             ULONG                   *p_packet_sz )\r
+{\r
+       UINT            buf_len;\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       NdisGetFirstBufferFromPacketSafe( p_packet,\r
+                                                                       pp_buf_desc,\r
+                                                                       pp_buf,\r
+                                                                       &buf_len,\r
+                                                                       p_packet_sz,\r
+                                                                       NormalPagePriority );\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+}\r
+\r
+static void\r
+data_postRecvs(\r
+               IN              Data_t          *pData )\r
+{\r
+       RecvIo_t                *pRecvIo;\r
+       LIST_ENTRY              *p_list_entry;\r
+       ib_api_status_t ib_status;\r
+\r
+       VNIC_ENTER ( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       while( ( p_list_entry = ExInterlockedRemoveHeadList( &pData->recvIos,\r
+                                                                                                                &pData->recvIosLock ))\r
+                                                                                                               != NULL )\r
+       {\r
+               pRecvIo = (RecvIo_t *)p_list_entry;\r
+\r
+               ib_status = ibqp_postRecv( &pData->qp, &pRecvIo->io );\r
+               if( ib_status != IB_SUCCESS )\r
+               {\r
+                       VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("ibqp_postRecv returned %s\n",\r
+                               pData->p_viport->p_adapter->ifc.get_err_str( ib_status )) );\r
+                       viport_failure( pData->p_viport );\r
+                       return;\r
+               }\r
+       }\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+       return;\r
+}\r
+\r
+static void\r
+_data_receivedKick(\r
+                       IN              Io_t            *pIo )\r
+{\r
+       Data_t        *pData = &pIo->pViport->data;\r
+       uint32_t                num_pkts = 0;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+#ifdef VNIC_STATISTIC\r
+       recvRef = cl_get_tick_count();\r
+#endif /* VNIC_STATISTIC */\r
+\r
+       ExInterlockedInsertTailList( &pData->recvIos, &pIo->listPtrs, &pData->recvIosLock );\r
+\r
+       data_postRecvs( pData );\r
+\r
+#ifdef VNIC_STATISTIC\r
+       pData->statistics.kickRecvs++;\r
+#endif /* VNIC_STATISTIC */\r
+\r
+       data_checkXmitBuffers( pData );\r
+\r
+       num_pkts = _data_incomingRecv( pData );\r
+\r
+       if( num_pkts )\r
+       {\r
+               NdisMIndicateReceivePacket( pData->p_viport->p_adapter->h_handle,\r
+                                                                       pData->recvPool.recv_pkt_array,\r
+                                                                       num_pkts );\r
+               pData->p_viport->stats.ifInOk++;\r
+       }\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+       return;\r
+}\r
+\r
+static void\r
+_data_xmitComplete(\r
+                       IN              Io_t            *pIo )\r
+{\r
+       RdmaIo_t       *pRdmaIo = (RdmaIo_t *)pIo;\r
+       Data_t         *pData = &pIo->pViport->data;\r
+       XmitPool_t     *p_xmitPool = &pData->xmitPool;\r
+       vnic_adapter_t  *p_adapter = pIo->pViport->p_adapter;\r
+       NDIS_PACKET             *p_packet;\r
+       NDIS_STATUS             ndis_status;\r
+       cl_list_item_t  *p_list_item;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       while ( p_xmitPool->lastCompBuf != pRdmaIo->index )\r
+       {\r
+               INC(p_xmitPool->lastCompBuf, 1, p_xmitPool->numXmitBufs);\r
+               p_packet = p_xmitPool->pXmitBufs[p_xmitPool->lastCompBuf].p_packet;\r
+       \r
+               p_xmitPool->pXmitBufs[p_xmitPool->lastCompBuf].p_packet = NULL;\r
+\r
+               if( p_packet != NULL )\r
+               {\r
+                       if( pIo->wc_status != IB_WCS_SUCCESS )\r
+                       {\r
+                               ndis_status = NDIS_STATUS_FAILURE;\r
+                               p_adapter->p_viport->stats.ifOutErrors++;\r
+                       }\r
+                       else\r
+                       {\r
+                               ndis_status = NDIS_STATUS_SUCCESS;\r
+                               p_adapter->p_viport->stats.ifOutOk++;\r
+                       }\r
+                       NDIS_SET_PACKET_STATUS( p_packet, ndis_status );\r
+                       NdisMSendComplete( pIo->pViport->p_adapter->h_handle,\r
+                                                               p_packet, ndis_status );\r
+               }\r
+       }\r
+       pIo->wc_status = IB_WCS_SUCCESS;\r
+       if( !p_adapter->packet_filter )\r
+       {\r
+               if( cl_qlist_count( &pIo->pViport->send_pending_list ) )\r
+               {\r
+                       for( p_list_item = cl_qlist_remove_head( &pIo->pViport->send_pending_list );\r
+                               p_list_item != cl_qlist_end( &pIo->pViport->send_pending_list );\r
+                               p_list_item = cl_qlist_remove_head( &pIo->pViport->send_pending_list ) )\r
+                       {\r
+                               p_packet = VNIC_PACKET_FROM_LIST_ITEM( p_list_item );\r
+                               NdisMSendComplete( p_adapter->h_handle, p_packet,\r
+                                                                       NDIS_STATUS_RESET_IN_PROGRESS );\r
+                       }\r
+               }\r
+       }\r
+       data_checkXmitBuffers(pData);\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+       return;\r
+}\r
+\r
+static void\r
+data_sendKickMessage(\r
+               IN              Data_t          *pData )\r
+{\r
+       XmitPool_t *pPool = &pData->xmitPool;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       /* stop timer for BundleTimeout */\r
+       _data_kickTimer_stop( pData );\r
+\r
+       pPool->kickCount = 0;\r
+       pPool->kickByteCount = 0;\r
+\r
+       /* TBD: Keep track of when kick is outstanding, and\r
+        * don't reuse until complete\r
+        */\r
+       if ( ibqp_postSend( &pData->qp, &pData->kickIo.io ) != IB_SUCCESS )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                                       ("Unable to send kick to EIOC\n") );\r
+               viport_failure( pData->p_viport );\r
+       }\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+}\r
+\r
+static void\r
+_data_kickTimeoutHandler( void * context )\r
+{\r
+       Data_t* pData = (Data_t *)context;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       pData->kickTimerOn = FALSE;\r
+       data_sendKickMessage( pData );\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       return;\r
+}\r
+\r
+static BOOLEAN\r
+data_allocXmitBuffer(\r
+               IN              Data_t                          *pData,\r
+               OUT             BufferPoolEntry_t       **ppBpe,\r
+               OUT             RdmaIo_t                        **ppRdmaIo,\r
+               OUT             BOOLEAN                         *pLast )\r
+{\r
+       XmitPool_t    *p_xmitPool = &pData->xmitPool;\r
+       KIRQL flags;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       KeAcquireSpinLock( &pData->xmitBufLock, &flags );\r
+\r
+       *pLast = FALSE;\r
+       *ppRdmaIo = &p_xmitPool->pXmitBufs[p_xmitPool->nextXmitBuf];\r
+       *ppBpe = &p_xmitPool->bufPool[p_xmitPool->nextXmitPool];\r
+\r
+       if ( (*ppBpe)->valid && p_xmitPool->nextXmitBuf != p_xmitPool->lastCompBuf )\r
+       {\r
+               INC(p_xmitPool->nextXmitBuf, 1, p_xmitPool->numXmitBufs);\r
+               INC(p_xmitPool->nextXmitPool, 1, p_xmitPool->poolSz);\r
+\r
+               if ( !p_xmitPool->bufPool[p_xmitPool->nextXmitPool].valid )\r
+               {\r
+                       VNIC_TRACE( VNIC_DBG_DATA | VNIC_DBG_INFO,\r
+                               ("Just used the last EIOU receive buffer\n") );\r
+\r
+                       *pLast = TRUE;\r
+                       p_xmitPool->needBuffers = TRUE;\r
+                       viport_stopXmit( pData->p_viport );\r
+#ifdef VNIC_STATISTIC\r
+                       pData->statistics.kickReqs++;\r
+#endif /* VNIC_STATISTIC */\r
+               }\r
+               else if ( p_xmitPool->nextXmitBuf == p_xmitPool->lastCompBuf )\r
+               {\r
+                       VNIC_TRACE( VNIC_DBG_DATA | VNIC_DBG_INFO,\r
+                                               ("Just used our last xmit buffer\n") );\r
+               \r
+                       p_xmitPool->needBuffers = TRUE;\r
+                       viport_stopXmit( pData->p_viport );\r
+               }\r
+\r
+               (*ppBpe)->valid  = 0;\r
+\r
+               KeReleaseSpinLock( &pData->xmitBufLock, flags );\r
+               return TRUE;\r
+       }\r
+       else\r
+       {\r
+#ifdef VNIC_STATISTIC\r
+               pData->statistics.noXmitBufs++;\r
+#endif /* VNIC_STATISTIC */\r
+       \r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                                       ("Out of xmit buffers\n") );\r
+\r
+               viport_stopXmit( pData->p_viport );\r
+\r
+               KeReleaseSpinLock( &pData->xmitBufLock, flags );\r
+               return FALSE;\r
+       }\r
+}\r
+\r
+static void\r
+data_checkXmitBuffers(\r
+               IN                      Data_t          *pData )\r
+{\r
+       XmitPool_t      *p_xmitPool = &pData->xmitPool;\r
+       KIRQL           flags;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       KeAcquireSpinLock( &pData->xmitBufLock, &flags );\r
+\r
+       if ( pData->xmitPool.needBuffers\r
+               && p_xmitPool->bufPool[p_xmitPool->nextXmitPool].valid\r
+               && p_xmitPool->nextXmitBuf != p_xmitPool->lastCompBuf )\r
+       {\r
+               pData->xmitPool.needBuffers = FALSE;\r
+               viport_restartXmit( pData->p_viport );\r
+\r
+               VNIC_TRACE( VNIC_DBG_DATA | VNIC_DBG_INFO,\r
+                                               ("There are free xmit buffers\n") );\r
+       }\r
+\r
+       KeReleaseSpinLock( &pData->xmitBufLock, flags );\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+       return;\r
+}\r
+\r
+static void\r
+data_rdmaPacket(\r
+                       IN                      Data_t                          *pData,\r
+                       IN                      BufferPoolEntry_t       *pBpe,\r
+                       IN                      RdmaIo_t                        *pRdmaIo )\r
+{\r
+       ib_send_wr_t    *pWrq;\r
+       uint64_t                remote_addr;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       pWrq = &pRdmaIo->io.wrq;\r
+\r
+       remote_addr  = ntoh64( pBpe->remoteAddr );\r
+       remote_addr += pData->xmitPool.bufferSz;\r
+       remote_addr -= ( pRdmaIo->len + sizeof(ViportTrailer_t) );\r
+\r
+       pWrq->remote_ops.vaddr          = remote_addr;\r
+       pWrq->remote_ops.rkey           = pBpe->rKey;\r
+\r
+       pData->xmitPool.notifyCount++;\r
+\r
+       if( pData->xmitPool.notifyCount >= pData->xmitPool.notifyBundle )\r
+       {\r
+               pData->xmitPool.notifyCount = 0;\r
+               pWrq->send_opt = IB_SEND_OPT_SIGNALED;\r
+       }\r
+       else\r
+       {\r
+               pWrq->send_opt &= ~IB_SEND_OPT_SIGNALED;\r
+       }\r
+       pWrq->send_opt = IB_SEND_OPT_SIGNALED;\r
+\r
+       if( ibqp_postSend( &pData->qp, &pRdmaIo->io ) != IB_SUCCESS )\r
+       {\r
+               VNIC_TRACE(VNIC_DBG_ERROR,\r
+                                       ("Failed sending data to EIOC\n") );\r
+               viport_failure( pData->p_viport );\r
+               return;\r
+       }\r
+#ifdef VNIC_STATISTIC\r
+       pData->statistics.xmitNum++;\r
+#endif /* VNIC_STATISTIC */\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+}\r
+\r
+static NDIS_PACKET *\r
+_data_recv_to_ndis_pkt(\r
+               IN              Data_t                  *pData,\r
+               IN              RdmaDest_t              *pRdmaDest )\r
+{\r
+       struct ViportTrailer *pTrailer;\r
+       NDIS_PACKET             *p_packet;\r
+       NDIS_STATUS             ndis_status;\r
+       int                  start;\r
+       unsigned int         len;\r
+       uint8_t rxChksumFlags;\r
+       NDIS_TCP_IP_CHECKSUM_PACKET_INFO  packet_info;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       pTrailer = pRdmaDest->pTrailer;\r
+       start = (int)data_offset(pData, pTrailer);\r
+       len = data_len(pData, pTrailer);\r
+\r
+       NdisAllocatePacket( &ndis_status,\r
+                                               &p_packet,\r
+                                               pData->h_recv_pkt_pool );\r
+\r
+       if ( ndis_status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+                       ( "NdisAllocatePacket failed %#x\n", ndis_status ) );\r
+               return NULL;\r
+       }\r
+       NdisAllocateBuffer( &ndis_status,\r
+                                               &pRdmaDest->p_buf,\r
+                                               pData->h_recv_buf_pool,\r
+                                               pRdmaDest->data + start,\r
+                                               len );\r
+\r
+       if ( ndis_status != NDIS_STATUS_SUCCESS )\r
+       {\r
+               VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+                       ( "NdisAllocateBuffer failed %#x\n", ndis_status ) );\r
+               NdisFreePacket( p_packet );\r
+               return NULL;\r
+       }\r
+\r
+       NdisChainBufferAtFront( p_packet, pRdmaDest->p_buf );\r
+       pRdmaDest->p_packet = p_packet;\r
+\r
+       if ( pTrailer->pktFlags & PF_VLAN_INSERT )\r
+       {\r
+               /*      TODO:\r
+                *      add OID_GEN_VLAN_ID\r
+                *      handle VLAN     tag insertion\r
+                *      set packet header size = eth_hdr + 4\r
+                */\r
+       }\r
+\r
+       NDIS_SET_PACKET_HEADER_SIZE( p_packet, sizeof(eth_hdr_t) );\r
+\r
+       rxChksumFlags = pTrailer->rxChksumFlags;\r
+\r
+       VNIC_TRACE( VNIC_DBG_DATA | VNIC_DBG_INFO,\r
+               ("rxChksumFlags = %d, LOOP = %c, IP = %c, TCP = %c, UDP = %c\n",\r
+               rxChksumFlags,\r
+               (rxChksumFlags & RX_CHKSUM_FLAGS_LOOPBACK)? 'Y': 'N',\r
+               (rxChksumFlags & RX_CHKSUM_FLAGS_IP_CHECKSUM_SUCCEEDED)? 'Y':\r
+               (rxChksumFlags & RX_CHKSUM_FLAGS_IP_CHECKSUM_FAILED)? 'N': '-',\r
+               (rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_SUCCEEDED)? 'Y':\r
+               (rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_FAILED)? 'N': '-',\r
+               (rxChksumFlags & RX_CHKSUM_FLAGS_UDP_CHECKSUM_SUCCEEDED)? 'Y':\r
+               (rxChksumFlags & RX_CHKSUM_FLAGS_UDP_CHECKSUM_FAILED)? 'N': '-') );\r
+\r
+       packet_info.Value = 0;\r
+\r
+       if( rxChksumFlags & RX_CHKSUM_FLAGS_IP_CHECKSUM_SUCCEEDED )\r
+               packet_info.Receive.NdisPacketIpChecksumSucceeded = TRUE;\r
+       else if( rxChksumFlags & RX_CHKSUM_FLAGS_IP_CHECKSUM_FAILED )\r
+               packet_info.Receive.NdisPacketIpChecksumFailed = TRUE;\r
+\r
+       if( rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_SUCCEEDED )\r
+               packet_info.Receive.NdisPacketTcpChecksumSucceeded = TRUE;\r
+       else if( rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_FAILED )\r
+               packet_info.Receive.NdisPacketTcpChecksumFailed = TRUE;\r
+\r
+       if( rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_SUCCEEDED )\r
+               packet_info.Receive.NdisPacketUdpChecksumSucceeded = TRUE;\r
+       else if( rxChksumFlags & RX_CHKSUM_FLAGS_TCP_CHECKSUM_FAILED )\r
+               packet_info.Receive.NdisPacketUdpChecksumFailed = TRUE;\r
+\r
+       NDIS_PER_PACKET_INFO_FROM_PACKET( p_packet, TcpIpChecksumPacketInfo )=\r
+                                                                               (void *)(uintn_t)packet_info.Value;\r
+\r
+       VNIC_RECV_FROM_PACKET( p_packet ) = pRdmaDest;\r
+       NDIS_SET_PACKET_STATUS( p_packet, NDIS_STATUS_SUCCESS );\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+       return p_packet;\r
+}\r
+\r
+/* NOTE: This routine is not reentrant */\r
+static void\r
+_data_allocBuffers(\r
+               IN                      Data_t          *pData,\r
+               IN                      BOOLEAN         initialAllocation )\r
+{\r
+       RecvPool_t     *p_recvPool = &pData->recvPool;\r
+       RdmaDest_t     *pRdmaDest;\r
+       LIST_ENTRY              *p_list_entry;\r
+       int            index;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       index = ADD(p_recvPool->nextFreeBuf, p_recvPool->numFreeBufs, p_recvPool->eiocPoolSz);\r
+\r
+       while ( !IsListEmpty( &p_recvPool->availRecvBufs ) )\r
+       {\r
+               p_list_entry = RemoveHeadList( &p_recvPool->availRecvBufs );\r
+               pRdmaDest       = (RdmaDest_t*)p_list_entry;\r
+       \r
+               if( initialAllocation )\r
+               {\r
+                       pRdmaDest->buf_sz = p_recvPool->bufferSz;\r
+                       pRdmaDest->pTrailer =\r
+                               (struct ViportTrailer*)(pRdmaDest->data + pRdmaDest->buf_sz\r
+                               - sizeof(struct ViportTrailer));\r
+                       pRdmaDest->pTrailer->connectionHashAndValid = 0;\r
+               }\r
+\r
+               pRdmaDest->p_packet = NULL;\r
+               _data_addFreeBuffer(pData, index, pRdmaDest);\r
+               index = NEXT(index,p_recvPool->eiocPoolSz);\r
+       }\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+       return;\r
+}\r
+\r
+static void\r
+_data_addFreeBuffer(\r
+               IN              Data_t                  *pData,\r
+               IN              int                             index,\r
+           IN          RdmaDest_t              *pRdmaDest )\r
+{\r
+       RecvPool_t        *p_recvPool = &pData->recvPool;\r
+       BufferPoolEntry_t *pBpe;\r
+\r
+       pRdmaDest->pTrailer->connectionHashAndValid = 0;\r
+       pBpe = &p_recvPool->bufPool[index];\r
+\r
+       pBpe->rKey       = pRdmaDest->region.rkey;\r
+       pBpe->remoteAddr = hton64( PTR64( pRdmaDest->data ) );\r
+       pBpe->valid      = (uint32_t)(pRdmaDest - &p_recvPool->pRecvBufs[0]) + 1;\r
+       ++p_recvPool->numFreeBufs;\r
+\r
+       return;\r
+}\r
+\r
+static uint32_t\r
+_data_incomingRecv(\r
+               IN              Data_t          *pData )\r
+{\r
+       RecvPool_t        *p_recvPool = &pData->recvPool;\r
+       RdmaDest_t        *pRdmaDest;\r
+       ViportTrailer_t   *pTrailer;\r
+       BufferPoolEntry_t *pBpe;\r
+       NDIS_PACKET             *p_packet = NULL;\r
+       uint32_t                idx = 0;\r
+       BOOLEAN status = FALSE;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       while( !status )\r
+       {\r
+               if ( p_recvPool->nextFullBuf == p_recvPool->nextFreeBuf )\r
+                       return idx;\r
+\r
+               pBpe = &p_recvPool->bufPool[p_recvPool->nextFullBuf];\r
+               pRdmaDest = &p_recvPool->pRecvBufs[pBpe->valid - 1];\r
+               pTrailer = pRdmaDest->pTrailer;\r
+\r
+               if ( ( pTrailer != NULL ) &&\r
+                       ( pTrailer->connectionHashAndValid & CHV_VALID ) )\r
+               {\r
+                       /* received a packet */\r
+                       if ( pTrailer->pktFlags & PF_KICK )\r
+                       {\r
+                               p_recvPool->kickOnFree = TRUE;\r
+                       }\r
+                       /* we do not want to indicate packet if  no filter is set */\r
+                       if( pData->p_viport->p_adapter->packet_filter )\r
+                       {\r
+                               p_packet = _data_recv_to_ndis_pkt( pData, pRdmaDest );\r
+                               if ( p_packet != NULL )\r
+                               {\r
+                                       p_recvPool->recv_pkt_array[idx++] = p_packet;\r
+                               }\r
+                       }\r
+                       else\r
+                       {       /* put back to free buffers pool */\r
+                               InsertTailList( &p_recvPool->availRecvBufs,\r
+                                       &pRdmaDest->listPtrs );\r
+                       }\r
+                       pBpe->valid = 0;\r
+                       INC( p_recvPool->nextFullBuf, 1, p_recvPool->eiocPoolSz );\r
+                       p_recvPool->numPostedBufs--;\r
+#ifdef VNIC_STATISTIC\r
+                       pData->statistics.recvNum++;\r
+#endif /* VNIC_STATISTIC */\r
+               }\r
+               else\r
+                       break;\r
+       }\r
+       return idx;\r
+}\r
+\r
+\r
+void\r
+vnic_return_packet(\r
+       IN              NDIS_HANDLE             adapter_context,\r
+       IN              NDIS_PACKET     * const p_packet )\r
+{\r
+\r
+\r
+       vnic_adapter_t  *p_adapter = (vnic_adapter_t *)adapter_context;\r
+       viport_t        *p_viport = p_adapter->p_currentPath->pViport;\r
+       RdmaDest_t      *p_rdma_dest = VNIC_RECV_FROM_PACKET( p_packet );\r
+\r
+       ASSERT( p_rdma_dest->p_packet == p_packet );\r
+       _data_return_recv( p_packet );\r
+       p_rdma_dest->p_packet = NULL;\r
+\r
+       InsertTailList( &p_viport->data.recvPool.availRecvBufs,\r
+                                       &p_rdma_dest->listPtrs );\r
+\r
+       if( p_viport->data.connected == TRUE )\r
+       {\r
+               _data_allocBuffers( &p_viport->data, FALSE );\r
+               _data_sendFreeRecvBuffers( &p_viport->data );\r
+       }\r
+}\r
+static void\r
+_data_return_recv(\r
+         IN    NDIS_PACKET             *p_packet )\r
+{\r
+       NDIS_BUFFER             *p_buf;\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
+       NdisFreeBuffer( p_buf );\r
+       NdisFreePacket( p_packet );\r
+}\r
+\r
+static void\r
+_data_sendFreeRecvBuffers(\r
+                       IN                      Data_t          *pData )\r
+{\r
+       RecvPool_t  *p_recvPool = &pData->recvPool;\r
+       ib_send_wr_t *pWrq = &pData->freeBufsIo.io.wrq;\r
+       BOOLEAN     bufsSent = FALSE;\r
+       uint64_t    rdmaAddr;\r
+       uint32_t    offset;\r
+       uint32_t    sz;\r
+       unsigned int numToSend,\r
+                   nextIncrement;\r
+\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       for (   numToSend = p_recvPool->szFreeBundle;\r
+                       numToSend <= p_recvPool->numFreeBufs;\r
+                       numToSend += p_recvPool->szFreeBundle )\r
+       {\r
+               /* Handle multiple bundles as one when possible. */\r
+               nextIncrement = numToSend + p_recvPool->szFreeBundle;\r
+               if (    ( nextIncrement <= p_recvPool->numFreeBufs )\r
+                               && ( p_recvPool->nextFreeBuf + nextIncrement <= p_recvPool->eiocPoolSz ) )\r
+               {\r
+                       continue;\r
+               }\r
+\r
+               offset   = p_recvPool->nextFreeBuf * sizeof(BufferPoolEntry_t);\r
+               sz       = numToSend * sizeof(BufferPoolEntry_t);\r
+               rdmaAddr = p_recvPool->eiocRdmaAddr + offset;\r
+       \r
+               //pWrq->MessageLen      = sz;\r
+               pWrq->ds_array->length  = sz;\r
+               pWrq->ds_array->vaddr = PTR64((uint8_t *)p_recvPool->bufPool + offset);\r
+               pWrq->remote_ops.vaddr = rdmaAddr;\r
+\r
+               if ( ibqp_postSend( &pData->qp, &pData->freeBufsIo.io ) != IB_SUCCESS )\r
+               {\r
+                       VNIC_TRACE(VNIC_DBG_ERROR,\r
+                                       ("Unable to rdma free buffers to EIOC\n") );\r
+\r
+                       viport_failure( pData->p_viport );\r
+                       break;\r
+               }\r
+\r
+               INC( p_recvPool->nextFreeBuf, numToSend, p_recvPool->eiocPoolSz );\r
+               p_recvPool->numFreeBufs -= numToSend;\r
+               p_recvPool->numPostedBufs += numToSend;\r
+               bufsSent = TRUE;\r
+       }\r
+\r
+       if( bufsSent )\r
+       {\r
+               if( p_recvPool->kickOnFree )\r
+               {\r
+                       data_sendKickMessage( pData );\r
+               }\r
+       }\r
+       if( p_recvPool->numPostedBufs == 0 )\r
+       {\r
+               VNIC_TRACE( VNIC_DBG_ERROR,\r
+                               ("%s: Unable to allocate receive buffers\n",\r
+                                                       pData->p_viport->p_adapter->name ) );\r
+       \r
+               viport_failure( pData->p_viport );\r
+       }\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+}\r
+\r
+\r
+void\r
+data_cleanup(\r
+       IN                      Data_t  *pData )\r
+{\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       if( pData->recvPool.recv_pkt_array )\r
+       {\r
+               cl_free( pData->recvPool.recv_pkt_array );\r
+               pData->recvPool.recv_pkt_array = NULL;\r
+               pData->recvPool.poolSz = 0;\r
+       }\r
+\r
+       if ( pData->pLocalStorage )\r
+       {\r
+               NdisFreeMemory( pData->pLocalStorage, pData->localStorageSz, 0 );\r
+               pData->pLocalStorage = NULL;\r
+       }\r
+       if(  pData->h_recv_buf_pool )\r
+       {\r
+               NdisFreeBufferPool( pData->h_recv_buf_pool );\r
+               pData->h_recv_buf_pool = NULL;\r
+       }\r
+       if ( pData->h_recv_pkt_pool )\r
+       {\r
+               NdisFreePacketPool( pData->h_recv_pkt_pool );\r
+               pData->h_recv_pkt_pool = NULL;\r
+       }\r
+       // clear Qp struct for reuse\r
+       cl_memclr( &pData->qp, sizeof( IbQp_t) );\r
+\r
+       cl_timer_destroy( &pData->kickTimer );\r
+\r
+       VNIC_EXIT( VNIC_DBG_CTRL );\r
+}\r
+\r
+\r
+static void\r
+_data_kickTimer_start(\r
+                 IN    Data_t          *pData,\r
+                 IN    uint32_t        microseconds )\r
+{\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       InterlockedExchange( (LONG *)&pData->kickTimerOn, TRUE );\r
+\r
+       usec_timer_start(&pData->kickTimer, microseconds );\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+       return;\r
+}\r
+\r
+static void\r
+_data_kickTimer_stop(\r
+                 IN    Data_t          *pData )\r
+{\r
+       VNIC_ENTER( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+\r
+       if( InterlockedExchange( &pData->kickTimerOn, FALSE ) == TRUE )\r
+       {\r
+               cl_timer_stop( &pData->kickTimer );\r
+       }\r
+\r
+       VNIC_EXIT( VNIC_DBG_DATA | VNIC_DBG_INFO );\r
+}\r
diff --git a/ulp/inic/kernel/vnic_data.h b/ulp/inic/kernel/vnic_data.h
new file mode 100644 (file)
index 0000000..1aec7ef
--- /dev/null
@@ -0,0 +1,204 @@
+/*\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$\r
+ */\r
+\r
+#ifndef _VNIC_DATA_H_\r
+#define _VNIC_DATA_H_\r
+\r
+#include "vnic_trailer.h"\r
+\r
+typedef struct RdmaDest {\r
+       LIST_ENTRY                      listPtrs;\r
+       IbRegion_t                      region;\r
+       NDIS_PACKET                     *p_packet;\r
+       NDIS_BUFFER                     *p_buf;\r
+       uint32_t                        buf_sz;\r
+       uint8_t                         *data;\r
+       struct ViportTrailer *pTrailer;\r
+} RdmaDest_t;\r
+\r
+typedef struct BufferPoolEntry {\r
+       uint64_t remoteAddr;\r
+       net32_t  rKey;\r
+       uint32_t valid;\r
+} BufferPoolEntry_t;\r
+\r
+typedef struct RecvPool {\r
+       uint32_t                        bufferSz;\r
+       uint32_t                        poolSz;\r
+       uint32_t                        eiocPoolSz;\r
+       uint32_t                        eiocRdmaRkey;\r
+       uint64_t                        eiocRdmaAddr;\r
+       uint32_t                        nextFullBuf;\r
+       uint32_t                        nextFreeBuf;\r
+       uint32_t                        numFreeBufs;\r
+       uint32_t                        numPostedBufs;\r
+       uint32_t                        szFreeBundle;\r
+       BOOLEAN                 kickOnFree;\r
+       BufferPoolEntry_t       *bufPool;\r
+       RdmaDest_t                      *pRecvBufs;\r
+       LIST_ENTRY                      availRecvBufs;\r
+       NDIS_PACKET                     **recv_pkt_array;\r
+} RecvPool_t;\r
+\r
+typedef struct XmitPool {\r
+       uint32_t                        bufferSz;\r
+       uint32_t                        poolSz;\r
+       uint32_t                        notifyCount;\r
+       uint32_t                        notifyBundle;\r
+       uint32_t                        nextXmitBuf;\r
+       uint32_t                        lastCompBuf;\r
+       uint32_t                        numXmitBufs;\r
+       uint32_t                        nextXmitPool;\r
+       uint32_t                        kickCount;\r
+       uint32_t                        kickByteCount;\r
+       uint32_t                        kickBundle;\r
+       uint32_t                        kickByteBundle;\r
+       BOOLEAN                         needBuffers;\r
+       BOOLEAN                         sendKicks;\r
+       uint32_t                        rdmaRKey;\r
+       uint64_t                        rdmaAddr;\r
+       BufferPoolEntry_t       *bufPool;\r
+       RdmaIo_t                        *pXmitBufs;\r
+} XmitPool_t;\r
+\r
+typedef struct Data {\r
+       struct _viport                  *p_viport;\r
+       DataConfig_t                    *p_conf;\r
+       IbRegion_t                              *p_phy_region;\r
+       IbRegion_t                              region;\r
+       IbRegion_t                              rbuf_region;\r
+       IbQp_t                                  qp;\r
+       uint8_t                                 *pLocalStorage;\r
+       uint32_t                                localStorageSz;\r
+       uint8_t                                 *p_recv_bufs;\r
+       uint32_t                                recv_bufs_sz;\r
+       Inic_RecvPoolConfig_t   hostPoolParms;\r
+       Inic_RecvPoolConfig_t   eiocPoolParms;\r
+       RecvPool_t                              recvPool;\r
+       XmitPool_t                              xmitPool;\r
+       RdmaIo_t                                freeBufsIo;\r
+       SendIo_t                                kickIo;\r
+       LIST_ENTRY                              recvIos;\r
+       KSPIN_LOCK                              recvIosLock;\r
+       KSPIN_LOCK                              xmitBufLock;\r
+       volatile LONG                   kickTimerOn;\r
+       BOOLEAN                                 connected;\r
+       cl_timer_t                              kickTimer;\r
+       NDIS_HANDLE                             h_recv_pkt_pool;\r
+       NDIS_HANDLE                             h_recv_buf_pool;\r
+#ifdef VNIC_STATISTIC\r
+       struct {\r
+               uint32_t                xmitNum;\r
+               uint32_t                recvNum;\r
+               uint32_t                freeBufSends;\r
+               uint32_t                freeBufNum;\r
+               uint32_t                freeBufMin;\r
+               uint32_t                kickRecvs;\r
+               uint32_t                kickReqs;\r
+               uint32_t                noXmitBufs;\r
+               uint64_t                noXmitBufTime;\r
+       } statistics;\r
+#endif /* VNIC_STATISTIC */\r
+} Data_t;\r
+\r
+void\r
+vnic_return_packet(\r
+       IN              NDIS_HANDLE                     adapter_context,\r
+       IN              NDIS_PACKET* const      p_packet );\r
+\r
+void\r
+data_construct(\r
+       IN              Data_t                  *pData,\r
+       IN              struct _viport  *pViport );\r
+\r
+ib_api_status_t\r
+data_init(\r
+               Data_t                  *pData,\r
+               DataConfig_t    *p_conf,\r
+               uint64_t                guid );\r
+\r
+ib_api_status_t\r
+data_connect(\r
+                       Data_t          *pData );\r
+\r
+void\r
+data_connected(\r
+                       Data_t          *pData );\r
+\r
+void\r
+data_disconnect(\r
+                       Data_t          *pData );\r
+\r
+BOOLEAN\r
+data_xmitPacket(\r
+                       Data_t                          *pData,\r
+                       NDIS_PACKET* const      p_pkt );\r
+\r
+void\r
+data_cleanup(\r
+                        Data_t         *pData );\r
+\r
+#define data_pathId(pData) (pData)->p_conf->pathId\r
+#define data_eiocPool(pData) &(pData)->eiocPoolParms\r
+#define data_hostPool(pData) &(pData)->hostPoolParms\r
+#define data_eiocPoolMin(pData) &(pData)->p_conf->eiocMin\r
+#define data_hostPoolMin(pData) &(pData)->p_conf->hostMin\r
+#define data_eiocPoolMax(pData) &(pData)->p_conf->eiocMax\r
+#define data_hostPoolMax(pData) &(pData)->p_conf->hostMax\r
+#define data_localPoolAddr(pData) (pData)->xmitPool.rdmaAddr\r
+#define data_localPoolRkey(pData) (pData)->xmitPool.rdmaRKey\r
+#define data_remotePoolAddr(pData) &(pData)->recvPool.eiocRdmaAddr\r
+#define data_remotePoolRkey(pData) &(pData)->recvPool.eiocRdmaRkey\r
+#define data_maxMtu(pData)  MAX_PAYLOAD(min((pData)->recvPool.bufferSz, (pData)->xmitPool.bufferSz)) - ETH_VLAN_HLEN\r
+#define data_len(pData, pTrailer)  ntoh16(pTrailer->dataLength)\r
+#define data_offset(pData, pTrailer) \\r
+                               pData->recvPool.bufferSz - sizeof(struct ViportTrailer) \\r
+                               - (uint32_t)ROUNDUPP2(data_len(pData, pTrailer), VIPORT_TRAILER_ALIGNMENT) \\r
+                               + pTrailer->dataAlignmentOffset\r
+\r
+\r
+/* The following macros manipulate ring buffer indexes.\r
+ * The ring buffer size must be a power of 2.\r
+ */\r
+#define ADD(index, increment, size) (((index) + (increment))&((size) - 1))\r
+#define NEXT(index, size) ADD(index, 1, size)\r
+#define INC(index, increment, size) (index) = ADD(index, increment, size)\r
+\r
+#define VNIC_RECV_FROM_PACKET( P )     \\r
+       (((RdmaDest_t **)P->MiniportReservedEx)[1])\r
+\r
+#define VNIC_LIST_ITEM_FROM_PACKET( P ) \\r
+               ((cl_list_item_t*)P->MiniportReservedEx)\r
+\r
+#define VNIC_PACKET_FROM_LIST_ITEM( I ) \\r
+               (PARENT_STRUCT( I, NDIS_PACKET, MiniportReservedEx ))\r
+\r
+#endif /* _VNIC_DATA_H_ */
\ No newline at end of file
diff --git a/ulp/inic/kernel/vnic_debug.h b/ulp/inic/kernel/vnic_debug.h
new file mode 100644 (file)
index 0000000..62e7f1d
--- /dev/null
@@ -0,0 +1,106 @@
+/*\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$\r
+ */\r
+\r
+\r
+#ifndef _VNIC_DEBUG_H_\r
+#define _VNIC_DEBUG_H_\r
+\r
+\r
+#include <complib/cl_debug.h>\r
+\r
+/*\r
+ * Debug macros\r
+ */\r
+extern uint32_t                g_vnic_dbg_lvl;\r
+\r
+\r
+#define VNIC_DBG_INIT          (0x00000001)\r
+#define VNIC_DBG_PNP           (0x00000002)\r
+#define VNIC_DBG_SEND          (0x00000004)\r
+#define VNIC_DBG_RECV          (0x00000008)\r
+#define VNIC_DBG_STATUS                (0x00000010)\r
+#define VNIC_DBG_IB                    (0x00000020)\r
+#define VNIC_DBG_BUF           (0x00000040)\r
+#define VNIC_DBG_MCAST         (0x00000080)\r
+#define VNIC_DBG_ALLOC         (0x00000100)\r
+#define VNIC_DBG_OID           (0x00000200)\r
+#define VNIC_DBG_DATA          (0x00000400)\r
+#define VNIC_DBG_CTRL          (0x00000800)\r
+#define VNIC_DBG_CTRL_PKT      (0x00001000) \r
+#define VNIC_DBG_CONF          (0x00002000)\r
+#define VNIC_DBG_VIPORT                (0x00004000)\r
+#define VNIC_DBG_ADAPTER       (0x00008000)\r
+#define VNIC_DBG_NETPATH       (0x00010000)\r
+\r
+#define VNIC_DBG_FUNC          (0x10000000)    /* For function entry/exit */\r
+#define VNIC_DBG_INFO          (0x20000000)    /* For verbose information */\r
+#define VNIC_DBG_WARN          (0x40000000)    /* For warnings. */\r
+#define VNIC_DBG_ERROR         CL_DBG_ERROR\r
+#define VNIC_DBG_ALL           CL_DBG_ALL\r
+\r
+#define VNIC_DEBUG_FLAGS ( VNIC_DBG_ERROR /*| VNIC_DBG_WARN |  VNIC_DBG_INFO | VNIC_DBG_FUNC | VNIC_DBG_OID | VNIC_DBG_VIPORT | VNIC_DBG_CTRL | VNIC_DBG_DATA */)\r
+\r
+/* Enter and exit macros automatically add VNIC_DBG_FUNC bit */\r
+#define VNIC_ENTER( lvl )      \\r
+       CL_ENTER( (lvl | VNIC_DBG_FUNC), g_vnic_dbg_lvl )\r
+\r
+#define VNIC_EXIT( lvl )       \\r
+       CL_EXIT( (lvl | VNIC_DBG_FUNC), g_vnic_dbg_lvl )\r
+\r
+#define VNIC_TRACE( lvl, msg ) \\r
+       CL_TRACE( (lvl), g_vnic_dbg_lvl, msg )\r
+\r
+#define VNIC_TRACE_EXIT( lvl, msg )    \\r
+       CL_TRACE_EXIT( (lvl), g_vnic_dbg_lvl, msg )\r
+\r
+#define VNIC_PRINT( lvl, msg ) \\r
+       CL_PRINT ( (lvl), g_vnic_dbg_lvl, msg )\r
+\r
+#define VNIC_TRACE_BYTES( lvl, ptr, len )                                                                      \\r
+       {                                                                                                                                               \\r
+               size_t _loop_;                                                                                                          \\r
+               for (_loop_ = 0; _loop_ < (len); ++_loop_)                                                      \\r
+               {                                                                                                                                       \\r
+                       CL_PRINT( (lvl), g_vnic_dbg_lvl, ("0x%.2X ", ((uint8_t*)(ptr))[_loop_]));       \\r
+                       if ((_loop_  + 1)% 16 == 0)                                                                                     \\r
+                       {                                                                                                                               \\r
+                               CL_PRINT( (lvl), g_vnic_dbg_lvl, ("\n") );                                      \\r
+                       }                                                                                                                               \\r
+                       else if ((_loop_ % 4 + 1) == 0)                                                                         \\r
+                       {                                                                                                                               \\r
+                               CL_PRINT( (lvl), g_vnic_dbg_lvl, ("  ") );                                      \\r
+                       }                                                                                                                               \\r
+               }                                                                                                                                       \\r
+               CL_PRINT( (lvl), g_vnic_dbg_lvl, ("\n") );                                                      \\r
+       }\r
+\r
+\r
+#endif /* _VNIC_DEBUG_H_ */\r
diff --git a/ulp/inic/kernel/vnic_driver.c b/ulp/inic/kernel/vnic_driver.c
new file mode 100644 (file)
index 0000000..67ecbb9
--- /dev/null
@@ -0,0 +1,1877 @@
+/*\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$\r
+ */\r
+\r
+\r
+\r
+#include <complib/cl_init.h>\r
+#include "vnic_driver.h"\r
+\r
+\r
+vnic_globals_t g_vnic;\r
+\r
+#define DEFAULT_HOST_NAME "VNIC Host"\r
+\r
+//uint32_t g_vnic_dbg_lvl = VNIC_DBG_ERROR | VNIC_DBG_INIT | VNIC_DBG_IB | VNIC_DBG_INFO;\r
+uint32_t g_vnic_dbg_lvl = VNIC_DEBUG_FLAGS;\r
+\r
+static void\r
+_vnic_complete_query(\r
+       IN                              vnic_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
+__vnic_get_tcp_task_offload(\r
+       IN                              vnic_adapter_t*                 p_adapter,\r
+       IN                              pending_oid_t* const            p_oid_info );\r
+\r
+static NDIS_STATUS\r
+__