2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
3 * Copyright (c) 2006 Mellanox Technologies. All rights reserved.
\r
4 * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.
\r
6 * This software is available to you under the OpenIB.org BSD license
\r
9 * Redistribution and use in source and binary forms, with or
\r
10 * without modification, are permitted provided that the following
\r
11 * conditions are met:
\r
13 * - Redistributions of source code must retain the above
\r
14 * copyright notice, this list of conditions and the following
\r
17 * - Redistributions in binary form must reproduce the above
\r
18 * copyright notice, this list of conditions and the following
\r
19 * disclaimer in the documentation and/or other materials
\r
20 * provided with the distribution.
\r
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
25 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
26 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
27 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
28 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
35 #include "ipoib_driver.h"
\r
36 #include "ipoib_debug.h"
\r
38 #if defined(EVENT_TRACING)
\r
42 #include "ipoib_driver.tmh"
\r
45 #include "ipoib_port.h"
\r
46 #include "ipoib_ibat.h"
\r
47 #include <complib/cl_bus_ifc.h>
\r
48 #include <complib/cl_init.h>
\r
49 #include <initguid.h>
\r
50 #include <iba/ipoib_ifc.h>
\r
51 #include "ntstrsafe.h"
\r
52 #include "strsafe.h"
\r
53 #include <offload.h>
\r
59 #if defined(NDIS50_MINIPORT)
\r
60 #define MAJOR_NDIS_VERSION 5
\r
61 #define MINOR_NDIS_VERSION 0
\r
62 #elif defined (NDIS51_MINIPORT)
\r
63 #define MAJOR_NDIS_VERSION 5
\r
64 #define MINOR_NDIS_VERSION 1
\r
66 #error NDIS Version not defined, try defining NDIS50_MINIPORT or NDIS51_MINIPORT
\r
69 PDRIVER_OBJECT g_p_drv_obj;
\r
71 static const NDIS_OID SUPPORTED_OIDS[] =
\r
73 OID_GEN_SUPPORTED_LIST,
\r
74 OID_GEN_HARDWARE_STATUS,
\r
75 OID_GEN_MEDIA_SUPPORTED,
\r
76 OID_GEN_MEDIA_IN_USE,
\r
77 OID_GEN_MAXIMUM_LOOKAHEAD,
\r
78 OID_GEN_MAXIMUM_FRAME_SIZE,
\r
80 OID_GEN_TRANSMIT_BUFFER_SPACE,
\r
81 OID_GEN_RECEIVE_BUFFER_SPACE,
\r
82 OID_GEN_TRANSMIT_BLOCK_SIZE,
\r
83 OID_GEN_RECEIVE_BLOCK_SIZE,
\r
85 OID_GEN_VENDOR_DESCRIPTION,
\r
86 OID_GEN_CURRENT_PACKET_FILTER,
\r
87 OID_GEN_CURRENT_LOOKAHEAD,
\r
88 OID_GEN_DRIVER_VERSION,
\r
89 OID_GEN_MAXIMUM_TOTAL_SIZE,
\r
90 OID_GEN_PROTOCOL_OPTIONS,
\r
91 OID_GEN_MAC_OPTIONS,
\r
92 OID_GEN_MEDIA_CONNECT_STATUS,
\r
93 OID_GEN_MAXIMUM_SEND_PACKETS,
\r
94 OID_GEN_NETWORK_LAYER_ADDRESSES,
\r
95 OID_GEN_VENDOR_DRIVER_VERSION,
\r
96 OID_GEN_PHYSICAL_MEDIUM,
\r
101 OID_GEN_RCV_NO_BUFFER,
\r
102 OID_GEN_DIRECTED_BYTES_XMIT,
\r
103 OID_GEN_DIRECTED_FRAMES_XMIT,
\r
104 OID_GEN_MULTICAST_BYTES_XMIT,
\r
105 OID_GEN_MULTICAST_FRAMES_XMIT,
\r
106 OID_GEN_BROADCAST_BYTES_XMIT,
\r
107 OID_GEN_BROADCAST_FRAMES_XMIT,
\r
108 OID_GEN_DIRECTED_BYTES_RCV,
\r
109 OID_GEN_DIRECTED_FRAMES_RCV,
\r
110 OID_GEN_MULTICAST_BYTES_RCV,
\r
111 OID_GEN_MULTICAST_FRAMES_RCV,
\r
112 OID_GEN_BROADCAST_BYTES_RCV,
\r
113 OID_GEN_BROADCAST_FRAMES_RCV,
\r
114 OID_802_3_PERMANENT_ADDRESS,
\r
115 OID_802_3_CURRENT_ADDRESS,
\r
116 OID_802_3_MULTICAST_LIST,
\r
117 OID_802_3_MAXIMUM_LIST_SIZE,
\r
118 OID_802_3_MAC_OPTIONS,
\r
119 OID_802_3_RCV_ERROR_ALIGNMENT,
\r
120 OID_802_3_XMIT_ONE_COLLISION,
\r
121 OID_802_3_XMIT_MORE_COLLISIONS,
\r
122 OID_TCP_TASK_OFFLOAD
\r
125 static const unsigned char VENDOR_ID[] = {0x00, 0x06, 0x6A, 0x00};
\r
127 #define VENDOR_DESCRIPTION "Internet Protocol over InfiniBand"
\r
129 #define IB_INFINITE_SERVICE_LEASE 0xFFFFFFFF
\r
131 //The mask is 8 bit and can't contain more than 6 non-zero bits
\r
132 #define MAX_GUID_MAX 0xFC
\r
135 /* Global driver debug level */
\r
136 uint32_t g_ipoib_dbg_level = TRACE_LEVEL_ERROR;
\r
137 uint32_t g_ipoib_dbg_flags = 0x00000fff;
\r
138 ipoib_globals_t g_ipoib = {0};
\r
140 typedef struct _IPOIB_REG_ENTRY
\r
142 NDIS_STRING RegName; // variable name text
\r
143 BOOLEAN bRequired; // 1 -> required, 0 -> optional
\r
144 UINT FieldOffset; // offset in parent struct
\r
145 UINT FieldSize; // size (in bytes) of the field
\r
146 UINT Default; // default value to use
\r
147 UINT Min; // minimum value allowed
\r
148 UINT Max; // maximum value allowed
\r
149 } IPOIB_REG_ENTRY, *PIPOIB_REG_ENTRY;
\r
151 IPOIB_REG_ENTRY HCARegTable[] = {
\r
152 // reg value name If Required Offset in parentr struct Field size Default Min Max
\r
153 {NDIS_STRING_CONST("GUIDMask"), 0, IPOIB_OFFSET(guid_mask), IPOIB_SIZE(guid_mask), 0, 0, MAX_GUID_MAX},
\r
154 /* GUIDMask should be the first element */
\r
155 {NDIS_STRING_CONST("RqDepth"), 1, IPOIB_OFFSET(rq_depth), IPOIB_SIZE(rq_depth), 512, 128, 1024},
\r
156 {NDIS_STRING_CONST("RqLowWatermark"), 0, IPOIB_OFFSET(rq_low_watermark), IPOIB_SIZE(rq_low_watermark), 4, 2, 8},
\r
157 {NDIS_STRING_CONST("SqDepth"), 1, IPOIB_OFFSET(sq_depth), IPOIB_SIZE(sq_depth), 512, 128, 1024},
\r
158 {NDIS_STRING_CONST("SendChksum"), 1, IPOIB_OFFSET(send_chksum_offload), IPOIB_SIZE(send_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS},
\r
159 {NDIS_STRING_CONST("RecvChksum"), 1, IPOIB_OFFSET(recv_chksum_offload), IPOIB_SIZE(recv_chksum_offload),CSUM_ENABLED,CSUM_DISABLED,CSUM_BYPASS},
\r
160 {NDIS_STRING_CONST("SaTimeout"), 1, IPOIB_OFFSET(sa_timeout), IPOIB_SIZE(sa_timeout), 1000, 250, UINT_MAX},
\r
161 {NDIS_STRING_CONST("SaRetries"), 1, IPOIB_OFFSET(sa_retry_cnt), IPOIB_SIZE(sa_retry_cnt), 10, 1, UINT_MAX},
\r
162 {NDIS_STRING_CONST("RecvRatio"), 1, IPOIB_OFFSET(recv_pool_ratio), IPOIB_SIZE(recv_pool_ratio), 1, 1, 10},
\r
163 {NDIS_STRING_CONST("PayloadMtu"), 1, IPOIB_OFFSET(payload_mtu), IPOIB_SIZE(payload_mtu), 2044, 512, 4092},
\r
164 {NDIS_STRING_CONST("lso"), 0, IPOIB_OFFSET(lso), IPOIB_SIZE(lso), 0, 0, 1},
\r
165 {NDIS_STRING_CONST("MCLeaveRescan"), 1, IPOIB_OFFSET(mc_leave_rescan), IPOIB_SIZE(mc_leave_rescan), 260, 1, 3600},
\r
166 {NDIS_STRING_CONST("BCJoinRetry"), 1, IPOIB_OFFSET(bc_join_retry), IPOIB_SIZE(bc_join_retry), 50, 0, 1000}
\r
170 #define IPOIB_NUM_REG_PARAMS (sizeof (HCARegTable) / sizeof(IPOIB_REG_ENTRY))
\r
175 NDIS_HANDLE h_adapter,
\r
177 ULONG eventLogMsgId)
\r
180 #define cMaxStrLen 40
\r
183 PWCHAR logMsgArray[cArrLen];
\r
184 WCHAR strVal[cMaxStrLen];
\r
185 NDIS_STRING AdapterInstanceName;
\r
187 IPOIB_INIT_NDIS_STRING(&AdapterInstanceName);
\r
188 if (NdisMQueryAdapterInstanceName(&AdapterInstanceName, h_adapter)!= NDIS_STATUS_SUCCESS ){
\r
190 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR, ("[IPoIB] Init:Failed to retreive adapter name.\n"));
\r
193 logMsgArray[0] = AdapterInstanceName.Buffer;
\r
195 if (RtlStringCbPrintfW(strVal, sizeof(strVal), L"0x%x", HCARegTable[ind].Default) != STATUS_SUCCESS) {
\r
197 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,
\r
198 ("[IPoIB] Init: Problem copying string value: exiting\n"));
\r
202 logMsgArray[0] = AdapterInstanceName.Buffer;
\r
203 logMsgArray[1] = HCARegTable[ind].RegName.Buffer;
\r
204 logMsgArray[2] = strVal;
\r
206 NdisWriteEventLogEntry(g_p_drv_obj, eventLogMsgId, 0, cArrLen, &logMsgArray, 0, NULL);
\r
214 IN PDRIVER_OBJECT p_drv_obj,
\r
215 IN PUNICODE_STRING p_reg_path );
\r
219 IN PDRIVER_OBJECT p_drv_obj );
\r
223 OUT PNDIS_STATUS p_open_err_status,
\r
224 OUT PUINT p_selected_medium_index,
\r
225 IN PNDIS_MEDIUM medium_array,
\r
226 IN UINT medium_array_size,
\r
227 IN NDIS_HANDLE h_adapter,
\r
228 IN NDIS_HANDLE wrapper_configuration_context );
\r
231 ipoib_check_for_hang(
\r
232 IN NDIS_HANDLE adapter_context );
\r
236 IN NDIS_HANDLE adapter_context );
\r
240 IN NDIS_HANDLE adapter_context,
\r
243 IN ULONG info_buf_len,
\r
244 OUT PULONG p_bytes_written,
\r
245 OUT PULONG p_bytes_needed );
\r
249 OUT PBOOLEAN p_addressing_reset,
\r
250 IN NDIS_HANDLE adapter_context );
\r
254 IN NDIS_HANDLE adapter_context,
\r
257 IN ULONG info_buf_length,
\r
258 OUT PULONG p_bytes_read,
\r
259 OUT PULONG p_bytes_needed );
\r
262 ipoib_send_packets(
\r
263 IN NDIS_HANDLE adapter_context,
\r
264 IN PPNDIS_PACKET packet_array,
\r
265 IN UINT num_packets );
\r
269 IN NDIS_HANDLE adapter_context,
\r
270 IN NDIS_DEVICE_PNP_EVENT pnp_event,
\r
272 IN ULONG info_buf_len );
\r
276 IN PVOID adapter_context );
\r
279 ipoib_complete_query(
\r
280 IN ipoib_adapter_t* const p_adapter,
\r
281 IN pending_oid_t* const p_oid_info,
\r
282 IN const NDIS_STATUS status,
\r
283 IN const void* const p_buf,
\r
284 IN const ULONG buf_len );
\r
287 __ipoib_set_net_addr(
\r
288 IN ipoib_adapter_t * p_adapter,
\r
290 IN ULONG info_buf_len,
\r
291 OUT PULONG p_bytes_read,
\r
292 OUT PULONG p_bytes_needed );
\r
295 __ipoib_get_tcp_task_offload(
\r
296 IN ipoib_adapter_t* p_adapter,
\r
297 IN pending_oid_t* const p_oid_info );
\r
300 __ipoib_ats_reg_cb(
\r
301 IN ib_reg_svc_rec_t *p_reg_svc_rec );
\r
304 __ipoib_ats_dereg_cb(
\r
305 IN void *context );
\r
308 __ipoib_read_registry(
\r
309 IN UNICODE_STRING* const p_registry_path );
\r
312 //! Standard Windows Device Driver Entry Point
\r
313 /*! DriverEntry is the first routine called after a driver is loaded, and
\r
314 is responsible for initializing the driver. On W2k this occurs when the PnP
\r
315 Manager matched a PnP ID to one in an INF file that references this driver.
\r
316 Any not success return value will cause the driver to fail to load.
\r
317 IRQL = PASSIVE_LEVEL
\r
319 @param p_drv_obj Pointer to Driver Object for this device driver
\r
320 @param p_registry_path Pointer to unicode string containing path to this driver's registry area
\r
321 @return STATUS_SUCCESS, NDIS_STATUS_BAD_CHARACTERISTICS, NDIS_STATUS_BAD_VERSION,
\r
322 NDIS_STATUS_RESOURCES, or NDIS_STATUS_FAILURE
\r
326 IN PDRIVER_OBJECT p_drv_obj,
\r
327 IN PUNICODE_STRING p_registry_path )
\r
329 NDIS_STATUS status;
\r
330 NDIS_HANDLE ndis_handle;
\r
331 NDIS_MINIPORT_CHARACTERISTICS characteristics;
\r
333 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
334 g_p_drv_obj = p_drv_obj;
\r
339 #if defined(EVENT_TRACING)
\r
340 WPP_INIT_TRACING(p_drv_obj, p_registry_path);
\r
343 if( !NT_SUCCESS( status ) )
\r
345 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
346 ("cl_init failed.\n") );
\r
350 status = NDIS_STATUS_SUCCESS;
\r
351 ndis_handle = NULL;
\r
353 __ipoib_read_registry(p_registry_path);
\r
355 KeInitializeSpinLock( &g_ipoib.lock );
\r
356 cl_qlist_init( &g_ipoib.adapter_list );
\r
358 g_stat.drv.obj = p_drv_obj;
\r
360 NdisMInitializeWrapper(
\r
361 &g_ipoib.h_ndis_wrapper, p_drv_obj, p_registry_path, NULL );
\r
363 memset(&characteristics, 0, sizeof(characteristics));
\r
364 characteristics.MajorNdisVersion = MAJOR_NDIS_VERSION;
\r
365 characteristics.MinorNdisVersion = MINOR_NDIS_VERSION;
\r
366 characteristics.CheckForHangHandler = ipoib_check_for_hang;
\r
367 characteristics.HaltHandler = ipoib_halt;
\r
368 characteristics.InitializeHandler = ipoib_initialize;
\r
369 characteristics.QueryInformationHandler = ipoib_query_info;
\r
370 characteristics.ResetHandler = ipoib_reset;
\r
371 characteristics.SetInformationHandler = ipoib_set_info;
\r
373 characteristics.ReturnPacketHandler = ipoib_return_packet;
\r
374 characteristics.SendPacketsHandler = ipoib_send_packets;
\r
376 #ifdef NDIS51_MINIPORT
\r
377 characteristics.PnPEventNotifyHandler = ipoib_pnp_notify;
\r
378 characteristics.AdapterShutdownHandler = ipoib_shutdown;
\r
381 status = NdisMRegisterMiniport(
\r
382 g_ipoib.h_ndis_wrapper, &characteristics, sizeof(characteristics) );
\r
383 if( status != NDIS_STATUS_SUCCESS )
\r
385 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
386 ("NdisMRegisterMiniport failed with status of %d\n", status) );
\r
387 NdisTerminateWrapper( g_ipoib.h_ndis_wrapper, NULL );
\r
392 NdisMRegisterUnloadHandler( g_ipoib.h_ndis_wrapper, ipoib_unload );
\r
394 IPOIB_PRINT_EXIT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,
\r
395 ("=====> DriverEntry exited\n"));
\r
401 __ipoib_read_registry(
\r
402 IN UNICODE_STRING* const p_registry_path )
\r
405 /* Remember the terminating entry in the table below. */
\r
406 RTL_QUERY_REGISTRY_TABLE table[4];
\r
407 UNICODE_STRING param_path;
\r
409 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
410 RtlInitUnicodeString( ¶m_path, NULL );
\r
411 param_path.MaximumLength = p_registry_path->Length +
\r
412 sizeof(L"\\Parameters");
\r
413 param_path.Buffer = cl_zalloc( param_path.MaximumLength );
\r
414 if( !param_path.Buffer )
\r
416 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
417 ("Failed to allocate parameters path buffer.\n") );
\r
418 return STATUS_INSUFFICIENT_RESOURCES;
\r
421 RtlAppendUnicodeStringToString( ¶m_path, p_registry_path );
\r
422 RtlAppendUnicodeToString( ¶m_path, L"\\Parameters" );
\r
425 * Clear the table. This clears all the query callback pointers,
\r
426 * and sets up the terminating table entry.
\r
428 cl_memclr( table, sizeof(table) );
\r
430 /* Setup the table entries. */
\r
431 table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
432 table[0].Name = L"DebugLevel";
\r
433 table[0].EntryContext = &g_ipoib_dbg_level;
\r
434 table[0].DefaultType = REG_DWORD;
\r
435 table[0].DefaultData = &g_ipoib_dbg_level;
\r
436 table[0].DefaultLength = sizeof(ULONG);
\r
438 table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
439 table[1].Name = L"DebugFlags";
\r
440 table[1].EntryContext = &g_ipoib_dbg_flags;
\r
441 table[1].DefaultType = REG_DWORD;
\r
442 table[1].DefaultData = &g_ipoib_dbg_flags;
\r
443 table[1].DefaultLength = sizeof(ULONG);
\r
445 table[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
446 table[2].Name = L"bypass_check_bcast_rate";
\r
447 table[2].EntryContext = &g_ipoib.bypass_check_bcast_rate;
\r
448 table[2].DefaultType = REG_DWORD;
\r
449 table[2].DefaultData = &g_ipoib.bypass_check_bcast_rate;
\r
450 table[2].DefaultLength = sizeof(ULONG);
\r
453 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
454 param_path.Buffer, table, NULL, NULL );
\r
456 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
457 ("debug level %d debug flags 0x%.8x\n",
\r
459 g_ipoib_dbg_flags));
\r
462 if( g_ipoib_dbg_flags & IPOIB_DBG_ERR )
\r
463 g_ipoib_dbg_flags |= CL_DBG_ERROR;
\r
466 cl_free( param_path.Buffer );
\r
467 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
474 IN PDRIVER_OBJECT p_drv_obj )
\r
476 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
477 #if defined(EVENT_TRACING)
\r
478 WPP_CLEANUP(p_drv_obj);
\r
481 UNREFERENCED_PARAMETER( p_drv_obj );
\r
483 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
489 ipoib_get_adapter_params(
\r
490 IN NDIS_HANDLE* const wrapper_config_context,
\r
491 IN OUT ipoib_adapter_t *p_adapter,
\r
495 NDIS_STATUS status;
\r
496 NDIS_HANDLE h_config;
\r
497 NDIS_CONFIGURATION_PARAMETER *p_param;
\r
499 PIPOIB_REG_ENTRY pRegEntry;
\r
501 PUCHAR structPointer;
\r
502 int sq_depth_step = 128;
\r
504 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
506 NdisOpenConfiguration( &status, &h_config, wrapper_config_context );
\r
507 if( status != NDIS_STATUS_SUCCESS )
\r
509 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
510 ("NdisOpenConfiguration returned 0x%.8x\n", status) );
\r
514 // read all the registry values
\r
515 for (i = 0, pRegEntry = HCARegTable; i < IPOIB_NUM_REG_PARAMS; ++i)
\r
517 // initialize pointer to appropriate place inside 'params'
\r
518 structPointer = (PUCHAR) &p_adapter->params + pRegEntry[i].FieldOffset;
\r
520 // Get the configuration value for a specific parameter. Under NT the
\r
521 // parameters are all read in as DWORDs.
\r
522 NdisReadConfiguration(
\r
526 &pRegEntry[i].RegName,
\r
527 NdisParameterInteger);
\r
529 // If the parameter was present, then check its value for validity.
\r
530 if (status == NDIS_STATUS_SUCCESS)
\r
532 // Check that param value is not too small or too large
\r
533 if (p_param->ParameterData.IntegerData < pRegEntry[i].Min ||
\r
534 p_param->ParameterData.IntegerData > pRegEntry[i].Max)
\r
536 value = pRegEntry[i].Default;
\r
537 ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_WRN);
\r
538 IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration.Registry %S value is out of range, setting default value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));
\r
543 value = p_param->ParameterData.IntegerData;
\r
544 IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));
\r
550 value = pRegEntry[i].Default;
\r
551 status = NDIS_STATUS_SUCCESS;
\r
552 if (pRegEntry[i].bRequired)
\r
554 ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_ERR);
\r
555 IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_INIT, ("Read configuration.Registry %S value not found, setting default value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));
\r
559 ipoib_create_log(p_adapter->h_adapter, i, EVENT_IPOIB_WRONG_PARAMETER_INFO);
\r
560 IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("Read configuration. Registry %S value not found, Value= 0x%x\n", pRegEntry[i].RegName.Buffer, value));
\r
565 // Store the value in the adapter structure.
\r
567 switch(pRegEntry[i].FieldSize)
\r
570 *((PUCHAR) structPointer) = (UCHAR) value;
\r
574 *((PUSHORT) structPointer) = (USHORT) value;
\r
578 *((PULONG) structPointer) = (ULONG) value;
\r
582 IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, ("Bogus field size %d\n", pRegEntry[i].FieldSize));
\r
587 // Send queue depth needs to be a power of two
\r
588 //static const INT sq_depth_step = 128;
\r
590 if (p_adapter->params.sq_depth % sq_depth_step) {
\r
591 static const c_sq_ind = 2;
\r
592 p_adapter->params.sq_depth = sq_depth_step *(
\r
593 p_adapter->params.sq_depth / sq_depth_step + !!( (p_adapter->params.sq_depth % sq_depth_step) > (sq_depth_step/2) ));
\r
594 ipoib_create_log(p_adapter->h_adapter, c_sq_ind, EVENT_IPOIB_WRONG_PARAMETER_WRN);
\r
595 IPOIB_PRINT(TRACE_LEVEL_VERBOSE, IPOIB_DBG_INIT, ("SQ DEPTH value was rounded to the closest acceptable value of 0x%x\n", p_adapter->params.sq_depth ));
\r
600 // Adjusting the low watermark parameter
\r
601 p_adapter->params.rq_low_watermark =
\r
602 p_adapter->params.rq_depth / p_adapter->params.rq_low_watermark;
\r
604 p_adapter->params.xfer_block_size = (sizeof(eth_hdr_t) + p_adapter->params.payload_mtu);
\r
605 NdisReadNetworkAddress( &status, p_mac, p_len, h_config );
\r
606 if (status != NDIS_STATUS_SUCCESS) {
\r
607 // Don't rely on NDIS, zero the values
\r
612 NdisCloseConfiguration( h_config );
\r
614 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
615 return NDIS_STATUS_SUCCESS;
\r
620 ipoib_get_adapter_guids(
\r
621 IN NDIS_HANDLE* const h_adapter,
\r
622 IN OUT ipoib_adapter_t *p_adapter )
\r
625 ib_al_ifc_data_t data;
\r
626 IO_STACK_LOCATION io_stack, *p_fwd_io_stack;
\r
627 DEVICE_OBJECT *p_pdo;
\r
630 IO_STATUS_BLOCK io_status;
\r
632 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
634 NdisMGetDeviceProperty( h_adapter, &p_pdo, NULL, NULL, NULL, NULL );
\r
636 /* Query for our interface */
\r
637 data.size = sizeof(ipoib_ifc_data_t);
\r
638 data.version = IPOIB_INTERFACE_DATA_VERSION;
\r
639 data.type = &GUID_IPOIB_INTERFACE_DATA;
\r
640 data.p_data = &p_adapter->guids;
\r
642 io_stack.MinorFunction = IRP_MN_QUERY_INTERFACE;
\r
643 io_stack.Parameters.QueryInterface.Version = AL_INTERFACE_VERSION;
\r
644 io_stack.Parameters.QueryInterface.Size = sizeof(ib_al_ifc_t);
\r
645 io_stack.Parameters.QueryInterface.Interface =
\r
646 (INTERFACE*)p_adapter->p_ifc;
\r
647 io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data;
\r
648 io_stack.Parameters.QueryInterface.InterfaceType =
\r
649 &GUID_IB_AL_INTERFACE;
\r
651 KeInitializeEvent( &event, NotificationEvent, FALSE );
\r
653 /* Build the IRP for the HCA. */
\r
654 p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_pdo,
\r
655 NULL, 0, NULL, &event, &io_status );
\r
658 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
659 ("Failed to allocate query interface IRP.\n") );
\r
660 return STATUS_INSUFFICIENT_RESOURCES;
\r
663 /* Copy the request query parameters. */
\r
664 p_fwd_io_stack = IoGetNextIrpStackLocation( p_irp );
\r
665 p_fwd_io_stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
\r
666 p_fwd_io_stack->Parameters.QueryInterface =
\r
667 io_stack.Parameters.QueryInterface;
\r
668 p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
\r
670 /* Send the IRP. */
\r
671 status = IoCallDriver( p_pdo, p_irp );
\r
672 if( status == STATUS_PENDING )
\r
674 KeWaitForSingleObject( &event, Executive, KernelMode,
\r
676 status = io_status.Status;
\r
679 if( !NT_SUCCESS( status ) )
\r
681 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
682 ("Query interface for IPOIB interface returned %08x.\n", status) );
\r
687 * Dereference the interface now so that the bus driver doesn't fail a
\r
688 * query remove IRP. We will always get unloaded before the bus driver
\r
689 * since we're a child device.
\r
691 if (p_adapter->p_ifc)
\r
692 p_adapter->p_ifc->wdm.InterfaceDereference(
\r
693 p_adapter->p_ifc->wdm.Context );
\r
694 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
695 return NDIS_STATUS_SUCCESS;
\r
699 //! Initialization function called for each IOC discovered
\r
700 /* The MiniportInitialize function is a required function that sets up a
\r
701 NIC (or virtual NIC) for network I/O operations, claims all hardware
\r
702 resources necessary to the NIC in the registry, and allocates resources
\r
703 the driver needs to carry out network I/O operations.
\r
704 IRQL = PASSIVE_LEVEL
\r
706 @param p_open_status Pointer to a status field set if this function returns NDIS_STATUS_OPEN_ERROR
\r
707 @param p_selected_medium_index Pointer to unsigned integer noting index into medium_array for this NIC
\r
708 @param medium_array Array of mediums for this NIC
\r
709 @param medium_array_size Number of elements in medium_array
\r
710 @param h_adapter Handle assigned by NDIS for this NIC
\r
711 @param wrapper_config_context Handle used for Ndis initialization functions
\r
712 @return NDIS_STATUS_SUCCESS, NDIS_STATUS_UNSUPPORTED_MEDIA, NDIS_STATUS_RESOURCES,
\r
713 NDIS_STATUS_NOT_SUPPORTED
\r
717 OUT PNDIS_STATUS p_open_status,
\r
718 OUT PUINT p_selected_medium_index,
\r
719 IN PNDIS_MEDIUM medium_array,
\r
720 IN UINT medium_array_size,
\r
721 IN NDIS_HANDLE h_adapter,
\r
722 IN NDIS_HANDLE wrapper_config_context )
\r
724 NDIS_STATUS status;
\r
725 ib_api_status_t ib_status;
\r
727 ipoib_adapter_t *p_adapter;
\r
729 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
735 UNUSED_PARAM( p_open_status );
\r
736 UNUSED_PARAM( wrapper_config_context );
\r
738 /* Search for our medium */
\r
739 for( medium_index = 0; medium_index < medium_array_size; ++medium_index )
\r
741 /* Check to see if we found our medium */
\r
742 if( medium_array[medium_index] == NdisMedium802_3 )
\r
746 if( medium_index == medium_array_size ) /* Never found it */
\r
748 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
749 ("No supported media.\n") );
\r
750 return NDIS_STATUS_UNSUPPORTED_MEDIA;
\r
753 *p_selected_medium_index = medium_index;
\r
755 /* Create the adapter adapter */
\r
756 ib_status = ipoib_create_adapter( wrapper_config_context, h_adapter, &p_adapter );
\r
757 if( ib_status != IB_SUCCESS )
\r
759 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
760 ("ipoib_create_adapter returned status %d.\n", ib_status ) );
\r
761 return NDIS_STATUS_FAILURE;
\r
764 /* Allow ten seconds for all SA queries to finish up. */
\r
765 NdisMSetAttributesEx( h_adapter, p_adapter, 5,
\r
766 NDIS_ATTRIBUTE_BUS_MASTER | NDIS_ATTRIBUTE_DESERIALIZE |
\r
767 NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS,
\r
768 NdisInterfacePNPBus );
\r
772 NdisMInitializeScatterGatherDma( h_adapter, TRUE, p_adapter->params.xfer_block_size );
\r
773 if( status != NDIS_STATUS_SUCCESS )
\r
775 ipoib_destroy_adapter( p_adapter );
\r
776 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
777 ("NdisMInitializeScatterGatherDma returned 0x%.8x.\n", status) );
\r
782 /* Create the adapter adapter */
\r
783 ib_status = ipoib_start_adapter( p_adapter );
\r
784 if( ib_status != IB_SUCCESS )
\r
786 NdisWriteErrorLogEntry( h_adapter,
\r
787 NDIS_ERROR_CODE_HARDWARE_FAILURE, 0 );
\r
788 ipoib_destroy_adapter( p_adapter );
\r
789 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
790 ("ipoib_start_adapter returned status %d.\n", ib_status ) );
\r
791 return NDIS_STATUS_FAILURE;
\r
794 p_adapter->p_stat = ipoib_st_dev_add();
\r
795 if ( p_adapter->p_stat )
\r
796 p_adapter->p_stat->p_adapter = p_adapter;
\r
800 IPOIB_PRINT_EXIT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,
\r
801 ("=====> ipoib_initialize exited\n"));
\r
807 //! Deallocates resources when the NIC is removed and halts the NIC..
\r
808 /* IRQL = DISPATCH_LEVEL
\r
810 @param adapter_context The adapter context allocated at start
\r
814 IN NDIS_HANDLE adapter_context )
\r
816 ipoib_adapter_t *p_adapter;
\r
817 PIPOIB_ST_DEVICE p_stat;
\r
819 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
821 ipoib_deref_ibat();
\r
823 CL_ASSERT( adapter_context );
\r
824 p_adapter = (ipoib_adapter_t*)adapter_context;
\r
825 p_stat = p_adapter->p_stat;
\r
826 p_stat->p_halt_thread = KeGetCurrentThread();
\r
828 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,
\r
829 ("Port %016I64x (CA %016I64x port %d) halting\n",
\r
830 p_adapter->guids.port_guid.guid, p_adapter->guids.ca_guid,
\r
831 p_adapter->guids.port_num) );
\r
833 ipoib_destroy_adapter( p_adapter );
\r
834 ipoib_st_dev_rmv( p_stat );
\r
836 IPOIB_PRINT_EXIT(TRACE_LEVEL_WARNING, IPOIB_DBG_INIT,
\r
837 ("=====> ipoib_halt exited\n"));
\r
841 //! Reports the state of the NIC, or monitors the responsiveness of an underlying device driver.
\r
842 /* IRQL = DISPATCH_LEVEL
\r
844 @param adapter_context The adapter context allocated at start
\r
845 @return TRUE if the driver determines that its NIC is not operating
\r
848 ipoib_check_for_hang(
\r
849 IN NDIS_HANDLE adapter_context )
\r
851 ipoib_adapter_t *p_adapter;
\r
853 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
854 CL_ASSERT( adapter_context );
\r
855 p_adapter = (ipoib_adapter_t*)adapter_context;
\r
857 if( p_adapter->reset )
\r
859 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
862 if (p_adapter->hung) {
\r
863 ipoib_resume_oids(p_adapter);
\r
866 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
867 return (p_adapter->hung? TRUE:FALSE);
\r
871 //! Returns information about the capabilities and status of the driver and/or its NIC.
\r
872 /* IRQL = DISPATCH_LEVEL
\r
874 @param adapter_context The adapter context allocated at start
\r
875 @param oid Object ID representing the query operation to be carried out
\r
876 @param info_buf Buffer containing any input for this query and location for output
\r
877 @param info_buf_len Number of bytes available in info_buf
\r
878 @param p_bytes_written Pointer to number of bytes written into info_buf
\r
879 @param p_bytes_needed Pointer to number of bytes needed to satisfy this oid
\r
880 @return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,
\r
881 NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_NOT_ACCEPTED, NDIS_STATUS_NOT_SUPPORTED,
\r
882 NDIS_STATUS_RESOURCES
\r
886 IN NDIS_HANDLE adapter_context,
\r
889 IN ULONG info_buf_len,
\r
890 OUT PULONG p_bytes_written,
\r
891 OUT PULONG p_bytes_needed )
\r
893 ipoib_adapter_t *p_adapter;
\r
894 NDIS_STATUS status;
\r
899 pending_oid_t oid_info;
\r
902 IPOIB_ENTER( IPOIB_DBG_OID );
\r
904 oid_info.oid = oid;
\r
905 oid_info.p_buf = info_buf;
\r
906 oid_info.buf_len = info_buf_len;
\r
907 oid_info.p_bytes_used = p_bytes_written;
\r
908 oid_info.p_bytes_needed = p_bytes_needed;
\r
910 CL_ASSERT( adapter_context );
\r
911 p_adapter = (ipoib_adapter_t*)adapter_context;
\r
913 CL_ASSERT( p_bytes_written );
\r
914 CL_ASSERT( p_bytes_needed );
\r
915 CL_ASSERT( !p_adapter->pending_query );
\r
917 status = NDIS_STATUS_SUCCESS;
\r
919 buf_len = sizeof(info);
\r
921 port_num = p_adapter->guids.port_num;
\r
925 /* Required General */
\r
926 case OID_GEN_SUPPORTED_LIST:
\r
927 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
928 ("Port %d received query for OID_GEN_SUPPORTED_LIST\n", port_num) );
\r
929 src_buf = (PVOID)SUPPORTED_OIDS;
\r
930 buf_len = sizeof(SUPPORTED_OIDS);
\r
933 case OID_GEN_HARDWARE_STATUS:
\r
934 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
935 ("Port %d received query for OID_GEN_HARDWARE_STATUS\n", port_num) );
\r
936 cl_obj_lock( &p_adapter->obj );
\r
937 switch( p_adapter->state )
\r
939 case IB_PNP_PORT_ADD:
\r
940 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
941 ("Port %d returning NdisHardwareStatusInitializing\n", port_num) );
\r
942 info = NdisHardwareStatusInitializing;
\r
945 case IB_PNP_PORT_ACTIVE:
\r
946 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
947 ("Port %d returning NdisHardwareStatusReady\n", port_num) );
\r
948 info = NdisHardwareStatusReady;
\r
952 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
953 ("Port %d returning NdisHardwareStatusNotReady\n", port_num) );
\r
954 info = NdisHardwareStatusNotReady;
\r
956 cl_obj_unlock( &p_adapter->obj );
\r
959 case OID_GEN_MEDIA_SUPPORTED:
\r
960 case OID_GEN_MEDIA_IN_USE:
\r
961 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
962 ("Port %d received query for OID_GEN_MEDIA_SUPPORTED "
\r
963 "or OID_GEN_MEDIA_IN_USE\n", port_num) );
\r
964 info = NdisMedium802_3;
\r
967 case OID_GEN_MAXIMUM_FRAME_SIZE:
\r
968 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
969 ("Port %d received query for OID_GEN_MAXIMUM_FRAME_SIZE\n", port_num) );
\r
970 info = p_adapter->params.payload_mtu;
\r
973 case OID_GEN_LINK_SPEED:
\r
974 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
975 ("Port %d received query for OID_GEN_LINK_SPEED\n", port_num) );
\r
976 cl_obj_lock( &p_adapter->obj );
\r
977 info = p_adapter->port_rate;
\r
978 cl_obj_unlock( &p_adapter->obj );
\r
981 case OID_GEN_TRANSMIT_BUFFER_SPACE:
\r
982 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
983 ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE\n", port_num) );
\r
984 info = p_adapter->params.sq_depth * p_adapter->params.xfer_block_size;
\r
987 case OID_GEN_RECEIVE_BUFFER_SPACE:
\r
988 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
989 ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE "
\r
990 "or OID_GEN_RECEIVE_BUFFER_SPACE\n", port_num) );
\r
991 info = p_adapter->params.rq_depth * p_adapter->params.xfer_block_size;
\r
994 case OID_GEN_MAXIMUM_LOOKAHEAD:
\r
995 case OID_GEN_CURRENT_LOOKAHEAD:
\r
996 case OID_GEN_TRANSMIT_BLOCK_SIZE:
\r
997 case OID_GEN_RECEIVE_BLOCK_SIZE:
\r
998 case OID_GEN_MAXIMUM_TOTAL_SIZE:
\r
999 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1000 ("Port %d received query for OID_GEN_MAXIMUM_LOOKAHEAD "
\r
1001 "or OID_GEN_CURRENT_LOOKAHEAD or "
\r
1002 "OID_GEN_TRANSMIT_BLOCK_SIZE or "
\r
1003 "OID_GEN_RECEIVE_BLOCK_SIZE or "
\r
1004 "OID_GEN_MAXIMUM_TOTAL_SIZE\n", port_num) );
\r
1005 info = p_adapter->params.xfer_block_size;
\r
1008 case OID_GEN_VENDOR_ID:
\r
1009 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1010 ("Port %d received query for OID_GEN_VENDOR_ID\n", port_num) );
\r
1011 src_buf = (void*)VENDOR_ID;
\r
1012 buf_len = sizeof(VENDOR_ID);
\r
1015 case OID_GEN_VENDOR_DESCRIPTION:
\r
1016 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1017 ("Port %d received query for OID_GEN_VENDOR_DESCRIPTION\n", port_num) );
\r
1018 src_buf = VENDOR_DESCRIPTION;
\r
1019 buf_len = sizeof(VENDOR_DESCRIPTION);
\r
1022 case OID_GEN_VENDOR_DRIVER_VERSION:
\r
1023 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1024 ("Port %d received query for OID_GEN_VENDOR_DRIVER_VERSION\n", port_num) );
\r
1025 src_buf = &version;
\r
1026 buf_len = sizeof(version);
\r
1027 //TODO: Figure out what the right version is.
\r
1028 version = 1 << 8 | 1;
\r
1031 case OID_GEN_PHYSICAL_MEDIUM:
\r
1032 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1033 ("Port %d received query for OID_GEN_PHYSICAL_MEDIUM\n", port_num) );
\r
1034 info = NdisPhysicalMediumUnspecified;
\r
1037 case OID_GEN_CURRENT_PACKET_FILTER:
\r
1038 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1039 ("Port %d received query for OID_GEN_CURRENT_PACKET_FILTER\n", port_num) );
\r
1040 info = p_adapter->packet_filter;
\r
1043 case OID_GEN_DRIVER_VERSION:
\r
1044 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1045 ("Port %d received query for OID_GEN_DRIVER_VERSION\n", port_num) );
\r
1046 src_buf = &version;
\r
1047 buf_len = sizeof(version);
\r
1048 version = MAJOR_NDIS_VERSION << 8 | MINOR_NDIS_VERSION;
\r
1051 case OID_GEN_MAC_OPTIONS:
\r
1052 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1053 ("Port %d received query for OID_GEN_MAC_OPTIONS\n", port_num) );
\r
1054 info = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
\r
1055 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
\r
1056 NDIS_MAC_OPTION_NO_LOOPBACK |
\r
1057 NDIS_MAC_OPTION_FULL_DUPLEX;
\r
1058 //TODO: Figure out if we will support priority and VLANs.
\r
1059 // NDIS_MAC_OPTION_8021P_PRIORITY;
\r
1060 //#ifdef NDIS51_MINIPORT
\r
1061 // info |= NDIS_MAC_OPTION_8021Q_VLAN;
\r
1065 case OID_GEN_MEDIA_CONNECT_STATUS:
\r
1066 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1067 ("Port %d received query for OID_GEN_MEDIA_CONNECT_STATUS\n", port_num) );
\r
1068 cl_obj_lock( &p_adapter->obj );
\r
1069 switch( p_adapter->state )
\r
1071 case IB_PNP_PORT_ADD:
\r
1072 case IB_PNP_PORT_INIT:
\r
1074 * Delay reporting media state until we know whether the port is
\r
1075 * either up or down.
\r
1077 p_adapter->pending_query = TRUE;
\r
1078 p_adapter->query_oid = oid_info;
\r
1080 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1081 ("Port %d returning NDIS_STATUS_PENDING\n", port_num) );
\r
1082 status = NDIS_STATUS_PENDING;
\r
1085 case IB_PNP_PORT_ACTIVE:
\r
1086 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1087 ("Port %d returning NdisMediaStateConnected\n", port_num) );
\r
1088 info = NdisMediaStateConnected;
\r
1091 case IB_PNP_PORT_REMOVE:
\r
1092 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1093 ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) );
\r
1094 status = NDIS_STATUS_NOT_ACCEPTED;
\r
1098 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1099 ("Port %d returning NdisMediaStateDisconnected\n", port_num) );
\r
1100 info = NdisMediaStateDisconnected;
\r
1102 cl_obj_unlock( &p_adapter->obj );
\r
1105 case OID_GEN_MAXIMUM_SEND_PACKETS:
\r
1106 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1107 ("Port %d received query for OID_GEN_MAXIMUM_SEND_PACKETS\n", port_num) );
\r
1108 info = MINIPORT_MAX_SEND_PACKETS;
\r
1111 /* Required General Statistics */
\r
1112 case OID_GEN_XMIT_OK:
\r
1113 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1114 ("Port %d received query for OID_GEN_XMIT_OK\n", port_num) );
\r
1116 status = ipoib_get_send_stat( p_adapter, IP_STAT_SUCCESS, &oid_info );
\r
1119 case OID_GEN_RCV_OK:
\r
1120 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1121 ("Port %d received query for OID_GEN_RCV_OK\n", port_num) );
\r
1123 status = ipoib_get_recv_stat( p_adapter, IP_STAT_SUCCESS, &oid_info );
\r
1126 case OID_GEN_XMIT_ERROR:
\r
1127 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1128 ("Port %d received query for OID_GEN_XMIT_ERROR\n", port_num) );
\r
1130 status = ipoib_get_send_stat( p_adapter, IP_STAT_ERROR, &oid_info );
\r
1133 case OID_GEN_RCV_ERROR:
\r
1134 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1135 ("Port %d received query for OID_GEN_RCV_ERROR\n", port_num) );
\r
1137 status = ipoib_get_recv_stat( p_adapter, IP_STAT_ERROR, &oid_info );
\r
1140 case OID_GEN_RCV_NO_BUFFER:
\r
1141 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1142 ("Port %d received query for OID_GEN_RCV_NO_BUFFER\n", port_num) );
\r
1144 status = ipoib_get_recv_stat( p_adapter, IP_STAT_DROPPED, &oid_info );
\r
1147 case OID_GEN_DIRECTED_BYTES_XMIT:
\r
1148 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1149 ("Port %d received query for OID_GEN_DIRECTED_BYTES_XMIT\n", port_num) );
\r
1151 status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info );
\r
1154 case OID_GEN_DIRECTED_FRAMES_XMIT:
\r
1155 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1156 ("Port %d received query for OID_GEN_DIRECTED_FRAMES_XMIT\n", port_num) );
\r
1158 status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info );
\r
1161 case OID_GEN_MULTICAST_BYTES_XMIT:
\r
1162 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1163 ("Port %d received query for OID_GEN_MULTICAST_BYTES_XMIT\n", port_num) );
\r
1165 status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info );
\r
1168 case OID_GEN_MULTICAST_FRAMES_XMIT:
\r
1169 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1170 ("Port %d received query for OID_GEN_MULTICAST_FRAMES_XMIT\n", port_num) );
\r
1172 status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info );
\r
1175 case OID_GEN_BROADCAST_BYTES_XMIT:
\r
1176 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1177 ("Port %d received query for OID_GEN_BROADCAST_BYTES_XMIT\n", port_num) );
\r
1179 status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info );
\r
1182 case OID_GEN_BROADCAST_FRAMES_XMIT:
\r
1183 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1184 ("Port %d received query for OID_GEN_BROADCAST_FRAMES_XMIT\n", port_num) );
\r
1186 status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info );
\r
1189 case OID_GEN_DIRECTED_BYTES_RCV:
\r
1190 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1191 ("Port %d received query for OID_GEN_DIRECTED_BYTES_RCV\n", port_num) );
\r
1193 status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info );
\r
1196 case OID_GEN_DIRECTED_FRAMES_RCV:
\r
1197 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1198 ("Port %d received query for OID_GEN_DIRECTED_FRAMES_RCV\n", port_num) );
\r
1200 status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info );
\r
1203 case OID_GEN_MULTICAST_BYTES_RCV:
\r
1204 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1205 ("Port %d received query for OID_GEN_MULTICAST_BYTES_RCV\n", port_num) );
\r
1207 status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info );
\r
1210 case OID_GEN_MULTICAST_FRAMES_RCV:
\r
1211 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1212 ("Port %d received query for OID_GEN_MULTICAST_FRAMES_RCV\n", port_num) );
\r
1214 status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info );
\r
1217 case OID_GEN_BROADCAST_BYTES_RCV:
\r
1218 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1219 ("Port %d received query for OID_GEN_BROADCAST_BYTES_RCV\n", port_num) );
\r
1221 status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info );
\r
1224 case OID_GEN_BROADCAST_FRAMES_RCV:
\r
1225 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1226 ("Port %d received query for OID_GEN_BROADCAST_FRAMES_RCV\n", port_num) );
\r
1228 status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info );
\r
1231 /* Required Ethernet operational characteristics */
\r
1232 case OID_802_3_PERMANENT_ADDRESS:
\r
1233 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1234 ("Port %d received query for OID_802_3_PERMANENT_ADDRESS\n", port_num) );
\r
1235 src_buf = &p_adapter->mac;
\r
1236 buf_len = sizeof(p_adapter->mac);
\r
1239 case OID_802_3_CURRENT_ADDRESS:
\r
1240 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1241 ("Port %d received query for OID_802_3_CURRENT_ADDRESS\n", port_num) );
\r
1242 src_buf = &p_adapter->params.conf_mac;
\r
1243 buf_len = sizeof(p_adapter->params.conf_mac);
\r
1246 case OID_802_3_MULTICAST_LIST:
\r
1247 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1248 ("Port %d received query for OID_802_3_MULTICAST_LIST\n", port_num) );
\r
1249 src_buf = p_adapter->mcast_array;
\r
1250 buf_len = p_adapter->mcast_array_size * sizeof(mac_addr_t);
\r
1253 case OID_802_3_MAXIMUM_LIST_SIZE:
\r
1254 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1255 ("Port %d received query for OID_802_3_MAXIMUM_LIST_SIZE\n", port_num) );
\r
1259 case OID_802_3_MAC_OPTIONS:
\r
1260 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1261 ("Port %d received query for OID_802_3_MAC_OPTIONS\n", port_num) );
\r
1265 /* Required Ethernet stats */
\r
1266 case OID_802_3_RCV_ERROR_ALIGNMENT:
\r
1267 case OID_802_3_XMIT_ONE_COLLISION:
\r
1268 case OID_802_3_XMIT_MORE_COLLISIONS:
\r
1269 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1270 ("Port %d received query for OID_802_3_RCV_ERROR_ALIGNMENT or "
\r
1271 "OID_802_3_XMIT_ONE_COLLISION or "
\r
1272 "OID_802_3_XMIT_MORE_COLLISIONS\n", port_num) );
\r
1276 case OID_TCP_TASK_OFFLOAD:
\r
1278 status = __ipoib_get_tcp_task_offload( p_adapter, &oid_info );
\r
1281 /* Optional General */
\r
1282 case OID_GEN_SUPPORTED_GUIDS:
\r
1283 #ifdef NDIS51_MINIPORT
\r
1284 case OID_GEN_VLAN_ID:
\r
1287 /* Optional General Stats */
\r
1288 case OID_GEN_RCV_CRC_ERROR:
\r
1289 case OID_GEN_TRANSMIT_QUEUE_LENGTH:
\r
1291 /* Optional Ethernet Stats */
\r
1292 case OID_802_3_XMIT_DEFERRED:
\r
1293 case OID_802_3_XMIT_MAX_COLLISIONS:
\r
1294 case OID_802_3_RCV_OVERRUN:
\r
1295 case OID_802_3_XMIT_UNDERRUN:
\r
1296 case OID_802_3_XMIT_HEARTBEAT_FAILURE:
\r
1297 case OID_802_3_XMIT_TIMES_CRS_LOST:
\r
1298 case OID_802_3_XMIT_LATE_COLLISIONS:
\r
1299 case OID_PNP_CAPABILITIES:
\r
1300 status = NDIS_STATUS_NOT_SUPPORTED;
\r
1301 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1302 ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid) );
\r
1305 case OID_GEN_PROTOCOL_OPTIONS:
\r
1306 case OID_GEN_NETWORK_LAYER_ADDRESSES:
\r
1307 case OID_GEN_TRANSPORT_HEADER_OFFSET:
\r
1308 #ifdef NDIS51_MINIPORT
\r
1309 case OID_GEN_MACHINE_NAME:
\r
1310 case OID_GEN_RNDIS_CONFIG_PARAMETER:
\r
1313 status = NDIS_STATUS_INVALID_OID;
\r
1314 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1315 ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid) );
\r
1320 * Complete the request as if it was handled asynchronously to maximize
\r
1321 * code reuse for when we really handle the requests asynchronously.
\r
1322 * Note that this requires the QueryInformation entry point to always
\r
1323 * return NDIS_STATUS_PENDING
\r
1325 if( status != NDIS_STATUS_PENDING )
\r
1327 ipoib_complete_query(
\r
1328 p_adapter, &oid_info, status, src_buf, buf_len );
\r
1331 IPOIB_EXIT( IPOIB_DBG_OID );
\r
1332 return NDIS_STATUS_PENDING;
\r
1337 ipoib_complete_query(
\r
1338 IN ipoib_adapter_t* const p_adapter,
\r
1339 IN pending_oid_t* const p_oid_info,
\r
1340 IN const NDIS_STATUS status,
\r
1341 IN const void* const p_buf,
\r
1342 IN const ULONG buf_len )
\r
1344 NDIS_STATUS oid_status = status;
\r
1346 IPOIB_ENTER( IPOIB_DBG_OID );
\r
1348 CL_ASSERT( status != NDIS_STATUS_PENDING );
\r
1350 if( status == NDIS_STATUS_SUCCESS )
\r
1352 if( p_oid_info->buf_len < buf_len )
\r
1354 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1355 ("Insufficient buffer space. "
\r
1356 "Returning NDIS_STATUS_INVALID_LENGTH.\n") );
\r
1357 oid_status = NDIS_STATUS_INVALID_LENGTH;
\r
1358 *p_oid_info->p_bytes_needed = buf_len;
\r
1359 *p_oid_info->p_bytes_used = 0;
\r
1361 else if( p_oid_info->p_buf )
\r
1363 /* Only copy if we have a distinct source buffer. */
\r
1366 NdisMoveMemory( p_oid_info->p_buf, p_buf, buf_len );
\r
1367 *p_oid_info->p_bytes_used = buf_len;
\r
1372 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1373 ("Returning NDIS_NOT_ACCEPTED") );
\r
1374 oid_status = NDIS_STATUS_NOT_ACCEPTED;
\r
1379 *p_oid_info->p_bytes_used = 0;
\r
1382 p_adapter->pending_query = FALSE;
\r
1384 NdisMQueryInformationComplete( p_adapter->h_adapter, oid_status );
\r
1386 IPOIB_EXIT( IPOIB_DBG_OID );
\r
1390 static NDIS_STATUS
\r
1391 __ipoib_get_tcp_task_offload(
\r
1392 IN ipoib_adapter_t* p_adapter,
\r
1393 IN pending_oid_t* const p_oid_info )
\r
1395 NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr;
\r
1396 NDIS_TASK_OFFLOAD *p_offload_task;
\r
1397 NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum;
\r
1399 NDIS_TASK_TCP_LARGE_SEND *p_offload_lso;
\r
1402 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1403 ("Port %d received query for OID_TCP_TASK_OFFLOAD\n",
\r
1404 p_adapter->guids.port_num) );
\r
1406 buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) +
\r
1407 offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +
\r
1408 sizeof(NDIS_TASK_TCP_IP_CHECKSUM) +
\r
1409 (p_adapter->params.lso ?
\r
1410 sizeof(NDIS_TASK_OFFLOAD) + sizeof(NDIS_TASK_TCP_LARGE_SEND)
\r
1413 *(p_oid_info->p_bytes_needed) = buf_len;
\r
1415 if( p_oid_info->buf_len < buf_len )
\r
1416 return NDIS_STATUS_INVALID_LENGTH;
\r
1418 p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_oid_info->p_buf;
\r
1419 if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )
\r
1420 return NDIS_STATUS_INVALID_DATA;
\r
1422 if( p_offload_hdr->EncapsulationFormat.Encapsulation !=
\r
1423 IEEE_802_3_Encapsulation )
\r
1425 return NDIS_STATUS_INVALID_DATA;
\r
1428 p_offload_hdr->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER);
\r
1429 p_offload_task = (NDIS_TASK_OFFLOAD*)(p_offload_hdr + 1);
\r
1430 p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;
\r
1431 p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);
\r
1432 p_offload_task->Task = TcpIpChecksumNdisTask;
\r
1433 p_offload_task->OffsetNextTask = 0;
\r
1434 p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
\r
1435 p_offload_chksum =
\r
1436 (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;
\r
1438 p_offload_chksum->V4Transmit.IpOptionsSupported =
\r
1439 p_offload_chksum->V4Transmit.TcpOptionsSupported =
\r
1440 p_offload_chksum->V4Transmit.TcpChecksum =
\r
1441 p_offload_chksum->V4Transmit.UdpChecksum =
\r
1442 p_offload_chksum->V4Transmit.IpChecksum =
\r
1443 !!(p_adapter->params.send_chksum_offload);
\r
1445 p_offload_chksum->V4Receive.IpOptionsSupported =
\r
1446 p_offload_chksum->V4Receive.TcpOptionsSupported =
\r
1447 p_offload_chksum->V4Receive.TcpChecksum =
\r
1448 p_offload_chksum->V4Receive.UdpChecksum =
\r
1449 p_offload_chksum->V4Receive.IpChecksum =
\r
1450 !!(p_adapter->params.recv_chksum_offload);
\r
1452 p_offload_chksum->V6Transmit.IpOptionsSupported = FALSE;
\r
1453 p_offload_chksum->V6Transmit.TcpOptionsSupported = FALSE;
\r
1454 p_offload_chksum->V6Transmit.TcpChecksum = FALSE;
\r
1455 p_offload_chksum->V6Transmit.UdpChecksum = FALSE;
\r
1457 p_offload_chksum->V6Receive.IpOptionsSupported = FALSE;
\r
1458 p_offload_chksum->V6Receive.TcpOptionsSupported = FALSE;
\r
1459 p_offload_chksum->V6Receive.TcpChecksum = FALSE;
\r
1460 p_offload_chksum->V6Receive.UdpChecksum = FALSE;
\r
1463 if (p_adapter->params.lso) {
\r
1464 // set the previous pointer to the correct place
\r
1465 p_offload_task->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) +
\r
1466 p_offload_task->TaskBufferLength;
\r
1467 // set the LSO packet
\r
1468 p_offload_task = (PNDIS_TASK_OFFLOAD)
\r
1469 ((PUCHAR)p_offload_task + p_offload_task->OffsetNextTask);
\r
1471 p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;
\r
1472 p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);
\r
1473 p_offload_task->Task = TcpLargeSendNdisTask;
\r
1474 p_offload_task->OffsetNextTask = 0;
\r
1475 p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
\r
1477 p_offload_lso = (PNDIS_TASK_TCP_LARGE_SEND) p_offload_task->TaskBuffer;
\r
1479 p_offload_lso->Version = 0;
\r
1480 //TODO optimal size: 60000, 64000 or 65536
\r
1481 //TODO LSO_MIN_SEG_COUNT to be 1
\r
1482 p_offload_lso->MaxOffLoadSize = LARGE_SEND_OFFLOAD_SIZE;
\r
1483 #define LSO_MIN_SEG_COUNT 2
\r
1484 p_offload_lso->MinSegmentCount = LSO_MIN_SEG_COUNT;
\r
1485 p_offload_lso->TcpOptions = TRUE;
\r
1486 p_offload_lso->IpOptions = TRUE;
\r
1489 *(p_oid_info->p_bytes_used) = buf_len;
\r
1491 return NDIS_STATUS_SUCCESS;
\r
1495 static NDIS_STATUS
\r
1496 __ipoib_set_tcp_task_offload(
\r
1497 IN ipoib_adapter_t* p_adapter,
\r
1498 IN void* const p_info_buf,
\r
1499 IN ULONG* const p_info_len )
\r
1501 NDIS_TASK_OFFLOAD_HEADER *p_offload_hdr;
\r
1502 NDIS_TASK_OFFLOAD *p_offload_task;
\r
1503 NDIS_TASK_TCP_IP_CHECKSUM *p_offload_chksum;
\r
1505 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1506 ("Port %d received set for OID_TCP_TASK_OFFLOAD\n",
\r
1507 p_adapter->guids.port_num) );
\r
1509 p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_info_buf;
\r
1511 if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) )
\r
1512 return NDIS_STATUS_INVALID_LENGTH;
\r
1514 if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )
\r
1515 return NDIS_STATUS_INVALID_DATA;
\r
1517 if( p_offload_hdr->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER) )
\r
1518 return NDIS_STATUS_INVALID_LENGTH;
\r
1520 if( !p_offload_hdr->OffsetFirstTask )
\r
1521 return NDIS_STATUS_SUCCESS;
\r
1523 if( p_offload_hdr->EncapsulationFormat.Encapsulation !=
\r
1524 IEEE_802_3_Encapsulation )
\r
1526 return NDIS_STATUS_INVALID_DATA;
\r
1529 p_offload_task = (NDIS_TASK_OFFLOAD*)
\r
1530 (((UCHAR*)p_offload_hdr) + p_offload_hdr->OffsetFirstTask);
\r
1532 if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) +
\r
1533 offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +
\r
1534 sizeof(NDIS_TASK_TCP_IP_CHECKSUM) )
\r
1536 return NDIS_STATUS_INVALID_LENGTH;
\r
1539 if( p_offload_task->Version != NDIS_TASK_OFFLOAD_VERSION )
\r
1540 return NDIS_STATUS_INVALID_DATA;
\r
1541 p_offload_chksum =
\r
1542 (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;
\r
1544 if( !p_adapter->params.send_chksum_offload &&
\r
1545 (p_offload_chksum->V4Transmit.IpOptionsSupported ||
\r
1546 p_offload_chksum->V4Transmit.TcpOptionsSupported ||
\r
1547 p_offload_chksum->V4Transmit.TcpChecksum ||
\r
1548 p_offload_chksum->V4Transmit.UdpChecksum ||
\r
1549 p_offload_chksum->V4Transmit.IpChecksum) )
\r
1551 return NDIS_STATUS_NOT_SUPPORTED;
\r
1554 if( !p_adapter->params.recv_chksum_offload &&
\r
1555 (p_offload_chksum->V4Receive.IpOptionsSupported ||
\r
1556 p_offload_chksum->V4Receive.TcpOptionsSupported ||
\r
1557 p_offload_chksum->V4Receive.TcpChecksum ||
\r
1558 p_offload_chksum->V4Receive.UdpChecksum ||
\r
1559 p_offload_chksum->V4Receive.IpChecksum) )
\r
1561 return NDIS_STATUS_NOT_SUPPORTED;
\r
1564 return NDIS_STATUS_SUCCESS;
\r
1568 //! Issues a hardware reset to the NIC and/or resets the driver's software state.
\r
1569 /* Tear down the connection and start over again. This is only called when there is a problem.
\r
1570 For example, if a send, query info, or set info had a time out. MiniportCheckForHang will
\r
1572 IRQL = DISPATCH_LEVEL
\r
1574 @param p_addr_resetPointer to BOOLLEAN that is set to TRUE if the NDIS
\r
1575 library should call MiniportSetInformation to restore addressing information to the current values.
\r
1576 @param adapter_context The adapter context allocated at start
\r
1577 @return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_NOT_RESETTABLE,
\r
1578 NDIS_STATUS_RESET_IN_PROGRESS, NDIS_STATUS_SOFT_ERRORS, NDIS_STATUS_HARD_ERRORS
\r
1582 OUT PBOOLEAN p_addr_reset,
\r
1583 IN NDIS_HANDLE adapter_context)
\r
1585 ipoib_adapter_t* p_adapter;
\r
1587 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
1589 CL_ASSERT( p_addr_reset );
\r
1590 CL_ASSERT( adapter_context );
\r
1591 p_adapter = (ipoib_adapter_t*)adapter_context;
\r
1593 switch( ipoib_reset_adapter( p_adapter ) )
\r
1596 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
1597 return NDIS_STATUS_PENDING;
\r
1600 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
1601 *p_addr_reset = TRUE;
\r
1602 return NDIS_STATUS_SUCCESS;
\r
1604 case IB_INVALID_STATE:
\r
1605 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
1606 return NDIS_STATUS_RESET_IN_PROGRESS;
\r
1609 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
1610 return NDIS_STATUS_HARD_ERRORS;
\r
1615 //! Request changes in the state information that the miniport driver maintains
\r
1616 /* For example, this is used to set multicast addresses and the packet filter.
\r
1617 IRQL = DISPATCH_LEVEL
\r
1619 @param adapter_context The adapter context allocated at start
\r
1620 @param oid Object ID representing the set operation to be carried out
\r
1621 @param info_buf Buffer containing input for this set and location for any output
\r
1622 @param info_buf_len Number of bytes available in info_buf
\r
1623 @param p_bytes_read Pointer to number of bytes read from info_buf
\r
1624 @param p_bytes_needed Pointer to number of bytes needed to satisfy this oid
\r
1625 @return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,
\r
1626 NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_INVALID_DATA, NDIS_STATUS_NOT_ACCEPTED,
\r
1627 NDIS_STATUS_NOT_SUPPORTED, NDIS_STATUS_RESOURCES
\r
1631 IN NDIS_HANDLE adapter_context,
\r
1633 IN PVOID info_buf,
\r
1634 IN ULONG info_buf_len,
\r
1635 OUT PULONG p_bytes_read,
\r
1636 OUT PULONG p_bytes_needed )
\r
1638 ipoib_adapter_t* p_adapter;
\r
1639 NDIS_STATUS status;
\r
1644 KLOCK_QUEUE_HANDLE hdl;
\r
1646 IPOIB_ENTER( IPOIB_DBG_OID );
\r
1648 CL_ASSERT( adapter_context );
\r
1649 p_adapter = (ipoib_adapter_t*)adapter_context;
\r
1651 CL_ASSERT( p_bytes_read );
\r
1652 CL_ASSERT( p_bytes_needed );
\r
1653 CL_ASSERT( !p_adapter->pending_set );
\r
1655 status = NDIS_STATUS_SUCCESS;
\r
1656 *p_bytes_needed = 0;
\r
1657 buf_len = sizeof(ULONG);
\r
1659 port_num = p_adapter->guids.port_num;
\r
1663 /* Required General */
\r
1664 case OID_GEN_CURRENT_PACKET_FILTER:
\r
1665 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1666 ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num));
\r
1667 if( info_buf_len < sizeof(p_adapter->packet_filter) )
\r
1669 status = NDIS_STATUS_INVALID_LENGTH;
\r
1671 else if( !info_buf )
\r
1673 status = NDIS_STATUS_INVALID_DATA;
\r
1677 KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );
\r
1678 cl_obj_lock( &p_adapter->obj );
\r
1679 switch( p_adapter->state )
\r
1681 case IB_PNP_PORT_ADD:
\r
1682 p_adapter->set_oid.oid = oid;
\r
1683 p_adapter->set_oid.p_buf = info_buf;
\r
1684 p_adapter->set_oid.buf_len = info_buf_len;
\r
1685 p_adapter->set_oid.p_bytes_used = p_bytes_read;
\r
1686 p_adapter->set_oid.p_bytes_needed = p_bytes_needed;
\r
1687 p_adapter->pending_set = TRUE;
\r
1688 status = NDIS_STATUS_PENDING;
\r
1691 case IB_PNP_PORT_REMOVE:
\r
1692 status = NDIS_STATUS_NOT_ACCEPTED;
\r
1696 if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) )
\r
1698 cl_qlist_insert_tail(
\r
1699 &g_ipoib.adapter_list, &p_adapter->entry );
\r
1702 * Filter was zero, now non-zero. Register IP addresses
\r
1705 ipoib_reg_addrs( p_adapter );
\r
1707 else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) )
\r
1710 * Filter was non-zero, now zero. Deregister IP addresses.
\r
1712 ipoib_dereg_addrs( p_adapter );
\r
1714 ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );
\r
1715 cl_qlist_remove_item(
\r
1716 &g_ipoib.adapter_list, &p_adapter->entry );
\r
1719 p_adapter->packet_filter = *(uint32_t*)info_buf;
\r
1721 cl_obj_unlock( &p_adapter->obj );
\r
1722 KeReleaseInStackQueuedSpinLock( &hdl );
\r
1726 case OID_GEN_CURRENT_LOOKAHEAD:
\r
1727 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1728 ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num));
\r
1729 if( info_buf_len < buf_len )
\r
1730 status = NDIS_STATUS_INVALID_LENGTH;
\r
1733 case OID_GEN_PROTOCOL_OPTIONS:
\r
1734 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1735 ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num));
\r
1736 if( info_buf_len < buf_len )
\r
1737 status = NDIS_STATUS_INVALID_LENGTH;
\r
1740 case OID_GEN_NETWORK_LAYER_ADDRESSES:
\r
1741 status = __ipoib_set_net_addr( p_adapter, info_buf, info_buf_len, p_bytes_read, p_bytes_needed);
\r
1744 #ifdef NDIS51_MINIPORT
\r
1745 case OID_GEN_MACHINE_NAME:
\r
1746 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,
\r
1747 ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) );
\r
1751 /* Required Ethernet operational characteristics */
\r
1752 case OID_802_3_MULTICAST_LIST:
\r
1753 IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,
\r
1754 ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) );
\r
1755 if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) )
\r
1757 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1758 ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) );
\r
1759 status = NDIS_STATUS_MULTICAST_FULL;
\r
1760 *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t);
\r
1762 else if( info_buf_len % sizeof(mac_addr_t) )
\r
1764 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1765 ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );
\r
1766 status = NDIS_STATUS_INVALID_DATA;
\r
1768 else if( !info_buf && info_buf_len )
\r
1770 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1771 ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );
\r
1772 status = NDIS_STATUS_INVALID_DATA;
\r
1776 ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf,
\r
1777 (uint8_t)(info_buf_len / sizeof(mac_addr_t)) );
\r
1779 buf_len = info_buf_len;
\r
1781 * Note that we don't return pending. It will likely take longer
\r
1782 * for our SA transactions to complete than NDIS will give us
\r
1783 * before reseting the adapter. If an SA failure is encountered,
\r
1784 * the adapter will be marked as hung and we will get reset.
\r
1786 status = NDIS_STATUS_SUCCESS;
\r
1790 case OID_TCP_TASK_OFFLOAD:
\r
1791 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1792 ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) );
\r
1794 buf_len = info_buf_len;
\r
1796 __ipoib_set_tcp_task_offload( p_adapter, info_buf, &buf_len );
\r
1799 /* Optional General */
\r
1800 case OID_GEN_TRANSPORT_HEADER_OFFSET:
\r
1801 #ifdef NDIS51_MINIPORT
\r
1802 case OID_GEN_RNDIS_CONFIG_PARAMETER:
\r
1803 case OID_GEN_VLAN_ID:
\r
1805 status = NDIS_STATUS_NOT_SUPPORTED;
\r
1806 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1807 ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid));
\r
1810 case OID_GEN_SUPPORTED_LIST:
\r
1811 case OID_GEN_HARDWARE_STATUS:
\r
1812 case OID_GEN_MEDIA_SUPPORTED:
\r
1813 case OID_GEN_MEDIA_IN_USE:
\r
1814 case OID_GEN_MAXIMUM_FRAME_SIZE:
\r
1815 case OID_GEN_LINK_SPEED:
\r
1816 case OID_GEN_TRANSMIT_BUFFER_SPACE:
\r
1817 case OID_GEN_RECEIVE_BUFFER_SPACE:
\r
1818 case OID_GEN_MAXIMUM_LOOKAHEAD:
\r
1819 case OID_GEN_TRANSMIT_BLOCK_SIZE:
\r
1820 case OID_GEN_RECEIVE_BLOCK_SIZE:
\r
1821 case OID_GEN_MAXIMUM_TOTAL_SIZE:
\r
1822 case OID_GEN_VENDOR_ID:
\r
1823 case OID_GEN_VENDOR_DESCRIPTION:
\r
1824 case OID_GEN_VENDOR_DRIVER_VERSION:
\r
1825 case OID_GEN_DRIVER_VERSION:
\r
1826 case OID_GEN_MAC_OPTIONS:
\r
1827 case OID_GEN_MEDIA_CONNECT_STATUS:
\r
1828 case OID_GEN_MAXIMUM_SEND_PACKETS:
\r
1829 case OID_GEN_SUPPORTED_GUIDS:
\r
1830 case OID_GEN_PHYSICAL_MEDIUM:
\r
1832 status = NDIS_STATUS_INVALID_OID;
\r
1833 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
1834 ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid));
\r
1838 if( status == NDIS_STATUS_SUCCESS )
\r
1840 *p_bytes_read = buf_len;
\r
1844 if( status == NDIS_STATUS_INVALID_LENGTH )
\r
1846 if ( !*p_bytes_needed )
\r
1848 *p_bytes_needed = buf_len;
\r
1852 *p_bytes_read = 0;
\r
1855 IPOIB_EXIT( IPOIB_DBG_OID );
\r
1860 //! Transfers some number of packets, specified as an array of packet pointers, over the network.
\r
1861 /* For a deserialized driver, these packets are completed asynchronously
\r
1862 using NdisMSendComplete.
\r
1863 IRQL <= DISPATCH_LEVEL
\r
1865 @param adapter_context Pointer to ipoib_adapter_t structure with per NIC state
\r
1866 @param packet_array Array of packets to send
\r
1867 @param numPackets Number of packets in the array
\r
1870 ipoib_send_packets(
\r
1871 IN NDIS_HANDLE adapter_context,
\r
1872 IN PPNDIS_PACKET packet_array,
\r
1873 IN UINT num_packets )
\r
1875 ipoib_adapter_t *p_adapter;
\r
1876 ipoib_port_t *p_port;
\r
1878 PERF_DECLARE( SendPackets );
\r
1879 PERF_DECLARE( PortSend );
\r
1881 IPOIB_ENTER( IPOIB_DBG_SEND );
\r
1883 cl_perf_start( SendPackets );
\r
1885 CL_ASSERT( adapter_context );
\r
1886 p_adapter = (ipoib_adapter_t*)adapter_context;
\r
1888 cl_obj_lock( &p_adapter->obj );
\r
1889 if( p_adapter->state != IB_PNP_PORT_ACTIVE || !p_adapter->p_port )
\r
1891 cl_obj_unlock( &p_adapter->obj );
\r
1892 for( packet_num = 0; packet_num < num_packets; ++packet_num )
\r
1894 ipoib_inc_send_stat( p_adapter, IP_STAT_DROPPED, 0 );
\r
1895 NdisMSendCompleteX( p_adapter->h_adapter,
\r
1896 packet_array[packet_num], NDIS_STATUS_ADAPTER_NOT_READY );
\r
1898 IPOIB_EXIT( IPOIB_DBG_SEND );
\r
1902 p_port = p_adapter->p_port;
\r
1903 ipoib_port_ref( p_port, ref_send_packets );
\r
1904 cl_obj_unlock( &p_adapter->obj );
\r
1906 cl_perf_start( PortSend );
\r
1907 ipoib_port_send( p_port, packet_array, num_packets );
\r
1908 cl_perf_stop( &p_port->p_adapter->perf, PortSend );
\r
1909 ipoib_port_deref( p_port, ref_send_packets );
\r
1911 cl_perf_stop( &p_adapter->perf, SendPackets );
\r
1913 cl_perf_log( &p_adapter->perf, SendBundle, num_packets );
\r
1915 IPOIB_EXIT( IPOIB_DBG_SEND );
\r
1921 IN NDIS_HANDLE adapter_context,
\r
1922 IN NDIS_DEVICE_PNP_EVENT pnp_event,
\r
1923 IN PVOID info_buf,
\r
1924 IN ULONG info_buf_len )
\r
1926 ipoib_adapter_t *p_adapter;
\r
1928 IPOIB_ENTER( IPOIB_DBG_PNP );
\r
1930 UNUSED_PARAM( info_buf );
\r
1931 UNUSED_PARAM( info_buf_len );
\r
1933 p_adapter = (ipoib_adapter_t*)adapter_context;
\r
1935 IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP, ("Event %d\n", pnp_event) );
\r
1936 if( pnp_event != NdisDevicePnPEventPowerProfileChanged )
\r
1938 cl_obj_lock( &p_adapter->obj );
\r
1939 p_adapter->state = IB_PNP_PORT_REMOVE;
\r
1940 cl_obj_unlock( &p_adapter->obj );
\r
1942 ipoib_resume_oids( p_adapter );
\r
1943 p_adapter->p_stat->n_pnp_irps++;
\r
1946 p_adapter->p_stat->n_power_irps++;
\r
1948 IPOIB_PRINT_EXIT(TRACE_LEVEL_WARNING, IPOIB_DBG_PNP,
\r
1949 ("=====> ipoib_pnp_notify exited, PnP event %d\n", pnp_event));
\r
1955 IN PVOID adapter_context )
\r
1957 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
1958 UNUSED_PARAM( adapter_context );
\r
1959 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
1964 ipoib_resume_oids(
\r
1965 IN ipoib_adapter_t* const p_adapter )
\r
1968 NDIS_STATUS status;
\r
1969 boolean_t pending_query, pending_set;
\r
1970 pending_oid_t query_oid = {0};
\r
1971 pending_oid_t set_oid = {0};
\r
1972 KLOCK_QUEUE_HANDLE hdl;
\r
1974 IPOIB_ENTER( IPOIB_DBG_INIT );
\r
1976 cl_obj_lock( &p_adapter->obj );
\r
1978 * Set the status depending on our state. Fail OID requests that
\r
1979 * are pending while we reset the adapter.
\r
1981 switch( p_adapter->state )
\r
1983 case IB_PNP_PORT_ADD:
\r
1984 status = NDIS_STATUS_FAILURE;
\r
1987 case IB_PNP_PORT_REMOVE:
\r
1988 status = NDIS_STATUS_NOT_ACCEPTED;
\r
1992 status = NDIS_STATUS_SUCCESS;
\r
1995 pending_query = p_adapter->pending_query;
\r
1996 if( pending_query )
\r
1998 query_oid = p_adapter->query_oid;
\r
1999 p_adapter->pending_query = FALSE;
\r
2001 pending_set = p_adapter->pending_set;
\r
2004 set_oid = p_adapter->set_oid;
\r
2005 p_adapter->pending_set = FALSE;
\r
2007 cl_obj_unlock( &p_adapter->obj );
\r
2010 * If we had a pending OID request for OID_GEN_LINK_SPEED,
\r
2011 * complete it now. Note that we hold the object lock since
\r
2012 * NdisMQueryInformationComplete is called at DISPATCH_LEVEL.
\r
2014 if( pending_query )
\r
2016 switch( query_oid.oid )
\r
2018 case OID_GEN_MEDIA_CONNECT_STATUS:
\r
2019 info = NdisMediaStateConnected;
\r
2020 ipoib_complete_query( p_adapter, &query_oid,
\r
2021 status, &info, sizeof(info) );
\r
2025 CL_ASSERT( query_oid.oid == OID_GEN_MEDIA_CONNECT_STATUS );
\r
2032 switch( set_oid.oid )
\r
2034 case OID_GEN_CURRENT_PACKET_FILTER:
\r
2035 /* Validation already performed in the SetInformation path. */
\r
2037 KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );
\r
2038 cl_obj_lock( &p_adapter->obj );
\r
2039 if( !p_adapter->packet_filter && (*(PULONG)set_oid.p_buf) )
\r
2041 cl_qlist_insert_tail(
\r
2042 &g_ipoib.adapter_list, &p_adapter->entry );
\r
2044 * Filter was zero, now non-zero. Register IP addresses
\r
2047 ipoib_reg_addrs( p_adapter );
\r
2049 else if( p_adapter->packet_filter && !(*(PULONG)set_oid.p_buf) )
\r
2051 /* Filter was non-zero, now zero. Deregister IP addresses. */
\r
2052 ipoib_dereg_addrs( p_adapter );
\r
2054 ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );
\r
2055 cl_qlist_remove_item(
\r
2056 &g_ipoib.adapter_list, &p_adapter->entry );
\r
2058 p_adapter->packet_filter = *(PULONG)set_oid.p_buf;
\r
2060 cl_obj_unlock( &p_adapter->obj );
\r
2061 KeReleaseInStackQueuedSpinLock( &hdl );
\r
2063 NdisMSetInformationComplete( p_adapter->h_adapter, status );
\r
2066 case OID_GEN_NETWORK_LAYER_ADDRESSES:
\r
2067 status = __ipoib_set_net_addr( p_adapter,
\r
2068 p_adapter->set_oid.p_buf,
\r
2069 p_adapter->set_oid.buf_len,
\r
2070 p_adapter->set_oid.p_bytes_used,
\r
2071 p_adapter->set_oid.p_bytes_needed );
\r
2072 if( status != NDIS_STATUS_PENDING )
\r
2074 NdisMSetInformationComplete( p_adapter->h_adapter, status );
\r
2079 CL_ASSERT( set_oid.oid && 0 );
\r
2084 IPOIB_EXIT( IPOIB_DBG_INIT );
\r
2088 static NDIS_STATUS
\r
2089 __ipoib_set_net_addr(
\r
2090 IN ipoib_adapter_t * p_adapter,
\r
2091 IN PVOID info_buf,
\r
2092 IN ULONG info_buf_len,
\r
2093 OUT PULONG p_bytes_read,
\r
2094 OUT PULONG p_bytes_needed )
\r
2096 NDIS_STATUS status;
\r
2097 PNETWORK_ADDRESS_LIST p_net_addrs;
\r
2098 PNETWORK_ADDRESS p_net_addr_oid;
\r
2099 PNETWORK_ADDRESS_IP p_ip_addr;
\r
2101 net_address_item_t *p_addr_item;
\r
2103 cl_status_t cl_status;
\r
2112 IPOIB_ENTER( IPOIB_DBG_OID );
\r
2114 status = NDIS_STATUS_SUCCESS;
\r
2115 port_num = p_adapter->guids.port_num;
\r
2117 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
2118 ("Port %d received set for OID_GEN_NETWORK_LAYER_ADDRESSES\n",
\r
2123 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
2124 ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - "
\r
2125 "NULL buffer\n", port_num) );
\r
2126 IPOIB_EXIT( IPOIB_DBG_OID );
\r
2127 return NDIS_STATUS_INVALID_DATA;
\r
2131 * Must use field offset because the structures define array's of size one
\r
2132 * of a the incorrect type for what is really stored.
\r
2134 if( info_buf_len < FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) )
\r
2136 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
2137 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "
\r
2138 "bad length of %d, not enough "
\r
2139 "for NETWORK_ADDRESS_LIST (%d)\n", port_num, info_buf_len,
\r
2140 FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address)) );
\r
2141 *p_bytes_needed = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address);
\r
2142 IPOIB_EXIT( IPOIB_DBG_OID );
\r
2143 return NDIS_STATUS_INVALID_LENGTH;
\r
2146 p_net_addrs = (PNETWORK_ADDRESS_LIST)info_buf;
\r
2147 if( p_net_addrs->AddressCount == 0)
\r
2149 if( p_net_addrs->AddressType == NDIS_PROTOCOL_ID_TCP_IP )
\r
2151 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,
\r
2152 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "
\r
2153 "clear TCP/IP addresses\n", port_num) );
\r
2157 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,
\r
2158 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "
\r
2159 "Non TCP/IP address type of 0x%.4X on clear\n",
\r
2160 port_num, p_net_addrs->AddressType) );
\r
2161 IPOIB_EXIT( IPOIB_DBG_OID );
\r
2162 return NDIS_STATUS_SUCCESS;
\r
2166 addr_size = FIELD_OFFSET(NETWORK_ADDRESS, Address) +
\r
2167 NETWORK_ADDRESS_LENGTH_IP;
\r
2168 total_size = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) +
\r
2169 addr_size * p_net_addrs->AddressCount;
\r
2171 if( info_buf_len < total_size )
\r
2173 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
2174 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "
\r
2175 "bad length of %d, %d required for %d addresses\n",
\r
2176 port_num, info_buf_len, total_size, p_net_addrs->AddressCount) );
\r
2177 *p_bytes_needed = total_size;
\r
2178 IPOIB_EXIT( IPOIB_DBG_OID );
\r
2179 return NDIS_STATUS_INVALID_LENGTH;
\r
2182 /* Lock lists for duration since SA callbacks can occur on other CPUs */
\r
2183 cl_obj_lock( &p_adapter->obj );
\r
2185 /* Set the capacity of the vector to accomodate all assinged addresses. */
\r
2186 cl_status = cl_vector_set_capacity(
\r
2187 &p_adapter->ip_vector, p_net_addrs->AddressCount );
\r
2188 if( cl_status != CL_SUCCESS )
\r
2190 cl_obj_unlock( &p_adapter->obj );
\r
2191 IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
2192 ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - "
\r
2193 "Failed to set IP vector capacity: %#x\n", port_num,
\r
2195 IPOIB_EXIT( IPOIB_DBG_OID );
\r
2196 return NDIS_STATUS_RESOURCES;
\r
2199 *p_bytes_read = total_size;
\r
2201 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
2202 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - List contains %d addresses\n",
\r
2203 port_num, p_net_addrs->AddressCount));
\r
2205 /* First look for addresses we had that should be removed */
\r
2206 for( idx = 0; idx != cl_vector_get_size( &p_adapter->ip_vector ); idx++ )
\r
2208 p_addr_item = (net_address_item_t*)
\r
2209 cl_vector_get_ptr( &p_adapter->ip_vector, idx );
\r
2210 p_net_addr_oid = (PNETWORK_ADDRESS)p_net_addrs->Address;
\r
2212 for( i = 0; i < p_net_addrs->AddressCount; ++i, p_net_addr_oid =
\r
2213 (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid +
\r
2214 FIELD_OFFSET(NETWORK_ADDRESS, Address) +
\r
2215 p_net_addr_oid->AddressLength) )
\r
2218 if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP )
\r
2220 IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,
\r
2221 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, "
\r
2222 "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType,
\r
2223 NDIS_PROTOCOL_ID_TCP_IP));
\r
2227 if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP)
\r
2229 IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,
\r
2230 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, "
\r
2231 "should be %d\n", port_num, i, p_net_addr_oid->AddressLength,
\r
2232 NETWORK_ADDRESS_LENGTH_IP));
\r
2236 p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address;
\r
2237 if( !cl_memcmp( &p_ip_addr->in_addr,
\r
2238 &p_addr_item->address.as_ulong, sizeof(ULONG) ) )
\r
2244 if( i == p_net_addrs->AddressCount )
\r
2246 /* Didn't find a match, delete from SA */
\r
2247 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
2248 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Deleting Address %d.%d.%d.%d\n",
\r
2250 p_addr_item->address.as_bytes[0],
\r
2251 p_addr_item->address.as_bytes[1],
\r
2252 p_addr_item->address.as_bytes[2],
\r
2253 p_addr_item->address.as_bytes[3]));
\r
2255 if( p_addr_item->p_reg )
\r
2257 if( p_addr_item->p_reg->h_reg_svc )
\r
2259 p_adapter->p_ifc->dereg_svc(
\r
2260 p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );
\r
2264 cl_free( p_addr_item->p_reg );
\r
2266 p_addr_item->p_reg = NULL;
\r
2268 p_addr_item->address.as_ulong = 0;
\r
2272 /* Now look for new addresses */
\r
2273 p_net_addr_oid = (NETWORK_ADDRESS *)p_net_addrs->Address;
\r
2275 for( i = 0; i < p_net_addrs->AddressCount; i++, p_net_addr_oid =
\r
2276 (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid +
\r
2277 FIELD_OFFSET(NETWORK_ADDRESS, Address) + p_net_addr_oid->AddressLength) )
\r
2280 if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP )
\r
2282 IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,
\r
2283 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, "
\r
2284 "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType,
\r
2285 NDIS_PROTOCOL_ID_TCP_IP));
\r
2289 if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP)
\r
2291 IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,
\r
2292 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, "
\r
2293 "should be %d\n", port_num, i, p_net_addr_oid->AddressLength,
\r
2294 NETWORK_ADDRESS_LENGTH_IP));
\r
2298 p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address;
\r
2300 /* Size the vector as needed. */
\r
2301 if( cl_vector_get_size( &p_adapter->ip_vector ) <= idx )
\r
2302 cl_vector_set_size( &p_adapter->ip_vector, idx + 1 );
\r
2304 p_addr_item = cl_vector_get_ptr( &p_adapter->ip_vector, idx );
\r
2305 if( !cl_memcmp( &p_ip_addr->in_addr, &p_addr_item->address.as_ulong,
\r
2309 /* Already have this address - no change needed */
\r
2314 * Copy the address information, but don't register yet - the port
\r
2317 if( p_addr_item->p_reg )
\r
2319 /* If in use by some other address, deregister. */
\r
2320 if( p_addr_item->p_reg->h_reg_svc )
\r
2322 p_adapter->p_ifc->dereg_svc(
\r
2323 p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );
\r
2327 cl_free( p_addr_item->p_reg );
\r
2329 p_addr_item->p_reg = NULL;
\r
2331 memcpy ((void *)&p_addr_item->address.as_ulong, (const void *)&p_ip_addr->in_addr, sizeof(ULONG) );
\r
2332 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
2333 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Adding Address %d.%d.%d.%d\n",
\r
2335 p_addr_item->address.as_bytes[0],
\r
2336 p_addr_item->address.as_bytes[1],
\r
2337 p_addr_item->address.as_bytes[2],
\r
2338 p_addr_item->address.as_bytes[3]) );
\r
2342 /* Now clear any extra entries that shouldn't be there. */
\r
2343 while( idx < cl_vector_get_size( &p_adapter->ip_vector ) )
\r
2345 p_addr_item = (net_address_item_t*)
\r
2346 cl_vector_get_ptr( &p_adapter->ip_vector,
\r
2347 cl_vector_get_size( &p_adapter->ip_vector ) - 1 );
\r
2349 if( p_addr_item->p_reg )
\r
2351 if( p_addr_item->p_reg->h_reg_svc )
\r
2353 p_adapter->p_ifc->dereg_svc(
\r
2354 p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );
\r
2358 cl_free( p_addr_item->p_reg );
\r
2360 p_addr_item->p_reg = NULL;
\r
2361 p_addr_item->address.as_ulong = 0;
\r
2364 /* No need to check return value - shrinking always succeeds. */
\r
2365 cl_vector_set_size( &p_adapter->ip_vector,
\r
2366 cl_vector_get_size( &p_adapter->ip_vector ) - 1 );
\r
2369 if( p_adapter->state == IB_PNP_PORT_ACTIVE && p_adapter->packet_filter )
\r
2370 ipoib_reg_addrs( p_adapter );
\r
2372 cl_obj_unlock( &p_adapter->obj );
\r
2374 IPOIB_EXIT( IPOIB_DBG_OID );
\r
2375 return NDIS_STATUS_SUCCESS;
\r
2379 /* Object lock is held when this function is called. */
\r
2382 IN ipoib_adapter_t* const p_adapter )
\r
2384 net_address_item_t *p_addr_item;
\r
2390 ib_api_status_t ib_status;
\r
2391 ib_reg_svc_req_t ib_service;
\r
2392 ib_gid_t port_gid;
\r
2394 IPOIB_ENTER( IPOIB_DBG_OID );
\r
2396 if(p_adapter->guids.port_guid.pkey != IB_DEFAULT_PKEY)
\r
2398 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,
\r
2399 ("ATS Service available for default pkey only\n"));
\r
2402 port_num = p_adapter->guids.port_num;
\r
2404 /* Setup our service call with things common to all calls */
\r
2405 cl_memset( &ib_service, 0, sizeof(ib_service) );
\r
2407 /* BUGBUG Only register local subnet GID prefix for now */
\r
2408 ib_gid_set_default( &port_gid, p_adapter->guids.port_guid.guid );
\r
2409 ib_service.svc_rec.service_gid = port_gid;
\r
2411 ib_service.svc_rec.service_pkey = IB_DEFAULT_PKEY;
\r
2412 ib_service.svc_rec.service_lease = IB_INFINITE_SERVICE_LEASE;
\r
2414 /* Must cast here because the service name is an array of unsigned chars but
\r
2415 * strcpy want a pointer to a signed char */
\r
2416 if ( StringCchCopy( (char *)ib_service.svc_rec.service_name,
\r
2417 sizeof(ib_service.svc_rec.service_name) / sizeof(char), ATS_NAME ) != S_OK) {
\r
2419 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR,IPOIB_DBG_ERROR,
\r
2420 ("Problem copying ATS name: exiting\n"));
\r
2424 /* IP Address in question will be put in below */
\r
2425 ib_service.port_guid = p_adapter->guids.port_guid.guid;
\r
2426 ib_service.timeout_ms = p_adapter->params.sa_timeout;
\r
2427 ib_service.retry_cnt = p_adapter->params.sa_retry_cnt;
\r
2429 /* Can't set IB_FLAGS_SYNC here because I can't wait at dispatch */
\r
2430 ib_service.flags = 0;
\r
2432 /* Service context will be put in below */
\r
2434 ib_service.svc_data_mask = IB_SR_COMPMASK_SID |
\r
2435 IB_SR_COMPMASK_SGID |
\r
2436 IB_SR_COMPMASK_SPKEY |
\r
2437 IB_SR_COMPMASK_SLEASE |
\r
2438 IB_SR_COMPMASK_SNAME |
\r
2439 IB_SR_COMPMASK_SDATA8_12 |
\r
2440 IB_SR_COMPMASK_SDATA8_13 |
\r
2441 IB_SR_COMPMASK_SDATA8_14 |
\r
2442 IB_SR_COMPMASK_SDATA8_15;
\r
2443 ib_service.pfn_reg_svc_cb = __ipoib_ats_reg_cb;
\r
2445 for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ )
\r
2447 p_addr_item = (net_address_item_t*)
\r
2448 cl_vector_get_ptr( &p_adapter->ip_vector, idx );
\r
2450 if( p_addr_item->p_reg )
\r
2453 p_addr_item->p_reg = cl_zalloc( sizeof(ats_reg_t) );
\r
2454 if( !p_addr_item->p_reg )
\r
2457 p_addr_item->p_reg->p_adapter = p_adapter;
\r
2459 ib_service.svc_context = p_addr_item->p_reg;
\r
2461 ib_service.svc_rec.service_id =
\r
2462 ATS_SERVICE_ID & CL_HTON64(0xFFFFFFFFFFFFFF00);
\r
2463 /* ATS service IDs start at 0x10000CE100415453 */
\r
2464 ib_service.svc_rec.service_id |= ((uint64_t)(idx + 0x53)) << 56;
\r
2466 cl_memcpy( &ib_service.svc_rec.service_data8[ATS_IPV4_OFFSET],
\r
2467 p_addr_item->address.as_bytes, IPV4_ADDR_SIZE );
\r
2469 /* Take a reference for each service request. */
\r
2470 cl_obj_ref(&p_adapter->obj);
\r
2471 ib_status = p_adapter->p_ifc->reg_svc(
\r
2472 p_adapter->h_al, &ib_service, &p_addr_item->p_reg->h_reg_svc );
\r
2473 if( ib_status != IB_SUCCESS )
\r
2475 if( ib_status == IB_INVALID_GUID )
\r
2477 /* If this occurs, we log the error but do not fail the OID yet */
\r
2478 IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,
\r
2479 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "
\r
2480 "Failed to register IP Address "
\r
2481 "of %d.%d.%d.%d with error IB_INVALID_GUID\n",
\r
2483 p_addr_item->address.as_bytes[0],
\r
2484 p_addr_item->address.as_bytes[1],
\r
2485 p_addr_item->address.as_bytes[2],
\r
2486 p_addr_item->address.as_bytes[3]) );
\r
2490 /* Fatal error. */
\r
2491 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,
\r
2492 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address "
\r
2493 "of %d.%d.%d.%d with error %s\n",
\r
2495 p_addr_item->address.as_bytes[0],
\r
2496 p_addr_item->address.as_bytes[1],
\r
2497 p_addr_item->address.as_bytes[2],
\r
2498 p_addr_item->address.as_bytes[3],
\r
2499 p_adapter->p_ifc->get_err_str( ib_status )) );
\r
2500 p_adapter->hung = TRUE;
\r
2502 cl_obj_deref(&p_adapter->obj);
\r
2503 cl_free( p_addr_item->p_reg );
\r
2504 p_addr_item->p_reg = NULL;
\r
2508 IPOIB_EXIT( IPOIB_DBG_OID );
\r
2512 /* Object lock is held when this function is called. */
\r
2514 ipoib_dereg_addrs(
\r
2515 IN ipoib_adapter_t* const p_adapter )
\r
2517 net_address_item_t *p_addr_item;
\r
2521 IPOIB_ENTER( IPOIB_DBG_OID );
\r
2523 for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ )
\r
2525 p_addr_item = (net_address_item_t*)
\r
2526 cl_vector_get_ptr( &p_adapter->ip_vector, idx );
\r
2528 if( !p_addr_item->p_reg )
\r
2531 if( p_addr_item->p_reg->h_reg_svc )
\r
2533 p_adapter->p_ifc->dereg_svc(
\r
2534 p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );
\r
2538 cl_free( p_addr_item->p_reg );
\r
2540 p_addr_item->p_reg = NULL;
\r
2543 IPOIB_EXIT( IPOIB_DBG_OID );
\r
2548 __ipoib_ats_reg_cb(
\r
2549 IN ib_reg_svc_rec_t *p_reg_svc_rec )
\r
2554 IPOIB_ENTER( IPOIB_DBG_OID );
\r
2556 CL_ASSERT( p_reg_svc_rec );
\r
2557 CL_ASSERT( p_reg_svc_rec->svc_context );
\r
2559 p_reg = (ats_reg_t*)p_reg_svc_rec->svc_context;
\r
2560 port_num = p_reg->p_adapter->guids.port_num;
\r
2562 cl_obj_lock( &p_reg->p_adapter->obj );
\r
2564 if( p_reg_svc_rec->req_status == IB_SUCCESS &&
\r
2565 !p_reg_svc_rec->resp_status )
\r
2567 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,
\r
2568 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Registered IP Address "
\r
2569 "of %d.%d.%d.%d\n",
\r
2571 p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET],
\r
2572 p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1],
\r
2573 p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2],
\r
2574 p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3]) );
\r
2576 else if( p_reg_svc_rec->req_status != IB_CANCELED )
\r
2578 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OID,
\r
2579 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address "
\r
2580 "of %d.%d.%d.%d with error %s\n",
\r
2582 p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET],
\r
2583 p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1],
\r
2584 p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2],
\r
2585 p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3],
\r
2586 p_reg->p_adapter->p_ifc->get_err_str( p_reg_svc_rec->resp_status )) );
\r
2587 p_reg->p_adapter->hung = TRUE;
\r
2588 p_reg->h_reg_svc = NULL;
\r
2591 cl_obj_unlock( &p_reg->p_adapter->obj );
\r
2592 cl_obj_deref(&p_reg->p_adapter->obj);
\r
2594 IPOIB_EXIT( IPOIB_DBG_OID );
\r
2599 __ipoib_ats_dereg_cb(
\r
2600 IN void *context )
\r
2602 cl_free( context );
\r