dapl \\r
ipoib \\r
srp \\r
- wsd\r
+ wsd \\r
+ inic\r
--- /dev/null
+DIRS=\\r
+ kernel\r
--- /dev/null
+########################################################################\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
--- /dev/null
+/*\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
--- /dev/null
+#\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
--- /dev/null
+; 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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+#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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
+__vnic_set_tcp_task_offload(\r
+ IN vnic_adapter_t* p_adapter,\r
+ IN void* const p_info_buf,\r
+ IN ULONG* const p_info_len );\r
+\r
+static NDIS_STATUS\r
+_vnic_process_packet_filter(\r
+ IN vnic_adapter_t* const p_adapter,\r
+ IN ULONG pkt_filter );\r
+\r
+static void\r
+__vnic_read_machine_name( void );\r
+\r
+static NDIS_STATUS\r
+__vnic_set_machine_name(\r
+ IN VOID *p_uni_array,\r
+ IN USHORT buf_size );\r
+\r
+/*\r
+p_drv_obj\r
+ Pointer to Driver Object for this device driver\r
+p_registry_path\r
+ Pointer to unicode string containing path to this driver's registry area\r
+return\r
+ STATUS_SUCCESS, NDIS_STATUS_BAD_CHARACTERISTICS, NDIS_STATUS_BAD_VERSION,\r
+ NDIS_STATUS_RESOURCES, or NDIS_STATUS_FAILURE\r
+IRQL = PASSIVE_LEVEL\r
+*/\r
+NTSTATUS\r
+DriverEntry(\r
+ IN PDRIVER_OBJECT p_drv_obj,\r
+ IN PUNICODE_STRING p_registry_path )\r
+{\r
+ NDIS_STATUS status;\r
+ NDIS_MINIPORT_CHARACTERISTICS characteristics;\r
+\r
+ VNIC_ENTER( VNIC_DBG_INIT );\r
+\r
+#ifdef _DEBUG_\r
+ PAGED_CODE();\r
+#endif\r
+\r
+ status = CL_INIT;\r
+\r
+ if( !NT_SUCCESS( status ) )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("cl_init failed.\n") );\r
+ return status;\r
+ }\r
+\r
+ status = NDIS_STATUS_SUCCESS;\r
+\r
+ KeInitializeSpinLock( &g_vnic.lock );\r
+ InitializeListHead( &g_vnic.adapter_list );\r
+\r
+ g_vnic.adapters = 0;\r
+ g_vnic.ndis_handle = NULL;\r
+\r
+ NdisMInitializeWrapper( &g_vnic.ndis_handle, p_drv_obj, p_registry_path, NULL );\r
+\r
+ if ( g_vnic.ndis_handle == NULL )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("NdisMInitializeWrapper failed\n"));\r
+ CL_DEINIT;\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+\r
+ cl_memclr( &characteristics, sizeof(characteristics) );\r
+\r
+ characteristics.MajorNdisVersion = MAJOR_NDIS_VERSION;\r
+ characteristics.MinorNdisVersion = MINOR_NDIS_VERSION;\r
+ characteristics.CheckForHangHandler = vnic_check_for_hang;\r
+ characteristics.HaltHandler = vnic_halt;\r
+ characteristics.InitializeHandler = vnic_initialize;\r
+ characteristics.QueryInformationHandler = vnic_oid_query_info;\r
+ characteristics.ResetHandler = vnic_reset;\r
+ characteristics.SetInformationHandler = vnic_oid_set_info;\r
+ characteristics.ReturnPacketHandler = vnic_return_packet;\r
+ characteristics.SendPacketsHandler = vnic_send_packets;\r
+\r
+#ifdef NDIS51_MINIPORT\r
+ characteristics.PnPEventNotifyHandler = vnic_pnp_notify;\r
+ characteristics.AdapterShutdownHandler = vnic_shutdown;\r
+#endif\r
+\r
+ status = NdisMRegisterMiniport(\r
+ g_vnic.ndis_handle, &characteristics, sizeof(characteristics) );\r
+\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("NdisMRegisterMiniport failed with status of %d\n", status) );\r
+ NdisTerminateWrapper( g_vnic.ndis_handle, NULL );\r
+ CL_DEINIT;\r
+ }\r
+ else\r
+ {\r
+ NdisMRegisterUnloadHandler( g_vnic.ndis_handle, vnic_unload );\r
+ \r
+ __vnic_read_machine_name();\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_INIT );\r
+ return status;\r
+}\r
+\r
+\r
+VOID\r
+vnic_unload(\r
+ IN PDRIVER_OBJECT p_drv_obj )\r
+{\r
+ VNIC_ENTER( VNIC_DBG_INIT );\r
+\r
+ UNREFERENCED_PARAMETER( p_drv_obj );\r
+ CL_DEINIT;\r
+\r
+ VNIC_EXIT( VNIC_DBG_INIT );\r
+}\r
+\r
+\r
+//! Initialization function called for each IOC discovered\r
+/* The MiniportInitialize function is a required function that sets up a\r
+NIC (or virtual NIC) for network I/O operations, claims all hardware\r
+resources necessary to the NIC in the registry, and allocates resources\r
+the driver needs to carry out network I/O operations.\r
+IRQL = PASSIVE_LEVEL\r
+\r
+@param p_open_status Pointer to a status field set if this function returns NDIS_STATUS_OPEN_ERROR\r
+@param p_selected_medium_index Pointer to unsigned integer noting index into medium_array for this NIC\r
+@param medium_array Array of mediums for this NIC\r
+@param medium_array_size Number of elements in medium_array\r
+@param h_handle Handle assigned by NDIS for this NIC\r
+@param wrapper_config_context Handle used for Ndis initialization functions\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_UNSUPPORTED_MEDIA, NDIS_STATUS_RESOURCES,\r
+NDIS_STATUS_NOT_SUPPORTED\r
+*/\r
+NDIS_STATUS\r
+vnic_initialize(\r
+ OUT PNDIS_STATUS p_open_status,\r
+ OUT PUINT p_selected_medium_index,\r
+ IN PNDIS_MEDIUM medium_array,\r
+ IN UINT medium_array_size,\r
+ IN NDIS_HANDLE h_handle,\r
+ IN NDIS_HANDLE wrapper_config_context )\r
+{\r
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;\r
+ ib_api_status_t ib_status;\r
+ ib_pnp_req_t pnp_req;\r
+ UINT medium_index;\r
+ vnic_adapter_t *p_adapter;\r
+ ULONG buffer_size;\r
+\r
+ VNIC_ENTER( VNIC_DBG_INIT );\r
+\r
+#ifdef _DEBUG_\r
+ PAGED_CODE();\r
+#endif\r
+\r
+ UNUSED_PARAM( p_open_status );\r
+ UNUSED_PARAM( wrapper_config_context );\r
+\r
+ /* Search for our medium */\r
+ for( medium_index = 0; medium_index < medium_array_size; ++medium_index )\r
+ {\r
+ /* Check to see if we found our medium */\r
+ if( medium_array[medium_index] == NdisMedium802_3 )\r
+ break;\r
+ }\r
+\r
+ if( medium_index == medium_array_size ) /* Never found it */\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("No supported media.\n") );\r
+ return NDIS_STATUS_UNSUPPORTED_MEDIA;\r
+ }\r
+\r
+ *p_selected_medium_index = medium_index;\r
+\r
+ /* Create the adapter */\r
+ ib_status = vnic_create_adapter( h_handle, &p_adapter );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("returned status %x\n", ib_status ) );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+\r
+ /* set NDIS features we support */\r
+ NdisMSetAttributesEx( h_handle,\r
+ p_adapter,\r
+ 5, /*check for hung t-out */\r
+ NDIS_ATTRIBUTE_BUS_MASTER |\r
+ NDIS_ATTRIBUTE_DESERIALIZE |\r
+ NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK |\r
+ NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS,\r
+ NdisInterfacePNPBus );\r
+\r
+ buffer_size = sizeof(ViportTrailer_t) +\r
+ ROUNDUPP2(p_adapter->params.MaxMtu + sizeof(eth_hdr_t),VIPORT_TRAILER_ALIGNMENT );\r
+\r
+ status = NdisMInitializeScatterGatherDma( h_handle, TRUE, buffer_size );\r
+ if ( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("Init ScatterGatherDma failed status %#x\n", status ) );\r
+ goto failure;\r
+ }\r
+\r
+ /* Register for IOC events */\r
+ pnp_req.pfn_pnp_cb = __vnic_pnp_cb;\r
+ pnp_req.pnp_class = IB_PNP_IOC | IB_PNP_FLAG_REG_SYNC;\r
+ pnp_req.pnp_context = p_adapter;\r
+\r
+ ib_status = p_adapter->ifc.reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp );\r
+\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("ib_reg_pnp returned %s\n", p_adapter->ifc.get_err_str( ib_status )) );\r
+ status = NDIS_STATUS_FAILURE;\r
+ goto failure;\r
+ }\r
+\r
+ if( p_adapter->state == INIC_UNINITIALIZED )\r
+ {\r
+ status = NDIS_STATUS_FAILURE;\r
+failure:\r
+ vnic_destroy_adapter( p_adapter );\r
+ return status;\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_INIT );\r
+ return status;\r
+\r
+}\r
+\r
+\r
+//! Deallocates resources when the NIC is removed and halts the NIC..\r
+/* IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+*/\r
+void\r
+vnic_halt(\r
+ IN NDIS_HANDLE adapter_context )\r
+{\r
+ vnic_adapter_t *p_adapter;\r
+\r
+ VNIC_ENTER( VNIC_DBG_INIT );\r
+ CL_ASSERT( adapter_context );\r
+\r
+ p_adapter = (vnic_adapter_t*)adapter_context;\r
+\r
+ vnic_destroy_adapter( p_adapter );\r
+\r
+ VNIC_EXIT( VNIC_DBG_INIT );\r
+}\r
+\r
+\r
+//! Reports the state of the NIC, or monitors the responsiveness of an underlying device driver.\r
+/* IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+@return TRUE if the driver determines that its NIC is not operating\r
+*/\r
+BOOLEAN\r
+vnic_check_for_hang(\r
+ IN NDIS_HANDLE adapter_context )\r
+{\r
+ vnic_adapter_t *p_adapter;\r
+\r
+ CL_ASSERT( adapter_context );\r
+ p_adapter = (vnic_adapter_t*)adapter_context;\r
+\r
+ if( p_adapter->p_viport )\r
+ {\r
+ p_adapter->hung =\r
+ (BOOLEAN)( p_adapter->p_viport->errored != 0 );\r
+ }\r
+ if( p_adapter->hung )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_WARN, ("Adapter Hung\n"));\r
+ p_adapter->hung = FALSE;\r
+ return TRUE;\r
+ }\r
+ return FALSE;\r
+}\r
+\r
+\r
+//! Returns information about the capabilities and status of the driver and/or its NIC.\r
+/* IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+@param oid Object ID representing the query operation to be carried out\r
+@param info_buf Buffer containing any input for this query and location for output\r
+@param info_buf_len Number of bytes available in info_buf\r
+@param p_bytes_written Pointer to number of bytes written into info_buf\r
+@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
+NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_NOT_ACCEPTED, NDIS_STATUS_NOT_SUPPORTED,\r
+NDIS_STATUS_RESOURCES\r
+*/\r
+NDIS_STATUS\r
+vnic_oid_query_info(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_OID oid,\r
+ IN PVOID info_buf,\r
+ IN ULONG info_buf_len,\r
+ OUT PULONG p_bytes_written,\r
+ OUT PULONG p_bytes_needed )\r
+{\r
+ vnic_adapter_t *p_adapter;\r
+ NDIS_STATUS status;\r
+ USHORT version;\r
+ uint32_t info32;\r
+ uint64_t info64;\r
+ PVOID src_buf;\r
+ ULONG buf_len;\r
+ pending_oid_t oid_info;\r
+\r
+ VNIC_ENTER( VNIC_DBG_OID );\r
+\r
+ oid_info.oid = oid;\r
+ oid_info.p_buf = info_buf;\r
+ oid_info.buf_len = info_buf_len;\r
+ oid_info.p_bytes_used = p_bytes_written;\r
+ oid_info.p_bytes_needed = p_bytes_needed;\r
+\r
+ CL_ASSERT( adapter_context );\r
+ p_adapter = (vnic_adapter_t *)adapter_context;\r
+\r
+ CL_ASSERT( p_bytes_written );\r
+ CL_ASSERT( p_bytes_needed );\r
+\r
+ status = NDIS_STATUS_SUCCESS;\r
+ src_buf = &info32;\r
+ buf_len = sizeof(info32);\r
+\r
+ switch( oid )\r
+ {\r
+ /* Required General */\r
+ case OID_GEN_SUPPORTED_LIST:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("received query for OID_GEN_SUPPORTED_LIST\n") );\r
+ src_buf = (PVOID)SUPPORTED_OIDS;\r
+ buf_len = sizeof(SUPPORTED_OIDS);\r
+ break;\r
+\r
+ case OID_GEN_HARDWARE_STATUS:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("received query for OID_GEN_HARDWARE_STATUS\n") );\r
+\r
+ if( p_adapter->p_currentPath->carrier )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("returning NdisHardwareStatusReady\n") );\r
+ info32 = NdisHardwareStatusReady;\r
+ }\r
+ else\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("returning NdisHardwareStatusInitializing\n") );\r
+ info32 = NdisHardwareStatusNotReady;\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_MEDIA_SUPPORTED:\r
+ case OID_GEN_MEDIA_IN_USE:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("received query for OID_GEN_MEDIA_SUPPORTED "\r
+ "or OID_GEN_MEDIA_IN_USE\n") );\r
+ info32 = NdisMedium802_3;\r
+ break;\r
+\r
+ case OID_GEN_MAXIMUM_FRAME_SIZE:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("received query for OID_GEN_MAXIMUM_FRAME_SIZE\n") );\r
+ if( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = p_adapter->params.MinMtu;\r
+ }\r
+ else\r
+ {\r
+ info32 = p_adapter->p_currentPath->pViport->mtu;\r
+ /*TODO: add VLAN tag size if support request */\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_LINK_SPEED:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("received query for OID_GEN_LINK_SPEED\n") );\r
+\r
+ if( p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = DEFAULT_LINK_SPEED_x100BPS; /* x 100bps units */\r
+ }\r
+ else\r
+ {\r
+ status = NDIS_STATUS_NOT_ACCEPTED;\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("received query for OID_GEN_TRANSMIT_BUFFER_SPACE\n") );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ p_adapter->pending_query = TRUE;\r
+ p_adapter->query_oid = oid_info;\r
+\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("returning NDIS_STATUS_PENDING\n") );\r
+ status = NDIS_STATUS_PENDING;\r
+ }\r
+ else\r
+ {\r
+ info32 = p_adapter->p_viport->data.xmitPool.bufferSz *\r
+ p_adapter->p_viport->data.xmitPool.poolSz;\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_RECEIVE_BUFFER_SPACE:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("received query for OID_GEN_RECEIVE_BUFFER_SPACE "\r
+ "or OID_GEN_RECEIVE_BUFFER_SPACE\n") );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ p_adapter->pending_query = TRUE;\r
+ p_adapter->query_oid = oid_info;\r
+\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("returning NDIS_STATUS_PENDING\n") );\r
+ status = NDIS_STATUS_PENDING;\r
+ }\r
+ else\r
+ {\r
+ info32 = p_adapter->p_viport->data.recvPool.bufferSz *\r
+ p_adapter->p_viport->data.recvPool.poolSz;\r
+ }\r
+ break;\r
+ case OID_GEN_MAXIMUM_LOOKAHEAD:\r
+ case OID_GEN_CURRENT_LOOKAHEAD:\r
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
+ case OID_GEN_RECEIVE_BLOCK_SIZE:\r
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("received query for OID_GEN_MAXIMUM_LOOKAHEAD "\r
+ "or OID_GEN_CURRENT_LOOKAHEAD or "\r
+ "OID_GEN_TRANSMIT_BLOCK_SIZE or "\r
+ "OID_GEN_RECEIVE_BLOCK_SIZE or "\r
+ "OID_GEN_MAXIMUM_TOTAL_SIZE\n") );\r
+ if( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = p_adapter->params.MinMtu;\r
+ }\r
+ else\r
+ {\r
+ info32 = p_adapter->p_currentPath->pViport->mtu;\r
+ }\r
+ /*TODO: add VLAN tag size if support requested */\r
+ info32 += sizeof(eth_hdr_t);\r
+ break;\r
+\r
+ case OID_GEN_VENDOR_ID:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("received query for OID_GEN_VENDOR_ID\n") );\r
+\r
+ src_buf = (void*)VENDOR_ID;\r
+ buf_len = sizeof(VENDOR_ID);\r
+ break;\r
+\r
+ case OID_GEN_VENDOR_DESCRIPTION:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("received query for OID_GEN_VENDOR_DESCRIPTION\n") );\r
+ src_buf = VENDOR_DESCRIPTION;\r
+ buf_len = sizeof(VENDOR_DESCRIPTION);\r
+ break;\r
+\r
+ case OID_GEN_VENDOR_DRIVER_VERSION:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_VENDOR_DRIVER_VERSION\n" ) );\r
+ src_buf = &version;\r
+ buf_len = sizeof(version);\r
+ //TODO: Figure out what the right version is.\r
+ version = INIC_MAJORVERSION << 8 | INIC_MINORVERSION;\r
+ break;\r
+\r
+ case OID_GEN_PHYSICAL_MEDIUM:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_PHYSICAL_MEDIUM\n" ) );\r
+ info32 = NdisPhysicalMediumUnspecified;\r
+ break;\r
+\r
+ case OID_GEN_CURRENT_PACKET_FILTER:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_CURRENT_PACKET_FILTER\n" ) );\r
+ info32 = p_adapter->packet_filter;\r
+ break;\r
+\r
+ case OID_GEN_DRIVER_VERSION:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_DRIVER_VERSION\n" ) );\r
+ src_buf = &version;\r
+ buf_len = sizeof(version);\r
+ version = MAJOR_NDIS_VERSION << 8 | MINOR_NDIS_VERSION;\r
+ break;\r
+\r
+ case OID_GEN_MAC_OPTIONS:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_MAC_OPTIONS\n" ) );\r
+ info32 = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |\r
+ NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
+ NDIS_MAC_OPTION_NO_LOOPBACK |\r
+ NDIS_MAC_OPTION_FULL_DUPLEX ;\r
+//TODO: Figure out if we will support priority and VLANs.\r
+// NDIS_MAC_OPTION_8021P_PRIORITY;\r
+//#ifdef NDIS51_MINIPORT\r
+// info |= NDIS_MAC_OPTION_8021Q_VLAN;\r
+//#endif\r
+ break;\r
+\r
+ case OID_GEN_MEDIA_CONNECT_STATUS:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_MEDIA_CONNECT_STATUS\n" ) );\r
+\r
+ info32 = ( p_adapter->carrier )?\r
+ NdisMediaStateConnected :\r
+ NdisMediaStateDisconnected;\r
+ break;\r
+\r
+ case OID_GEN_MAXIMUM_SEND_PACKETS:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_MAXIMUM_SEND_PACKETS\n" ) );\r
+ info32 = MAXLONG; // NDIS ignored it anyway\r
+ break;\r
+\r
+ /* Required General Statistics */\r
+ case OID_GEN_XMIT_OK:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_XMIT_OK\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifOutOk;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_RCV_OK:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_RCV_OK\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier)\r
+ {\r
+ info32 = 0;\r
+ break;\r
+ }\r
+ if ( info_buf_len == sizeof(info32) )\r
+ {\r
+ info32 = (uint32_t)p_adapter->p_viport->stats.ifInOk;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifInOk;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_XMIT_ERROR:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_XMIT_ERROR\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifOutErrors;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_RCV_ERROR:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_RCV_ERROR\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifInErrors;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_RCV_NO_BUFFER:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_RCV_NO_BUFFER\n" ) );\r
+ info32 = 0;\r
+ status = NDIS_STATUS_SUCCESS;\r
+ break;\r
+\r
+ case OID_GEN_DIRECTED_BYTES_XMIT:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_DIRECTED_BYTES_XMIT\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifOutUcastBytes;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_DIRECTED_FRAMES_XMIT:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_DIRECTED_FRAMES_XMIT\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifOutNUcastPkts;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_MULTICAST_BYTES_XMIT:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_MULTICAST_BYTES_XMIT\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifOutMulticastBytes;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_MULTICAST_FRAMES_XMIT:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_MULTICAST_FRAMES_XMIT\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifOutMulticastPkts;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_BROADCAST_BYTES_XMIT:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_BROADCAST_BYTES_XMIT\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifOutBroadcastBytes;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_BROADCAST_FRAMES_XMIT:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_BROADCAST_FRAMES_XMIT\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifOutBroadcastPkts;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+ case OID_GEN_DIRECTED_BYTES_RCV:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_DIRECTED_BYTES_RCV\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifInUcastBytes;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_DIRECTED_FRAMES_RCV:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_DIRECTED_FRAMES_RCV\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifInNUcastPkts;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_MULTICAST_BYTES_RCV:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_MULTICAST_BYTES_RCV\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifInMulticastBytes;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_MULTICAST_FRAMES_RCV:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_MULTICAST_FRAMES_RCV\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifInMulticastPkts;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_BROADCAST_BYTES_RCV:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_BROADCAST_BYTES_RCV\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifInBroadcastBytes;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_BROADCAST_FRAMES_RCV:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_GEN_BROADCAST_FRAMES_RCV\n" ) );\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ info32 = 0;\r
+ }\r
+ else\r
+ {\r
+ info64 = p_adapter->p_viport->stats.ifInBroadcastPkts;\r
+ src_buf = &info64;\r
+ buf_len = sizeof(info64);\r
+ }\r
+ break;\r
+\r
+ /* Required Ethernet operational characteristics */\r
+ case OID_802_3_PERMANENT_ADDRESS:\r
+ case OID_802_3_CURRENT_ADDRESS:\r
+#if defined( _DEBUG_ )\r
+ if( oid == OID_802_3_PERMANENT_ADDRESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_802_3_PERMANENT_ADDRESS\n" ) );\r
+ }\r
+ else\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_802_3_CURRENT_ADDRESS\n" ) );\r
+ }\r
+#endif /* defined( _DEBUG_ )*/\r
+ if ( !p_adapter->macSet )\r
+ {\r
+ p_adapter->pending_query = TRUE;\r
+ p_adapter->query_oid = oid_info;\r
+\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("returning NDIS_STATUS_PENDING\n") );\r
+ status = NDIS_STATUS_PENDING;\r
+ }\r
+ else\r
+ {\r
+ src_buf = &p_adapter->p_viport->hwMacAddress;\r
+ buf_len = HW_ADDR_LEN;\r
+ }\r
+ break;\r
+\r
+ case OID_802_3_MULTICAST_LIST:\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ (" received query for OID_802_3_MULTICAST_LIST\n" ) );\r
+ \r
+ if (!p_adapter->p_currentPath->carrier &&\r
+ !(p_adapter->p_viport->flags & INIC_FLAG_ENABLE_NIC) )\r
+ {\r
+ p_adapter->pending_query = TRUE;\r
+ p_adapter->query_oid = oid_info;\r
+\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ ("returning NDIS_STATUS_PENDING\n") );\r
+ status = NDIS_STATUS_PENDING;\r
+ }\r
+ else if ( p_adapter->mc_count > 0 )\r
+ {\r
+ buf_len = p_adapter->mc_count * sizeof( mac_addr_t );\r
+ src_buf = &p_adapter->mcast_array;\r
+ }\r
+ else\r
+ {\r
+ info32 = 0;\r
+ }\r
+ break;\r
+\r
+ case OID_802_3_MAXIMUM_LIST_SIZE:\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ (" received query for OID_802_3_MAXIMUM_LIST_SIZE\n" ) );\r
+ if ( !p_adapter->macSet )\r
+ {\r
+ info32 = MAX_MCAST;\r
+ }\r
+ else\r
+ {\r
+ info32 = p_adapter->p_viport->numMacAddresses - MCAST_ADDR_START;\r
+ }\r
+ break;\r
+ case OID_802_3_MAC_OPTIONS:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_802_3_MAC_OPTIONS\n" ) );\r
+ info32 = 0;\r
+ break;\r
+\r
+ /* Required Ethernet stats */\r
+ case OID_802_3_RCV_ERROR_ALIGNMENT:\r
+ case OID_802_3_XMIT_ONE_COLLISION:\r
+ case OID_802_3_XMIT_MORE_COLLISIONS:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_802_3_RCV_ERROR_ALIGNMENT or "\r
+ "OID_802_3_XMIT_ONE_COLLISION or "\r
+ "OID_802_3_XMIT_MORE_COLLISIONS\n" ) );\r
+ info32 = 0;\r
+ break;\r
+\r
+ case OID_TCP_TASK_OFFLOAD:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received query for OID_TCP_TASK_OFFLOAD\n" ) );\r
+\r
+ src_buf = NULL;\r
+ status = __vnic_get_tcp_task_offload( p_adapter, &oid_info );\r
+ break;\r
+\r
+ /* Optional General */\r
+ case OID_GEN_SUPPORTED_GUIDS:\r
+#ifdef NDIS51_MINIPORT\r
+ case OID_GEN_VLAN_ID:\r
+#endif\r
+\r
+ /* Optional General Stats */\r
+ case OID_GEN_RCV_CRC_ERROR:\r
+ case OID_GEN_TRANSMIT_QUEUE_LENGTH:\r
+\r
+ /* Optional Ethernet Stats */\r
+ case OID_802_3_XMIT_DEFERRED:\r
+ case OID_802_3_XMIT_MAX_COLLISIONS:\r
+ case OID_802_3_RCV_OVERRUN:\r
+ case OID_802_3_XMIT_UNDERRUN:\r
+ case OID_802_3_XMIT_HEARTBEAT_FAILURE:\r
+ case OID_802_3_XMIT_TIMES_CRS_LOST:\r
+ case OID_802_3_XMIT_LATE_COLLISIONS:\r
+ case OID_PNP_CAPABILITIES:\r
+ status = NDIS_STATUS_NOT_SUPPORTED;\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received an unsupported oid of 0x%.8X!\n" , oid) );\r
+ break;\r
+\r
+ case OID_GEN_PROTOCOL_OPTIONS:\r
+ case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
+#ifdef NDIS51_MINIPORT\r
+ case OID_GEN_MACHINE_NAME:\r
+ case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
+#endif\r
+ default:\r
+ status = NDIS_STATUS_INVALID_OID;\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received an invalid oid of 0x%.8X!\n" , oid) );\r
+ break;\r
+ }\r
+\r
+ /*\r
+ * Complete the request as if it was handled asynchronously to maximize\r
+ * code reuse for when we really handle the requests asynchronously.\r
+ * Note that this requires the QueryInformation entry point to always\r
+ * return NDIS_STATUS_PENDING\r
+ */\r
+ if( status != NDIS_STATUS_PENDING )\r
+ {\r
+ _vnic_complete_query(\r
+ p_adapter, &oid_info, status, src_buf, buf_len );\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_OID );\r
+ return NDIS_STATUS_PENDING;\r
+}\r
+\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
+ NDIS_STATUS oid_status = status;\r
+\r
+ VNIC_ENTER( VNIC_DBG_OID );\r
+\r
+ CL_ASSERT( status != NDIS_STATUS_PENDING );\r
+\r
+ if( status == NDIS_STATUS_SUCCESS )\r
+ {\r
+ if( p_oid_info->buf_len < buf_len )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("Insufficient buffer space. "\r
+ "Returning NDIS_STATUS_INVALID_LENGTH.\n") );\r
+ oid_status = NDIS_STATUS_INVALID_LENGTH;\r
+ *p_oid_info->p_bytes_needed = buf_len;\r
+ *p_oid_info->p_bytes_used = 0;\r
+ }\r
+ else if( p_oid_info->p_buf )\r
+ {\r
+ /* Only copy if we have a distinct source buffer. */\r
+ if( p_buf )\r
+ {\r
+ NdisMoveMemory( p_oid_info->p_buf, p_buf, buf_len );\r
+ *p_oid_info->p_bytes_used = buf_len;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("Returning NDIS_NOT_ACCEPTED") );\r
+ oid_status = NDIS_STATUS_NOT_ACCEPTED;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ *p_oid_info->p_bytes_used = 0;\r
+ }\r
+\r
+ p_adapter->pending_query = FALSE;\r
+\r
+ NdisMQueryInformationComplete( p_adapter->h_handle, oid_status );\r
+\r
+ VNIC_EXIT( VNIC_DBG_OID );\r
+}\r
+\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
+ NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr;\r
+ NDIS_TASK_OFFLOAD *p_offload_task;\r
+ NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum;\r
+ //uint8_t port_num;\r
+ ULONG buf_len;\r
+\r
+ buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
+ sizeof(NDIS_TASK_OFFLOAD) +\r
+ sizeof(NDIS_TASK_TCP_IP_CHECKSUM) - 1;\r
+\r
+ *(p_oid_info->p_bytes_needed) = buf_len;\r
+\r
+ if( p_oid_info->buf_len < buf_len )\r
+ return NDIS_STATUS_INVALID_LENGTH;\r
+\r
+ p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_oid_info->p_buf;\r
+ if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
+ return NDIS_STATUS_INVALID_DATA;\r
+\r
+ if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
+ IEEE_802_3_Encapsulation )\r
+ {\r
+ return NDIS_STATUS_INVALID_DATA;\r
+ }\r
+\r
+ p_offload_hdr->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER);\r
+ p_offload_task = (NDIS_TASK_OFFLOAD*)(p_offload_hdr + 1);\r
+ p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;\r
+ p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);\r
+ p_offload_task->Task = TcpIpChecksumNdisTask;\r
+ p_offload_task->OffsetNextTask = 0;\r
+ p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);\r
+ p_offload_chksum =\r
+ (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
+\r
+ p_offload_chksum->V4Transmit.IpOptionsSupported =\r
+ p_adapter->params.UseTxCsum;\r
+ p_offload_chksum->V4Transmit.TcpOptionsSupported =\r
+ p_adapter->params.UseTxCsum;\r
+ p_offload_chksum->V4Transmit.TcpChecksum =\r
+ p_adapter->params.UseTxCsum;\r
+ p_offload_chksum->V4Transmit.UdpChecksum =\r
+ p_adapter->params.UseTxCsum;\r
+ p_offload_chksum->V4Transmit.IpChecksum =\r
+ p_adapter->params.UseTxCsum;\r
+\r
+ p_offload_chksum->V4Receive.IpOptionsSupported = TRUE;\r
+ p_offload_chksum->V4Receive.TcpOptionsSupported = TRUE;\r
+ p_offload_chksum->V4Receive.TcpChecksum =\r
+ p_adapter->params.UseRxCsum;\r
+ p_offload_chksum->V4Receive.UdpChecksum =\r
+ p_adapter->params.UseRxCsum;\r
+ p_offload_chksum->V4Receive.IpChecksum =\r
+ p_adapter->params.UseRxCsum;\r
+\r
+ p_offload_chksum->V6Transmit.IpOptionsSupported = FALSE;\r
+ p_offload_chksum->V6Transmit.TcpOptionsSupported = FALSE;\r
+ p_offload_chksum->V6Transmit.TcpChecksum = FALSE;\r
+ p_offload_chksum->V6Transmit.UdpChecksum = FALSE;\r
+\r
+ p_offload_chksum->V6Receive.IpOptionsSupported = FALSE;\r
+ p_offload_chksum->V6Receive.TcpOptionsSupported = FALSE;\r
+ p_offload_chksum->V6Receive.TcpChecksum = FALSE;\r
+ p_offload_chksum->V6Receive.UdpChecksum = FALSE;\r
+\r
+ *(p_oid_info->p_bytes_used) = buf_len;\r
+\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+static NDIS_STATUS\r
+__vnic_set_tcp_task_offload(\r
+ IN vnic_adapter_t* p_adapter,\r
+ IN void* const p_info_buf,\r
+ IN ULONG* const p_info_len )\r
+{\r
+ NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr;\r
+ NDIS_TASK_OFFLOAD *p_offload_task;\r
+ NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum;\r
+\r
+ VNIC_ENTER( VNIC_DBG_OID );\r
+\r
+ p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_info_buf;\r
+\r
+ if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
+ return NDIS_STATUS_INVALID_LENGTH;\r
+\r
+ if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
+ return NDIS_STATUS_INVALID_DATA;\r
+\r
+ if( p_offload_hdr->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
+ return NDIS_STATUS_INVALID_LENGTH;\r
+\r
+ if( !p_offload_hdr->OffsetFirstTask )\r
+ return NDIS_STATUS_SUCCESS;\r
+\r
+ if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
+ IEEE_802_3_Encapsulation )\r
+ {\r
+ return NDIS_STATUS_INVALID_DATA;\r
+ }\r
+\r
+ p_offload_task = (NDIS_TASK_OFFLOAD*)\r
+ (((UCHAR*)p_offload_hdr) + p_offload_hdr->OffsetFirstTask);\r
+\r
+ if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
+ offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +\r
+ sizeof(NDIS_TASK_TCP_IP_CHECKSUM) )\r
+ {\r
+ return NDIS_STATUS_INVALID_LENGTH;\r
+ }\r
+\r
+ if( p_offload_task->Version != NDIS_TASK_OFFLOAD_VERSION )\r
+ return NDIS_STATUS_INVALID_DATA;\r
+ p_offload_chksum =\r
+ (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
+\r
+ if( !p_adapter->params.UseTxCsum &&\r
+ (p_offload_chksum->V4Transmit.IpOptionsSupported ||\r
+ p_offload_chksum->V4Transmit.TcpOptionsSupported ||\r
+ p_offload_chksum->V4Transmit.TcpChecksum ||\r
+ p_offload_chksum->V4Transmit.UdpChecksum ||\r
+ p_offload_chksum->V4Transmit.IpChecksum) )\r
+ {\r
+ return NDIS_STATUS_NOT_SUPPORTED;\r
+ }\r
+\r
+ if( !p_adapter->params.UseRxCsum &&\r
+ (p_offload_chksum->V4Receive.IpOptionsSupported ||\r
+ p_offload_chksum->V4Receive.TcpOptionsSupported ||\r
+ p_offload_chksum->V4Receive.TcpChecksum ||\r
+ p_offload_chksum->V4Receive.UdpChecksum ||\r
+ p_offload_chksum->V4Receive.IpChecksum) )\r
+ {\r
+ return NDIS_STATUS_NOT_SUPPORTED;\r
+ }\r
+ if( p_offload_chksum->V6Receive.IpOptionsSupported ||\r
+ p_offload_chksum->V6Receive.TcpOptionsSupported ||\r
+ p_offload_chksum->V6Receive.TcpChecksum ||\r
+ p_offload_chksum->V6Receive.UdpChecksum ||\r
+ p_offload_chksum->V6Transmit.IpOptionsSupported ||\r
+ p_offload_chksum->V6Transmit.TcpOptionsSupported ||\r
+ p_offload_chksum->V6Transmit.TcpChecksum ||\r
+ p_offload_chksum->V6Transmit.UdpChecksum )\r
+ {\r
+ return NDIS_STATUS_NOT_SUPPORTED;\r
+ }\r
+ VNIC_EXIT( VNIC_DBG_OID );\r
+\r
+ return NDIS_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+//! Issues a hardware reset to the NIC and/or resets the driver's software state.\r
+/* Tear down the connection and start over again. This is only called when there is a problem.\r
+For example, if a send, query info, or set info had a time out. MiniportCheckForHang will\r
+be called first.\r
+IRQL = DISPATCH_LEVEL\r
+\r
+@param p_addr_resetPointer to BOOLLEAN that is set to TRUE if the NDIS\r
+library should call MiniportSetInformation to restore addressing information to the current values.\r
+@param adapter_context The adapter context allocated at start\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_NOT_RESETTABLE,\r
+NDIS_STATUS_RESET_IN_PROGRESS, NDIS_STATUS_SOFT_ERRORS, NDIS_STATUS_HARD_ERRORS\r
+*/\r
+NDIS_STATUS\r
+vnic_reset(\r
+ OUT PBOOLEAN p_addr_reset,\r
+ IN NDIS_HANDLE adapter_context)\r
+{\r
+// vnic_adapter_t* p_adapter;\r
+\r
+ VNIC_ENTER( VNIC_DBG_INIT );\r
+ CL_ASSERT( p_addr_reset );\r
+ CL_ASSERT( adapter_context );\r
+ //p_adapter = (vnic_adapter_t*)adapter_context;\r
+ *p_addr_reset = TRUE;\r
+\r
+ UNREFERENCED_PARAMETER( adapter_context );\r
+\r
+ VNIC_EXIT( VNIC_DBG_INIT );\r
+ return NDIS_STATUS_NOT_RESETTABLE;\r
+}\r
+\r
+\r
+//! Request changes in the state information that the miniport driver maintains\r
+/* For example, this is used to set multicast addresses and the packet filter.\r
+IRQL = DISPATCH_LEVEL\r
+\r
+@param adapter_context The adapter context allocated at start\r
+@param oid Object ID representing the set operation to be carried out\r
+@param info_buf Buffer containing input for this set and location for any output\r
+@param info_buf_len Number of bytes available in info_buf\r
+@param p_bytes_read Pointer to number of bytes read from info_buf\r
+@param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
+@return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
+NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_INVALID_DATA, NDIS_STATUS_NOT_ACCEPTED,\r
+NDIS_STATUS_NOT_SUPPORTED, NDIS_STATUS_RESOURCES\r
+*/\r
+NDIS_STATUS\r
+vnic_oid_set_info(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_OID oid,\r
+ IN PVOID info_buf,\r
+ IN ULONG info_buf_len,\r
+ OUT PULONG p_bytes_read,\r
+ OUT PULONG p_bytes_needed )\r
+{\r
+ vnic_adapter_t* p_adapter;\r
+ NDIS_STATUS status;\r
+ ULONG buf_len;\r
+ pending_oid_t oid_info;\r
+\r
+ VNIC_ENTER( VNIC_DBG_OID );\r
+\r
+ CL_ASSERT( adapter_context );\r
+ p_adapter = (vnic_adapter_t*)adapter_context;\r
+\r
+ CL_ASSERT( p_bytes_read );\r
+ CL_ASSERT( p_bytes_needed );\r
+ CL_ASSERT( !p_adapter->pending_set );\r
+\r
+ status = NDIS_STATUS_SUCCESS;\r
+ *p_bytes_needed = 0;\r
+ buf_len = sizeof(ULONG);\r
+\r
+ oid_info.oid = oid;\r
+ oid_info.p_buf = info_buf;\r
+ oid_info.buf_len = info_buf_len;\r
+ oid_info.p_bytes_used = p_bytes_read;\r
+ oid_info.p_bytes_needed = p_bytes_needed;\r
+\r
+ /* do not set anything until IB path initialized and NIC is enabled */\r
+ if( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ *p_bytes_read = 0;\r
+ return NDIS_STATUS_NOT_ACCEPTED;\r
+ }\r
+\r
+ switch( oid )\r
+ {\r
+ /* Required General */\r
+ case OID_GEN_CURRENT_PACKET_FILTER:\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ (" received set for OID_GEN_CURRENT_PACKET_FILTER, %#x\n", *(uint32_t*)info_buf ));\r
+ if ( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ status = NDIS_STATUS_NOT_ACCEPTED;\r
+ break;\r
+ }\r
+ if( info_buf_len < sizeof( p_adapter->packet_filter ) )\r
+ {\r
+ status = NDIS_STATUS_INVALID_LENGTH;\r
+ }\r
+ else if( !info_buf )\r
+ {\r
+ status = NDIS_STATUS_INVALID_DATA;\r
+ }\r
+ else\r
+ {\r
+ p_adapter->set_oid = oid_info;\r
+ status = _vnic_process_packet_filter( p_adapter, *((uint32_t*)info_buf) );\r
+ }\r
+ break;\r
+\r
+ case OID_GEN_CURRENT_LOOKAHEAD:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received set for OID_GEN_CURRENT_LOOKAHEAD\n" ));\r
+ if( info_buf_len < buf_len )\r
+ status = NDIS_STATUS_INVALID_LENGTH;\r
+ break;\r
+\r
+ case OID_GEN_PROTOCOL_OPTIONS:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received set for OID_GEN_PROTOCOL_OPTIONS\n" ));\r
+ if( info_buf_len < buf_len )\r
+ status = NDIS_STATUS_INVALID_LENGTH;\r
+ break;\r
+\r
+#ifdef NDIS51_MINIPORT\r
+ case OID_GEN_MACHINE_NAME:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received set for OID_GEN_MACHINE_NAME\n" ) );\r
+ if( info_buf_len < buf_len )\r
+ status = NDIS_STATUS_INVALID_LENGTH;\r
+ // else\r
+ // status = __vnic_set_machine_name( info_buf,\r
+ // (USHORT)info_buf_len );\r
+ break;\r
+#endif\r
+\r
+ /* Required Ethernet operational characteristics */\r
+ case OID_802_3_MULTICAST_LIST:\r
+ if( !p_adapter->p_currentPath->carrier )\r
+ {\r
+ status = NDIS_STATUS_NOT_ACCEPTED;\r
+ break;\r
+ }\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ (" received set for OID_802_3_MULTICAST_LIST\n" ) );\r
+ if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ (" OID_802_3_MULTICAST_LIST - Multicast list full.\n" ) );\r
+ status = NDIS_STATUS_MULTICAST_FULL;\r
+ *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t);\r
+ }\r
+ else if( info_buf_len % sizeof(mac_addr_t) )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ (" OID_802_3_MULTICAST_LIST - Invalid input buffer length.\n" ) );\r
+ status = NDIS_STATUS_INVALID_DATA;\r
+ }\r
+ else if( info_buf == NULL && info_buf_len != 0 )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" OID_802_3_MULTICAST_LIST - Invalid input buffer.\n" ) );\r
+ status = NDIS_STATUS_INVALID_DATA;\r
+ }\r
+ else\r
+ {\r
+ p_adapter->set_oid = oid_info;\r
+ status = vnic_set_mcast( p_adapter, (mac_addr_t*)info_buf,\r
+ (uint8_t)(info_buf_len / sizeof(mac_addr_t)) );\r
+ }\r
+ break;\r
+\r
+ case OID_TCP_TASK_OFFLOAD:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received set for OID_TCP_TASK_OFFLOAD\n" ) );\r
+ buf_len = info_buf_len;\r
+ status = __vnic_set_tcp_task_offload( p_adapter, info_buf, &buf_len );\r
+ break;\r
+\r
+ /* Optional General */\r
+ case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ ("Set for OID_GEN_TRANSPORT_HEADER_OFFSET\n") );\r
+ break;\r
+#ifdef NDIS51_MINIPORT\r
+ case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
+ case OID_GEN_VLAN_ID:\r
+#endif\r
+ status = NDIS_STATUS_NOT_SUPPORTED;\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received an unsupported oid of 0x%.8X!\n" , oid));\r
+ break;\r
+\r
+ case OID_GEN_SUPPORTED_LIST:\r
+ case OID_GEN_HARDWARE_STATUS:\r
+ case OID_GEN_MEDIA_SUPPORTED:\r
+ case OID_GEN_MEDIA_IN_USE:\r
+ case OID_GEN_MAXIMUM_FRAME_SIZE:\r
+ case OID_GEN_LINK_SPEED:\r
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
+ case OID_GEN_RECEIVE_BUFFER_SPACE:\r
+ case OID_GEN_MAXIMUM_LOOKAHEAD:\r
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
+ case OID_GEN_RECEIVE_BLOCK_SIZE:\r
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
+ case OID_GEN_VENDOR_ID:\r
+ case OID_GEN_VENDOR_DESCRIPTION:\r
+ case OID_GEN_VENDOR_DRIVER_VERSION:\r
+ case OID_GEN_DRIVER_VERSION:\r
+ case OID_GEN_MAC_OPTIONS:\r
+ case OID_GEN_MEDIA_CONNECT_STATUS:\r
+ case OID_GEN_MAXIMUM_SEND_PACKETS:\r
+ case OID_GEN_SUPPORTED_GUIDS:\r
+ case OID_GEN_PHYSICAL_MEDIUM:\r
+ default:\r
+ status = NDIS_STATUS_INVALID_OID;\r
+ VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
+ (" received an invalid oid of 0x%.8X!\n" , oid));\r
+ break;\r
+ }\r
+\r
+ if( status == NDIS_STATUS_SUCCESS )\r
+ {\r
+ *p_bytes_read = buf_len;\r
+ }\r
+ else\r
+ {\r
+ if( status == NDIS_STATUS_INVALID_LENGTH )\r
+ {\r
+ if ( !*p_bytes_needed )\r
+ {\r
+ *p_bytes_needed = buf_len;\r
+ }\r
+ }\r
+\r
+ *p_bytes_read = 0;\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_OID );\r
+ return status;\r
+}\r
+\r
+\r
+//! Transfers some number of packets, specified as an array of packet pointers, over the network.\r
+/* For a deserialized driver, these packets are completed asynchronously\r
+using NdisMSendComplete.\r
+IRQL <= DISPATCH_LEVEL\r
+\r
+@param adapter_context Pointer to vnic_adapter_t structure with per NIC state\r
+@param packet_array Array of packets to send\r
+@param numPackets Number of packets in the array\r
+*/\r
+void\r
+vnic_send_packets(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN PPNDIS_PACKET packet_array,\r
+ IN UINT num_packets )\r
+{\r
+ vnic_adapter_t *p_adapter;\r
+ viport_t *p_viport;\r
+ UINT packet_num;\r
+\r
+ VNIC_ENTER( VNIC_DBG_SEND );\r
+\r
+ CL_ASSERT( adapter_context );\r
+\r
+ p_adapter = (vnic_adapter_t*)adapter_context;\r
+ p_viport = p_adapter->p_viport;\r
+\r
+ NdisAcquireSpinLock( &p_adapter->lock );\r
+\r
+ if( !p_adapter->carrier )\r
+ {\r
+ NdisReleaseSpinLock( &p_adapter->lock );\r
+ for( packet_num = 0; packet_num < num_packets; ++packet_num )\r
+ {\r
+ NdisMSendComplete( p_adapter->h_handle,\r
+ packet_array[packet_num], NDIS_STATUS_ADAPTER_NOT_READY );\r
+ }\r
+ VNIC_EXIT( VNIC_DBG_SEND );\r
+ return;\r
+ }\r
+ NdisReleaseSpinLock( &p_adapter->lock );\r
+\r
+ for( packet_num = 0; packet_num < num_packets; ++packet_num )\r
+ {\r
+ netpath_xmitPacket( p_adapter->p_currentPath,\r
+ packet_array[packet_num] );\r
+ }\r
+ VNIC_EXIT( VNIC_DBG_SEND );\r
+}\r
+\r
+void\r
+vnic_pnp_notify(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_DEVICE_PNP_EVENT pnp_event,\r
+ IN PVOID info_buf,\r
+ IN ULONG info_buf_len )\r
+{\r
+ vnic_adapter_t *p_adapter;\r
+\r
+ VNIC_ENTER( VNIC_DBG_PNP );\r
+\r
+ UNUSED_PARAM( info_buf );\r
+ UNUSED_PARAM( info_buf_len );\r
+\r
+ p_adapter = (vnic_adapter_t*)adapter_context;\r
+\r
+ VNIC_TRACE( VNIC_DBG_PNP, ("Event %d\n", pnp_event) );\r
+ if( pnp_event != NdisDevicePnPEventPowerProfileChanged )\r
+ {\r
+ InterlockedExchange( (volatile LONG *)&p_adapter->pnp_state, IB_PNP_IOC_REMOVE );\r
+ vnic_resume_oids( p_adapter );\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_PNP );\r
+}\r
+\r
+\r
+void\r
+vnic_shutdown(\r
+ IN PVOID adapter_context )\r
+{\r
+ VNIC_ENTER( VNIC_DBG_INIT );\r
+\r
+ UNUSED_PARAM( adapter_context );\r
+\r
+ VNIC_EXIT( VNIC_DBG_INIT );\r
+}\r
+\r
+\r
+void\r
+vnic_resume_set_oids(\r
+ IN vnic_adapter_t* const p_adapter )\r
+{\r
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;\r
+ BOOLEAN pending_set;\r
+ pending_oid_t set_oid = {0};\r
+\r
+ VNIC_ENTER( VNIC_DBG_OID );\r
+\r
+ NdisAcquireSpinLock( &p_adapter->lock );\r
+ /*\r
+ * Set the status depending on our state. Fail OID requests that\r
+ * are pending while we reset the adapter.\r
+ */\r
+ switch( p_adapter->pnp_state )\r
+ {\r
+ case IB_PNP_IOC_ADD:\r
+ break;\r
+\r
+ case IB_PNP_IOC_REMOVE:\r
+ default:\r
+ status = NDIS_STATUS_NOT_ACCEPTED;\r
+ break;\r
+ }\r
+\r
+ pending_set = p_adapter->pending_set;\r
+ if( pending_set )\r
+ {\r
+ set_oid = p_adapter->set_oid;\r
+ p_adapter->pending_set = FALSE;\r
+ }\r
+ NdisReleaseSpinLock( &p_adapter->lock );\r
+\r
+ ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL );\r
+\r
+ if( pending_set )\r
+ {\r
+ switch( set_oid.oid )\r
+ {\r
+ case OID_GEN_CURRENT_PACKET_FILTER:\r
+ /* Validation already performed in the SetInformation path. */\r
+ p_adapter->packet_filter = *(PULONG)set_oid.p_buf;\r
+ NdisMSetInformationComplete( p_adapter->h_handle, status );\r
+ break;\r
+\r
+ case OID_GEN_MACHINE_NAME:\r
+ status = __vnic_set_machine_name ( p_adapter->set_oid.p_buf, (USHORT)p_adapter->set_oid.buf_len );\r
+ NdisMSetInformationComplete( p_adapter->h_handle, status );\r
+ break;\r
+\r
+ case OID_802_3_MULTICAST_LIST:\r
+ NdisMSetInformationComplete( p_adapter->h_handle, status );\r
+ break;\r
+\r
+ default:\r
+ CL_ASSERT( set_oid.oid && 0 );\r
+ break;\r
+ }\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_OID );\r
+}\r
+\r
+\r
+void\r
+vnic_resume_oids(\r
+ IN vnic_adapter_t* const p_adapter )\r
+{\r
+ ULONG info;\r
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;\r
+ BOOLEAN pending_query;\r
+ pending_oid_t query_oid = {0};\r
+ KIRQL irql;\r
+\r
+ uint8_t mac[HW_ADDR_LEN];\r
+\r
+ VNIC_ENTER( VNIC_DBG_OID );\r
+\r
+ NdisAcquireSpinLock( &p_adapter->lock );\r
+ /*\r
+ * Set the status depending on our state. Fail OID requests that\r
+ * are pending while we reset the adapter.\r
+ */\r
+ switch( p_adapter->pnp_state )\r
+ {\r
+ case IB_PNP_IOC_ADD:\r
+ break;\r
+\r
+ case IB_PNP_IOC_REMOVE:\r
+ default:\r
+ status = NDIS_STATUS_NOT_ACCEPTED;\r
+ break;\r
+ }\r
+\r
+ pending_query = p_adapter->pending_query;\r
+\r
+ if( pending_query )\r
+ {\r
+ query_oid = p_adapter->query_oid;\r
+ p_adapter->pending_query = FALSE;\r
+ }\r
+ NdisReleaseSpinLock( &p_adapter->lock );\r
+\r
+ KeRaiseIrql( DISPATCH_LEVEL, &irql );\r
+\r
+ /*\r
+ * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
+ * complete it now. Note that we hold the object lock since\r
+ * NdisMQueryInformationComplete is called at DISPATCH_LEVEL.\r
+ */\r
+ if( pending_query )\r
+ {\r
+ switch( query_oid.oid )\r
+ {\r
+ case OID_802_3_CURRENT_ADDRESS:\r
+ case OID_802_3_PERMANENT_ADDRESS:\r
+ cl_memcpy( mac, p_adapter->p_viport->hwMacAddress, HW_ADDR_LEN );\r
+ _vnic_complete_query( p_adapter,\r
+ &query_oid,\r
+ status,\r
+ mac,\r
+ HW_ADDR_LEN );\r
+ break;\r
+ case OID_GEN_LINK_SPEED:\r
+ info = DEFAULT_LINK_SPEED_x100BPS;\r
+ _vnic_complete_query( p_adapter,\r
+ &query_oid,\r
+ status,\r
+ &info,\r
+ sizeof( info ) );\r
+ break;\r
+\r
+ case OID_GEN_MEDIA_CONNECT_STATUS:\r
+ info = ( p_adapter->carrier )? NdisMediaStateConnected :\r
+ NdisMediaStateDisconnected;\r
+ _vnic_complete_query( p_adapter,\r
+ &query_oid,\r
+ status,\r
+ &info,\r
+ sizeof( info ) );\r
+ break;\r
+ case OID_802_3_MULTICAST_LIST:\r
+ ASSERT( p_adapter->p_viport );\r
+ _vnic_complete_query( p_adapter,\r
+ &query_oid,\r
+ status,\r
+ &p_adapter->p_viport->macAddresses[MCAST_ADDR_START],\r
+ (p_adapter->p_viport->numMacAddresses -\r
+ MCAST_ADDR_START) * sizeof( mac_addr_t ) );\r
+ break;\r
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
+ info = p_adapter->p_viport->data.xmitPool.bufferSz *\r
+ p_adapter->p_viport->data.xmitPool.numXmitBufs;\r
+ _vnic_complete_query( p_adapter,\r
+ &query_oid,\r
+ status,\r
+ &info,\r
+ sizeof( info ) );\r
+ break;\r
+ case OID_GEN_RECEIVE_BUFFER_SPACE:\r
+ info = p_adapter->p_viport->data.recvPool.bufferSz *\r
+ p_adapter->p_viport->data.recvPool.poolSz;\r
+ _vnic_complete_query( p_adapter,\r
+ &query_oid,\r
+ status,\r
+ &info,\r
+ sizeof( info ) );\r
+ break;\r
+ default:\r
+ CL_ASSERT( query_oid.oid == OID_GEN_LINK_SPEED ||\r
+ query_oid.oid == OID_GEN_MEDIA_CONNECT_STATUS ||\r
+ query_oid.oid == OID_802_3_MULTICAST_LIST ||\r
+ query_oid.oid == OID_802_3_CURRENT_ADDRESS ||\r
+ query_oid.oid == OID_802_3_PERMANENT_ADDRESS ||\r
+ query_oid.oid == OID_GEN_RECEIVE_BUFFER_SPACE ||\r
+ query_oid.oid == OID_GEN_TRANSMIT_BUFFER_SPACE );\r
+ break;\r
+ }\r
+ }\r
+\r
+ vnic_resume_set_oids( p_adapter );\r
+\r
+ KeLowerIrql( irql );\r
+\r
+ VNIC_EXIT( VNIC_DBG_OID );\r
+}\r
+\r
+static NDIS_STATUS\r
+__vnic_set_machine_name(\r
+ IN VOID *p_uni_array,\r
+ IN USHORT buf_size )\r
+{\r
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;\r
+ uint8_t *p_src_buf = (uint8_t *)p_uni_array;\r
+ int i;\r
+\r
+ VNIC_ENTER( VNIC_DBG_OID );\r
+\r
+ cl_memclr(g_vnic.host_name, 65 );\r
+ for( i = 0; i < ( buf_size >1 ); i++ )\r
+ {\r
+ g_vnic.host_name[i] = *(p_src_buf + i*2);\r
+ }\r
+\r
+ return status;\r
+}\r
+\r
+static void\r
+__vnic_read_machine_name( void )\r
+{\r
+ /* this code is borrowed from the bus_driver */\r
+\r
+ NTSTATUS nt_status;\r
+ /* Remember the terminating entry in the table below. */\r
+ RTL_QUERY_REGISTRY_TABLE table[2];\r
+ UNICODE_STRING hostNamePath;\r
+ UNICODE_STRING hostNameW;\r
+ ANSI_STRING hostName;\r
+\r
+ VNIC_ENTER( VNIC_DBG_INIT );\r
+\r
+ /* Get the host name. */\r
+ RtlInitUnicodeString( &hostNamePath, L"ComputerName\\ComputerName" );\r
+ RtlInitUnicodeString( &hostNameW, NULL );\r
+\r
+ /*\r
+ * Clear the table. This clears all the query callback pointers,\r
+ * and sets up the terminating table entry.\r
+ */\r
+ cl_memclr( table, sizeof(table) );\r
+\r
+ /* Setup the table entries. */\r
+ table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;\r
+ table[0].Name = L"ComputerName";\r
+ table[0].EntryContext = &hostNameW;\r
+ table[0].DefaultType = REG_SZ;\r
+ table[0].DefaultData = &hostNameW;\r
+ table[0].DefaultLength = 0;\r
+\r
+ /* Have at it! */\r
+ nt_status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL,\r
+ hostNamePath.Buffer, table, NULL, NULL );\r
+ if( NT_SUCCESS( nt_status ) )\r
+ {\r
+ /* Convert the UNICODE host name to UTF-8 (ASCII). */\r
+ hostName.Length = 0;\r
+ hostName.MaximumLength = sizeof(g_vnic.host_name) - 1;\r
+ hostName.Buffer = (PCHAR)g_vnic.host_name;\r
+ nt_status = RtlUnicodeStringToAnsiString( &hostName, &hostNameW, FALSE );\r
+ RtlFreeUnicodeString( &hostNameW );\r
+ }\r
+ else\r
+ {\r
+ VNIC_TRACE(VNIC_DBG_ERROR , ("Failed to get host name from registry\n") );\r
+ /* Use the default name... */\r
+ cl_memcpy( g_vnic.host_name,\r
+ DEFAULT_HOST_NAME,\r
+ min (sizeof( g_vnic.host_name), sizeof(DEFAULT_HOST_NAME) ) );\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_INIT );\r
+}\r
+\r
+/* function: usec_timer_start\r
+ uses cl_timer* functionality (init/destroy/stop/start )\r
+ except it takes expiration time parameter in microseconds.\r
+*/\r
+cl_status_t\r
+usec_timer_start(\r
+ IN cl_timer_t* const p_timer,\r
+ IN const uint32_t time_usec )\r
+{\r
+ LARGE_INTEGER due_time;\r
+\r
+ CL_ASSERT( p_timer );\r
+ CL_ASSERT( p_timer->pfn_callback );\r
+ CL_ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL );\r
+\r
+ /* Due time is in 100 ns increments. Negative for relative time. */\r
+ due_time.QuadPart = -(int64_t)(((uint64_t)time_usec) * 10);\r
+\r
+ /* Store the timeout time in the timer object. in microseconds */\r
+ p_timer->timeout_time = cl_get_time_stamp() + (((uint64_t)time_usec));\r
+\r
+ KeSetTimer( &p_timer->timer, due_time, &p_timer->dpc );\r
+ return( CL_SUCCESS );\r
+}\r
+\r
+\r
+static NDIS_STATUS\r
+_vnic_process_packet_filter(\r
+ IN vnic_adapter_t* const p_adapter,\r
+ IN ULONG pkt_filter )\r
+{\r
+ NDIS_STATUS status;\r
+\r
+ VNIC_ENTER(VNIC_DBG_FUNC );\r
+\r
+ ASSERT( p_adapter );\r
+ ASSERT( p_adapter->p_viport );\r
+ ASSERT( !(p_adapter->p_viport->updates & SYNC_QUERY) );\r
+\r
+ InterlockedExchange((volatile LONG*)&p_adapter->packet_filter, pkt_filter );\r
+\r
+ ASSERT( (p_adapter->p_viport->updates & ~MCAST_OVERFLOW) == 0 );\r
+\r
+ if( pkt_filter & NDIS_PACKET_TYPE_ALL_MULTICAST )\r
+ {\r
+ if( !p_adapter->p_viport->flags & INIC_FLAG_ENABLE_MCAST_ALL )\r
+ {\r
+ p_adapter->p_viport->newFlags |= INIC_FLAG_ENABLE_MCAST_ALL;\r
+ // TODO: Shouldn't MCAST_OVERFLOW be a flag bit, not an update bit?\r
+ InterlockedOr( &p_adapter->p_viport->updates,\r
+ NEED_LINK_CONFIG | MCAST_OVERFLOW );\r
+ }\r
+ }\r
+ if ( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS )\r
+ {\r
+ if( !p_adapter->p_viport->flags & INIC_FLAG_ENABLE_PROMISC )\r
+ {\r
+ p_adapter->p_viport->newFlags |= INIC_FLAG_ENABLE_PROMISC;\r
+ InterlockedOr( &p_adapter->p_viport->updates, NEED_LINK_CONFIG );\r
+ }\r
+ }\r
+ /* BROADCAST and MULTICAST flags VEx enable by default */\r
+ p_adapter->pending_set = TRUE;\r
+ status = _viport_process_query( p_adapter->p_viport, FALSE );\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ ("LINK CONFIG status %x\n", status ));\r
+ if( status != NDIS_STATUS_PENDING )\r
+ p_adapter->pending_set = FALSE;\r
+\r
+ VNIC_EXIT( VNIC_DBG_FUNC );\r
+ return status;\r
+}\r
+\r
--- /dev/null
+/*\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_DRIVER_H_\r
+#define _VNIC_DRIVER_H_\r
+\r
+#include "vnic_adapter.h"\r
+#include "vnic_debug.h"\r
+\r
+\r
+#if defined(NDIS50_MINIPORT)\r
+#define MAJOR_NDIS_VERSION 5\r
+#define MINOR_NDIS_VERSION 0\r
+#elif defined (NDIS51_MINIPORT)\r
+#define MAJOR_NDIS_VERSION 5\r
+#define MINOR_NDIS_VERSION 1\r
+#else\r
+#error NDIS Version not defined, try defining NDIS50_MINIPORT or NDIS51_MINIPORT\r
+#endif\r
+\r
+#include <ndis.h>\r
+\r
+static const NDIS_OID SUPPORTED_OIDS[] =\r
+{\r
+ OID_GEN_SUPPORTED_LIST,\r
+ OID_GEN_HARDWARE_STATUS,\r
+ OID_GEN_MEDIA_SUPPORTED,\r
+ OID_GEN_MEDIA_IN_USE,\r
+ OID_GEN_MAXIMUM_LOOKAHEAD,\r
+ OID_GEN_MAXIMUM_FRAME_SIZE,\r
+ OID_GEN_LINK_SPEED,\r
+ OID_GEN_TRANSMIT_BUFFER_SPACE,\r
+ OID_GEN_RECEIVE_BUFFER_SPACE,\r
+ OID_GEN_TRANSMIT_BLOCK_SIZE,\r
+ OID_GEN_RECEIVE_BLOCK_SIZE,\r
+ OID_GEN_VENDOR_ID,\r
+ OID_GEN_VENDOR_DESCRIPTION,\r
+ OID_GEN_CURRENT_PACKET_FILTER,\r
+ OID_GEN_CURRENT_LOOKAHEAD,\r
+ OID_GEN_DRIVER_VERSION,\r
+ OID_GEN_MAXIMUM_TOTAL_SIZE,\r
+ OID_GEN_PROTOCOL_OPTIONS, // ?\r
+ OID_GEN_MAC_OPTIONS,\r
+ OID_GEN_MEDIA_CONNECT_STATUS,\r
+ OID_GEN_MAXIMUM_SEND_PACKETS,\r
+ OID_GEN_VENDOR_DRIVER_VERSION,\r
+ OID_GEN_PHYSICAL_MEDIUM,\r
+ OID_GEN_XMIT_OK,\r
+ OID_GEN_RCV_OK,\r
+ OID_GEN_XMIT_ERROR,\r
+ OID_GEN_RCV_ERROR,\r
+ OID_GEN_RCV_NO_BUFFER,\r
+ OID_GEN_DIRECTED_BYTES_XMIT,\r
+ OID_GEN_DIRECTED_FRAMES_XMIT,\r
+ OID_GEN_MULTICAST_BYTES_XMIT,\r
+ OID_GEN_MULTICAST_FRAMES_XMIT,\r
+ OID_GEN_BROADCAST_BYTES_XMIT,\r
+ OID_GEN_BROADCAST_FRAMES_XMIT,\r
+ OID_GEN_DIRECTED_BYTES_RCV,\r
+ OID_GEN_DIRECTED_FRAMES_RCV,\r
+ OID_GEN_MULTICAST_BYTES_RCV,\r
+ OID_GEN_MULTICAST_FRAMES_RCV,\r
+ OID_GEN_BROADCAST_BYTES_RCV,\r
+ OID_GEN_BROADCAST_FRAMES_RCV,\r
+ OID_802_3_PERMANENT_ADDRESS,\r
+ OID_802_3_CURRENT_ADDRESS,\r
+ OID_802_3_MULTICAST_LIST,\r
+ OID_802_3_MAXIMUM_LIST_SIZE,\r
+ OID_802_3_MAC_OPTIONS,\r
+ OID_802_3_RCV_ERROR_ALIGNMENT,\r
+ OID_802_3_XMIT_ONE_COLLISION,\r
+ OID_802_3_XMIT_MORE_COLLISIONS,\r
+ OID_TCP_TASK_OFFLOAD\r
+};\r
+\r
+static const unsigned char VENDOR_ID[] = {0x00, 0x06, 0x6A, 0x00};\r
+#define VENDOR_DESCRIPTION "Virtual Ethernet over InfiniBand"\r
+#define DEFAULT_VNIC_NAME "VNIC"\r
+\r
+NTSTATUS\r
+DriverEntry(\r
+ IN PDRIVER_OBJECT p_drv_obj,\r
+ IN PUNICODE_STRING p_reg_path );\r
+\r
+VOID\r
+vnic_unload(\r
+ IN PDRIVER_OBJECT p_drv_obj );\r
+\r
+NDIS_STATUS\r
+vnic_initialize(\r
+ OUT PNDIS_STATUS p_open_err_status,\r
+ OUT PUINT p_selected_medium_index,\r
+ IN PNDIS_MEDIUM medium_array,\r
+ IN UINT medium_array_size,\r
+ IN NDIS_HANDLE h_handle,\r
+ IN NDIS_HANDLE wrapper_configuration_context );\r
+\r
+BOOLEAN\r
+vnic_check_for_hang(\r
+ IN NDIS_HANDLE adapter_context );\r
+\r
+void\r
+vnic_halt(\r
+ IN NDIS_HANDLE adapter_context );\r
+\r
+NDIS_STATUS\r
+vnic_oid_query_info(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_OID oid,\r
+ IN PVOID info_buf,\r
+ IN ULONG info_buf_len,\r
+ OUT PULONG p_bytes_written,\r
+ OUT PULONG p_bytes_needed );\r
+\r
+NDIS_STATUS\r
+vnic_reset(\r
+ OUT PBOOLEAN p_addressing_reset,\r
+ IN NDIS_HANDLE adapter_context );\r
+\r
+NDIS_STATUS\r
+vnic_oid_set_info(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_OID oid,\r
+ IN PVOID info_buf,\r
+ IN ULONG info_buf_length,\r
+ OUT PULONG p_bytes_read,\r
+ OUT PULONG p_bytes_needed );\r
+\r
+void\r
+vnic_send_packets(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN PPNDIS_PACKET packet_array,\r
+ IN UINT num_packets );\r
+\r
+void\r
+vnic_pnp_notify(\r
+ IN NDIS_HANDLE adapter_context,\r
+ IN NDIS_DEVICE_PNP_EVENT pnp_event,\r
+ IN PVOID info_buf,\r
+ IN ULONG info_buf_len );\r
+\r
+void\r
+vnic_shutdown(\r
+ IN PVOID adapter_context );\r
+\r
+NDIS_STATUS\r
+vnic_get_agapter_interface(\r
+ IN NDIS_HANDLE h_handle,\r
+ IN vnic_adapter_t *p_adapter);\r
+\r
+\r
+/* same as cl_timer_start() except it takes timeout param in usec */\r
+/* need to run kicktimer */\r
+cl_status_t \r
+usec_timer_start(\r
+ IN cl_timer_t* const p_timer,\r
+ IN const uint32_t time_usec );\r
+\r
+#endif /* _VNIC_DRIVER_H_ */
\ No newline at end of file
--- /dev/null
+/*\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 "vnic_adapter.h"\r
+#include "vnic_util.h"\r
+\r
+#ifndef max_t\r
+#define max_t(type,x,y) \\r
+ ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })\r
+#endif\r
+\r
+\r
+static int inicIbInited = 0;\r
+\r
+extern struct _vnic_globals g_vnic;\r
+\r
+void\r
+ib_asyncEvent(\r
+ ib_async_event_rec_t *pEventRecord );\r
+\r
+static void\r
+_ib_qpCompletion(\r
+ IN IbQp_t *pQp);\r
+static void\r
+_ibqp_connect_cb(\r
+ IN ib_cm_rep_rec_t *p_cm_rep );\r
+\r
+static void\r
+_ibqp_detach_cb(\r
+ IN ib_cm_drep_rec_t *p_drep_rec );\r
+\r
+static void\r
+_ibqp_dreq_cb(\r
+ IN ib_cm_dreq_rec_t *p_dreq_rec );\r
+\r
+static void\r
+_ibqp_mra_cb(\r
+ IN ib_cm_mra_rec_t *p_mra_rec );\r
+\r
+static void\r
+_ibqp_rej_cb(\r
+ IN ib_cm_rej_rec_t *p_rej_rec );\r
+static\r
+void ib_workCompletion(\r
+ IN ib_cq_handle_t h_cq,\r
+ IN void *cqContext );\r
+\r
+\r
+uint8_t\r
+ibca_findPortNum(\r
+ struct _viport *p_viport,\r
+ uint64_t guid )\r
+{\r
+ uint8_t port;\r
+\r
+ for (port = 0; port < p_viport->p_adapter->ca.numPorts; port++ )\r
+ {\r
+ if (p_viport->p_adapter->ca.portGuids[port] == guid )\r
+ {\r
+ return port+1;\r
+ }\r
+ }\r
+ return 0;\r
+}\r
+\r
+ib_api_status_t\r
+ibregion_physInit(\r
+ IN struct _vnic_adapter* p_adapter,\r
+ IN IbRegion_t *pRegion,\r
+ IN ib_pd_handle_t hPd,\r
+ IN uint64_t *p_vaddr,\r
+ IN uint64_t len )\r
+{\r
+ ib_phys_create_t phys_mem;\r
+ ib_phys_range_t phys_range;\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+ uint64_t vaddr = 0;\r
+ VNIC_ENTER ( VNIC_DBG_IB );\r
+\r
+ UNUSED_PARAM( p_vaddr );\r
+\r
+ phys_range.base_addr = *(p_vaddr);\r
+ phys_range.size = len;\r
+ phys_mem.access_ctrl = ( IB_AC_LOCAL_WRITE | IB_AC_RDMA_WRITE );\r
+ phys_mem.buf_offset = 0;\r
+ phys_mem.hca_page_size = PAGE_SIZE;\r
+ phys_mem.length = len;\r
+ phys_mem.num_ranges = 1;\r
+ phys_mem.range_array = &phys_range;\r
+\r
+ ib_status = p_adapter->ifc.reg_phys( hPd,\r
+ &phys_mem,\r
+ &vaddr,\r
+ &pRegion->lkey,\r
+ &pRegion->rkey,\r
+ &pRegion->h_mr );\r
+\r
+ if ( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("ib_reg_phys failed status %s(%d)\n",\r
+ p_adapter->ifc.get_err_str(ib_status), ib_status ) );\r
+ pRegion->h_mr = NULL;\r
+ }\r
+ pRegion->virtAddress = vaddr;\r
+ pRegion->len = len;\r
+\r
+ VNIC_EXIT( VNIC_DBG_IB );\r
+ return ib_status;\r
+}\r
+\r
+ib_api_status_t\r
+ibregion_init (\r
+ IN viport_t *p_viport,\r
+ IN OUT IbRegion_t *pRegion,\r
+ IN ib_pd_handle_t hPd,\r
+ IN void* __ptr64 vaddr,\r
+ IN uint64_t len,\r
+ IN ib_access_t access_ctrl )\r
+{\r
+ ib_api_status_t ib_status;\r
+ ib_mr_create_t create_mem;\r
+\r
+ VNIC_ENTER ( VNIC_DBG_IB );\r
+\r
+ create_mem.length = len;\r
+ create_mem.vaddr = vaddr;\r
+ create_mem.access_ctrl = access_ctrl;\r
+\r
+ ib_status = p_viport->p_adapter->ifc.reg_mem( hPd,\r
+ &create_mem,\r
+ &pRegion->lkey,\r
+ &pRegion->rkey,\r
+ &pRegion->h_mr );\r
+ if ( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("ib_reg_mem failed status %s(%d)\n",\r
+ p_viport->p_adapter->ifc.get_err_str( ib_status ), ib_status ));\r
+ pRegion->h_mr = NULL;\r
+ }\r
+ else\r
+ {\r
+ pRegion->len = len;\r
+ pRegion->virtAddress = (uint64_t)( vaddr );\r
+ }\r
+ VNIC_EXIT ( VNIC_DBG_IB );\r
+ return ib_status;\r
+}\r
+\r
+void\r
+ibregion_cleanup(\r
+ IN viport_t *p_viport,\r
+ IN IbRegion_t *pRegion )\r
+{\r
+ void *mr_handle;\r
+ ib_api_status_t ib_status;\r
+\r
+ VNIC_ENTER( VNIC_DBG_IB );\r
+\r
+ if( ( mr_handle = InterlockedExchangePointer( (void *)&pRegion->h_mr, NULL )) != NULL )\r
+ {\r
+ ib_status = p_viport->p_adapter->ifc.dereg_mr( (ib_mr_handle_t)mr_handle );\r
+ if ( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("Dereg MR failed status %s(%d)\n",\r
+ p_viport->p_adapter->ifc.get_err_str(ib_status), ib_status ) );\r
+ return;\r
+ }\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_IB );\r
+}\r
+\r
+\r
+void\r
+ibqp_construct(\r
+ IN OUT IbQp_t *pQp,\r
+ IN viport_t *pViport )\r
+{\r
+ VNIC_ENTER ( VNIC_DBG_IB );\r
+\r
+ ASSERT( pQp->qpState == IB_UNINITTED );\r
+\r
+ pQp->qp = NULL;\r
+ pQp->cq = NULL;\r
+ pQp->pViport = pViport;\r
+ pQp->pCa = &pViport->p_adapter->ca;\r
+\r
+ NdisAllocateSpinLock( &pQp->qpLock );\r
+\r
+ InitializeListHead( &pQp->listPtrs);\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ibqp_init(\r
+ IN OUT IbQp_t *pQp,\r
+ IN uint64_t guid,\r
+ IN IbConfig_t *p_conf )\r
+{\r
+ ib_qp_create_t attribCreate;\r
+ ib_qp_mod_t attribMod;\r
+ ib_qp_attr_t qpAttribs;\r
+\r
+ ib_cq_create_t cq_create;\r
+ ib_cq_handle_t h_cq;\r
+\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+\r
+ VNIC_ENTER ( VNIC_DBG_IB );\r
+\r
+ if (pQp->qpState != IB_UNINITTED && pQp->qpState != IB_DETACHED )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("ibqp_init: out of state (%d)\n", pQp->qpState) );\r
+ return IB_ERROR;\r
+ }\r
+\r
+ InterlockedExchange( &pQp->qpState, IB_UNINITTED );\r
+\r
+ pQp->p_conf = p_conf;\r
+\r
+ cq_create.size = p_conf->numSends + p_conf->numRecvs;\r
+ cq_create.pfn_comp_cb = ib_workCompletion;\r
+ cq_create.h_wait_obj = NULL;\r
+\r
+ ib_status = pQp->pViport->p_adapter->ifc.create_cq(\r
+ pQp->pViport->p_adapter->h_ca, &cq_create, pQp, NULL, &h_cq );\r
+\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("Failed allocating completion queue\n") );\r
+ goto err1;\r
+ }\r
+\r
+ pQp->cq = h_cq;\r
+\r
+ cl_memclr( &attribCreate, sizeof(attribCreate) );\r
+\r
+ attribCreate.qp_type = IB_QPT_RELIABLE_CONN;\r
+ attribCreate.sq_depth = p_conf->numSends;\r
+ attribCreate.rq_depth = p_conf->numRecvs;\r
+ attribCreate.sq_sge = p_conf->sendGather;\r
+ attribCreate.rq_sge = p_conf->recvScatter;\r
+ attribCreate.h_sq_cq = pQp->cq;\r
+ attribCreate.h_rq_cq = pQp->cq;\r
+ attribCreate.sq_signaled = FALSE;\r
+\r
+ ib_status = pQp->pViport->p_adapter->ifc.create_qp(\r
+ pQp->pViport->p_adapter->ca.hPd, &attribCreate, pQp, NULL, &pQp->qp );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_IB, ("Create QP failed %s\n",\r
+ pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
+ goto err2;\r
+ }\r
+ ib_status = pQp->pViport->p_adapter->ifc.query_qp(pQp->qp, &qpAttribs);\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR, ("Query QP failed %s\n",\r
+ pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
+ goto err3;\r
+ }\r
+ pQp->qpNumber = qpAttribs.num;\r
+ pQp->portGuid = guid;\r
+ cl_memclr( &attribMod, sizeof(attribMod) );\r
+\r
+ attribMod.req_state = IB_QPS_INIT;\r
+ attribMod.state.init.primary_port = ibca_findPortNum( pQp->pViport, guid );\r
+ attribMod.state.init.pkey_index = 0;\r
+ attribMod.state.init.access_ctrl = IB_AC_LOCAL_WRITE;\r
+ attribMod.state.init.access_ctrl |= (p_conf->sendGather > 1) ? IB_AC_RDMA_WRITE : 0;\r
+\r
+ ib_status = pQp->pViport->p_adapter->ifc.modify_qp( pQp->qp, &attribMod );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_IB, ("Init QP failed %s\n",\r
+ pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
+\r
+err3:\r
+ pQp->pViport->p_adapter->ifc.destroy_qp( pQp->qp, NULL );\r
+err2:\r
+ pQp->pViport->p_adapter->ifc.destroy_cq( pQp->cq, NULL );\r
+ }\r
+ else\r
+ {\r
+ InterlockedExchange( &pQp->qpState, IB_INITTED );\r
+ }\r
+\r
+err1:\r
+ VNIC_EXIT ( VNIC_DBG_IB );\r
+ return ib_status;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ibqp_connect(\r
+ IN IbQp_t *pQp)\r
+{\r
+ IbCa_t *pCa;\r
+ viport_t *p_viport;\r
+ IbConfig_t *p_conf;\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+ ib_cm_req_t conn_req;\r
+\r
+ VNIC_ENTER( VNIC_DBG_IB );\r
+\r
+ if ( pQp->qpState != IB_INITTED )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_IB,\r
+ ("ibqp_connect: out of state (%d)\n",pQp->qpState) );\r
+ return IB_INVALID_STATE;\r
+ }\r
+\r
+ p_viport = pQp->pViport;\r
+ pCa = pQp->pCa;\r
+ p_conf = pQp->p_conf;\r
+\r
+#ifdef VNIC_STATISTIC\r
+ pQp->statistics.connectionTime = cl_get_time_stamp();\r
+#endif\r
+\r
+ cl_memclr( &conn_req, sizeof(conn_req));\r
+\r
+ conn_req.h_al = p_viport->p_adapter->h_al;\r
+ conn_req.qp_type = IB_QPT_RELIABLE_CONN;\r
+ conn_req.h_qp = pQp->qp;\r
+ conn_req.p_req_pdata = (uint8_t*)&pQp->p_conf->connData;\r
+ conn_req.req_length = sizeof( Inic_ConnectionData_t );\r
+ conn_req.svc_id = pQp->p_conf->sid;\r
+ conn_req.pkey = pQp->p_conf->pathInfo.pkey;\r
+\r
+ conn_req.p_primary_path = &pQp->p_conf->pathInfo;\r
+\r
+ conn_req.retry_cnt = (uint8_t)pQp->p_conf->retryCount;\r
+ conn_req.rnr_nak_timeout = pQp->p_conf->minRnrTimer;\r
+ conn_req.rnr_retry_cnt = (uint8_t)pQp->p_conf->rnrRetryCount;\r
+ conn_req.max_cm_retries = 5;\r
+ conn_req.remote_resp_timeout = ib_path_rec_pkt_life( &pQp->p_conf->pathInfo ) + 1;\r
+ conn_req.local_resp_timeout = ib_path_rec_pkt_life( &pQp->p_conf->pathInfo ) + 1;\r
+\r
+ conn_req.compare_length = 0;\r
+ conn_req.resp_res = 0;\r
+\r
+ conn_req.flow_ctrl = TRUE;\r
+ \r
+ conn_req.pfn_cm_req_cb = NULL;\r
+ conn_req.pfn_cm_rep_cb = _ibqp_connect_cb;\r
+ conn_req.pfn_cm_mra_cb = _ibqp_mra_cb;\r
+ conn_req.pfn_cm_rej_cb = _ibqp_rej_cb;\r
+\r
+ InterlockedExchange( &pQp->qpState, IB_ATTACHING );\r
+\r
+ ib_status = p_viport->p_adapter->ifc.cm_req ( &conn_req );\r
+ if ( ib_status != IB_SUCCESS && ib_status != IB_PENDING )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("Connect request return status %s\n",\r
+ p_viport->p_adapter->ifc.get_err_str( ib_status )) );\r
+ InterlockedExchange( &pQp->qpState, IB_DETACHED );\r
+ return ib_status;\r
+ }\r
+\r
+ if( cl_event_wait_on(\r
+ &p_viport->conn_event, EVENT_NO_TIMEOUT, FALSE ) != CL_SUCCESS )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("conn event timeout!\n") );\r
+ return IB_TIMEOUT;\r
+ }\r
+\r
+ if( pQp->qpState != IB_ATTACHED )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR, ("QP connect failed\n") );\r
+ ib_status = IB_ERROR;\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_IB );\r
+ return ib_status;\r
+}\r
+\r
+\r
+static void\r
+_ibqp_detach_cb(\r
+ IN ib_cm_drep_rec_t *p_drep_rec )\r
+{\r
+ IbQp_t *pQp = (IbQp_t * __ptr64 )p_drep_rec->qp_context;\r
+ VNIC_ENTER( VNIC_DBG_IB );\r
+ CL_ASSERT( p_drep_rec );\r
+\r
+ InterlockedExchange( &pQp->qpState, IB_DETACHED );\r
+\r
+ VNIC_EXIT( VNIC_DBG_IB );\r
+}\r
+\r
+static void\r
+_ibqp_rej_cb(\r
+ IN ib_cm_rej_rec_t *p_rej_rec )\r
+{\r
+ IbQp_t *pQp = (IbQp_t * __ptr64 )p_rej_rec->qp_context;\r
+ CL_ASSERT(p_rej_rec );\r
+\r
+ InterlockedExchange( &pQp->qpState, IB_DETACHED );\r
+ switch ( p_rej_rec->rej_status )\r
+ {\r
+ case IB_REJ_USER_DEFINED:\r
+ \r
+ VNIC_TRACE ( VNIC_DBG_IB | VNIC_DBG_ERROR,\r
+ ("Conn req user reject status %d\nARI: %s\n",\r
+ cl_ntoh16( p_rej_rec->rej_status ),\r
+ p_rej_rec->p_ari ));\r
+ break;\r
+ default:\r
+ VNIC_TRACE( VNIC_DBG_IB | VNIC_DBG_ERROR,\r
+ ("Conn req reject status %d\n",\r
+ cl_ntoh16( p_rej_rec->rej_status )) );\r
+ }\r
+ viport_failure( pQp->pViport );\r
+ cl_event_signal( &pQp->pViport->conn_event );\r
+}\r
+\r
+static void\r
+_ibqp_mra_cb(\r
+ IN ib_cm_mra_rec_t *p_mra_rec )\r
+{\r
+ VNIC_ENTER( VNIC_DBG_IB );\r
+ CL_ASSERT( p_mra_rec );\r
+ UNREFERENCED_PARAMETER( p_mra_rec );\r
+ VNIC_EXIT( VNIC_DBG_IB );\r
+}\r
+\r
+static void\r
+_ibqp_dreq_cb(\r
+ IN ib_cm_dreq_rec_t *p_dreq_rec )\r
+{\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+ ib_cm_drep_t cm_drep;\r
+ IbQp_t *pQp = (IbQp_t * __ptr64 )p_dreq_rec->qp_context;\r
+\r
+ VNIC_ENTER( VNIC_DBG_IB );\r
+ CL_ASSERT( p_dreq_rec );\r
+\r
+ cm_drep.drep_length = 0;\r
+ cm_drep.p_drep_pdata = NULL;\r
+\r
+ ib_status = pQp->pViport->p_adapter->ifc.cm_drep(\r
+ p_dreq_rec->h_cm_dreq, &cm_drep );\r
+ if ( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("dreq_cb failed status %s(%d)\n",\r
+ pQp->pViport->p_adapter->ifc.get_err_str( ib_status ), ib_status));\r
+ return;\r
+ }\r
+\r
+ InterlockedExchange (&pQp->qpState, IB_DETACHED );\r
+\r
+ VNIC_EXIT( VNIC_DBG_IB );\r
+}\r
+\r
+void\r
+ibqp_detach(\r
+ IN IbQp_t *pQp )\r
+{\r
+ ib_cm_dreq_t cm_dreq;\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+\r
+ VNIC_ENTER( VNIC_DBG_IB );\r
+\r
+ NdisAcquireSpinLock( &pQp->qpLock );\r
+\r
+ if( pQp->qpState == IB_ATTACHED )\r
+ {\r
+ InterlockedExchange ( &pQp->qpState, IB_DETACHING );\r
+\r
+ cm_dreq.h_qp = pQp->qp;\r
+ cm_dreq.qp_type = IB_QPT_RELIABLE_CONN;\r
+ cm_dreq.p_dreq_pdata = NULL;\r
+ cm_dreq.dreq_length = 0;\r
+ cm_dreq.pfn_cm_drep_cb = _ibqp_detach_cb;\r
+ ib_status = pQp->pViport->p_adapter->ifc.cm_dreq( &cm_dreq );\r
+ if ( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ (" cm_dreq failed status %s\n",\r
+ pQp->pViport->p_adapter->ifc.get_err_str( ib_status )));\r
+ }\r
+ ib_status = pQp->pViport->p_adapter->ifc.destroy_qp( pQp->qp, NULL );\r
+ }\r
+ NdisReleaseSpinLock( &pQp->qpLock );\r
+\r
+ VNIC_EXIT( VNIC_DBG_IB );\r
+ return;\r
+}\r
+\r
+void\r
+ibqp_cleanup(\r
+ IN IbQp_t *pQp )\r
+{\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+ LONG qp_state;\r
+\r
+ VNIC_ENTER( VNIC_DBG_IB );\r
+\r
+ qp_state = InterlockedExchange( &pQp->qpState, IB_UNINITTED );\r
+ if ( qp_state != IB_UNINITTED &&\r
+ qp_state != IB_DETACHED &&\r
+ qp_state != IB_DETACHING )\r
+ {\r
+ ib_status = pQp->pViport->p_adapter->ifc.destroy_qp( pQp->qp, NULL );\r
+ if ( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("destroy_qp failed status %s\n",\r
+ pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
+ }\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_IB );\r
+ return;\r
+}\r
+\r
+ib_api_status_t ibqp_postSend(IbQp_t *pQp, Io_t *pIo)\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+#ifdef VNIC_STATISTIC\r
+ int64_t postTime;\r
+#endif /* VNIC_STATISTIC */\r
+\r
+ VNIC_ENTER( VNIC_DBG_IB );\r
+\r
+ NdisAcquireSpinLock( &pQp->qpLock );\r
+\r
+ if( pQp->qpState != IB_ATTACHED )\r
+ {\r
+ ib_status = IB_INVALID_STATE;\r
+ goto failure;\r
+ }\r
+\r
+#ifdef VNIC_STATISTIC\r
+ pIo->time = postTime = cl_get_time_stamp();\r
+#endif /* VNIC_STATISTIC */\r
+ if (pIo->wrq.wr_type == WR_RDMA_WRITE )\r
+ pIo->type = RDMA;\r
+ else\r
+ pIo->type = SEND;\r
+\r
+ ib_status =\r
+ pQp->pViport->p_adapter->ifc.post_send( pQp->qp, &pIo->wrq, NULL );\r
+\r
+#ifdef VNIC_STATISTIC\r
+ postTime = cl_get_time_stamp() - postTime;\r
+#endif /* VNIC_STATISTIC */\r
+\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR, ("ib_post_send returned %s\n",\r
+ pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
+ }\r
+ else\r
+ {\r
+#ifdef VNIC_STATISTIC\r
+ if (pIo->wrq.wr_type == WR_RDMA_WRITE)\r
+ {\r
+ pQp->statistics.rdmaPostTime += postTime;\r
+ pQp->statistics.rdmaPostIos++;\r
+ }\r
+ else\r
+ {\r
+ pQp->statistics.sendPostTime += postTime;\r
+ pQp->statistics.sendPostIos++;\r
+ }\r
+#endif /* VNIC_STATISTIC */\r
+ }\r
+\r
+failure:\r
+ NdisReleaseSpinLock( &pQp->qpLock );\r
+ VNIC_EXIT( VNIC_DBG_IB );\r
+ return ib_status;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+ibqp_postRecv(IbQp_t *pQp, Io_t *pIo)\r
+{\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+#ifdef VNIC_STATISTIC\r
+ int64_t postTime;\r
+#endif /* VNIC_STATISTIC */\r
+\r
+ NdisAcquireSpinLock( &pQp->qpLock );\r
+ /* can post recvieves before connecting queue pair */\r
+ if( pQp->qpState != IB_INITTED && pQp->qpState != IB_ATTACHED )\r
+ {\r
+ NdisReleaseSpinLock( &pQp->qpLock );\r
+ return IB_INVALID_STATE;\r
+ }\r
+ pIo->type = RECV;\r
+\r
+#ifdef VNIC_STATISTIC\r
+ postTime = cl_get_time_stamp();\r
+ if (pIo->time != 0)\r
+ {\r
+ pQp->statistics.recvCompTime += postTime - pIo->time;\r
+ pQp->statistics.recvCompIos++;\r
+ }\r
+#endif /* VNIC_STATISTIC */\r
+\r
+ ib_status =\r
+ pQp->pViport->p_adapter->ifc.post_recv(pQp->qp, &pIo->r_wrq, NULL );\r
+\r
+#ifdef VNIC_STATISTIC\r
+ postTime = (cl_get_time_stamp()) - postTime;\r
+#endif /* VNIC_STATISTIC */\r
+\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("Post Recv failed status %s(%d)\n",\r
+ pQp->pViport->p_adapter->ifc.get_err_str(ib_status), ib_status ));\r
+\r
+ NdisReleaseSpinLock( &pQp->qpLock );\r
+ return FALSE;\r
+ }\r
+ else\r
+ {\r
+#ifdef VNIC_STATISTIC\r
+ pQp->statistics.recvPostTime += postTime;\r
+ pQp->statistics.recvPostIos++;\r
+#endif /* VNIC_STATISTIC */\r
+ }\r
+\r
+ NdisReleaseSpinLock( &pQp->qpLock );\r
+ return ib_status;\r
+}\r
+\r
+\r
+static void\r
+_ibqp_connect_cb(\r
+ IN ib_cm_rep_rec_t *p_cm_rep )\r
+{\r
+ IbQp_t *pQp;\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+\r
+ union\r
+ {\r
+ ib_cm_rtu_t cm_rtu;\r
+ ib_cm_mra_t cm_mra;\r
+ ib_cm_rej_t cm_rej;\r
+ } u_reply;\r
+\r
+ viport_t *p_viport;\r
+\r
+ VNIC_ENTER( VNIC_DBG_IB );\r
+\r
+ pQp = (IbQp_t * __ptr64 )p_cm_rep->qp_context;\r
+ p_viport = pQp->pViport;\r
+\r
+ ASSERT( pQp->qpState == IB_ATTACHING );\r
+\r
+ ib_status = p_viport->p_adapter->ifc.rearm_cq( pQp->cq, FALSE );\r
+ if ( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("Rearm CQ failed %s\n",\r
+ p_viport->p_adapter->ifc.get_err_str( ib_status )) );\r
+\r
+ cl_memclr( &u_reply.cm_rej, sizeof( u_reply.cm_rej ) );\r
+ u_reply.cm_rej.rej_status = IB_REJ_INSUF_RESOURCES;\r
+\r
+ p_viport->p_adapter->ifc.cm_rej( p_cm_rep->h_cm_rep, &u_reply.cm_rej );\r
+ goto err;\r
+ }\r
+\r
+ cl_memclr( &u_reply.cm_rtu, sizeof( u_reply.cm_rtu ) );\r
+ u_reply.cm_rtu.access_ctrl = IB_AC_LOCAL_WRITE;\r
+\r
+ if( pQp->p_conf->sendGather > 1 )\r
+ u_reply.cm_rtu.access_ctrl |= ( IB_AC_RDMA_WRITE );\r
+\r
+ u_reply.cm_rtu.pfn_cm_dreq_cb = _ibqp_dreq_cb;\r
+\r
+ ib_status = p_viport->p_adapter->ifc.cm_rtu ( p_cm_rep->h_cm_rep, &u_reply.cm_rtu );\r
+ if ( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("Send RTU failed\n") );\r
+err:\r
+ InterlockedExchange( &pQp->qpState, IB_DETACHED );\r
+ viport_failure( p_viport );\r
+ }\r
+ else\r
+ {\r
+ InterlockedExchange ( &pQp->qpState, IB_ATTACHED );\r
+ }\r
+\r
+ cl_event_signal( &p_viport->conn_event );\r
+ VNIC_EXIT( VNIC_DBG_IB );\r
+}\r
+\r
+\r
+#define WC_LIST_SIZE_TO_POLL 4\r
+static void\r
+_ib_qpCompletion(\r
+ IN IbQp_t *pQp )\r
+{\r
+ Io_t *pIo;\r
+ ib_wc_t wc[WC_LIST_SIZE_TO_POLL];\r
+ ib_wc_t *p_free_wc;\r
+ ib_wc_t *p_done_wc;\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+ int i;\r
+\r
+#ifdef VNIC_STATISTIC\r
+ int64_t compTime;\r
+ uint32_t compNum = 0;\r
+#endif /* VNIC_STATISTIC */\r
+\r
+ VNIC_ENTER ( VNIC_DBG_IB );\r
+\r
+ if ( pQp->qpState != IB_ATTACHING && pQp->qpState != IB_ATTACHED )\r
+ return;\r
+\r
+#ifdef VNIC_STATISTIC\r
+ compTime = cl_get_time_stamp();\r
+ pQp->statistics.numCallbacks++;\r
+#endif /* VNIC_STATISTIC */\r
+\r
+ for( i = 0; i < (WC_LIST_SIZE_TO_POLL - 1); i++ )\r
+ {\r
+ wc[i].p_next = &wc[i + 1];\r
+ }\r
+ wc[(WC_LIST_SIZE_TO_POLL - 1)].p_next = NULL;\r
+\r
+ p_free_wc = wc;\r
+ p_done_wc = NULL;\r
+\r
+ ib_status = pQp->pViport->p_adapter->ifc.poll_cq( pQp->cq, &p_free_wc, &p_done_wc );\r
+\r
+ if ( ib_status != IB_SUCCESS && ib_status != IB_NOT_FOUND )\r
+ {\r
+ VNIC_TRACE ( VNIC_DBG_ERROR,\r
+ ("ib_poll_cq failed status %d(%s)\n", ib_status,\r
+ pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
+ return;\r
+ }\r
+\r
+ while ( p_done_wc )\r
+ {\r
+ pIo = (Io_t *)(uintn_t)p_done_wc->wr_id;\r
+\r
+ if (pIo)\r
+ {\r
+ /* keep completion status for proper ndis packet return status */\r
+ pIo->wc_status = p_done_wc->status;\r
+#ifdef VNIC_STATISTIC\r
+ if (pIo->type == RECV)\r
+ {\r
+ pIo->time = compTime;\r
+ }\r
+ else if (pIo->type == RDMA)\r
+ {\r
+ pQp->statistics.rdmaCompTime += compTime - pIo->time;\r
+ pQp->statistics.rdmaCompIos++;\r
+ }\r
+ else if (pIo->type == SEND)\r
+ {\r
+ pQp->statistics.sendCompTime += compTime - pIo->time;\r
+ pQp->statistics.sendCompIos++;\r
+ }\r
+ pQp->statistics.numIos++;\r
+ if ( ++compNum > pQp->statistics.maxIos)\r
+ {\r
+ pQp->statistics.maxIos = compNum;\r
+ }\r
+#endif /* VNIC_STATISTIC */\r
+ VNIC_TRACE( VNIC_DBG_IB,\r
+ ("ib_workCompletion: WcType = %d, Status = %d, Length = %d\n",\r
+ p_done_wc->wc_type,\r
+ p_done_wc->status,\r
+ ( p_done_wc->wc_type == IB_WC_RECV )? p_done_wc->length : 0 ) );\r
+\r
+ if( pIo->pRoutine )\r
+ {\r
+ (*pIo->pRoutine)( pIo );\r
+ }\r
+ }\r
+\r
+ if (p_done_wc->status != IB_WCS_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_IB,\r
+ ("Failed completion, type = %d, status = %d (%s)\n",\r
+ p_done_wc->wc_type,\r
+ p_done_wc->status,\r
+ pQp->pViport->p_adapter->ifc.get_wc_status_str (p_done_wc->status) ) );\r
+ }\r
+\r
+ p_done_wc = p_done_wc->p_next;\r
+ }\r
+\r
+ ib_status = pQp->pViport->p_adapter->ifc.rearm_cq( pQp->cq, FALSE );\r
+\r
+ if ( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("Rearm CQ failed status %d(%s)\n", ib_status,\r
+ pQp->pViport->p_adapter->ifc.get_err_str( ib_status )) );\r
+ }\r
+ return;\r
+}\r
+\r
+\r
+static\r
+void ib_workCompletion(\r
+ IN ib_cq_handle_t h_cq,\r
+ IN void *cqContext )\r
+{\r
+ IbQp_t *pQp;\r
+\r
+ VNIC_ENTER ( VNIC_DBG_IB );\r
+ UNREFERENCED_PARAMETER( h_cq );\r
+ pQp = (IbQp_t *)cqContext;\r
+ _ib_qpCompletion(pQp);\r
+\r
+ VNIC_EXIT ( VNIC_DBG_IB );\r
+ return;\r
+}\r
+\r
+void\r
+ib_asyncEvent(\r
+ IN ib_async_event_rec_t *pEventRecord )\r
+{\r
+ IbQp_t *pQp;\r
+\r
+ VNIC_ENTER ( VNIC_DBG_IB );\r
+\r
+ if ( pEventRecord )\r
+ {\r
+ switch ( pEventRecord->code )\r
+ {\r
+ case IB_AE_QP_COMM:\r
+ case IB_AE_QP_FATAL:\r
+\r
+ pQp = (IbQp_t * __ptr64 )pEventRecord->context;\r
+ if (pQp)\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("Async Event %d QP State %#x\n",\r
+ pEventRecord->code, pQp->qpState ));\r
+ }\r
+ break;\r
+ default:\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("Async Event %d received\n", pEventRecord->code) );\r
+ break;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR, ("Unknown NULL event\n") );\r
+ }\r
+ VNIC_EXIT ( VNIC_DBG_IB );\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
--- /dev/null
+/*\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
+#ifndef _VNIC_IB_H_\r
+#define _VNIC_IB_H_\r
+\r
+\r
+#include <iba/ib_al.h>\r
+#include <complib/comp_lib.h>\r
+#include "vnic_trailer.h"\r
+struct Io;\r
+\r
+typedef void (CompRoutine_t)(struct Io *pIo);\r
+\r
+#define MAX_HCAS 4\r
+#define MAX_NUM_SGE 8\r
+\r
+#define MAX_PHYS_MEMORY 0xFFFFFFFFFFFFFFFF\r
+#define CONTROL_SID 0\r
+#define DATA_SID 1\r
+\r
+#include <complib/cl_packon.h>\r
+typedef union _vnic_sid {\r
+ uint64_t as_uint64;\r
+ struct {\r
+ uint8_t base_id; /* base id for vnic is 0x10 */\r
+ uint8_t oui[3]; /* OUI */\r
+ uint16_t reserved; /* should be zero */\r
+ uint8_t type; /* control or data */\r
+ uint8_t ioc_num; /* ioc number */\r
+ }s;\r
+} vnic_sid_t;\r
+\r
+typedef union _vnic_ioc_guid {\r
+ uint64_t as_uint64;\r
+ struct {\r
+ uint8_t oui[3];\r
+ uint8_t ioc_num;\r
+ uint32_t counter; /* SST device type: 8 bits, counter:24 bits */\r
+ }s;\r
+} vnic_ioc_guid_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+typedef enum {\r
+ IB_UNINITTED = 0,\r
+ IB_INITTED,\r
+ IB_ATTACHING,\r
+ IB_ATTACHED,\r
+ IB_DETACHING,\r
+ IB_DETACHED,\r
+ IB_DISCONNECTED\r
+} IbState_t;\r
+#pragma warning ( disable : 4324 )\r
+typedef struct _vnic_path_record {\r
+ cl_list_item_t list_entry;\r
+ uint32_t num_entries;\r
+ ib_path_rec_t path_rec;\r
+} vnic_path_record_t;\r
+#pragma warning( default : 4324 )\r
+\r
+typedef struct IbQp {\r
+ LIST_ENTRY listPtrs;\r
+ struct _viport *pViport;\r
+ struct IbConfig *p_conf;\r
+ NDIS_SPIN_LOCK qpLock;\r
+ volatile LONG qpState;\r
+ uint32_t qpNumber;\r
+ struct IbCa *pCa;\r
+ uint64_t portGuid;\r
+ ib_qp_handle_t qp;\r
+ ib_cq_handle_t cq;\r
+#ifdef VNIC_STATISTIC\r
+ struct {\r
+ int64_t connectionTime;\r
+ int64_t rdmaPostTime;\r
+ uint32_t rdmaPostIos;\r
+ int64_t rdmaCompTime;\r
+ uint32_t rdmaCompIos;\r
+ int64_t sendPostTime;\r
+ uint32_t sendPostIos;\r
+ int64_t sendCompTime;\r
+ uint32_t sendCompIos;\r
+ int64_t recvPostTime;\r
+ uint32_t recvPostIos;\r
+ int64_t recvCompTime;\r
+ uint32_t recvCompIos;\r
+ uint32_t numIos;\r
+ uint32_t numCallbacks;\r
+ uint32_t maxIos;\r
+ } statistics;\r
+#endif /* VNIC_STATISTIC */\r
+} IbQp_t;\r
+\r
+typedef struct IbRegion {\r
+ uint64_t virtAddress;\r
+ net64_t len;\r
+ ib_mr_handle_t h_mr;\r
+ net32_t lkey;\r
+ net32_t rkey;\r
+} IbRegion_t;\r
+\r
+\r
+#define VNIC_CA_MAX_PORTS 2\r
+typedef struct IbCa {\r
+ cl_list_item_t list_entry;\r
+ net64_t caGuid;\r
+ ib_pd_handle_t hPd;\r
+ IbRegion_t region;\r
+ uint32_t numPorts;\r
+ uint64_t portGuids[VNIC_CA_MAX_PORTS];\r
+} IbCa_t;\r
+\r
+typedef enum _OpType { RECV, RDMA, SEND }OpType_t;\r
+\r
+typedef struct Io {\r
+ LIST_ENTRY listPtrs;\r
+ struct _viport *pViport;\r
+ CompRoutine_t *pRoutine;\r
+ ib_send_wr_t wrq;\r
+ ib_recv_wr_t r_wrq;\r
+ ib_wc_status_t wc_status;\r
+#ifdef VNIC_STATISTIC\r
+ int64_t time;\r
+#endif /* VNIC_STATISTIC */\r
+ OpType_t type;\r
+} Io_t;\r
+\r
+typedef struct RdmaIo {\r
+ Io_t io;\r
+ ib_local_ds_t dsList[MAX_NUM_SGE];\r
+ uint16_t index;\r
+ uint32_t len;\r
+ NDIS_PACKET *p_packet;\r
+ NDIS_BUFFER *p_buf;\r
+ ULONG packet_sz;\r
+ struct ViportTrailer *p_trailer;\r
+ uint8_t data[2* VIPORT_TRAILER_ALIGNMENT];\r
+} RdmaIo_t;\r
+\r
+typedef struct SendIo {\r
+ Io_t io;\r
+ ib_local_ds_t dsList;\r
+} SendIo_t;\r
+\r
+typedef struct RecvIo {\r
+ Io_t io;\r
+ ib_local_ds_t dsList;\r
+} RecvIo_t;\r
+\r
+void\r
+ibqp_construct(\r
+ IN OUT IbQp_t *pQp,\r
+ IN struct _viport *pViport );\r
+ib_api_status_t ibqp_init(IbQp_t *pQp, uint64_t guid, struct IbConfig *p_conf);\r
+ib_api_status_t ibqp_connect(IbQp_t *pQp);\r
+void ibqp_detach(IbQp_t *pQp);\r
+void ibqp_cleanup(IbQp_t *pQp);\r
+ib_api_status_t ibqp_postSend(IbQp_t *pQp, Io_t *pIo);\r
+ib_api_status_t ibqp_postRecv(IbQp_t *pQp, Io_t *pIo);\r
+\r
+uint8_t ibca_findPortNum( struct _viport *p_viport, uint64_t guid );\r
+\r
+ib_api_status_t\r
+ibregion_init(\r
+ IN struct _viport *p_viport,\r
+ OUT IbRegion_t *pRegion,\r
+ IN ib_pd_handle_t hPd,\r
+ IN void* __ptr64 vaddr,\r
+ IN uint64_t len,\r
+ IN ib_access_t access_ctrl );\r
+\r
+void\r
+ibregion_cleanup(\r
+ struct _viport *p_viport,\r
+ IbRegion_t *pRegion );\r
+\r
+void ib_asyncEvent( ib_async_event_rec_t *pEventRecord );\r
+\r
+#define ibpd_fromCa(pCa) (&(pCa)->pd)\r
+\r
+\r
+#endif /* _VNIC_IB_H_ */\r
--- /dev/null
+\r
+#include "vnic_adapter.h"\r
+\r
+extern vnic_globals_t g_vnic;\r
+\r
+\r
+void\r
+netpath_init(\r
+ IN Netpath_t *pNetpath,\r
+ IN vnic_adapter_t *p_adapter )\r
+{\r
+ int i;\r
+\r
+ VNIC_ENTER( VNIC_DBG_FUNC );\r
+\r
+ pNetpath->p_adapter = p_adapter;\r
+ pNetpath->carrier = 0;\r
+ pNetpath->pViport = NULL;\r
+ pNetpath->timerState = NETPATH_TS_IDLE;\r
+\r
+ for ( i = 0; i < INICNP_NUM_EVENTS; i++ )\r
+ {\r
+ p_adapter->np_event[i].p_adapter = p_adapter;\r
+ p_adapter->np_event[i].event_num = (uint8_t)i;\r
+ InitializeListHead( &p_adapter->np_event[i].listPtrs );\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_FUNC );\r
+ return;\r
+}\r
+\r
+\r
+BOOLEAN\r
+netpath_addPath (\r
+ Netpath_t *pNetpath,\r
+ viport_t *pViport )\r
+{\r
+\r
+ if( pNetpath->pViport )\r
+ {\r
+ return FALSE;\r
+ }\r
+ else\r
+ {\r
+ pNetpath->pViport = pViport;\r
+ viport_setParent( pViport, pNetpath );\r
+ return TRUE;\r
+ }\r
+}\r
+\r
+BOOLEAN\r
+netpath_removePath(\r
+ Netpath_t *pNetpath,\r
+ viport_t *pViport)\r
+{\r
+ if( pNetpath->pViport != pViport )\r
+ {\r
+ return FALSE;\r
+ }\r
+ else\r
+ {\r
+ pNetpath->pViport = NULL;\r
+ viport_unsetParent( pViport, pNetpath );\r
+ return TRUE;\r
+ }\r
+}\r
+\r
+\r
+BOOLEAN netpath_setUnicast(Netpath_t *pNetpath, uint8_t *pAddress)\r
+{\r
+ BOOLEAN ret = FALSE;\r
+\r
+ // TODO: Not called anywhere!!!\r
+ VNIC_TRACE( VNIC_DBG_NETPATH | VNIC_DBG_INFO,\r
+ ("Set %s MAC to %02X:%02X:%02X:%02X:%02X:%02X\n",\r
+ netpath_to_string(pNetpath->p_adapter, pNetpath),\r
+ pAddress[0],\r
+ pAddress[1],\r
+ pAddress[2],\r
+ pAddress[3],\r
+ pAddress[4],\r
+ pAddress[5]) );\r
+\r
+ if (pNetpath->pViport)\r
+ {\r
+ ret = viport_setUnicast( pNetpath->pViport, pAddress );\r
+ }\r
+ return ret;\r
+}\r
+\r
+\r
+int netpath_maxMtu(Netpath_t *pNetpath)\r
+{\r
+ int ret = MAX_PARAM_VALUE;\r
+\r
+ if (pNetpath->pViport) {\r
+ ret = viport_maxMtu(pNetpath->pViport);\r
+ }\r
+ return ret;\r
+}\r
+\r
+BOOLEAN\r
+netpath_xmitPacket(\r
+ IN Netpath_t *pNetpath,\r
+ IN NDIS_PACKET * const p_packet )\r
+{\r
+ BOOLEAN ret = FALSE;\r
+\r
+ if ( pNetpath->pViport )\r
+ {\r
+ ret = viport_xmitPacket(pNetpath->pViport, p_packet );\r
+ }\r
+ return ret;\r
+}\r
+\r
+\r
+void\r
+netpath_stopXmit(\r
+ IN Netpath_t *pNetpath )\r
+\r
+{\r
+\r
+ VNIC_ENTER( VNIC_DBG_NETPATH );\r
+\r
+ if (pNetpath == pNetpath->p_adapter->p_currentPath )\r
+ {\r
+ InterlockedCompareExchange( &pNetpath->p_adapter->xmitStarted, 0, 1 );\r
+ }\r
+#ifdef INIC_STATISTICS\r
+ if ( pNetpath->p_adapter->statistics.xmitRef == 0)\r
+ {\r
+ pNetpath->p_adapter->statistics.xmitRef = get_time_stamp_ms();\r
+ }\r
+#endif /* INIC_STATISTICS */\r
+ return;\r
+}\r
+\r
+void netpath_restartXmit(\r
+ IN Netpath_t *pNetpath )\r
+{\r
+ VNIC_ENTER( VNIC_DBG_NETPATH );\r
+\r
+ if (pNetpath == pNetpath->p_adapter->p_currentPath )\r
+ {\r
+ InterlockedCompareExchange( &pNetpath->p_adapter->xmitStarted, 1, 0 );\r
+ }\r
+#ifdef INIC_STATISTICS\r
+ if (pNetpath->p_adapter->statistics.xmitRef != 0)\r
+ {\r
+ pNetpath->p_adapter->statistics.xmitOffTime +=\r
+ get_time_stamp_ms() - pNetpath->p_adapter->statistics.xmitRef;\r
+ pNetpath->p_adapter->statistics.xmitOffNum++;\r
+ pNetpath->p_adapter->statistics.xmitRef = 0;\r
+ }\r
+#endif /* INIC_STATISTICS */\r
+ return;\r
+}\r
+\r
+// Viport on input calls this\r
+void netpath_recvPacket(\r
+ IN Netpath_t *pNetpath,\r
+ IN NDIS_PACKET* p_packet )\r
+{\r
+ #ifdef INIC_STATISTICS\r
+ extern cycles_t recvRef;\r
+#endif /* INIC_STATISTICS */\r
+\r
+ VNIC_ENTER( VNIC_DBG_NETPATH );\r
+\r
+#ifdef INIC_STATISTICS\r
+ pNetpath->p_adapter->statistics.recvTime += get_time_stamp_ms() - recvRef;\r
+ pNetpath->p_adapter->statistics.recvNum++;\r
+#endif /* INIC_STATISTICS */\r
+\r
+ NdisMIndicateReceivePacket( pNetpath->p_adapter->h_handle, &p_packet, 1 );\r
+\r
+ return;\r
+}\r
+\r
+void netpath_tx_timeout(\r
+ IN Netpath_t *pNetpath )\r
+{\r
+ if ( pNetpath->pViport )\r
+ {\r
+ viport_failure( pNetpath->pViport );\r
+ }\r
+}\r
+\r
+const char *\r
+netpath_to_string(\r
+ IN vnic_adapter_t *p_adapter,\r
+ IN Netpath_t *pNetpath )\r
+{\r
+ if ( !pNetpath )\r
+ {\r
+ return "NULL";\r
+ }\r
+ else if ( pNetpath == &p_adapter->primaryPath )\r
+ {\r
+ return "PRIMARY";\r
+ }\r
+ else if ( pNetpath == &p_adapter->secondaryPath )\r
+ {\r
+ return "SECONDARY";\r
+ } else\r
+ {\r
+ return "UNKNOWN";\r
+ }\r
+}\r
+\r
+\r
+static BOOLEAN\r
+__netpath_npevent_register(vnic_adapter_t *p_adapter, Netpath_t *pNetpath)\r
+{\r
+ VNIC_ENTER( VNIC_DBG_NETPATH );\r
+\r
+ UNUSED_PARAM( pNetpath );\r
+ p_adapter->state = INIC_REGISTERED;\r
+ return TRUE;\r
+}\r
+\r
+static const char * const inicNPEventStr[] = {\r
+ "PRIMARY CONNECTED",\r
+ "PRIMARY DISCONNECTED",\r
+ "PRIMARY CARRIER",\r
+ "PRIMARY NO CARRIER",\r
+ "PRIMARY TIMER EXPIRED",\r
+ "SETLINK",\r
+\r
+ "SECONDARY CONNECTED",\r
+ "SECONDARY DISCONNECTED",\r
+ "SECONDARY CARRIER",\r
+ "SECONDARY NO CARRIER",\r
+ "SECONDARY TIMER EXPIRED",\r
+ "FREE INIC",\r
+};\r
+\r
--- /dev/null
+/*\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_TRAILER_H_\r
+#define _VNIC_TRAILER_H_\r
+\r
+/* pktFlags values */\r
+#define PF_CHASH_VALID 0x01\r
+#define PF_IPSEC_VALID 0x02\r
+#define PF_TCP_SEGMENT 0x04\r
+#define PF_KICK 0x08\r
+#define PF_VLAN_INSERT 0x10\r
+#define PF_PVID_OVERRIDDEN 0x20\r
+#define PF_FCS_INCLUDED 0x40\r
+#define PF_FORCE_ROUTE 0x80\r
+\r
+/* txChksumFlags values */\r
+#define TX_CHKSUM_FLAGS_CHECKSUM_V4 0x01\r
+#define TX_CHKSUM_FLAGS_CHECKSUM_V6 0x02\r
+#define TX_CHKSUM_FLAGS_TCP_CHECKSUM 0x04\r
+#define TX_CHKSUM_FLAGS_UDP_CHECKSUM 0x08\r
+#define TX_CHKSUM_FLAGS_IP_CHECKSUM 0x10\r
+\r
+/* rxChksumFlags values */\r
+#define RX_CHKSUM_FLAGS_TCP_CHECKSUM_FAILED 0x01\r
+#define RX_CHKSUM_FLAGS_UDP_CHECKSUM_FAILED 0x02\r
+#define RX_CHKSUM_FLAGS_IP_CHECKSUM_FAILED 0x04\r
+#define RX_CHKSUM_FLAGS_TCP_CHECKSUM_SUCCEEDED 0x08\r
+#define RX_CHKSUM_FLAGS_UDP_CHECKSUM_SUCCEEDED 0x10\r
+#define RX_CHKSUM_FLAGS_IP_CHECKSUM_SUCCEEDED 0x20\r
+#define RX_CHKSUM_FLAGS_LOOPBACK 0x40\r
+#define RX_CHKSUM_FLAGS_RESERVED 0x80\r
+\r
+/* connectionHashAndValid values */\r
+#define CHV_VALID 0x80\r
+#define CHV_HASH_MASH 0x7f\r
+\r
+/* round down value to align, align must be a power of 2 */\r
+#ifndef ROUNDDOWNP2\r
+#define ROUNDDOWNP2(val, align) \\r
+ (((uintn_t)(val)) & (~((uintn_t)(align)-1)))\r
+#endif\r
+\r
+/* round up value to align, align must be a power of 2 */\r
+#ifndef ROUNDUPP2\r
+#define ROUNDUPP2(val, align) \\r
+ (((uintn_t)(val) + (uintn_t)(align) - 1) & (~((uintn_t)(align)-1)))\r
+#endif\r
+\r
+#define VIPORT_TRAILER_ALIGNMENT 32\r
+#define BUFFER_SIZE(len) (sizeof(ViportTrailer_t) + ROUNDUPP2((len), VIPORT_TRAILER_ALIGNMENT))\r
+#define MAX_PAYLOAD(len) ROUNDDOWNP2((len) - sizeof(ViportTrailer_t), VIPORT_TRAILER_ALIGNMENT)\r
+\r
+#include <complib/cl_packon.h>\r
+\r
+typedef struct ViportTrailer {\r
+ int8_t dataAlignmentOffset;\r
+ uint8_t rndisHeaderLength; /* reserved for use by Edp */\r
+ uint16_t dataLength;\r
+ uint8_t pktFlags;\r
+\r
+ uint8_t txChksumFlags;\r
+\r
+ uint8_t rxChksumFlags;\r
+\r
+ uint8_t ipSecFlags;\r
+ uint32_t tcpSeqNo;\r
+ uint32_t ipSecOffloadHandle;\r
+ uint32_t ipSecNextOffloadHandle;\r
+ uint8_t destMacAddr[6];\r
+ uint16_t vLan;\r
+ uint16_t timeStamp;\r
+ uint8_t origin;\r
+ uint8_t connectionHashAndValid;\r
+} ViportTrailer_t;\r
+\r
+#include <complib/cl_packoff.h>\r
+\r
+#endif /* _VNIC_TRAILER_H_ */
\ No newline at end of file
--- /dev/null
+/*\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_UTIL_H_\r
+#define _VNIC_UTIL_H_\r
+\r
+#include "vnic_debug.h"\r
+\r
+#define MAXU32 0xffffffff\r
+#define MAXU64 ((uint64_t)(~0))\r
+\r
+#define MODULE_NAME "VNIC"\r
+\r
+#define PTR64(what) ((uint64_t)(void * __ptr64)(what))\r
+\r
+#define CONV2JIFFIES(time) (((time) * HZ) / 100) /* source time is 100ths of a sec */\r
+#define CONV2USEC(time) ((time) * 10000) /* source time is 100ths of a sec */\r
+\r
+#ifndef min\r
+#define min(a,b) ((a)<(b)?(a):(b))\r
+#endif\r
+\r
+#define hton16(x) _byteswap_ushort(x)\r
+#define hton32(x) _byteswap_ulong(x)\r
+#define hton64(x) _byteswap_uint64(x)\r
+\r
+#define ntoh16(x) hton16(x)\r
+#define ntoh32(x) hton32(x)\r
+#define ntoh64(x) hton64(x)\r
+\r
+#define IsPowerOf2(value) (((value) & ((value - 1))) == 0)\r
+/* round down to closest power of 2 value */\r
+\r
+#define SetMinPowerOf2(_val) ((_val) & ( 1 << RtlFindMostSignificantBit( (uint64_t)(_val) )))\r
+\r
+#define PRINT(level,x) VNIC_PRINT(level, x )\r
+\r
+#define PRINT_CONDITIONAL(level,x,condition) if (condition){PRINT( level, x)}\r
+\r
+#ifdef _DEBUG_\r
+#define IB_FSTATUS(functionName) \\r
+ if( (ib_status != IB_SUCCESS) && \\r
+ (ib_status != IB_PENDING) ) \\r
+ VNIC_PRINT( g_vnic_dbg_lvl,("[%s]: %d\n", functionName,ib_status))\r
+\r
+#else\r
+#define IB_FSTATUS(functionName)\r
+#endif\r
+\r
+#define IB_TEST_FSTATUS( functionName ) IB_FSTATUS( functionName ); \\r
+ if ((ib_status != IB_SUCCESS) && (ib_status != IB_PENDING)) goto failure\r
+\r
+#endif /* _VNIC_UTIL_H_ */\r
+\r
--- /dev/null
+/*\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 "vnic_util.h"\r
+#include "vnic_driver.h"\r
+#include "vnic_viport.h"\r
+#include "vnic_control.h"\r
+#include "vnic_data.h"\r
+#include "vnic_config.h"\r
+#include "vnic_controlpkt.h"\r
+\r
+extern vnic_globals_t g_vnic;\r
+\r
+static void viport_timeout( void *context );\r
+static ib_api_status_t viport_initMacAddresses( viport_t *p_viport );\r
+static void viport_statemachine( void *context );\r
+\r
+uint32_t\r
+viport_get_adapter_name(\r
+ IN viport_t *p_viport )\r
+{\r
+ cl_memcpy(p_viport->p_adapter->name, DEFAULT_VNIC_NAME, sizeof(DEFAULT_VNIC_NAME) );\r
+ return ( sizeof(DEFAULT_VNIC_NAME) );\r
+}\r
+\r
+BOOLEAN\r
+viport_config_defaults(\r
+ IN viport_t *p_viport )\r
+{\r
+\r
+ vnic_adapter_t *p_adapter = p_viport->p_adapter;\r
+ ViportConfig_t *pConfig = &p_viport->port_config;\r
+ ControlConfig_t *pControlConfig = &p_viport->port_config.controlConfig;\r
+ DataConfig_t *pDataConfig = &p_viport->port_config.dataConfig;\r
+\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ p_viport->state = VIPORT_DISCONNECTED;\r
+ p_viport->linkState = LINK_RETRYWAIT;\r
+ p_viport->newMtu = 1500;\r
+ p_viport->newFlags = 0;\r
+\r
+ cl_timer_init( &p_viport->timer, viport_timeout, p_viport );\r
+\r
+ pConfig->statsInterval = p_adapter->params.ViportStatsInterval;\r
+ pConfig->hbInterval = p_adapter->params.ViportHbInterval;\r
+ pConfig->hbTimeout = p_adapter->params.ViportHbTimeout;\r
+\r
+ cl_memcpy ( pConfig->ioc_string,\r
+ p_adapter->ioc_info.profile.id_string,\r
+ min( sizeof( p_adapter->ioc_info.profile.id_string ),\r
+ sizeof( pConfig->ioc_string )) );\r
+\r
+ pControlConfig->ibConfig.sid =\r
+ 0x10ULL << 56 |\r
+ 0x00ULL << 48 |\r
+ 0x06ULL << 40 |\r
+ 0x6aULL << 32 |\r
+ 0x00ULL << 24 |\r
+ 0x00ULL << 16 |\r
+ 0x00ULL << 8 |\r
+ ( (uint8_t)( p_adapter->ioc_info.profile.ioc_guid >> 24 ) & 0xFF );\r
+\r
+ pControlConfig->ibConfig.connData.pathId = 0;\r
+ pControlConfig->ibConfig.connData.inicInstance = 0;\r
+ pControlConfig->ibConfig.connData.pathNum = 0;\r
+\r
+ pControlConfig->ibConfig.retryCount = p_adapter->params.RetryCount;\r
+ pControlConfig->ibConfig.rnrRetryCount = p_adapter->params.RetryCount;\r
+ pControlConfig->ibConfig.minRnrTimer = (uint8_t)p_adapter->params.MinRnrTimer;\r
+ pControlConfig->ibConfig.numRecvs = 5; /* Not configurable */\r
+ pControlConfig->ibConfig.numSends = 1; /* Not configurable */\r
+ pControlConfig->ibConfig.recvScatter = 1; /* Not configurable */\r
+ pControlConfig->ibConfig.sendGather = 1; /* Not configurable */\r
+\r
+ /* indicate new features support capabilities */\r
+ pControlConfig->ibConfig.connData.featuresSupported =\r
+ hton32((uint32_t)(INIC_FEAT_IGNORE_VLAN | INIC_FEAT_RDMA_IMMED ));\r
+\r
+ cl_memcpy ( pControlConfig->ibConfig.connData.nodename,\r
+ g_vnic.host_name,\r
+ min( sizeof( g_vnic.host_name ),\r
+ sizeof( pControlConfig->ibConfig.connData.nodename )) );\r
+\r
+ pControlConfig->numRecvs = pControlConfig->ibConfig.numRecvs;\r
+\r
+ pControlConfig->inicInstance = pControlConfig->ibConfig.connData.inicInstance;\r
+ pControlConfig->maxAddressEntries = (uint16_t)p_adapter->params.MaxAddressEntries;\r
+ pControlConfig->minAddressEntries = (uint16_t)p_adapter->params.MinAddressEntries;\r
+ pControlConfig->reqRetryCount = (uint8_t)p_adapter->params.ControlReqRetryCount;\r
+ pControlConfig->rspTimeout = p_adapter->params.ControlRspTimeout;\r
+\r
+ pDataConfig->ibConfig.sid =\r
+ 0x10LL << 56 |\r
+ 0x00LL << 48 |\r
+ 0x06LL << 40 |\r
+ 0x6aLL << 32 |\r
+ 0x00LL << 24 |\r
+ 0x00LL << 16 |\r
+ 0x01LL << 8 |\r
+ ( (uint8_t)( p_adapter->ioc_info.profile.ioc_guid >> 24 ) & 0xFF );\r
+\r
+ pDataConfig->ibConfig.connData.pathId = get_time_stamp_ms();\r
+ pDataConfig->ibConfig.connData.inicInstance = pControlConfig->inicInstance;\r
+ pDataConfig->ibConfig.connData.pathNum = 0;\r
+\r
+ pDataConfig->ibConfig.retryCount = p_adapter->params.RetryCount;\r
+ pDataConfig->ibConfig.rnrRetryCount = p_adapter->params.RetryCount;\r
+ pDataConfig->ibConfig.minRnrTimer = (uint8_t)p_adapter->params.MinRnrTimer;\r
+\r
+ /*\r
+ * NOTE: The numRecvs size assumes that the EIOC could\r
+ * RDMA enough packets to fill all of the host recv\r
+ * pool entries, plus send a kick message after each\r
+ * packet, plus RDMA new buffers for the size of\r
+ * the EIOC recv buffer pool, plus send kick messages\r
+ * after each MinHostUpdateSz of new buffers all\r
+ * before the Host can even pull off the first completed\r
+ * receive off the completion queue, and repost the\r
+ * receive. NOT LIKELY!\r
+ */\r
+ pDataConfig->ibConfig.numRecvs = p_adapter->params.HostRecvPoolEntries +\r
+ ( p_adapter->params.MaxEiocPoolSz / p_adapter->params.MinHostUpdateSz );\r
+\r
+#if TRUE //defined(LIMIT_OUTSTANDING_SENDS)\r
+\r
+ pDataConfig->ibConfig.numSends = (2 * p_adapter->params.NotifyBundleSz ) +\r
+ ( p_adapter->params.HostRecvPoolEntries / p_adapter->params.MinEiocUpdateSz ) + 1;\r
+\r
+#else /* !defined(LIMIT_OUTSTANDING_SENDS) */\r
+ /*\r
+ * NOTE: The numSends size assumes that the HOST could\r
+ * post RDMA sends for every single buffer in the EIOCs\r
+ * receive pool, and allocate a full complement of\r
+ * receive buffers on the host, and RDMA free buffers\r
+ * every MinEiocUpdateSz entries all before the HCA\r
+ * can complete a single RDMA transfer. VERY UNLIKELY,\r
+ * BUT NOT COMPLETELY IMPOSSIBLE IF THERE IS AN IB\r
+ * PROBLEM!\r
+ */\r
+ pDataConfig->ibConfig.numSends = p_adapter->params.MaxEiocPoolSz +\r
+ ( p_adapter->params.HostRecvPoolEntries / p_adapter->params.MinEiocUpdateSz ) + 1;\r
+\r
+#endif /* !defined(LIMIT_OUTSTANDING_SENDS) */\r
+\r
+ pDataConfig->ibConfig.recvScatter = 1; /* Not configurable */\r
+ pDataConfig->ibConfig.sendGather = MAX_NUM_SGE; /* Not configurable */\r
+\r
+ pDataConfig->numRecvs = pDataConfig->ibConfig.numRecvs;\r
+ pDataConfig->pathId = pDataConfig->ibConfig.connData.pathId;\r
+\r
+ pDataConfig->hostMin.sizeRecvPoolEntry =\r
+ (uint32_t)BUFFER_SIZE(ETH_VLAN_HLEN + p_adapter->params.MinMtu);\r
+ pDataConfig->hostMax.sizeRecvPoolEntry =\r
+ (uint32_t)BUFFER_SIZE(ETH_VLAN_HLEN + p_adapter->params.MaxMtu);\r
+ pDataConfig->eiocMin.sizeRecvPoolEntry =\r
+ (uint32_t)BUFFER_SIZE(ETH_VLAN_HLEN + p_adapter->params.MinMtu);\r
+ pDataConfig->eiocMax.sizeRecvPoolEntry = MAX_PARAM_VALUE;\r
+\r
+ pDataConfig->hostRecvPoolEntries = p_adapter->params.HostRecvPoolEntries;\r
+ pDataConfig->notifyBundle = p_adapter->params.NotifyBundleSz;\r
+\r
+ pDataConfig->hostMin.numRecvPoolEntries = p_adapter->params.MinHostPoolSz;\r
+ pDataConfig->hostMax.numRecvPoolEntries = MAX_PARAM_VALUE;\r
+ pDataConfig->eiocMin.numRecvPoolEntries = p_adapter->params.MinEiocPoolSz;\r
+ pDataConfig->eiocMax.numRecvPoolEntries = p_adapter->params.MaxEiocPoolSz;\r
+\r
+ pDataConfig->hostMin.timeoutBeforeKick = p_adapter->params.MinHostKickTimeout;\r
+ pDataConfig->hostMax.timeoutBeforeKick = p_adapter->params.MaxHostKickTimeout;\r
+ pDataConfig->eiocMin.timeoutBeforeKick = 0;\r
+ pDataConfig->eiocMax.timeoutBeforeKick = MAX_PARAM_VALUE;\r
+\r
+ pDataConfig->hostMin.numRecvPoolEntriesBeforeKick = p_adapter->params.MinHostKickEntries;\r
+ pDataConfig->hostMax.numRecvPoolEntriesBeforeKick = p_adapter->params.MaxHostKickEntries;\r
+ pDataConfig->eiocMin.numRecvPoolEntriesBeforeKick = 0;\r
+ pDataConfig->eiocMax.numRecvPoolEntriesBeforeKick = MAX_PARAM_VALUE;\r
+\r
+ pDataConfig->hostMin.numRecvPoolBytesBeforeKick = p_adapter->params.MinHostKickBytes;\r
+ pDataConfig->hostMax.numRecvPoolBytesBeforeKick = p_adapter->params.MaxHostKickBytes;\r
+ pDataConfig->eiocMin.numRecvPoolBytesBeforeKick = 0;\r
+ pDataConfig->eiocMax.numRecvPoolBytesBeforeKick = MAX_PARAM_VALUE;\r
+\r
+ pDataConfig->hostMin.freeRecvPoolEntriesPerUpdate = p_adapter->params.MinHostUpdateSz;\r
+ pDataConfig->hostMax.freeRecvPoolEntriesPerUpdate = p_adapter->params.MaxHostUpdateSz;\r
+ pDataConfig->eiocMin.freeRecvPoolEntriesPerUpdate = p_adapter->params.MinEiocUpdateSz;\r
+ pDataConfig->eiocMax.freeRecvPoolEntriesPerUpdate = p_adapter->params.MaxEiocUpdateSz;\r
+\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return TRUE;\r
+}\r
+\r
+static BOOLEAN config_isValid(ViportConfig_t *pConfig)\r
+{\r
+ UNREFERENCED_PARAMETER( pConfig );\r
+ return TRUE;\r
+}\r
+\r
+\r
+void\r
+viport_cleanup(\r
+ viport_t *p_viport )\r
+{\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ if( p_viport )\r
+ {\r
+ InterlockedExchange( &p_viport->p_adapter->carrier, FALSE );\r
+ InterlockedExchange( &p_viport->p_netpath->carrier, FALSE );\r
+ viport_timerStop( p_viport );\r
+\r
+ data_disconnect( &p_viport->data );\r
+\r
+ control_cleanup( &p_viport->control );\r
+\r
+ data_cleanup( &p_viport->data );\r
+\r
+ if( p_viport->macAddresses != NULL )\r
+ {\r
+ NdisFreeMemory( p_viport->macAddresses,\r
+ p_viport->numMacAddresses * sizeof(Inic_AddressOp_t), 0 );\r
+ }\r
+\r
+ cl_timer_destroy( &p_viport->timer );\r
+\r
+ NdisFreeMemory ( p_viport, sizeof(viport_t), 0 );\r
+ }\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return;\r
+}\r
+\r
+\r
+void\r
+viport_setPath(\r
+ IN viport_t *p_viport,\r
+ IN ib_path_rec_t *p_path,\r
+ IN uint64_t *p_guid )\r
+{\r
+\r
+ UNUSED_PARAM( p_guid );\r
+\r
+ VNIC_ENTER( VNIC_DBG_FUNC );\r
+\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ ("Using SLID=%d DLID=%d Target:%s\n",\r
+ cl_ntoh16( p_path->slid ),\r
+ cl_ntoh16( p_path->dlid ),\r
+ p_viport->p_adapter->ioc_info.profile.id_string) );\r
+\r
+ p_viport->portGuid = p_path->sgid.unicast.interface_id;\r
+ p_viport->iocGuid = *p_guid;\r
+ p_viport->port_config.dataConfig.ibConfig.pathInfo = *p_path;\r
+ p_viport->port_config.controlConfig.ibConfig.pathInfo = *p_path;\r
+ p_viport->port_config.controlConfig.ibConfig.sid =\r
+ p_viport->p_adapter->p_svc_entries[0].id;\r
+ p_viport->port_config.dataConfig.ibConfig.sid =\r
+ p_viport->p_adapter->p_svc_entries[1].id;\r
+\r
+ VNIC_EXIT( VNIC_DBG_FUNC );\r
+}\r
+\r
+BOOLEAN\r
+viport_setParent(\r
+ IN viport_t *p_viport,\r
+ IN Netpath_t *pNetpath )\r
+{\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+\r
+ if(p_viport->p_netpath != NULL)\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ p_viport->p_netpath = pNetpath;\r
+\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return TRUE;\r
+}\r
+\r
+BOOLEAN\r
+viport_unsetParent(\r
+ IN viport_t *p_viport,\r
+ IN Netpath_t *pNetpath )\r
+{\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+ if( pNetpath->pViport == p_viport )\r
+ viport_free( p_viport );\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return TRUE;\r
+}\r
+\r
+void\r
+viport_free(\r
+ IN viport_t *p_viport )\r
+{\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ viport_timerStop( p_viport );\r
+ viport_disconnect(p_viport);\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return;\r
+}\r
+\r
+void\r
+viport_disconnect(\r
+ IN viport_t *p_viport )\r
+{\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ InterlockedExchange( (volatile LONG *)&p_viport->disconnect, TRUE );\r
+ viport_failure( p_viport );\r
+\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+viport_setLink(\r
+ IN viport_t *p_viport,\r
+ IN uint8_t flags,\r
+ IN uint16_t mtu )\r
+{\r
+ KIRQL irql;\r
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;\r
+\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ if(mtu > data_maxMtu(&p_viport->data))\r
+ {\r
+ viport_failure(p_viport);\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("Configuration error. Mtu of %d unsupported by %s\n", mtu, p_viport->p_adapter->name ) );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+\r
+ KeAcquireSpinLock( &p_viport->lock, &irql );\r
+\r
+ flags &= ( INIC_FLAG_ENABLE_NIC |\r
+ INIC_FLAG_ENABLE_MCAST_ALL |\r
+ INIC_FLAG_ENABLE_PROMISC );\r
+\r
+ if( (p_viport->newFlags != flags) ||\r
+ (p_viport->newMtu != mtu))\r
+ {\r
+ p_viport->newFlags = flags;\r
+ p_viport->newMtu = mtu;\r
+ InterlockedOr( &p_viport->updates, NEED_LINK_CONFIG );\r
+ }\r
+ KeReleaseSpinLock( &p_viport->lock, irql );\r
+\r
+ status = _viport_process_query( p_viport, TRUE );\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return status;\r
+}\r
+\r
+BOOLEAN\r
+viport_setUnicast(\r
+ IN viport_t *p_viport,\r
+ IN uint8_t *p_address )\r
+{\r
+ KIRQL flags;\r
+\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ if( !p_viport )\r
+ return FALSE;\r
+\r
+ KeAcquireSpinLock( &p_viport->lock, &flags );\r
+ if( p_viport->macAddresses == NULL )\r
+ {\r
+ KeReleaseSpinLock( &p_viport->lock, flags );\r
+ return FALSE;\r
+ }\r
+ if( cl_memcmp(p_viport->macAddresses[UNICAST_ADDR].address,\r
+ p_address, MAC_ADDR_LEN ) )\r
+ {\r
+ cl_memcpy( p_viport->macAddresses[UNICAST_ADDR].address,\r
+ p_address, MAC_ADDR_LEN );\r
+ p_viport->macAddresses[UNICAST_ADDR].operation\r
+ = INIC_OP_SET_ENTRY;\r
+ InterlockedOr( &p_viport->updates, NEED_ADDRESS_CONFIG );\r
+ }\r
+ KeReleaseSpinLock( &p_viport->lock, flags );\r
+\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return TRUE;\r
+}\r
+\r
+\r
+/* Returns flags for state machine operations. */\r
+NDIS_STATUS\r
+viport_setMulticast(\r
+ IN viport_t *p_viport )\r
+{\r
+ vnic_adapter_t *p_adapter = p_viport->p_adapter;\r
+ uint32_t updates = 0;\r
+ int i;\r
+ KIRQL flags;\r
+ NDIS_STATUS status;\r
+\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ KeAcquireSpinLock( &p_viport->lock, &flags );\r
+\r
+ if( p_viport->macAddresses == NULL )\r
+ {\r
+ KeReleaseSpinLock( &p_viport->lock, flags );\r
+ return NDIS_STATUS_NOT_ACCEPTED;\r
+ }\r
+\r
+ ASSERT( (p_viport->updates & ~MCAST_OVERFLOW) == 0 );\r
+\r
+ if( p_adapter->mc_count > p_viport->numMacAddresses - MCAST_ADDR_START )\r
+ {\r
+ updates |= NEED_LINK_CONFIG | MCAST_OVERFLOW;\r
+ }\r
+ else if( p_adapter->mc_count == 0 )\r
+ {\r
+ /* NDIS can send us a NULL array to clear all entries */\r
+ if( InterlockedAnd(\r
+ &p_viport->updates, ~MCAST_OVERFLOW ) & MCAST_OVERFLOW )\r
+ {\r
+ updates |= NEED_LINK_CONFIG;\r
+ }\r
+ /* invalidate all entries for the remote */\r
+ for (i = MCAST_ADDR_START;\r
+ i < min( MAX_ADDR_ARRAY, p_viport->numMacAddresses ); i++ )\r
+ {\r
+ p_viport->macAddresses[i].valid = 0;\r
+ p_viport->macAddresses[i].operation = INIC_OP_SET_ENTRY;\r
+ }\r
+ updates |= NEED_ADDRESS_CONFIG;\r
+ }\r
+ else\r
+ {\r
+ if( InterlockedAnd(\r
+ &p_viport->updates, ~MCAST_OVERFLOW ) & MCAST_OVERFLOW )\r
+ {\r
+ updates |= NEED_LINK_CONFIG;\r
+ }\r
+ /* Brute force algorithm */\r
+ for (i = MCAST_ADDR_START;\r
+ i < min( MAX_ADDR_ARRAY, p_adapter->mc_count + MCAST_ADDR_START );\r
+ i++ )\r
+ {\r
+ if( p_viport->macAddresses[i].valid &&\r
+ NdisEqualMemory( p_viport->macAddresses[i].address,\r
+ p_adapter->mcast_array[i - MCAST_ADDR_START].addr,\r
+ MAC_ADDR_LEN ) )\r
+ {\r
+ continue;\r
+ }\r
+\r
+ NdisMoveMemory( &p_viport->macAddresses[i].address,\r
+ p_adapter->mcast_array[i - MCAST_ADDR_START].addr,\r
+ MAC_ADDR_LEN );\r
+\r
+ p_viport->macAddresses[i].valid = 1;\r
+ p_viport->macAddresses[i].operation = INIC_OP_SET_ENTRY;\r
+\r
+ updates |= NEED_ADDRESS_CONFIG;\r
+ }\r
+ for (; i < min( MAX_ADDR_ARRAY, p_viport->numMacAddresses ); i++ )\r
+ {\r
+ if( !p_viport->macAddresses[i].valid )\r
+ continue;\r
+\r
+ updates |= NEED_ADDRESS_CONFIG;\r
+\r
+ p_viport->macAddresses[i].valid = 0;\r
+ p_viport->macAddresses[i].operation = INIC_OP_SET_ENTRY;\r
+ }\r
+ }\r
+\r
+ /*\r
+ * Now that the mac array is setup, we can set the update bits\r
+ * to send the request.\r
+ */\r
+ InterlockedOr( &p_viport->updates, updates );\r
+ KeReleaseSpinLock( &p_viport->lock, flags );\r
+\r
+ status = _viport_process_query( p_viport, FALSE );\r
+\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return status;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+viport_getStats(\r
+ IN viport_t *p_viport )\r
+{\r
+ uint64_t stats_update_ms;\r
+ NDIS_STATUS status = STATUS_SUCCESS;\r
+\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ stats_update_ms = get_time_stamp_ms();\r
+\r
+ if( stats_update_ms > p_viport->lastStatsTime + p_viport->port_config.statsInterval )\r
+ {\r
+ p_viport->lastStatsTime = (uint32_t)stats_update_ms;\r
+\r
+ InterlockedOr( &p_viport->updates, NEED_STATS );\r
+ // TODO: Should the following call be synchronous?\r
+ status = _viport_process_query( p_viport, TRUE );\r
+ if ( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("Query NEED_STATS Failed\n") );\r
+ }\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return status;\r
+}\r
+\r
+\r
+BOOLEAN\r
+viport_xmitPacket(\r
+ IN viport_t* const p_viport,\r
+ IN NDIS_PACKET* const p_packet )\r
+{\r
+ BOOLEAN status = FALSE;\r
+ KIRQL flags;\r
+ cl_list_item_t *p_list_item;\r
+\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ KeAcquireSpinLock( &p_viport->lock, &flags );\r
+\r
+ if( p_viport->p_adapter->xmitStarted )\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
+ status = data_xmitPacket( &p_viport->data,\r
+ VNIC_PACKET_FROM_LIST_ITEM( p_list_item ));\r
+ }\r
+ status = data_xmitPacket( &p_viport->data, p_packet );\r
+ }\r
+ else\r
+ {\r
+ cl_qlist_insert_tail( &p_viport->send_pending_list,\r
+ VNIC_LIST_ITEM_FROM_PACKET( p_packet ) );\r
+ }\r
+\r
+ KeReleaseSpinLock( &p_viport->lock, flags );\r
+\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return status;\r
+}\r
+\r
+void viport_linkUp(viport_t *p_viport)\r
+{\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+ InterlockedExchange( &p_viport->p_adapter->carrier, TRUE );\r
+ NdisMIndicateStatus( p_viport->p_adapter->h_handle,\r
+ NDIS_STATUS_MEDIA_CONNECT, NULL, 0 );\r
+ NdisMIndicateStatusComplete( p_viport->p_adapter->h_handle );\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return;\r
+}\r
+\r
+void viport_linkDown(viport_t *p_viport)\r
+{\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+ InterlockedExchange( &p_viport->p_adapter->carrier, FALSE );\r
+ NdisMIndicateStatus( p_viport->p_adapter->h_handle,\r
+ NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );\r
+ NdisMIndicateStatusComplete( p_viport->p_adapter->h_handle );\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return;\r
+}\r
+\r
+void viport_stopXmit(viport_t *p_viport)\r
+{\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+ netpath_stopXmit( p_viport->p_netpath );\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return;\r
+}\r
+\r
+void viport_restartXmit(viport_t *p_viport)\r
+{\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+ netpath_restartXmit( p_viport->p_netpath );\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return;\r
+}\r
+\r
+void\r
+viport_recvPacket(\r
+ IN viport_t *p_viport,\r
+ IN NDIS_PACKET *p_packet )\r
+{\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+ netpath_recvPacket(p_viport->p_netpath, p_packet );\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return;\r
+}\r
+\r
+\r
+void\r
+viport_failure(\r
+ IN viport_t *p_viport )\r
+{\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ InterlockedExchange( (volatile LONG*)&p_viport->errored, 1 );\r
+\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+}\r
+\r
+\r
+void\r
+viport_timeout(\r
+ IN void *context )\r
+{\r
+ viport_t *p_viport = (viport_t *)context;\r
+\r
+ InterlockedExchange( &p_viport->timerActive, FALSE );\r
+ if( p_viport && p_viport->data.connected )\r
+ {\r
+ // TODO: What about send failure?\r
+ control_heartbeatReq( &p_viport->control,\r
+ p_viport->port_config.hbTimeout );\r
+ }\r
+}\r
+\r
+\r
+void\r
+viport_timer(\r
+ IN viport_t *p_viport,\r
+ IN int timeout )\r
+{\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );;\r
+\r
+ InterlockedExchange( &p_viport->timerActive, TRUE );\r
+ cl_timer_start( &p_viport->timer, (uint32_t)timeout );\r
+\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+}\r
+\r
+\r
+void\r
+viport_timerStop(\r
+ IN viport_t *p_viport )\r
+{\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ if( p_viport )\r
+ {\r
+ if( InterlockedExchange( &p_viport->timerActive, FALSE ) == TRUE )\r
+ {\r
+ cl_timer_stop( &p_viport->timer );\r
+ }\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return;\r
+}\r
+\r
+static ib_api_status_t\r
+viport_initMacAddresses(\r
+ IN viport_t *p_viport )\r
+{\r
+ int i, size;\r
+ KIRQL flags;\r
+ NDIS_STATUS status;\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ size = p_viport->numMacAddresses * sizeof(Inic_AddressOp_t);\r
+ status = NdisAllocateMemoryWithTag( &p_viport->macAddresses, size , 'acam' );\r
+\r
+ if ( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("Failed allocating MAC address table size %d\n", size) );\r
+ return IB_INSUFFICIENT_MEMORY;\r
+ }\r
+\r
+ NdisZeroMemory( p_viport->macAddresses, size );\r
+\r
+ KeAcquireSpinLock( &p_viport->lock, &flags );\r
+ for( i = 0; i < p_viport->numMacAddresses; i++ )\r
+ {\r
+ p_viport->macAddresses[i].index = (uint16_t)i;\r
+ p_viport->macAddresses[i].vlan = p_viport->defaultVlan;\r
+ }\r
+\r
+ NdisFillMemory( p_viport->macAddresses[BROADCAST_ADDR].address,\r
+ MAC_ADDR_LEN, 0xFF );\r
+ p_viport->macAddresses[BROADCAST_ADDR].valid = TRUE;\r
+\r
+ NdisMoveMemory( p_viport->macAddresses[UNICAST_ADDR].address,\r
+ p_viport->hwMacAddress, MAC_ADDR_LEN );\r
+\r
+ p_viport->macAddresses[UNICAST_ADDR].valid = TRUE;\r
+ p_viport->p_adapter->macSet = TRUE;\r
+\r
+ KeReleaseSpinLock( &p_viport->lock, flags );\r
+\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+viport_control_connect(\r
+ IN viport_t* const p_viport )\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ ib_status = control_init( &p_viport->control, p_viport,\r
+ &p_viport->port_config.controlConfig, p_viport->portGuid );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return ib_status;\r
+ }\r
+\r
+ ib_status = ibqp_connect( &p_viport->control.qp );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ ("control QP connect failed\n"));\r
+ goto err1;\r
+ }\r
+\r
+ InterlockedExchange( (volatile LONG*)&p_viport->linkState,\r
+ (LONG)LINK_INITINICREQ );\r
+\r
+ ib_status = control_initInicReq( &p_viport->control );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_INFO, ("CMD_INIT_INIC REQ failed\n") );\r
+ goto err2;\r
+ }\r
+ cl_event_wait_on( &p_viport->conn_event,\r
+ (p_viport->control.p_conf->rspTimeout << 11), TRUE );\r
+\r
+ if( p_viport->linkState != LINK_INITINICRSP )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ ("CMD_INIT_INIC RSP failed\n"));\r
+ ib_status = IB_INSUFFICIENT_RESOURCES;\r
+ goto err2;\r
+ }\r
+\r
+ vnic_resume_oids( p_viport->p_adapter );\r
+\r
+ ib_status = viport_initMacAddresses( p_viport );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ ("Init MAC Addresses failed\n"));\r
+err2:\r
+ control_resetReq( &p_viport->control );\r
+err1:\r
+ control_cleanup( &p_viport->control );\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return ib_status;\r
+}\r
+\r
+ib_api_status_t\r
+viport_data_connect(\r
+ IN viport_t* const p_viport )\r
+{\r
+ NDIS_STATUS status;\r
+ ib_api_status_t ib_status;\r
+\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ ib_status = data_init( &p_viport->data,\r
+ &p_viport->port_config.dataConfig,\r
+ p_viport->portGuid );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR, ("Data init returned %s\n",\r
+ p_viport->p_adapter->ifc.get_err_str( ib_status )) );\r
+ return ib_status;\r
+ }\r
+ InterlockedExchange( (volatile LONG*)&p_viport->linkState,\r
+ (LONG)LINK_CONFIGDATAPATHREQ );\r
+\r
+ ib_status = control_configDataPathReq( &p_viport->control,\r
+ data_pathId(&p_viport->data ), data_hostPoolMax( &p_viport->data ),\r
+ data_eiocPoolMax( &p_viport->data ) );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("command CONFIGDATAPATH REQ failed\n"));\r
+ return ib_status;\r
+ }\r
+ cl_event_wait_on( &p_viport->conn_event,\r
+ (p_viport->control.p_conf->rspTimeout << 11), TRUE );\r
+ \r
+ if( p_viport->linkState != LINK_CONFIGDATAPATHRSP )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("failed to get CONFIGDATAPATH RSP\n"));\r
+ return IB_INSUFFICIENT_RESOURCES;\r
+ }\r
+\r
+ ib_status = data_connect( &p_viport->data );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return ib_status;\r
+ }\r
+ cl_event_wait_on( &p_viport->conn_event,\r
+ (p_viport->control.p_conf->rspTimeout << 11), TRUE );\r
+ if( p_viport->data.qp.qpState != IB_ATTACHED )\r
+ {\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return IB_ERROR;\r
+ }\r
+ InterlockedExchange( (volatile LONG*)&p_viport->linkState,\r
+ (LONG)LINK_XCHGPOOLREQ );\r
+ ib_status = control_exchangePoolsReq( &p_viport->control,\r
+ data_localPoolAddr(&p_viport->data),\r
+ data_localPoolRkey(&p_viport->data) );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("command XCHGPOOL REQ failed\n"));\r
+ return ib_status;\r
+ }\r
+ cl_event_wait_on( &p_viport->conn_event,\r
+ (p_viport->control.p_conf->rspTimeout << 11), TRUE );\r
+\r
+ if( p_viport->linkState != LINK_XCHGPOOLRSP )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("failed to get LINK_XCHGPOOL RSP\n"));\r
+ return IB_ERROR;\r
+ }\r
+\r
+ InterlockedExchange( (volatile LONG*)&p_viport->linkState,\r
+ (LONG)LINK_INITIALIZED );\r
+ p_viport->state = VIPORT_CONNECTED;\r
+\r
+ data_connected(&p_viport->data);\r
+\r
+ InterlockedExchange( (volatile LONG *)&p_viport->mtu, 1500 );\r
+ InterlockedExchange( (volatile LONG *)&p_viport->flags, 0 );\r
+ status = viport_setLink( p_viport, INIC_FLAG_ENABLE_NIC, 1500 );\r
+ if( status != NDIS_STATUS_SUCCESS )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
+ ("failed to set Link flags\n"));\r
+ return IB_ERROR;\r
+ }\r
+\r
+ /* now we have to start periodic heartbeat timer */\r
+ if( p_viport->port_config.hbInterval )\r
+ {\r
+ viport_timer( p_viport, p_viport->port_config.hbInterval );\r
+ }\r
+\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return IB_SUCCESS;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+_viport_process_query(\r
+ IN viport_t* const p_viport,\r
+ IN BOOLEAN sync )\r
+{\r
+ NDIS_STATUS status;\r
+ ib_api_status_t ib_status;\r
+ KIRQL irql;\r
+ LinkState_t expected_state = 0;\r
+\r
+ VNIC_ENTER( VNIC_DBG_VIPORT );\r
+\r
+ if ( p_viport->state != VIPORT_CONNECTED ||\r
+ p_viport->errored != 0 )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_WARN, ("Invalid state or error.\n") );\r
+ return NDIS_STATUS_NOT_ACCEPTED;\r
+ }\r
+\r
+ // Check for updates. Note that unless sync is set to TRUE, this\r
+ // is the only way for this function to return success.\r
+ if( !InterlockedCompareExchange( &p_viport->updates, 0, 0 ) )\r
+ {\r
+ VNIC_TRACE_EXIT( VNIC_DBG_VIPORT, ("No updates.\n") );\r
+ return NDIS_STATUS_SUCCESS;\r
+ }\r
+\r
+ if( sync )\r
+ {\r
+ status = NDIS_STATUS_SUCCESS;\r
+ InterlockedOr( &p_viport->updates, SYNC_QUERY );\r
+ }\r
+ else\r
+ {\r
+ status = NDIS_STATUS_PENDING;\r
+ }\r
+\r
+ // Handle update bits one at a time.\r
+ if( p_viport->updates & NEED_ADDRESS_CONFIG )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ ("QUERY NEED_ADDRESS_CONFIG\n"));\r
+ KeAcquireSpinLock(&p_viport->lock, &irql );\r
+ p_viport->linkState = LINK_CONFIGADDRSREQ;\r
+ ib_status = control_configAddrsReq(\r
+ &p_viport->control, p_viport->macAddresses,\r
+ p_viport->numMacAddresses, &p_viport->addrs_query_done );\r
+ KeReleaseSpinLock( &p_viport->lock, irql );\r
+ if ( ib_status != IB_SUCCESS )\r
+ {\r
+ InterlockedAnd( &p_viport->updates, ~NEED_ADDRESS_CONFIG );\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ expected_state = LINK_CONFIGADDRSRSP;\r
+ }\r
+ else if( p_viport->updates & NEED_LINK_CONFIG )\r
+ {\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ ("QUERY NEED_LINK_CONFIG\n"));\r
+\r
+ KeAcquireSpinLock(&p_viport->lock, &irql );\r
+ p_viport->linkState = LINK_CONFIGLINKREQ;\r
+\r
+ if( (InterlockedAnd(\r
+ &p_viport->updates, ~MCAST_OVERFLOW ) & MCAST_OVERFLOW) )\r
+ {\r
+ p_viport->newFlags |= INIC_FLAG_ENABLE_MCAST_ALL;\r
+ }\r
+ else\r
+ {\r
+ p_viport->newFlags &= ~INIC_FLAG_ENABLE_MCAST_ALL;\r
+ }\r
+\r
+ if ( p_viport->mtu != p_viport->newMtu )\r
+ p_viport->mtu = p_viport->newMtu;\r
+\r
+ ib_status = control_configLinkReq( &p_viport->control,\r
+ p_viport->newFlags, p_viport->mtu );\r
+ KeReleaseSpinLock( &p_viport->lock, irql );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ InterlockedAnd( &p_viport->updates, ~NEED_LINK_CONFIG );\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ expected_state = LINK_CONFIGLINKRSP;\r
+ }\r
+ else if( p_viport->updates & NEED_STATS )\r
+ {\r
+ // TODO: This is dead code.\r
+ VNIC_TRACE( VNIC_DBG_INFO,\r
+ ("QUERY NEED_STATS\n"));\r
+\r
+ KeAcquireSpinLock( &p_viport->lock, &irql );\r
+ p_viport->linkState = LINK_REPORTSTATREQ;\r
+\r
+ ib_status = control_reportStatisticsReq( &p_viport->control );\r
+ KeReleaseSpinLock( &p_viport->lock, irql );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ InterlockedAnd( &p_viport->updates, ~NEED_STATS );\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return NDIS_STATUS_FAILURE;\r
+ }\r
+ expected_state = LINK_REPORTSTATRSP;\r
+ }\r
+\r
+ if( sync )\r
+ {\r
+ cl_event_wait_on( &p_viport->conn_event, EVENT_NO_TIMEOUT, FALSE );\r
+\r
+ if( p_viport->linkState != expected_state )\r
+ {\r
+ status = NDIS_STATUS_FAILURE;\r
+ VNIC_TRACE( VNIC_DBG_ERROR,\r
+ ("Link state error: expected %d but got %d\n",\r
+ expected_state, p_viport->linkState));\r
+ }\r
+ }\r
+ VNIC_EXIT( VNIC_DBG_VIPORT );\r
+ return status;\r
+}\r
+\r
--- /dev/null
+/*\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
+#ifndef _VNIC_VIPORT_H_\r
+#define _VNIC_VIPORT_H_\r
+\r
+typedef struct _mc_list {\r
+ uint8_t mc_addr[MAC_ADDR_LEN];\r
+} mc_list_t;\r
+\r
+typedef enum {\r
+ VIPORT_DISCONNECTED,\r
+ VIPORT_CONNECTED\r
+} viport_state_t;\r
+\r
+typedef enum {\r
+ LINK_UNINITIALIZED,\r
+ LINK_INITIALIZE,\r
+ LINK_INITIALIZECONTROL,\r
+ LINK_INITIALIZEDATA,\r
+ LINK_CONTROLCONNECT,\r
+ LINK_CONTROLCONNECTWAIT,\r
+ LINK_INITINICREQ,\r
+ LINK_INITINICRSP,\r
+ LINK_BEGINDATAPATH,\r
+ LINK_CONFIGDATAPATHREQ,\r
+ LINK_CONFIGDATAPATHRSP,\r
+ LINK_DATACONNECT,\r
+ LINK_DATACONNECTWAIT,\r
+ LINK_XCHGPOOLREQ,\r
+ LINK_XCHGPOOLRSP,\r
+ LINK_INITIALIZED,\r
+ LINK_IDLE,\r
+ LINK_IDLING,\r
+ LINK_CONFIGLINKREQ,\r
+ LINK_CONFIGLINKRSP,\r
+ LINK_CONFIGADDRSREQ,\r
+ LINK_CONFIGADDRSRSP,\r
+ LINK_REPORTSTATREQ,\r
+ LINK_REPORTSTATRSP,\r
+ LINK_HEARTBEATREQ,\r
+ LINK_HEARTBEATRSP,\r
+ LINK_RESET,\r
+ LINK_RESETRSP,\r
+ LINK_RESETCONTROL,\r
+ LINK_RESETCONTROLRSP,\r
+ LINK_DATADISCONNECT,\r
+ LINK_CONTROLDISCONNECT,\r
+ LINK_CLEANUPDATA,\r
+ LINK_CLEANUPCONTROL,\r
+ LINK_DISCONNECTED,\r
+ LINK_RETRYWAIT\r
+} LinkState_t;\r
+\r
+/* index entries */\r
+#define BROADCAST_ADDR 0\r
+#define UNICAST_ADDR 1\r
+#define MCAST_ADDR_START 2\r
+#define MAX_MCAST (MAX_ADDR_ARRAY - MCAST_ADDR_START)\r
+\r
+#define currentMacAddress macAddresses[UNICAST_ADDR].address\r
+\r
+#define NEED_STATS 0x00000001\r
+#define NEED_ADDRESS_CONFIG 0x00000002\r
+#define NEED_LINK_CONFIG 0x00000004\r
+#define MCAST_OVERFLOW 0x00000008\r
+#define SYNC_QUERY 0x80000000\r
+\r
+typedef enum {\r
+ NETPATH_TS_IDLE,\r
+ NETPATH_TS_ACTIVE,\r
+ NETPATH_TS_EXPIRED\r
+} netpathTS_t;\r
+\r
+\r
+typedef struct {\r
+ LIST_ENTRY listPtrs;\r
+ struct _vnic_adapter *p_adapter;\r
+ uint8_t event_num;\r
+} InicNPEvent_t;\r
+\r
+typedef enum {\r
+ INICNP_CONNECTED = 0,\r
+ INICNP_DISCONNECTED,\r
+ INICNP_LINKUP,\r
+ INICNP_LINKDOWN,\r
+ INICNP_TIMEREXPIRED,\r
+ INICNP_UNIVERSAL1,\r
+ /* SECONDARYOFFSET MUST ALWAYS COME AT THE END */\r
+ INICNP_SECONDARYOFFSET\r
+} InicNPEventPos_t;\r
+\r
+#define INICNP_NUM_EVENTS (2 * INICNP_SECONDARYOFFSET)\r
+\r
+#define INIC_PRINP_CONNECTED INICNP_CONNECTED\r
+#define INIC_PRINP_DISCONNECTED INICNP_DISCONNECTED\r
+#define INIC_PRINP_LINKUP INICNP_LINKUP\r
+#define INIC_PRINP_LINKDOWN INICNP_LINKDOWN\r
+#define INIC_PRINP_TIMEREXPIRED INICNP_TIMEREXPIRED\r
+#define INIC_NP_SETLINK INICNP_UNIVERSAL1\r
+\r
+#define INIC_SECNP_CONNECTED (INICNP_CONNECTED + INICNP_SECONDARYOFFSET)\r
+#define INIC_SECNP_DISCONNECTED (INICNP_DISCONNECTED + INICNP_SECONDARYOFFSET)\r
+#define INIC_SECNP_LINKUP (INICNP_LINKUP + INICNP_SECONDARYOFFSET)\r
+#define INIC_SECNP_LINKDOWN (INICNP_LINKDOWN + INICNP_SECONDARYOFFSET)\r
+#define INIC_SECNP_TIMEREXPIRED (INICNP_TIMEREXPIRED + INICNP_SECONDARYOFFSET)\r
+#define INIC_NP_FREEINIC (INICNP_UNIVERSAL1 + INICNP_SECONDARYOFFSET)\r
+\r
+\r
+typedef struct Netpath {\r
+ volatile LONG carrier;\r
+ struct _vnic_adapter *p_adapter;\r
+ struct _viport *pViport;\r
+ size_t pathIdx;\r
+ uint64_t connectTime;\r
+ netpathTS_t timerState;\r
+} Netpath_t;\r
+\r
+typedef enum {\r
+ WAIT,\r
+ DELAY,\r
+ NOW\r
+} conn_wait_state_t;\r
+\r
+typedef struct _viport {\r
+ LIST_ENTRY listPtrs;\r
+ KSPIN_LOCK lock;\r
+ cl_obj_t obj;\r
+ cl_qlist_t send_pending_list;\r
+ struct _vnic_adapter *p_adapter;\r
+ struct Netpath *p_netpath;\r
+ struct ViportConfig port_config;\r
+ struct Control control;\r
+ struct Data data;\r
+ uint64_t iocGuid;\r
+ uint64_t portGuid;\r
+\r
+ // connected/disconnected state of control and data QPs.\r
+ viport_state_t state;\r
+\r
+ // State machine state?\r
+ LinkState_t linkState;\r
+\r
+ Inic_CmdReportStatisticsRsp_t stats;\r
+ uint64_t lastStatsTime;\r
+ uint32_t featuresSupported;\r
+ uint8_t hwMacAddress[MAC_ADDR_LEN];\r
+ uint16_t defaultVlan;\r
+ uint16_t numMacAddresses;\r
+ Inic_AddressOp_t *macAddresses;\r
+ int32_t addrs_query_done;\r
+\r
+ // Indicates actions (to the VEx) that need to be taken.\r
+ volatile LONG updates;\r
+ // ???\r
+ uint8_t flags;\r
+ // TODO: Can we eliminate newFlags?\r
+ uint8_t newFlags;\r
+\r
+ uint16_t mtu;\r
+ uint16_t newMtu;\r
+ uint32_t errored;\r
+ uint32_t disconnect;\r
+ volatile LONG timerActive;\r
+ cl_timer_t timer;\r
+ cl_event_t conn_event;\r
+\r
+} viport_t;\r
+\r
+\r
+BOOLEAN\r
+viport_xmitPacket(\r
+ viport_t* const p_viport,\r
+ NDIS_PACKET* const p_pkt );\r
+\r
+BOOLEAN \r
+viport_config_defaults(\r
+ IN viport_t *p_viport );\r
+\r
+uint32_t\r
+viport_get_adapter_name(\r
+ IN viport_t *p_viport );\r
+\r
+void viport_cleanup(viport_t *p_viport );\r
+void viport_setPath(viport_t *pViport, ib_path_rec_t *path, uint64_t *guid);\r
+BOOLEAN viport_setParent(viport_t *pViport, struct Netpath *pNetpath);\r
+BOOLEAN viport_unsetParent(viport_t *pViport, struct Netpath *pNetpath);\r
+void viport_free(viport_t *pViport);\r
+void viport_disconnect(viport_t *pViport);\r
+NDIS_STATUS viport_setLink(viport_t *pViport, uint8_t flags, uint16_t mtu);\r
+NDIS_STATUS viport_getStats(viport_t *pViport );\r
+\r
+void viport_timer( viport_t *p_viport, int timeout );\r
+void viport_timerStop( viport_t *p_viport );\r
+\r
+void viport_linkUp(viport_t *pViport);\r
+void viport_linkDown(viport_t *pViport);\r
+void viport_stopXmit(viport_t *pViport);\r
+void viport_restartXmit(viport_t *pViport);\r
+void viport_recvPacket(viport_t *pViport, NDIS_PACKET *pkt );\r
+void viport_failure(viport_t *pViport);\r
+BOOLEAN viport_setUnicast(viport_t *pViport, uint8_t *pAddress);\r
+NDIS_STATUS viport_setMulticast( viport_t *pViport );\r
+#define viport_portGuid(pViport) ((pViport)->portGuid)\r
+#define viport_maxMtu(pViport) data_maxMtu(&(pViport)->data)\r
+\r
+#define viport_getHwAddr(pViport,pAddress) \\r
+ cl_memcpy(pAddress, (pViport)->hwMacAddress, MAC_ADDR_LEN)\r
+\r
+#define viport_features(pViport) ((pViport)->featuresSupported)\r
+#define viport_canTxCsum(pViport) (((pViport)->featuresSupported & \\r
+ (INIC_FEAT_IPV4_CSUM_TX|INIC_FEAT_TCP_CSUM_TX|INIC_FEAT_UDP_CSUM_TX)) \\r
+ == (INIC_FEAT_IPV4_CSUM_TX|INIC_FEAT_TCP_CSUM_TX|INIC_FEAT_UDP_CSUM_TX))\r
+\r
+\r
+void netpath_init( struct Netpath *pNetpath, struct _vnic_adapter *p_adapter );\r
+BOOLEAN netpath_addPath(struct Netpath *pNetpath, viport_t *pViport);\r
+BOOLEAN netpath_removePath(struct Netpath *pNetpath, viport_t *pViport);\r
+BOOLEAN netpath_getStats(struct Netpath *pNetpath );\r
+BOOLEAN netpath_setUnicast(struct Netpath *pNetpath, uint8_t *pAddress);\r
+BOOLEAN netpath_setMulticast(struct Netpath *pNetpath, mc_list_t *mc_list,\r
+ int mc_count);\r
+int netpath_maxMtu(struct Netpath *pNetpath);\r
+\r
+BOOLEAN\r
+netpath_xmitPacket(\r
+ struct Netpath* pNetpath,\r
+ NDIS_PACKET* const p_pkt );\r
+void \r
+netpath_recvPacket(\r
+ struct Netpath* pNetpath,\r
+ NDIS_PACKET* p_pkt );\r
+\r
+void netpath_stopXmit(struct Netpath *pNetpath );\r
+void netpath_restartXmit(struct Netpath *pNetpath );\r
+\r
+void netpath_kick(struct Netpath *pNetpath);\r
+void netpath_timer(struct Netpath *pNetpath, int timeout);\r
+void netpath_tx_timeout(struct Netpath *pNetpath);\r
+\r
+const char * netpath_to_string(struct _vnic_adapter *p_adapter, struct Netpath *pNetpath);\r
+#define netpath_getHwAddr(pNetpath, pAddress) viport_getHwAddr((pNetpath)->pViport, pAddress)\r
+#define netpath_isConnected(pNetpath) (pNetpath->state == NETPATH_CONNECTED)\r
+#define netpath_canTxCsum(pNetpath) viport_canTxCsum(pNetpath->pViport)\r
+\r
+ib_api_status_t\r
+viport_control_connect(\r
+ IN viport_t* const p_viport );\r
+ib_api_status_t\r
+viport_data_connect(\r
+ IN viport_t* const p_viport );\r
+\r
+NDIS_STATUS\r
+_viport_process_query(\r
+ IN viport_t* const p_viport,\r
+ IN BOOLEAN sync );\r
+\r
+\r
+#endif /* _VNIC_VIPORT_H_ */\r