01afadca31b58b6edbd1e4fd8f12f0bc3d65cca4
[mirror/winof/.git] / ulp / ipoib / kernel / ipoib_driver.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 \r
33 #include "ipoib_driver.h"\r
34 #include "ipoib_debug.h"\r
35 \r
36 #if defined(EVENT_TRACING)\r
37 #ifdef offsetof\r
38 #undef offsetof\r
39 #endif\r
40 #include "ipoib_driver.tmh"\r
41 #endif\r
42 \r
43 #include "ipoib_port.h"\r
44 #include "ipoib_ibat.h"\r
45 #include <complib/cl_bus_ifc.h>\r
46 #include <complib/cl_init.h>\r
47 #include <initguid.h>\r
48 #include <iba/ipoib_ifc.h>\r
49 \r
50 \r
51 /* Default parameters values for optional parameters */\r
52 #define DEF_WSDP_ENABLED        FALSE\r
53 #define DEF_STATIC_LID          0\r
54 #define DEF_RECV_GROWTH         0\r
55 \r
56 \r
57 #if defined(NDIS50_MINIPORT)\r
58 #define MAJOR_NDIS_VERSION 5\r
59 #define MINOR_NDIS_VERSION 0\r
60 #elif defined (NDIS51_MINIPORT)\r
61 #define MAJOR_NDIS_VERSION 5\r
62 #define MINOR_NDIS_VERSION 1\r
63 #else\r
64 #error NDIS Version not defined, try defining NDIS50_MINIPORT or NDIS51_MINIPORT\r
65 #endif\r
66 \r
67 static const NDIS_OID SUPPORTED_OIDS[] =\r
68 {\r
69         OID_GEN_SUPPORTED_LIST,\r
70         OID_GEN_HARDWARE_STATUS,\r
71         OID_GEN_MEDIA_SUPPORTED,\r
72         OID_GEN_MEDIA_IN_USE,\r
73         OID_GEN_MAXIMUM_LOOKAHEAD,\r
74         OID_GEN_MAXIMUM_FRAME_SIZE,\r
75         OID_GEN_LINK_SPEED,\r
76         OID_GEN_TRANSMIT_BUFFER_SPACE,\r
77         OID_GEN_RECEIVE_BUFFER_SPACE,\r
78         OID_GEN_TRANSMIT_BLOCK_SIZE,\r
79         OID_GEN_RECEIVE_BLOCK_SIZE,\r
80         OID_GEN_VENDOR_ID,\r
81         OID_GEN_VENDOR_DESCRIPTION,\r
82         OID_GEN_CURRENT_PACKET_FILTER,\r
83         OID_GEN_CURRENT_LOOKAHEAD,\r
84         OID_GEN_DRIVER_VERSION,\r
85         OID_GEN_MAXIMUM_TOTAL_SIZE,\r
86         OID_GEN_PROTOCOL_OPTIONS,\r
87         OID_GEN_MAC_OPTIONS,\r
88         OID_GEN_MEDIA_CONNECT_STATUS,\r
89         OID_GEN_MAXIMUM_SEND_PACKETS,\r
90         OID_GEN_NETWORK_LAYER_ADDRESSES,\r
91         OID_GEN_VENDOR_DRIVER_VERSION,\r
92         OID_GEN_PHYSICAL_MEDIUM,\r
93         OID_GEN_XMIT_OK,\r
94         OID_GEN_RCV_OK,\r
95         OID_GEN_XMIT_ERROR,\r
96         OID_GEN_RCV_ERROR,\r
97         OID_GEN_RCV_NO_BUFFER,\r
98         OID_GEN_DIRECTED_BYTES_XMIT,\r
99         OID_GEN_DIRECTED_FRAMES_XMIT,\r
100         OID_GEN_MULTICAST_BYTES_XMIT,\r
101         OID_GEN_MULTICAST_FRAMES_XMIT,\r
102         OID_GEN_BROADCAST_BYTES_XMIT,\r
103         OID_GEN_BROADCAST_FRAMES_XMIT,\r
104         OID_GEN_DIRECTED_BYTES_RCV,\r
105         OID_GEN_DIRECTED_FRAMES_RCV,\r
106         OID_GEN_MULTICAST_BYTES_RCV,\r
107         OID_GEN_MULTICAST_FRAMES_RCV,\r
108         OID_GEN_BROADCAST_BYTES_RCV,\r
109         OID_GEN_BROADCAST_FRAMES_RCV,\r
110         OID_802_3_PERMANENT_ADDRESS,\r
111         OID_802_3_CURRENT_ADDRESS,\r
112         OID_802_3_MULTICAST_LIST,\r
113         OID_802_3_MAXIMUM_LIST_SIZE,\r
114         OID_802_3_MAC_OPTIONS,\r
115         OID_802_3_RCV_ERROR_ALIGNMENT,\r
116         OID_802_3_XMIT_ONE_COLLISION,\r
117         OID_802_3_XMIT_MORE_COLLISIONS,\r
118         OID_TCP_TASK_OFFLOAD\r
119 };\r
120 \r
121 static const unsigned char VENDOR_ID[] = {0x00, 0x06, 0x6A, 0x00};\r
122 \r
123 #define VENDOR_DESCRIPTION "Internet Protocol over InfiniBand"\r
124 \r
125 #define IB_INFINITE_SERVICE_LEASE       0xFFFFFFFF\r
126 \r
127 \r
128 /* Global driver debug level */\r
129 uint32_t                g_ipoib_dbg_level = TRACE_LEVEL_ERROR;\r
130 uint32_t                g_ipoib_dbg_flags = 0x00000fff;\r
131 ipoib_globals_t g_ipoib = {0};\r
132 \r
133 \r
134 NTSTATUS\r
135 DriverEntry(\r
136         IN                              PDRIVER_OBJECT                          p_drv_obj,\r
137         IN                              PUNICODE_STRING                         p_reg_path );\r
138 \r
139 VOID\r
140 ipoib_unload(\r
141         IN                              PDRIVER_OBJECT                          p_drv_obj );\r
142 \r
143 NDIS_STATUS\r
144 ipoib_initialize(\r
145                 OUT                     PNDIS_STATUS                            p_open_err_status,\r
146                 OUT                     PUINT                                           p_selected_medium_index,\r
147         IN                              PNDIS_MEDIUM                            medium_array,\r
148         IN                              UINT                                            medium_array_size,\r
149         IN                              NDIS_HANDLE                                     h_adapter,\r
150         IN                              NDIS_HANDLE                                     wrapper_configuration_context );\r
151 \r
152 BOOLEAN\r
153 ipoib_check_for_hang(\r
154         IN                              NDIS_HANDLE                                     adapter_context );\r
155 \r
156 void\r
157 ipoib_halt(\r
158         IN                              NDIS_HANDLE                                     adapter_context );\r
159 \r
160 NDIS_STATUS\r
161 ipoib_query_info(\r
162         IN                              NDIS_HANDLE                                     adapter_context,\r
163         IN                              NDIS_OID                                        oid,\r
164         IN                              PVOID                                           info_buf,\r
165         IN                              ULONG                                           info_buf_len,\r
166                 OUT                     PULONG                                          p_bytes_written,\r
167                 OUT                     PULONG                                          p_bytes_needed );\r
168 \r
169 NDIS_STATUS\r
170 ipoib_reset(\r
171                 OUT                     PBOOLEAN                                        p_addressing_reset,\r
172         IN                              NDIS_HANDLE                                     adapter_context );\r
173 \r
174 NDIS_STATUS\r
175 ipoib_set_info(\r
176         IN                              NDIS_HANDLE                                     adapter_context,\r
177         IN                              NDIS_OID                                        oid,\r
178         IN                              PVOID                                           info_buf,\r
179         IN                              ULONG                                           info_buf_length,\r
180                 OUT                     PULONG                                          p_bytes_read,\r
181                 OUT                     PULONG                                          p_bytes_needed );\r
182 \r
183 void\r
184 ipoib_send_packets(\r
185         IN                              NDIS_HANDLE                                     adapter_context,\r
186         IN                              PPNDIS_PACKET                           packet_array,\r
187         IN                              UINT                                            num_packets );\r
188 \r
189 void\r
190 ipoib_pnp_notify(\r
191         IN                              NDIS_HANDLE                                     adapter_context,\r
192         IN                              NDIS_DEVICE_PNP_EVENT           pnp_event,\r
193         IN                              PVOID                                           info_buf,\r
194         IN                              ULONG                                           info_buf_len );\r
195 \r
196 void\r
197 ipoib_shutdown(\r
198         IN                              PVOID                                           adapter_context );\r
199 \r
200 static void\r
201 ipoib_complete_query(\r
202         IN                              ipoib_adapter_t* const          p_adapter,\r
203         IN                              pending_oid_t* const            p_oid_info,\r
204         IN              const   NDIS_STATUS                                     status,\r
205         IN              const   void* const                                     p_buf,\r
206         IN              const   ULONG                                           buf_len );\r
207 \r
208 static NDIS_STATUS\r
209 __ipoib_set_net_addr(\r
210         IN              ipoib_adapter_t *       p_adapter,\r
211         IN              PVOID                           info_buf,\r
212         IN              ULONG                           info_buf_len,\r
213                 OUT     PULONG                          p_bytes_read,\r
214                 OUT     PULONG                          p_bytes_needed );\r
215 \r
216 static NDIS_STATUS\r
217 __ipoib_get_tcp_task_offload(\r
218         IN                              ipoib_adapter_t*                        p_adapter,\r
219         IN                              pending_oid_t* const            p_oid_info );\r
220 \r
221 static void\r
222 __ipoib_ats_reg_cb(\r
223         IN                              ib_reg_svc_rec_t                        *p_reg_svc_rec );\r
224 \r
225 static void\r
226 __ipoib_ats_dereg_cb(\r
227         IN                              void                                            *context );\r
228 \r
229 static NTSTATUS\r
230 __ipoib_read_registry(\r
231         IN                              UNICODE_STRING* const           p_registry_path );\r
232 \r
233 \r
234 //! Standard Windows Device Driver Entry Point\r
235 /*! DriverEntry is the first routine called after a driver is loaded, and\r
236 is responsible for initializing the driver.  On W2k this occurs when the PnP\r
237 Manager matched a PnP ID to one in an INF file that references this driver.\r
238 Any not success return value will cause the driver to fail to load.\r
239 IRQL = PASSIVE_LEVEL\r
240 \r
241 @param p_drv_obj Pointer to Driver Object for this device driver\r
242 @param p_registry_path Pointer to unicode string containing path to this driver's registry area\r
243 @return STATUS_SUCCESS, NDIS_STATUS_BAD_CHARACTERISTICS, NDIS_STATUS_BAD_VERSION,\r
244 NDIS_STATUS_RESOURCES, or NDIS_STATUS_FAILURE\r
245 */\r
246 NTSTATUS\r
247 DriverEntry(\r
248         IN                              PDRIVER_OBJECT                          p_drv_obj,\r
249         IN                              PUNICODE_STRING                         p_registry_path )\r
250 {\r
251         NDIS_STATUS                                             status;\r
252         NDIS_HANDLE                                             ndis_handle;\r
253         NDIS_MINIPORT_CHARACTERISTICS   characteristics;\r
254 \r
255         IPOIB_ENTER( IPOIB_DBG_INIT );\r
256 \r
257 #ifdef _DEBUG_\r
258         PAGED_CODE();\r
259 #endif\r
260 #if defined(EVENT_TRACING)\r
261         WPP_INIT_TRACING(p_drv_obj, p_registry_path);\r
262 #endif\r
263         status = CL_INIT;\r
264         if( !NT_SUCCESS( status ) )\r
265         {\r
266                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
267                         ("cl_init failed.\n") );\r
268                 return status;\r
269         }\r
270 \r
271         status          = NDIS_STATUS_SUCCESS;\r
272         ndis_handle     = NULL;\r
273 \r
274         __ipoib_read_registry(p_registry_path);\r
275         \r
276         KeInitializeSpinLock( &g_ipoib.lock );\r
277         cl_qlist_init( &g_ipoib.adapter_list );\r
278 \r
279         NdisMInitializeWrapper(\r
280                 &g_ipoib.h_ndis_wrapper, p_drv_obj, p_registry_path, NULL );\r
281 \r
282         memset(&characteristics, 0, sizeof(characteristics));\r
283         characteristics.MajorNdisVersion                = MAJOR_NDIS_VERSION;\r
284         characteristics.MinorNdisVersion                = MINOR_NDIS_VERSION;\r
285         characteristics.CheckForHangHandler             = ipoib_check_for_hang;\r
286         characteristics.HaltHandler                             = ipoib_halt;\r
287         characteristics.InitializeHandler               = ipoib_initialize;\r
288         characteristics.QueryInformationHandler = ipoib_query_info;\r
289         characteristics.ResetHandler                    = ipoib_reset;\r
290         characteristics.SetInformationHandler   = ipoib_set_info;\r
291 \r
292         characteristics.ReturnPacketHandler             = ipoib_return_packet;\r
293         characteristics.SendPacketsHandler              = ipoib_send_packets;\r
294 \r
295 #ifdef NDIS51_MINIPORT\r
296         characteristics.PnPEventNotifyHandler   = ipoib_pnp_notify;\r
297         characteristics.AdapterShutdownHandler  = ipoib_shutdown;\r
298 #endif\r
299 \r
300         status = NdisMRegisterMiniport(\r
301                 g_ipoib.h_ndis_wrapper, &characteristics, sizeof(characteristics) );\r
302         if( status != NDIS_STATUS_SUCCESS )\r
303         {\r
304                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
305                         ("NdisMRegisterMiniport failed with status of %d\n", status) );\r
306                 NdisTerminateWrapper( g_ipoib.h_ndis_wrapper, NULL );\r
307                 CL_DEINIT;\r
308                 return status;\r
309         }\r
310 \r
311         NdisMRegisterUnloadHandler( g_ipoib.h_ndis_wrapper, ipoib_unload );\r
312 \r
313         IPOIB_EXIT( IPOIB_DBG_INIT );\r
314         return status;\r
315 }\r
316 \r
317 \r
318 static NTSTATUS\r
319 __ipoib_read_registry(\r
320         IN                              UNICODE_STRING* const           p_registry_path )\r
321 {\r
322         NTSTATUS                                                status;\r
323         /* Remember the terminating entry in the table below. */\r
324         RTL_QUERY_REGISTRY_TABLE                table[3];\r
325         UNICODE_STRING                                  param_path;\r
326 \r
327         IPOIB_ENTER( IPOIB_DBG_INIT );\r
328         RtlInitUnicodeString( &param_path, NULL );\r
329         param_path.MaximumLength = p_registry_path->Length + \r
330                 sizeof(L"\\Parameters");\r
331         param_path.Buffer = cl_zalloc( param_path.MaximumLength );\r
332         if( !param_path.Buffer )\r
333         {\r
334                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
335                         ("Failed to allocate parameters path buffer.\n") );\r
336                 return STATUS_INSUFFICIENT_RESOURCES;\r
337         }\r
338 \r
339         RtlAppendUnicodeStringToString( &param_path, p_registry_path );\r
340         RtlAppendUnicodeToString( &param_path, L"\\Parameters" );\r
341 \r
342         /*\r
343          * Clear the table.  This clears all the query callback pointers,\r
344          * and sets up the terminating table entry.\r
345          */\r
346         cl_memclr( table, sizeof(table) );\r
347 \r
348         /* Setup the table entries. */\r
349         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
350         table[0].Name = L"DebugLevel";\r
351         table[0].EntryContext = &g_ipoib_dbg_level;\r
352         table[0].DefaultType = REG_DWORD;\r
353         table[0].DefaultData = &g_ipoib_dbg_level;\r
354         table[0].DefaultLength = sizeof(ULONG);\r
355 \r
356         table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
357         table[1].Name = L"DebugFlags";\r
358         table[1].EntryContext = &g_ipoib_dbg_flags;\r
359         table[1].DefaultType = REG_DWORD;\r
360         table[1].DefaultData = &g_ipoib_dbg_flags;\r
361         table[1].DefaultLength = sizeof(ULONG);\r
362 \r
363         /* Have at it! */\r
364         status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
365                 param_path.Buffer, table, NULL, NULL );\r
366 \r
367         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
368                         ("debug level %d debug flags 0x%.8x\n",\r
369                         g_ipoib_dbg_level,\r
370                         g_ipoib_dbg_flags));\r
371 \r
372         if( g_ipoib_dbg_flags & IPOIB_DBG_ERR )\r
373                 g_ipoib_dbg_flags |= CL_DBG_ERROR;\r
374 \r
375         cl_free( param_path.Buffer );\r
376         IPOIB_EXIT( IPOIB_DBG_INIT );\r
377         return status;\r
378 }\r
379 \r
380 \r
381 VOID\r
382 ipoib_unload(\r
383         IN                              PDRIVER_OBJECT                          p_drv_obj )\r
384 {\r
385         IPOIB_ENTER( IPOIB_DBG_INIT );\r
386         #if defined(EVENT_TRACING)\r
387         WPP_CLEANUP(p_drv_obj);\r
388         #endif\r
389 \r
390         UNREFERENCED_PARAMETER( p_drv_obj );\r
391         CL_DEINIT;\r
392         IPOIB_EXIT( IPOIB_DBG_INIT );\r
393 }\r
394 \r
395 \r
396 NDIS_STATUS\r
397 ipoib_get_adapter_params(\r
398         IN                              NDIS_HANDLE* const                      wrapper_config_context,\r
399         IN      OUT                     ipoib_adapter_t                         *p_adapter )\r
400 {\r
401         NDIS_STATUS                                             status;\r
402         NDIS_HANDLE                                             h_config;\r
403         NDIS_CONFIGURATION_PARAMETER    *p_param;\r
404         NDIS_STRING                                             keyword;\r
405         PUCHAR                                                  mac;\r
406         UINT                                                    len;\r
407 \r
408         IPOIB_ENTER( IPOIB_DBG_INIT );\r
409 \r
410         NdisOpenConfiguration( &status, &h_config, wrapper_config_context );\r
411         if( status != NDIS_STATUS_SUCCESS )\r
412         {\r
413                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
414                         ("NdisOpenConfiguration returned 0x%.8x\n", status) );\r
415                 return status;\r
416         }\r
417 \r
418         /* Required: Receive queue depth. */\r
419         RtlInitUnicodeString( &keyword, L"RqDepth" );\r
420         NdisReadConfiguration(\r
421                 &status, &p_param, h_config, &keyword, NdisParameterInteger );\r
422         if( status != NDIS_STATUS_SUCCESS )\r
423         {\r
424                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
425                         ("Receive Queue Depth parameter missing.\n") );\r
426                 return status;\r
427         }\r
428         p_adapter->params.rq_depth = p_param->ParameterData.IntegerData;\r
429 \r
430         /* Required: Send queue depth. */\r
431         RtlInitUnicodeString( &keyword, L"SqDepth" );\r
432         NdisReadConfiguration(\r
433                 &status, &p_param, h_config, &keyword, NdisParameterInteger );\r
434         if( status != NDIS_STATUS_SUCCESS )\r
435         {\r
436                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
437                         ("Send Queue Depth parameter missing.\n") );\r
438                 return status;\r
439         }\r
440         p_adapter->params.sq_depth = p_param->ParameterData.IntegerData;\r
441         /* Send queue depth needs to be a power of two. */\r
442         if( p_adapter->params.sq_depth <= 128 )\r
443                 p_adapter->params.sq_depth = 128;\r
444         else if( p_adapter->params.sq_depth <= 256 )\r
445                 p_adapter->params.sq_depth = 256;\r
446         else if( p_adapter->params.sq_depth <= 512 )\r
447                 p_adapter->params.sq_depth = 512;\r
448         else\r
449                 p_adapter->params.sq_depth = 1024;\r
450 \r
451         /* Required: Send Checksum Offload. */\r
452         RtlInitUnicodeString( &keyword, L"SendChksum" );\r
453         NdisReadConfiguration(\r
454                 &status, &p_param, h_config, &keyword, NdisParameterInteger );\r
455         if( status != NDIS_STATUS_SUCCESS )\r
456         {\r
457                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
458                         ("Send Checksum Offload parameter missing.\n") );\r
459                 return status;\r
460         }\r
461         p_adapter->params.send_chksum_offload = (p_param->ParameterData.IntegerData != 0);\r
462 \r
463         /* Optional: WSDP support. */\r
464         RtlInitUnicodeString( &keyword, L"WsdpEnabled" );\r
465         NdisReadConfiguration(\r
466                 &status, &p_param, h_config, &keyword, NdisParameterInteger );\r
467         if( status != NDIS_STATUS_SUCCESS )\r
468                 p_adapter->params.wsdp_enabled = DEF_WSDP_ENABLED;\r
469         else\r
470                 p_adapter->params.wsdp_enabled = (p_param->ParameterData.IntegerData != 0);\r
471 \r
472         /* Optional: Static LID assignment if SM is not up. */\r
473         RtlInitUnicodeString( &keyword, L"StaticLid" );\r
474         NdisReadConfiguration(\r
475                 &status, &p_param, h_config, &keyword, NdisParameterInteger );\r
476         if( status != NDIS_STATUS_SUCCESS )\r
477                 p_adapter->params.static_lid = DEF_STATIC_LID;\r
478         else\r
479                 p_adapter->params.static_lid = (uint16_t)p_param->ParameterData.IntegerData;\r
480 \r
481         /* Required: SA query timeout, in milliseconds. */\r
482         RtlInitUnicodeString( &keyword, L"SaTimeout" );\r
483         NdisReadConfiguration(\r
484                 &status, &p_param, h_config, &keyword, NdisParameterInteger );\r
485         if( status != NDIS_STATUS_SUCCESS )\r
486         {\r
487                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
488                         ("SA query timeout parameter missing.\n") );\r
489                 return status;\r
490         }\r
491         p_adapter->params.sa_timeout = p_param->ParameterData.IntegerData;\r
492 \r
493         /* Required: SA query retry count. */\r
494         RtlInitUnicodeString( &keyword, L"SaRetries" );\r
495         NdisReadConfiguration(\r
496                 &status, &p_param, h_config, &keyword, NdisParameterInteger );\r
497         if( status != NDIS_STATUS_SUCCESS )\r
498         {\r
499                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
500                         ("SA query retry count parameter missing.\n") );\r
501                 return status;\r
502         }\r
503         p_adapter->params.sa_retry_cnt = p_param->ParameterData.IntegerData;\r
504 \r
505         /* Required: Receive pool to queue depth ratio. */\r
506         RtlInitUnicodeString( &keyword, L"RecvRatio" );\r
507         NdisReadConfiguration(\r
508                 &status, &p_param, h_config, &keyword, NdisParameterInteger );\r
509         if( status != NDIS_STATUS_SUCCESS )\r
510         {\r
511                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
512                         ("Receive pool to queue depth ratio parameter missing.\n") );\r
513                 return status;\r
514         }\r
515         p_adapter->params.recv_pool_ratio = p_param->ParameterData.IntegerData;\r
516 \r
517         /* Required: Receive pool growth threshold. */\r
518         RtlInitUnicodeString( &keyword, L"RecvGrowth" );\r
519         NdisReadConfiguration(\r
520                 &status, &p_param, h_config, &keyword, NdisParameterInteger );\r
521         if( status != NDIS_STATUS_SUCCESS )\r
522                 p_adapter->params.recv_growth = DEF_RECV_GROWTH;\r
523         else\r
524                 p_adapter->params.recv_growth = (p_param->ParameterData.IntegerData != 0);\r
525 \r
526         NdisReadNetworkAddress( &status, &mac, &len, h_config );\r
527 \r
528         ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, p_adapter->mac.addr );\r
529         /* If there is a NetworkAddress override in registry, use it */\r
530         if( (status == NDIS_STATUS_SUCCESS) && (len == HW_ADDR_LEN) )\r
531         {\r
532                 if( ETH_IS_MULTICAST(mac) || ETH_IS_BROADCAST(mac) ||\r
533                         !ETH_IS_LOCALLY_ADMINISTERED(mac) )\r
534                 {\r
535                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_INIT,\r
536                                 ("Overriding NetworkAddress is invalid - "\r
537                                 "%02x-%02x-%02x-%02x-%02x-%02x\n",\r
538                                 mac[0], mac[1], mac[2],\r
539                                 mac[3], mac[4], mac[5]) );\r
540                 }\r
541                 else\r
542                 {\r
543                         ETH_COPY_NETWORK_ADDRESS( p_adapter->params.conf_mac.addr, mac );\r
544                 }\r
545         }\r
546 \r
547         NdisCloseConfiguration( h_config );\r
548 \r
549         IPOIB_EXIT( IPOIB_DBG_INIT );\r
550         return NDIS_STATUS_SUCCESS;\r
551 }\r
552 \r
553 \r
554 NDIS_STATUS\r
555 ipoib_get_adapter_guids(\r
556         IN                              NDIS_HANDLE* const                      h_adapter,\r
557         IN      OUT                     ipoib_adapter_t                         *p_adapter )\r
558 {\r
559         NTSTATUS                        status;\r
560         ib_al_ifc_data_t        data;\r
561         IO_STACK_LOCATION       io_stack, *p_fwd_io_stack;\r
562         DEVICE_OBJECT           *p_pdo;\r
563         IRP                                     *p_irp;\r
564         KEVENT                          event;\r
565         IO_STATUS_BLOCK         io_status;\r
566 \r
567         IPOIB_ENTER( IPOIB_DBG_INIT );\r
568 \r
569         NdisMGetDeviceProperty( h_adapter, &p_pdo, NULL, NULL, NULL, NULL );\r
570 \r
571         /* Query for our interface */\r
572         data.size = sizeof(ipoib_ifc_data_t);\r
573         data.version = IPOIB_INTERFACE_DATA_VERSION;\r
574         data.type = &GUID_IPOIB_INTERFACE_DATA;\r
575         data.p_data = &p_adapter->guids;\r
576 \r
577         io_stack.MinorFunction = IRP_MN_QUERY_INTERFACE;\r
578         io_stack.Parameters.QueryInterface.Version = AL_INTERFACE_VERSION;\r
579         io_stack.Parameters.QueryInterface.Size = sizeof(ib_al_ifc_t);\r
580         io_stack.Parameters.QueryInterface.Interface =\r
581                 (INTERFACE*)p_adapter->p_ifc;\r
582         io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data;\r
583         io_stack.Parameters.QueryInterface.InterfaceType = \r
584                 &GUID_IB_AL_INTERFACE;\r
585 \r
586         KeInitializeEvent( &event, NotificationEvent, FALSE );\r
587 \r
588         /* Build the IRP for the HCA. */\r
589         p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_pdo,\r
590                 NULL, 0, NULL, &event, &io_status );\r
591         if( !p_irp )\r
592         {\r
593                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
594                         ("Failed to allocate query interface IRP.\n") );\r
595                 return STATUS_INSUFFICIENT_RESOURCES;\r
596         }\r
597 \r
598         /* Copy the request query parameters. */\r
599         p_fwd_io_stack = IoGetNextIrpStackLocation( p_irp );\r
600         p_fwd_io_stack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
601         p_fwd_io_stack->Parameters.QueryInterface =\r
602                 io_stack.Parameters.QueryInterface;\r
603         p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
604 \r
605         /* Send the IRP. */\r
606         status = IoCallDriver( p_pdo, p_irp );\r
607         if( status == STATUS_PENDING )\r
608         {\r
609                 KeWaitForSingleObject( &event, Executive, KernelMode,\r
610                         FALSE, NULL );\r
611                 status = io_status.Status;\r
612         }\r
613 \r
614         if( !NT_SUCCESS( status ) )\r
615         {\r
616                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
617                         ("Query interface for IPOIB interface returned %08x.\n", status) );\r
618                 return status;\r
619         }\r
620 \r
621         /*\r
622          * Dereference the interface now so that the bus driver doesn't fail a\r
623          * query remove IRP.  We will always get unloaded before the bus driver\r
624          * since we're a child device.\r
625          */\r
626         p_adapter->p_ifc->wdm.InterfaceDereference(\r
627                 p_adapter->p_ifc->wdm.Context );\r
628         IPOIB_EXIT( IPOIB_DBG_INIT );\r
629         return NDIS_STATUS_SUCCESS;\r
630 }\r
631 \r
632 \r
633 //! Initialization function called for each IOC discovered\r
634 /*  The MiniportInitialize function is a required function that sets up a\r
635 NIC (or virtual NIC) for network I/O operations, claims all hardware\r
636 resources necessary to the NIC in the registry, and allocates resources\r
637 the driver needs to carry out network I/O operations.\r
638 IRQL = PASSIVE_LEVEL\r
639 \r
640 @param p_open_status Pointer to a status field set if this function returns NDIS_STATUS_OPEN_ERROR\r
641 @param p_selected_medium_index Pointer to unsigned integer noting index into medium_array for this NIC\r
642 @param medium_array Array of mediums for this NIC\r
643 @param medium_array_size Number of elements in medium_array\r
644 @param h_adapter Handle assigned by NDIS for this NIC\r
645 @param wrapper_config_context Handle used for Ndis initialization functions\r
646 @return NDIS_STATUS_SUCCESS, NDIS_STATUS_UNSUPPORTED_MEDIA, NDIS_STATUS_RESOURCES,\r
647 NDIS_STATUS_NOT_SUPPORTED \r
648 */\r
649 NDIS_STATUS\r
650 ipoib_initialize(\r
651                 OUT                     PNDIS_STATUS                            p_open_status,\r
652                 OUT                     PUINT                                           p_selected_medium_index,\r
653         IN                              PNDIS_MEDIUM                            medium_array,\r
654         IN                              UINT                                            medium_array_size,\r
655         IN                              NDIS_HANDLE                                     h_adapter,\r
656         IN                              NDIS_HANDLE                                     wrapper_config_context )\r
657 {\r
658         NDIS_STATUS                     status;\r
659         ib_api_status_t         ib_status;\r
660         UINT                            medium_index;\r
661         ipoib_adapter_t         *p_adapter;\r
662 \r
663         IPOIB_ENTER( IPOIB_DBG_INIT );\r
664 \r
665 #ifdef _DEBUG_\r
666         PAGED_CODE();\r
667 #endif\r
668 \r
669         UNUSED_PARAM( p_open_status );\r
670         UNUSED_PARAM( wrapper_config_context );\r
671 \r
672         /* Search for our medium */\r
673         for( medium_index = 0; medium_index < medium_array_size; ++medium_index )\r
674         {\r
675                 /* Check to see if we found our medium */\r
676                 if( medium_array[medium_index] == NdisMedium802_3 )\r
677                         break;\r
678         }\r
679 \r
680         if( medium_index == medium_array_size ) /* Never found it */\r
681         {\r
682                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
683                         ("No supported media.\n") );\r
684                 return NDIS_STATUS_UNSUPPORTED_MEDIA;\r
685         }\r
686 \r
687         *p_selected_medium_index = medium_index;\r
688 \r
689         /* Create the adapter adapter */\r
690         ib_status = ipoib_create_adapter( wrapper_config_context, h_adapter, &p_adapter );\r
691         if( ib_status != IB_SUCCESS )\r
692         {\r
693                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
694                         ("ipoib_create_adapter returned status %d.\n", ib_status ) );\r
695                 return NDIS_STATUS_FAILURE;\r
696         }\r
697 \r
698         /* Allow ten seconds for all SA queries to finish up. */\r
699         NdisMSetAttributesEx( h_adapter, p_adapter, 5,\r
700                 NDIS_ATTRIBUTE_BUS_MASTER | NDIS_ATTRIBUTE_DESERIALIZE |\r
701                 NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS,\r
702                 NdisInterfacePNPBus );\r
703 \r
704 #if IPOIB_USE_DMA\r
705         status =\r
706                 NdisMInitializeScatterGatherDma( h_adapter, TRUE, XFER_BLOCK_SIZE );\r
707         if( status != NDIS_STATUS_SUCCESS )\r
708         {\r
709                 ipoib_destroy_adapter( p_adapter );\r
710                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
711                         ("NdisMInitializeScatterGatherDma returned 0x%.8x.\n", status) );\r
712                 return status;\r
713         }\r
714 #endif\r
715 \r
716         /* Create the adapter adapter */\r
717         ib_status = ipoib_start_adapter( p_adapter );\r
718         if( ib_status != IB_SUCCESS )\r
719         {\r
720                 NdisWriteErrorLogEntry( h_adapter,\r
721                         NDIS_ERROR_CODE_HARDWARE_FAILURE, 0 );\r
722                 ipoib_destroy_adapter( p_adapter );\r
723                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
724                         ("ipoib_start_adapter returned status %d.\n", ib_status ) );\r
725                 return NDIS_STATUS_FAILURE;\r
726         }\r
727 \r
728         ipoib_ref_ibat();\r
729 \r
730         IPOIB_EXIT( IPOIB_DBG_INIT );\r
731         return status;\r
732 }\r
733 \r
734 \r
735 //! Deallocates resources when the NIC is removed and halts the NIC..\r
736 /*  IRQL = DISPATCH_LEVEL\r
737 \r
738 @param adapter_context The adapter context allocated at start\r
739 */\r
740 void\r
741 ipoib_halt(\r
742         IN                              NDIS_HANDLE                                     adapter_context )\r
743 {\r
744         ipoib_adapter_t *p_adapter;\r
745 \r
746         IPOIB_ENTER( IPOIB_DBG_INIT );\r
747 \r
748         ipoib_deref_ibat();\r
749 \r
750         CL_ASSERT( adapter_context );\r
751         p_adapter = (ipoib_adapter_t*)adapter_context;\r
752 \r
753         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_INIT,\r
754                         ("Port %016I64x (CA %016I64x port %d) halting\n",\r
755                         p_adapter->guids.port_guid, p_adapter->guids.ca_guid,\r
756                         p_adapter->guids.port_num) );\r
757 \r
758         ipoib_destroy_adapter( p_adapter );\r
759 \r
760         IPOIB_EXIT( IPOIB_DBG_INIT );\r
761 }\r
762 \r
763 \r
764 //! Reports the state of the NIC, or monitors the responsiveness of an underlying device driver.\r
765 /*  IRQL = DISPATCH_LEVEL\r
766 \r
767 @param adapter_context The adapter context allocated at start\r
768 @return TRUE if the driver determines that its NIC is not operating\r
769 */\r
770 BOOLEAN\r
771 ipoib_check_for_hang(\r
772         IN                              NDIS_HANDLE                                     adapter_context )\r
773 {\r
774         ipoib_adapter_t *p_adapter;\r
775 \r
776         IPOIB_ENTER( IPOIB_DBG_INIT );\r
777         CL_ASSERT( adapter_context );\r
778         p_adapter = (ipoib_adapter_t*)adapter_context;\r
779 \r
780         if( p_adapter->reset )\r
781         {\r
782                 IPOIB_EXIT( IPOIB_DBG_INIT );\r
783                 return FALSE;\r
784         }\r
785 \r
786         IPOIB_EXIT( IPOIB_DBG_INIT );\r
787         return (p_adapter->hung? TRUE:FALSE);\r
788 }\r
789 \r
790 \r
791 //! Returns information about the capabilities and status of the driver and/or its NIC.\r
792 /*  IRQL = DISPATCH_LEVEL\r
793 \r
794 @param adapter_context The adapter context allocated at start\r
795 @param oid Object ID representing the query operation to be carried out\r
796 @param info_buf Buffer containing any input for this query and location for output\r
797 @param info_buf_len Number of bytes available in info_buf\r
798 @param p_bytes_written Pointer to number of bytes written into info_buf\r
799 @param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
800 @return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
801 NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_NOT_ACCEPTED, NDIS_STATUS_NOT_SUPPORTED,\r
802 NDIS_STATUS_RESOURCES\r
803 */\r
804 NDIS_STATUS\r
805 ipoib_query_info(\r
806         IN                              NDIS_HANDLE                                     adapter_context,\r
807         IN                              NDIS_OID                                        oid,\r
808         IN                              PVOID                                           info_buf,\r
809         IN                              ULONG                                           info_buf_len,\r
810                 OUT                     PULONG                                          p_bytes_written,\r
811                 OUT                     PULONG                                          p_bytes_needed )\r
812 {\r
813         ipoib_adapter_t         *p_adapter;\r
814         NDIS_STATUS                     status;\r
815         USHORT                          version;\r
816         ULONG                           info;\r
817         PVOID                           src_buf;\r
818         ULONG                           buf_len;\r
819         pending_oid_t           oid_info;\r
820         uint8_t                         port_num;\r
821 \r
822         IPOIB_ENTER( IPOIB_DBG_OID );\r
823 \r
824         oid_info.oid = oid;\r
825         oid_info.p_buf = info_buf;\r
826         oid_info.buf_len = info_buf_len;\r
827         oid_info.p_bytes_used = p_bytes_written;\r
828         oid_info.p_bytes_needed = p_bytes_needed;\r
829 \r
830         CL_ASSERT( adapter_context );\r
831         p_adapter = (ipoib_adapter_t*)adapter_context;\r
832 \r
833         CL_ASSERT( p_bytes_written );\r
834         CL_ASSERT( p_bytes_needed );\r
835         CL_ASSERT( !p_adapter->pending_query );\r
836 \r
837         status = NDIS_STATUS_SUCCESS;\r
838         src_buf = &info;\r
839         buf_len = sizeof(info);\r
840 \r
841         port_num = p_adapter->guids.port_num;\r
842 \r
843         switch( oid )\r
844         {\r
845         /* Required General */\r
846         case OID_GEN_SUPPORTED_LIST:\r
847                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
848                         ("Port %d received query for OID_GEN_SUPPORTED_LIST\n", port_num) );\r
849                 src_buf = (PVOID)SUPPORTED_OIDS;\r
850                 buf_len = sizeof(SUPPORTED_OIDS);\r
851                 break;\r
852 \r
853         case OID_GEN_HARDWARE_STATUS:\r
854                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
855                         ("Port %d received query for OID_GEN_HARDWARE_STATUS\n", port_num) );\r
856                 cl_obj_lock( &p_adapter->obj );\r
857                 switch( p_adapter->state )\r
858                 {\r
859                 case IB_PNP_PORT_ADD:\r
860                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
861                                 ("Port %d returning NdisHardwareStatusInitializing\n", port_num) );\r
862                         info = NdisHardwareStatusInitializing;\r
863                         break;\r
864                         \r
865                 case IB_PNP_PORT_ACTIVE:\r
866                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
867                                 ("Port %d returning NdisHardwareStatusReady\n", port_num) );\r
868                         info = NdisHardwareStatusReady;\r
869                         break;\r
870 \r
871                 default:\r
872                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
873                                 ("Port %d returning NdisHardwareStatusNotReady\n", port_num) );\r
874                         info = NdisHardwareStatusNotReady;\r
875                 }\r
876                 cl_obj_unlock( &p_adapter->obj );\r
877                 break;\r
878 \r
879         case OID_GEN_MEDIA_SUPPORTED:\r
880         case OID_GEN_MEDIA_IN_USE:\r
881                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
882                         ("Port %d received query for OID_GEN_MEDIA_SUPPORTED "\r
883                         "or OID_GEN_MEDIA_IN_USE\n", port_num) );\r
884                 info = NdisMedium802_3;\r
885                 break;\r
886 \r
887         case OID_GEN_MAXIMUM_FRAME_SIZE:\r
888                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
889                         ("Port %d received query for OID_GEN_MAXIMUM_FRAME_SIZE\n", port_num) );\r
890                 info = PAYLOAD_MTU;\r
891                 break;\r
892 \r
893         case OID_GEN_LINK_SPEED:\r
894                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
895                         ("Port %d received query for OID_GEN_LINK_SPEED\n", port_num) );\r
896                 cl_obj_lock( &p_adapter->obj );\r
897                 switch( p_adapter->state )\r
898                 {\r
899                 case IB_PNP_PORT_ADD:\r
900                         /* Mark the adapter as pending an OID */\r
901                         p_adapter->pending_query = TRUE;\r
902 \r
903                         /* Save the request parameters. */\r
904                         p_adapter->query_oid = oid_info;\r
905 \r
906                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
907                                 ("Port %d returning NDIS_STATUS_PENDING\n", port_num) );\r
908                         status = NDIS_STATUS_PENDING;\r
909                         break;\r
910 \r
911                 case IB_PNP_PORT_REMOVE:\r
912                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
913                                 ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) );\r
914                         status = NDIS_STATUS_NOT_ACCEPTED;\r
915                         break;\r
916 \r
917                 default:\r
918                         CL_ASSERT( p_adapter->p_port );\r
919                         info = p_adapter->rate;\r
920                         break;\r
921                 }\r
922                 cl_obj_unlock( &p_adapter->obj );\r
923                 break;\r
924 \r
925         case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
926                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
927                         ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE\n", port_num) );\r
928                 info = p_adapter->params.sq_depth * XFER_BLOCK_SIZE;\r
929                 break;\r
930 \r
931         case OID_GEN_RECEIVE_BUFFER_SPACE:\r
932                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
933                         ("Port %d received query for OID_GEN_TRANSMIT_BUFFER_SPACE "\r
934                         "or OID_GEN_RECEIVE_BUFFER_SPACE\n", port_num) );\r
935                 info = p_adapter->params.rq_depth * XFER_BLOCK_SIZE;\r
936                 break;\r
937 \r
938         case OID_GEN_MAXIMUM_LOOKAHEAD:\r
939         case OID_GEN_CURRENT_LOOKAHEAD:\r
940         case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
941         case OID_GEN_RECEIVE_BLOCK_SIZE:\r
942         case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
943                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
944                         ("Port %d received query for OID_GEN_MAXIMUM_LOOKAHEAD "\r
945                         "or OID_GEN_CURRENT_LOOKAHEAD or "\r
946                         "OID_GEN_TRANSMIT_BLOCK_SIZE or "\r
947                         "OID_GEN_RECEIVE_BLOCK_SIZE or "\r
948                         "OID_GEN_MAXIMUM_TOTAL_SIZE\n", port_num) );\r
949                 info = XFER_BLOCK_SIZE;\r
950                 break;\r
951 \r
952         case OID_GEN_VENDOR_ID:\r
953                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
954                         ("Port %d received query for OID_GEN_VENDOR_ID\n", port_num) );\r
955                 src_buf = (void*)VENDOR_ID;\r
956                 buf_len = sizeof(VENDOR_ID);\r
957                 break;\r
958 \r
959         case OID_GEN_VENDOR_DESCRIPTION:\r
960                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID, \r
961                         ("Port %d received query for OID_GEN_VENDOR_DESCRIPTION\n", port_num) );\r
962                 src_buf = VENDOR_DESCRIPTION;\r
963                 buf_len = sizeof(VENDOR_DESCRIPTION);\r
964                 break;\r
965 \r
966         case OID_GEN_VENDOR_DRIVER_VERSION:\r
967                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
968                         ("Port %d received query for OID_GEN_VENDOR_DRIVER_VERSION\n", port_num) );\r
969                 src_buf = &version;\r
970                 buf_len = sizeof(version);\r
971                 //TODO: Figure out what the right version is.\r
972                 version = 1 << 8 | 1;\r
973                 break;\r
974 \r
975         case OID_GEN_PHYSICAL_MEDIUM:\r
976                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
977                         ("Port %d received query for OID_GEN_PHYSICAL_MEDIUM\n", port_num) );\r
978                 info = NdisPhysicalMediumUnspecified;\r
979                 break;\r
980 \r
981         case OID_GEN_CURRENT_PACKET_FILTER:\r
982                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
983                         ("Port %d received query for OID_GEN_CURRENT_PACKET_FILTER\n", port_num) );\r
984                 info = p_adapter->packet_filter;\r
985                 break;\r
986 \r
987         case OID_GEN_DRIVER_VERSION:\r
988                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
989                         ("Port %d received query for OID_GEN_DRIVER_VERSION\n", port_num) );\r
990                 src_buf = &version;\r
991                 buf_len = sizeof(version);\r
992                 version = MAJOR_NDIS_VERSION << 8 | MINOR_NDIS_VERSION;\r
993                 break;\r
994 \r
995         case OID_GEN_MAC_OPTIONS:\r
996                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
997                         ("Port %d received query for OID_GEN_MAC_OPTIONS\n", port_num) );\r
998                 info = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |\r
999                         NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
1000                         NDIS_MAC_OPTION_NO_LOOPBACK |\r
1001                         NDIS_MAC_OPTION_FULL_DUPLEX;\r
1002 //TODO: Figure out if we will support priority and VLANs.\r
1003 //                              NDIS_MAC_OPTION_8021P_PRIORITY;\r
1004 //#ifdef NDIS51_MINIPORT\r
1005 //                      info |= NDIS_MAC_OPTION_8021Q_VLAN;\r
1006 //#endif\r
1007                 break;\r
1008 \r
1009         case OID_GEN_MEDIA_CONNECT_STATUS:\r
1010                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1011                         ("Port %d received query for OID_GEN_MEDIA_CONNECT_STATUS\n", port_num) );\r
1012                 cl_obj_lock( &p_adapter->obj );\r
1013                 switch( p_adapter->state )\r
1014                 {\r
1015                 case IB_PNP_PORT_ADD:\r
1016                 case IB_PNP_PORT_INIT:\r
1017                         /*\r
1018                          * Delay reporting media state until we know whether the port is\r
1019                          * either up or down.\r
1020                          */\r
1021                         p_adapter->pending_query = TRUE;\r
1022                         p_adapter->query_oid = oid_info;\r
1023 \r
1024                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1025                                 ("Port %d returning NDIS_STATUS_PENDING\n", port_num) );\r
1026                         status = NDIS_STATUS_PENDING;\r
1027                         break;\r
1028 \r
1029                 case IB_PNP_PORT_ACTIVE:\r
1030                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1031                                 ("Port %d returning NdisMediaStateConnected\n", port_num) );\r
1032                         info = NdisMediaStateConnected;\r
1033                         break;\r
1034 \r
1035                 case IB_PNP_PORT_REMOVE:\r
1036                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1037                                 ("Port %d returning NDIS_STATUS_NOT_ACCEPTED\n", port_num) );\r
1038                         status = NDIS_STATUS_NOT_ACCEPTED;\r
1039                         break;\r
1040 \r
1041                 default:\r
1042                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1043                                 ("Port %d returning NdisMediaStateDisconnected\n", port_num) );\r
1044                         info = NdisMediaStateDisconnected;\r
1045                 }\r
1046                 cl_obj_unlock( &p_adapter->obj );\r
1047                 break;\r
1048 \r
1049         case OID_GEN_MAXIMUM_SEND_PACKETS:\r
1050                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1051                         ("Port %d received query for OID_GEN_MAXIMUM_SEND_PACKETS\n", port_num) );\r
1052                 info = MAXULONG;\r
1053                 break;\r
1054 \r
1055         /* Required General Statistics */\r
1056         case OID_GEN_XMIT_OK:\r
1057                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1058                         ("Port %d received query for OID_GEN_XMIT_OK\n", port_num) );\r
1059                 src_buf = NULL;\r
1060                 status = ipoib_get_send_stat( p_adapter, IP_STAT_SUCCESS, &oid_info );\r
1061                 break;\r
1062 \r
1063         case OID_GEN_RCV_OK:\r
1064                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1065                         ("Port %d received query for OID_GEN_RCV_OK\n", port_num) );\r
1066                 src_buf = NULL;\r
1067                 status = ipoib_get_recv_stat( p_adapter, IP_STAT_SUCCESS, &oid_info );\r
1068                 break;\r
1069 \r
1070         case OID_GEN_XMIT_ERROR:\r
1071                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1072                         ("Port %d received query for OID_GEN_XMIT_ERROR\n", port_num) );\r
1073                 src_buf = NULL;\r
1074                 status = ipoib_get_send_stat( p_adapter, IP_STAT_ERROR, &oid_info );\r
1075                 break;\r
1076 \r
1077         case OID_GEN_RCV_ERROR:\r
1078                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1079                         ("Port %d received query for OID_GEN_RCV_ERROR\n", port_num) );\r
1080                 src_buf = NULL;\r
1081                 status = ipoib_get_recv_stat( p_adapter, IP_STAT_ERROR, &oid_info );\r
1082                 break;\r
1083 \r
1084         case OID_GEN_RCV_NO_BUFFER:\r
1085                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1086                         ("Port %d received query for OID_GEN_RCV_NO_BUFFER\n", port_num) );\r
1087                 src_buf = NULL;\r
1088                 status = ipoib_get_recv_stat( p_adapter, IP_STAT_DROPPED, &oid_info );\r
1089                 break;\r
1090 \r
1091         case OID_GEN_DIRECTED_BYTES_XMIT:\r
1092                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1093                         ("Port %d received query for OID_GEN_DIRECTED_BYTES_XMIT\n", port_num) );\r
1094                 src_buf = NULL;\r
1095                 status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info );\r
1096                 break;\r
1097 \r
1098         case OID_GEN_DIRECTED_FRAMES_XMIT:\r
1099                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1100                         ("Port %d received query for OID_GEN_DIRECTED_FRAMES_XMIT\n", port_num) );\r
1101                 src_buf = NULL;\r
1102                 status = ipoib_get_send_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info );\r
1103                 break;\r
1104 \r
1105         case OID_GEN_MULTICAST_BYTES_XMIT:\r
1106                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1107                         ("Port %d received query for OID_GEN_MULTICAST_BYTES_XMIT\n", port_num) );\r
1108                 src_buf = NULL;\r
1109                 status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info );\r
1110                 break;\r
1111 \r
1112         case OID_GEN_MULTICAST_FRAMES_XMIT:\r
1113                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1114                         ("Port %d received query for OID_GEN_MULTICAST_FRAMES_XMIT\n", port_num) );\r
1115                 src_buf = NULL;\r
1116                 status = ipoib_get_send_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info );\r
1117                 break;\r
1118 \r
1119         case OID_GEN_BROADCAST_BYTES_XMIT:\r
1120                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1121                         ("Port %d received query for OID_GEN_BROADCAST_BYTES_XMIT\n", port_num) );\r
1122                 src_buf = NULL;\r
1123                 status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info );\r
1124                 break;\r
1125 \r
1126         case OID_GEN_BROADCAST_FRAMES_XMIT:\r
1127                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1128                         ("Port %d received query for OID_GEN_BROADCAST_FRAMES_XMIT\n", port_num) );\r
1129                 src_buf = NULL;\r
1130                 status = ipoib_get_send_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info );\r
1131                 break;\r
1132 \r
1133         case OID_GEN_DIRECTED_BYTES_RCV:\r
1134                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1135                         ("Port %d received query for OID_GEN_DIRECTED_BYTES_RCV\n", port_num) );\r
1136                 src_buf = NULL;\r
1137                 status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_BYTES, &oid_info );\r
1138                 break;\r
1139 \r
1140         case OID_GEN_DIRECTED_FRAMES_RCV:\r
1141                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1142                         ("Port %d received query for OID_GEN_DIRECTED_FRAMES_RCV\n", port_num) );\r
1143                 src_buf = NULL;\r
1144                 status = ipoib_get_recv_stat( p_adapter, IP_STAT_UCAST_FRAMES, &oid_info );\r
1145                 break;\r
1146 \r
1147         case OID_GEN_MULTICAST_BYTES_RCV:\r
1148                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1149                         ("Port %d received query for OID_GEN_MULTICAST_BYTES_RCV\n", port_num) );\r
1150                 src_buf = NULL;\r
1151                 status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_BYTES, &oid_info );\r
1152                 break;\r
1153 \r
1154         case OID_GEN_MULTICAST_FRAMES_RCV:\r
1155                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1156                         ("Port %d received query for OID_GEN_MULTICAST_FRAMES_RCV\n", port_num) );\r
1157                 src_buf = NULL;\r
1158                 status = ipoib_get_recv_stat( p_adapter, IP_STAT_MCAST_FRAMES, &oid_info );\r
1159                 break;\r
1160 \r
1161         case OID_GEN_BROADCAST_BYTES_RCV:\r
1162                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1163                         ("Port %d received query for OID_GEN_BROADCAST_BYTES_RCV\n", port_num) );\r
1164                 src_buf = NULL;\r
1165                 status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_BYTES, &oid_info );\r
1166                 break;\r
1167 \r
1168         case OID_GEN_BROADCAST_FRAMES_RCV:\r
1169                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1170                         ("Port %d received query for OID_GEN_BROADCAST_FRAMES_RCV\n", port_num) );\r
1171                 src_buf = NULL;\r
1172                 status = ipoib_get_recv_stat( p_adapter, IP_STAT_BCAST_FRAMES, &oid_info );\r
1173                 break;\r
1174 \r
1175         /* Required Ethernet operational characteristics */\r
1176         case OID_802_3_PERMANENT_ADDRESS:\r
1177                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1178                         ("Port %d received query for OID_802_3_PERMANENT_ADDRESS\n", port_num) );\r
1179                 src_buf = &p_adapter->mac;\r
1180                 buf_len = sizeof(p_adapter->mac);\r
1181                 break;\r
1182 \r
1183         case OID_802_3_CURRENT_ADDRESS:\r
1184                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1185                         ("Port %d received query for OID_802_3_CURRENT_ADDRESS\n", port_num) );\r
1186                 src_buf = &p_adapter->params.conf_mac;\r
1187                 buf_len = sizeof(p_adapter->params.conf_mac);\r
1188                 break;\r
1189 \r
1190         case OID_802_3_MULTICAST_LIST:\r
1191                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1192                         ("Port %d received query for OID_802_3_MULTICAST_LIST\n", port_num) );\r
1193                 src_buf = p_adapter->mcast_array;\r
1194                 buf_len = p_adapter->mcast_array_size * sizeof(mac_addr_t);\r
1195                 break;\r
1196 \r
1197         case OID_802_3_MAXIMUM_LIST_SIZE:\r
1198                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1199                         ("Port %d received query for OID_802_3_MAXIMUM_LIST_SIZE\n", port_num) );\r
1200                 info = MAX_MCAST;\r
1201                 break;\r
1202 \r
1203         case OID_802_3_MAC_OPTIONS:\r
1204                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1205                         ("Port %d received query for OID_802_3_MAC_OPTIONS\n", port_num) );\r
1206                 info = 0;\r
1207                 break;\r
1208 \r
1209         /* Required Ethernet stats */\r
1210         case OID_802_3_RCV_ERROR_ALIGNMENT:\r
1211         case OID_802_3_XMIT_ONE_COLLISION:\r
1212         case OID_802_3_XMIT_MORE_COLLISIONS:\r
1213                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1214                         ("Port %d received query for OID_802_3_RCV_ERROR_ALIGNMENT or "\r
1215                         "OID_802_3_XMIT_ONE_COLLISION or "\r
1216                         "OID_802_3_XMIT_MORE_COLLISIONS\n", port_num) );\r
1217                 info = 0;\r
1218                 break;\r
1219 \r
1220         case OID_TCP_TASK_OFFLOAD:\r
1221                 src_buf = NULL;\r
1222                 status = __ipoib_get_tcp_task_offload( p_adapter, &oid_info );\r
1223                 break;\r
1224 \r
1225         /* Optional General */\r
1226         case OID_GEN_SUPPORTED_GUIDS:\r
1227 #ifdef NDIS51_MINIPORT\r
1228         case OID_GEN_VLAN_ID:\r
1229 #endif\r
1230 \r
1231         /* Optional General Stats */\r
1232         case OID_GEN_RCV_CRC_ERROR:\r
1233         case OID_GEN_TRANSMIT_QUEUE_LENGTH:\r
1234 \r
1235         /* Optional Ethernet Stats */\r
1236         case OID_802_3_XMIT_DEFERRED:\r
1237         case OID_802_3_XMIT_MAX_COLLISIONS:\r
1238         case OID_802_3_RCV_OVERRUN:\r
1239         case OID_802_3_XMIT_UNDERRUN:\r
1240         case OID_802_3_XMIT_HEARTBEAT_FAILURE:\r
1241         case OID_802_3_XMIT_TIMES_CRS_LOST:\r
1242         case OID_802_3_XMIT_LATE_COLLISIONS:\r
1243         case OID_PNP_CAPABILITIES:\r
1244                 status = NDIS_STATUS_NOT_SUPPORTED;\r
1245                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1246                         ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid) );\r
1247                 break;\r
1248 \r
1249         case OID_GEN_PROTOCOL_OPTIONS:\r
1250         case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
1251         case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
1252 #ifdef NDIS51_MINIPORT\r
1253         case OID_GEN_MACHINE_NAME:\r
1254         case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
1255 #endif\r
1256         default:\r
1257                 status = NDIS_STATUS_INVALID_OID;\r
1258                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1259                         ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid) );\r
1260                 break;\r
1261         }\r
1262 \r
1263         /*\r
1264          * Complete the request as if it was handled asynchronously to maximize\r
1265          * code reuse for when we really handle the requests asynchronously.\r
1266          * Note that this requires the QueryInformation entry point to always\r
1267          * return NDIS_STATUS_PENDING\r
1268          */\r
1269         if( status != NDIS_STATUS_PENDING )\r
1270         {\r
1271                 ipoib_complete_query(\r
1272                         p_adapter, &oid_info, status, src_buf, buf_len );\r
1273         }\r
1274 \r
1275         IPOIB_EXIT( IPOIB_DBG_OID );\r
1276         return NDIS_STATUS_PENDING;\r
1277 }\r
1278 \r
1279 \r
1280 static void\r
1281 ipoib_complete_query(\r
1282         IN                              ipoib_adapter_t* const          p_adapter,\r
1283         IN                              pending_oid_t* const            p_oid_info,\r
1284         IN              const   NDIS_STATUS                                     status,\r
1285         IN              const   void* const                                     p_buf,\r
1286         IN              const   ULONG                                           buf_len )\r
1287 {\r
1288         NDIS_STATUS             oid_status = status;\r
1289 \r
1290         IPOIB_ENTER( IPOIB_DBG_OID );\r
1291 \r
1292         CL_ASSERT( status != NDIS_STATUS_PENDING );\r
1293 \r
1294         if( status == NDIS_STATUS_SUCCESS )\r
1295         {\r
1296                 if( p_oid_info->buf_len < buf_len )\r
1297                 {\r
1298                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1299                                 ("Insufficient buffer space.  "\r
1300                                 "Returning NDIS_STATUS_INVALID_LENGTH.\n") );\r
1301                         oid_status = NDIS_STATUS_INVALID_LENGTH;\r
1302                         *p_oid_info->p_bytes_needed = buf_len;\r
1303                         *p_oid_info->p_bytes_used = 0;\r
1304                 }\r
1305                 else if( p_oid_info->p_buf )\r
1306                 {\r
1307                         /* Only copy if we have a distinct source buffer. */\r
1308                         if( p_buf )\r
1309                         {\r
1310                                 NdisMoveMemory( p_oid_info->p_buf, p_buf, buf_len );\r
1311                                 *p_oid_info->p_bytes_used = buf_len;\r
1312                         }\r
1313                 }\r
1314                 else\r
1315                 {\r
1316                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1317                                 ("Returning NDIS_NOT_ACCEPTED") );\r
1318                         oid_status = NDIS_STATUS_NOT_ACCEPTED;\r
1319                 }\r
1320         }\r
1321         else\r
1322         {\r
1323                 *p_oid_info->p_bytes_used = 0;\r
1324         }\r
1325 \r
1326         p_adapter->pending_query = FALSE;\r
1327 \r
1328         NdisMQueryInformationComplete( p_adapter->h_adapter, oid_status );\r
1329 \r
1330         IPOIB_EXIT( IPOIB_DBG_OID );\r
1331 }\r
1332 \r
1333 \r
1334 static NDIS_STATUS\r
1335 __ipoib_get_tcp_task_offload(\r
1336         IN                              ipoib_adapter_t*                        p_adapter,\r
1337         IN                              pending_oid_t* const            p_oid_info )\r
1338 {\r
1339         NDIS_TASK_OFFLOAD_HEADER        *p_offload_hdr;\r
1340         NDIS_TASK_OFFLOAD                       *p_offload_task;\r
1341         NDIS_TASK_TCP_IP_CHECKSUM       *p_offload_chksum;\r
1342         ULONG                                           buf_len;\r
1343 \r
1344         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1345                 ("Port %d received query for OID_TCP_TASK_OFFLOAD\n",\r
1346                 p_adapter->guids.port_num) );\r
1347 \r
1348         buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
1349                 offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +\r
1350                 sizeof(NDIS_TASK_TCP_IP_CHECKSUM);\r
1351 \r
1352         *(p_oid_info->p_bytes_needed) = buf_len;\r
1353 \r
1354         if( p_oid_info->buf_len < buf_len )\r
1355                 return NDIS_STATUS_INVALID_LENGTH;\r
1356 \r
1357         p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_oid_info->p_buf;\r
1358         if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
1359                 return NDIS_STATUS_INVALID_DATA;\r
1360 \r
1361         if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
1362                 IEEE_802_3_Encapsulation )\r
1363         {\r
1364                 return NDIS_STATUS_INVALID_DATA;\r
1365         }\r
1366 \r
1367         p_offload_hdr->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER);\r
1368         p_offload_task = (NDIS_TASK_OFFLOAD*)(p_offload_hdr + 1);\r
1369         p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;\r
1370         p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);\r
1371         p_offload_task->Task = TcpIpChecksumNdisTask;\r
1372         p_offload_task->OffsetNextTask = 0;\r
1373         p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);\r
1374         p_offload_chksum =\r
1375                 (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
1376 \r
1377         p_offload_chksum->V4Transmit.IpOptionsSupported =\r
1378                 p_adapter->params.send_chksum_offload;\r
1379         p_offload_chksum->V4Transmit.TcpOptionsSupported =\r
1380                 p_adapter->params.send_chksum_offload;\r
1381         p_offload_chksum->V4Transmit.TcpChecksum =\r
1382                 p_adapter->params.send_chksum_offload;\r
1383         p_offload_chksum->V4Transmit.UdpChecksum =\r
1384                 p_adapter->params.send_chksum_offload;\r
1385         p_offload_chksum->V4Transmit.IpChecksum =\r
1386                 p_adapter->params.send_chksum_offload;\r
1387 \r
1388         /*\r
1389          * Only receive checksum can be offloaded thanks to\r
1390          * the IB physical layer.\r
1391          */\r
1392         p_offload_chksum->V4Receive.IpOptionsSupported = TRUE;\r
1393         p_offload_chksum->V4Receive.TcpOptionsSupported = TRUE;\r
1394         p_offload_chksum->V4Receive.TcpChecksum = TRUE;\r
1395         p_offload_chksum->V4Receive.UdpChecksum = TRUE;\r
1396         p_offload_chksum->V4Receive.IpChecksum = TRUE;\r
1397 \r
1398         p_offload_chksum->V6Transmit.IpOptionsSupported = FALSE;\r
1399         p_offload_chksum->V6Transmit.TcpOptionsSupported = FALSE;\r
1400         p_offload_chksum->V6Transmit.TcpChecksum = FALSE;\r
1401         p_offload_chksum->V6Transmit.UdpChecksum = FALSE;\r
1402 \r
1403         p_offload_chksum->V6Receive.IpOptionsSupported = FALSE;\r
1404         p_offload_chksum->V6Receive.TcpOptionsSupported = FALSE;\r
1405         p_offload_chksum->V6Receive.TcpChecksum = FALSE;\r
1406         p_offload_chksum->V6Receive.UdpChecksum = FALSE;\r
1407 \r
1408         *(p_oid_info->p_bytes_used) = buf_len;\r
1409 \r
1410         return NDIS_STATUS_SUCCESS;\r
1411 }\r
1412 \r
1413 \r
1414 static NDIS_STATUS\r
1415 __ipoib_set_tcp_task_offload(\r
1416         IN                              ipoib_adapter_t*                        p_adapter,\r
1417         IN                              void* const                                     p_info_buf,\r
1418         IN                              ULONG* const                            p_info_len )\r
1419 {\r
1420         NDIS_TASK_OFFLOAD_HEADER        *p_offload_hdr;\r
1421         NDIS_TASK_OFFLOAD                       *p_offload_task;\r
1422         NDIS_TASK_TCP_IP_CHECKSUM       *p_offload_chksum;\r
1423 \r
1424         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1425                 ("Port %d received set for OID_TCP_TASK_OFFLOAD\n",\r
1426                 p_adapter->guids.port_num) );\r
1427 \r
1428         p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_info_buf;\r
1429 \r
1430         if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
1431                 return NDIS_STATUS_INVALID_LENGTH;\r
1432 \r
1433         if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
1434                 return NDIS_STATUS_INVALID_DATA;\r
1435 \r
1436         if( p_offload_hdr->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
1437                 return NDIS_STATUS_INVALID_LENGTH;\r
1438 \r
1439         if( !p_offload_hdr->OffsetFirstTask )\r
1440                 return NDIS_STATUS_SUCCESS;\r
1441 \r
1442         if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
1443                 IEEE_802_3_Encapsulation )\r
1444         {\r
1445                 return NDIS_STATUS_INVALID_DATA;\r
1446         }\r
1447 \r
1448         p_offload_task = (NDIS_TASK_OFFLOAD*)\r
1449                 (((UCHAR*)p_offload_hdr) + p_offload_hdr->OffsetFirstTask);\r
1450 \r
1451         if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
1452                 offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +\r
1453                 sizeof(NDIS_TASK_TCP_IP_CHECKSUM) )\r
1454         {\r
1455                 return NDIS_STATUS_INVALID_LENGTH;\r
1456         }\r
1457 \r
1458         if( p_offload_task->Version != NDIS_TASK_OFFLOAD_VERSION )\r
1459                 return NDIS_STATUS_INVALID_DATA;\r
1460         p_offload_chksum =\r
1461                 (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
1462 \r
1463         if( !p_adapter->params.send_chksum_offload &&\r
1464                 (p_offload_chksum->V4Transmit.IpOptionsSupported ||\r
1465                 p_offload_chksum->V4Transmit.TcpOptionsSupported ||\r
1466                 p_offload_chksum->V4Transmit.TcpChecksum ||\r
1467                 p_offload_chksum->V4Transmit.UdpChecksum ||\r
1468                 p_offload_chksum->V4Transmit.IpChecksum) )\r
1469         {\r
1470                 return NDIS_STATUS_NOT_SUPPORTED;\r
1471         }\r
1472 \r
1473         return NDIS_STATUS_SUCCESS;\r
1474 }\r
1475 \r
1476 \r
1477 //! Issues a hardware reset to the NIC and/or resets the driver's software state.\r
1478 /*  Tear down the connection and start over again.  This is only called when there is a problem.\r
1479 For example, if a send, query info, or set info had a time out.  MiniportCheckForHang will\r
1480 be called first.\r
1481 IRQL = DISPATCH_LEVEL\r
1482 \r
1483 @param p_addr_resetPointer to BOOLLEAN that is set to TRUE if the NDIS\r
1484 library should call MiniportSetInformation to restore addressing information to the current values.\r
1485 @param adapter_context The adapter context allocated at start\r
1486 @return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_NOT_RESETTABLE,\r
1487 NDIS_STATUS_RESET_IN_PROGRESS, NDIS_STATUS_SOFT_ERRORS, NDIS_STATUS_HARD_ERRORS\r
1488 */\r
1489 NDIS_STATUS\r
1490 ipoib_reset(\r
1491                 OUT                     PBOOLEAN                                        p_addr_reset,\r
1492         IN                              NDIS_HANDLE                                     adapter_context)\r
1493 {\r
1494         ipoib_adapter_t* p_adapter;\r
1495 \r
1496         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1497 \r
1498         CL_ASSERT( p_addr_reset );\r
1499         CL_ASSERT( adapter_context );\r
1500         p_adapter = (ipoib_adapter_t*)adapter_context;\r
1501 \r
1502         switch( ipoib_reset_adapter( p_adapter ) )\r
1503         {\r
1504         case IB_NOT_DONE:\r
1505                 IPOIB_EXIT( IPOIB_DBG_INIT );\r
1506                 return NDIS_STATUS_PENDING;\r
1507 \r
1508         case IB_SUCCESS:\r
1509                 IPOIB_EXIT( IPOIB_DBG_INIT );\r
1510                 *p_addr_reset = TRUE;\r
1511                 return NDIS_STATUS_SUCCESS;\r
1512 \r
1513         case IB_INVALID_STATE:\r
1514                 IPOIB_EXIT( IPOIB_DBG_INIT );\r
1515                 return NDIS_STATUS_RESET_IN_PROGRESS;\r
1516 \r
1517         default:\r
1518                 IPOIB_EXIT( IPOIB_DBG_INIT );\r
1519                 return NDIS_STATUS_HARD_ERRORS;\r
1520         }\r
1521 }\r
1522 \r
1523 \r
1524 //! Request changes in the state information that the miniport driver maintains\r
1525 /*  For example, this is used to set multicast addresses and the packet filter.\r
1526 IRQL = DISPATCH_LEVEL\r
1527 \r
1528 @param adapter_context The adapter context allocated at start\r
1529 @param oid Object ID representing the set operation to be carried out\r
1530 @param info_buf Buffer containing input for this set and location for any output\r
1531 @param info_buf_len Number of bytes available in info_buf\r
1532 @param p_bytes_read Pointer to number of bytes read from info_buf\r
1533 @param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
1534 @return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
1535 NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_INVALID_DATA, NDIS_STATUS_NOT_ACCEPTED,\r
1536 NDIS_STATUS_NOT_SUPPORTED, NDIS_STATUS_RESOURCES\r
1537 */\r
1538 NDIS_STATUS\r
1539 ipoib_set_info(\r
1540         IN                              NDIS_HANDLE                                     adapter_context,\r
1541         IN                              NDIS_OID                                        oid,\r
1542         IN                              PVOID                                           info_buf,\r
1543         IN                              ULONG                                           info_buf_len,\r
1544                 OUT                     PULONG                                          p_bytes_read,\r
1545                 OUT                     PULONG                                          p_bytes_needed )\r
1546 {\r
1547         ipoib_adapter_t*        p_adapter;\r
1548         NDIS_STATUS                     status;\r
1549 \r
1550         ULONG                           buf_len;\r
1551         uint8_t                         port_num;\r
1552 \r
1553         KLOCK_QUEUE_HANDLE      hdl;\r
1554         \r
1555         IPOIB_ENTER( IPOIB_DBG_OID );\r
1556 \r
1557         CL_ASSERT( adapter_context );\r
1558         p_adapter = (ipoib_adapter_t*)adapter_context;\r
1559 \r
1560         CL_ASSERT( p_bytes_read );\r
1561         CL_ASSERT( p_bytes_needed );\r
1562         CL_ASSERT( !p_adapter->pending_set );\r
1563 \r
1564         status = NDIS_STATUS_SUCCESS;\r
1565         *p_bytes_needed = 0;\r
1566         buf_len = sizeof(ULONG);\r
1567 \r
1568         port_num = p_adapter->guids.port_num;\r
1569 \r
1570         switch( oid )\r
1571         {\r
1572         /* Required General */\r
1573         case OID_GEN_CURRENT_PACKET_FILTER:\r
1574                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1575                         ("Port %d received set for OID_GEN_CURRENT_PACKET_FILTER\n", port_num));\r
1576                 if( info_buf_len < sizeof(p_adapter->packet_filter) )\r
1577                 {\r
1578                         status = NDIS_STATUS_INVALID_LENGTH;\r
1579                 }\r
1580                 else if( !info_buf )\r
1581                 {\r
1582                         status = NDIS_STATUS_INVALID_DATA;\r
1583                 }\r
1584                 else\r
1585                 {\r
1586                         KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
1587                         cl_obj_lock( &p_adapter->obj );\r
1588                         switch( p_adapter->state )\r
1589                         {\r
1590                         case IB_PNP_PORT_ADD:\r
1591                                 p_adapter->set_oid.oid = oid;\r
1592                                 p_adapter->set_oid.p_buf = info_buf;\r
1593                                 p_adapter->set_oid.buf_len = info_buf_len;\r
1594                                 p_adapter->set_oid.p_bytes_used = p_bytes_read;\r
1595                                 p_adapter->set_oid.p_bytes_needed = p_bytes_needed;\r
1596                                 p_adapter->pending_set = TRUE;\r
1597                                 status = NDIS_STATUS_PENDING;\r
1598                                 break;\r
1599 \r
1600                         case IB_PNP_PORT_REMOVE:\r
1601                                 status = NDIS_STATUS_NOT_ACCEPTED;\r
1602                                 break;\r
1603 \r
1604                         default:\r
1605                                 if( !p_adapter->packet_filter && (*(uint32_t*)info_buf) )\r
1606                                 {\r
1607                                         cl_qlist_insert_tail(\r
1608                                                 &g_ipoib.adapter_list, &p_adapter->entry );\r
1609 \r
1610                                         /*\r
1611                                          * Filter was zero, now non-zero.  Register IP addresses\r
1612                                          * with SA.\r
1613                                          */\r
1614                                         ipoib_reg_addrs( p_adapter );\r
1615                                 }\r
1616                                 else if( p_adapter->packet_filter && !(*(uint32_t*)info_buf) )\r
1617                                 {\r
1618                                         /*\r
1619                                          * Filter was non-zero, now zero.  Deregister IP addresses.\r
1620                                          */\r
1621                                         ipoib_dereg_addrs( p_adapter );\r
1622 \r
1623                                         ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
1624                                         cl_qlist_remove_item(\r
1625                                                 &g_ipoib.adapter_list, &p_adapter->entry );\r
1626                                 }\r
1627 \r
1628                                 p_adapter->packet_filter = *(uint32_t*)info_buf;\r
1629                         }\r
1630                         cl_obj_unlock( &p_adapter->obj );\r
1631                         KeReleaseInStackQueuedSpinLock( &hdl );\r
1632                 }\r
1633                 break;\r
1634 \r
1635         case OID_GEN_CURRENT_LOOKAHEAD:\r
1636                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1637                         ("Port %d received set for OID_GEN_CURRENT_LOOKAHEAD\n", port_num));\r
1638                 if( info_buf_len < buf_len )\r
1639                         status = NDIS_STATUS_INVALID_LENGTH;\r
1640                 break;\r
1641 \r
1642         case OID_GEN_PROTOCOL_OPTIONS:\r
1643                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1644                         ("Port %d received set for OID_GEN_PROTOCOL_OPTIONS\n", port_num));\r
1645                 if( info_buf_len < buf_len )\r
1646                         status = NDIS_STATUS_INVALID_LENGTH;\r
1647                 break;\r
1648 \r
1649         case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
1650                 status = __ipoib_set_net_addr( p_adapter, info_buf, info_buf_len, p_bytes_read, p_bytes_needed);\r
1651                 break;\r
1652 \r
1653 #ifdef NDIS51_MINIPORT\r
1654         case OID_GEN_MACHINE_NAME:\r
1655                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
1656                         ("Port %d received set for OID_GEN_MACHINE_NAME\n", port_num) );\r
1657                 break;\r
1658 #endif\r
1659 \r
1660         /* Required Ethernet operational characteristics */\r
1661         case OID_802_3_MULTICAST_LIST:\r
1662                 IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
1663                         ("Port %d received set for OID_802_3_MULTICAST_LIST\n", port_num) );\r
1664                 if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) )\r
1665                 {\r
1666                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1667                                 ("Port %d OID_802_3_MULTICAST_LIST - Multicast list full.\n", port_num) );\r
1668                         status = NDIS_STATUS_MULTICAST_FULL;\r
1669                         *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t);\r
1670                 }\r
1671                 else if( info_buf_len % sizeof(mac_addr_t) )\r
1672                 {\r
1673                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1674                                 ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
1675                         status = NDIS_STATUS_INVALID_DATA;\r
1676                 }\r
1677                 else if( !info_buf && info_buf_len )\r
1678                 {\r
1679                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1680                                 ("Port %d OID_802_3_MULTICAST_LIST - Invalid input buffer.\n", port_num) );\r
1681                         status = NDIS_STATUS_INVALID_DATA;\r
1682                 }\r
1683                 else\r
1684                 {\r
1685                         ipoib_refresh_mcast( p_adapter, (mac_addr_t*)info_buf,\r
1686                                 (uint8_t)(info_buf_len / sizeof(mac_addr_t)) );\r
1687 \r
1688                         buf_len = info_buf_len;\r
1689                         /*\r
1690                          * Note that we don't return pending.  It will likely take longer\r
1691                          * for our SA transactions to complete than NDIS will give us\r
1692                          * before reseting the adapter.  If an SA failure is encountered,\r
1693                          * the adapter will be marked as hung and we will get reset.\r
1694                          */\r
1695                         status = NDIS_STATUS_SUCCESS;\r
1696                 }\r
1697                 break;\r
1698 \r
1699         case OID_TCP_TASK_OFFLOAD:\r
1700                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1701                         ("Port %d received set for OID_TCP_TASK_OFFLOAD\n", port_num) );\r
1702 \r
1703                 buf_len = info_buf_len;\r
1704                 status =\r
1705                         __ipoib_set_tcp_task_offload( p_adapter, info_buf, &buf_len );\r
1706                 break;\r
1707 \r
1708         /* Optional General */\r
1709         case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
1710 #ifdef NDIS51_MINIPORT\r
1711         case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
1712         case OID_GEN_VLAN_ID:\r
1713 #endif\r
1714                 status = NDIS_STATUS_NOT_SUPPORTED;\r
1715                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1716                         ("Port %d received an unsupported oid of 0x%.8X!\n", port_num, oid));\r
1717                 break;\r
1718 \r
1719         case OID_GEN_SUPPORTED_LIST:\r
1720         case OID_GEN_HARDWARE_STATUS:\r
1721         case OID_GEN_MEDIA_SUPPORTED:\r
1722         case OID_GEN_MEDIA_IN_USE:\r
1723         case OID_GEN_MAXIMUM_FRAME_SIZE:\r
1724         case OID_GEN_LINK_SPEED:\r
1725         case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
1726         case OID_GEN_RECEIVE_BUFFER_SPACE:\r
1727         case OID_GEN_MAXIMUM_LOOKAHEAD:\r
1728         case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
1729         case OID_GEN_RECEIVE_BLOCK_SIZE:\r
1730         case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
1731         case OID_GEN_VENDOR_ID:\r
1732         case OID_GEN_VENDOR_DESCRIPTION:\r
1733         case OID_GEN_VENDOR_DRIVER_VERSION:\r
1734         case OID_GEN_DRIVER_VERSION:\r
1735         case OID_GEN_MAC_OPTIONS:\r
1736         case OID_GEN_MEDIA_CONNECT_STATUS:\r
1737         case OID_GEN_MAXIMUM_SEND_PACKETS:\r
1738         case OID_GEN_SUPPORTED_GUIDS:\r
1739         case OID_GEN_PHYSICAL_MEDIUM:\r
1740         default:\r
1741                 status = NDIS_STATUS_INVALID_OID;\r
1742                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
1743                         ("Port %d received an invalid oid of 0x%.8X!\n", port_num, oid));\r
1744                 break;\r
1745         }\r
1746 \r
1747         if( status == NDIS_STATUS_SUCCESS )\r
1748         {\r
1749                 *p_bytes_read = buf_len;\r
1750         }\r
1751         else\r
1752         {\r
1753                 if( status == NDIS_STATUS_INVALID_LENGTH )\r
1754                 {\r
1755                         if ( !*p_bytes_needed )\r
1756                         {\r
1757                                 *p_bytes_needed = buf_len;\r
1758                         }\r
1759                 }\r
1760 \r
1761                 *p_bytes_read = 0;\r
1762         }\r
1763 \r
1764         IPOIB_EXIT( IPOIB_DBG_OID );\r
1765         return status;\r
1766 }\r
1767 \r
1768 \r
1769 //! Transfers some number of packets, specified as an array of packet pointers, over the network. \r
1770 /*  For a deserialized driver, these packets are completed asynchronously\r
1771 using NdisMSendComplete.\r
1772 IRQL <= DISPATCH_LEVEL\r
1773 \r
1774 @param adapter_context Pointer to ipoib_adapter_t structure with per NIC state\r
1775 @param packet_array Array of packets to send\r
1776 @param numPackets Number of packets in the array\r
1777 */\r
1778 void\r
1779 ipoib_send_packets(\r
1780         IN                              NDIS_HANDLE                                     adapter_context,\r
1781         IN                              PPNDIS_PACKET                           packet_array,\r
1782         IN                              UINT                                            num_packets )\r
1783 {\r
1784         ipoib_adapter_t         *p_adapter;\r
1785         ipoib_port_t            *p_port;\r
1786         UINT                            packet_num;\r
1787         PERF_DECLARE( SendPackets );\r
1788         PERF_DECLARE( PortSend );\r
1789 \r
1790         IPOIB_ENTER( IPOIB_DBG_SEND );\r
1791 \r
1792         cl_perf_start( SendPackets );\r
1793 \r
1794         CL_ASSERT( adapter_context );\r
1795         p_adapter = (ipoib_adapter_t*)adapter_context;\r
1796 \r
1797         cl_obj_lock( &p_adapter->obj );\r
1798         if( p_adapter->state != IB_PNP_PORT_ACTIVE || !p_adapter->p_port )\r
1799         {\r
1800                 cl_obj_unlock( &p_adapter->obj );\r
1801                 for( packet_num = 0; packet_num < num_packets; ++packet_num )\r
1802                 {\r
1803                         ipoib_inc_send_stat( p_adapter, IP_STAT_DROPPED, 0 );\r
1804                         NdisMSendComplete( p_adapter->h_adapter,\r
1805                                 packet_array[packet_num], NDIS_STATUS_ADAPTER_NOT_READY );\r
1806                 }\r
1807                 IPOIB_EXIT( IPOIB_DBG_SEND );\r
1808                 return;\r
1809         }\r
1810 \r
1811         p_port = p_adapter->p_port;\r
1812         cl_obj_ref( &p_port->obj );\r
1813         cl_obj_unlock( &p_adapter->obj );\r
1814 \r
1815         cl_perf_start( PortSend );\r
1816         ipoib_port_send( p_port, packet_array, num_packets );\r
1817         cl_perf_stop( &p_port->p_adapter->perf, PortSend );\r
1818         cl_obj_deref( &p_port->obj );\r
1819 \r
1820         cl_perf_stop( &p_adapter->perf, SendPackets );\r
1821 \r
1822         cl_perf_log( &p_adapter->perf, SendBundle, num_packets );\r
1823 \r
1824         IPOIB_EXIT( IPOIB_DBG_SEND );\r
1825 }\r
1826 \r
1827 \r
1828 void\r
1829 ipoib_pnp_notify(\r
1830         IN                              NDIS_HANDLE                                     adapter_context,\r
1831         IN                              NDIS_DEVICE_PNP_EVENT           pnp_event,\r
1832         IN                              PVOID                                           info_buf,\r
1833         IN                              ULONG                                           info_buf_len )\r
1834 {\r
1835         ipoib_adapter_t *p_adapter;\r
1836 \r
1837         IPOIB_ENTER( IPOIB_DBG_PNP );\r
1838 \r
1839         UNUSED_PARAM( info_buf );\r
1840         UNUSED_PARAM( info_buf_len );\r
1841 \r
1842         p_adapter = (ipoib_adapter_t*)adapter_context;\r
1843 \r
1844         IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_PNP, ("Event %d\n", pnp_event) );\r
1845         if( pnp_event != NdisDevicePnPEventPowerProfileChanged )\r
1846         {\r
1847                 cl_obj_lock( &p_adapter->obj );\r
1848                 p_adapter->state = IB_PNP_PORT_REMOVE;\r
1849                 cl_obj_unlock( &p_adapter->obj );\r
1850 \r
1851                 ipoib_resume_oids( p_adapter );\r
1852         }\r
1853 \r
1854         IPOIB_EXIT( IPOIB_DBG_PNP );\r
1855 }\r
1856 \r
1857 \r
1858 void\r
1859 ipoib_shutdown(\r
1860         IN                              PVOID                                           adapter_context )\r
1861 {\r
1862         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1863         UNUSED_PARAM( adapter_context );\r
1864         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1865 }\r
1866 \r
1867 \r
1868 void\r
1869 ipoib_resume_oids(\r
1870         IN                              ipoib_adapter_t* const          p_adapter )\r
1871 {\r
1872         ULONG                           info;\r
1873         NDIS_STATUS                     status;\r
1874         boolean_t                       pending_query, pending_set;\r
1875         pending_oid_t           query_oid = {0};\r
1876         pending_oid_t           set_oid = {0};\r
1877         KLOCK_QUEUE_HANDLE      hdl;\r
1878 \r
1879         IPOIB_ENTER( IPOIB_DBG_INIT );\r
1880 \r
1881         cl_obj_lock( &p_adapter->obj );\r
1882         /*\r
1883          * Set the status depending on our state.  Fail OID requests that\r
1884          * are pending while we reset the adapter.\r
1885          */\r
1886         switch( p_adapter->state )\r
1887         {\r
1888         case IB_PNP_PORT_ADD:\r
1889                 status = NDIS_STATUS_FAILURE;\r
1890                 break;\r
1891 \r
1892         case IB_PNP_PORT_REMOVE:\r
1893                 status = NDIS_STATUS_NOT_ACCEPTED;\r
1894                 break;\r
1895                 \r
1896         default:\r
1897                 status = NDIS_STATUS_SUCCESS;\r
1898         }\r
1899 \r
1900         pending_query = p_adapter->pending_query;\r
1901         if( pending_query )\r
1902         {\r
1903                 query_oid = p_adapter->query_oid;\r
1904                 p_adapter->pending_query = FALSE;\r
1905         }\r
1906         pending_set = p_adapter->pending_set;\r
1907         if( pending_set )\r
1908         {\r
1909                 set_oid = p_adapter->set_oid;\r
1910                 p_adapter->pending_set = FALSE;\r
1911         }\r
1912         cl_obj_unlock( &p_adapter->obj );\r
1913 \r
1914         /*\r
1915          * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
1916          * complete it now.  Note that we hold the object lock since\r
1917          * NdisMQueryInformationComplete is called at DISPATCH_LEVEL.\r
1918          */\r
1919         if( pending_query )\r
1920         {\r
1921                 switch( query_oid.oid )\r
1922                 {\r
1923                 case OID_GEN_LINK_SPEED:\r
1924                         ipoib_complete_query( p_adapter, &query_oid,\r
1925                                 status, &p_adapter->rate, sizeof(p_adapter->rate) );\r
1926                         break;\r
1927 \r
1928                 case OID_GEN_MEDIA_CONNECT_STATUS:\r
1929                         info = NdisMediaStateConnected;\r
1930                         ipoib_complete_query( p_adapter, &query_oid,\r
1931                                 status, &info, sizeof(info) );\r
1932                         break;\r
1933 \r
1934                 default:\r
1935                         CL_ASSERT( query_oid.oid == OID_GEN_LINK_SPEED ||\r
1936                                 query_oid.oid == OID_GEN_MEDIA_CONNECT_STATUS );\r
1937                         break;\r
1938                 }\r
1939         }\r
1940 \r
1941         if( pending_set )\r
1942         {\r
1943                 switch( set_oid.oid )\r
1944                 {\r
1945                 case OID_GEN_CURRENT_PACKET_FILTER:\r
1946                         /* Validation already performed in the SetInformation path. */\r
1947 \r
1948                         KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
1949                         cl_obj_lock( &p_adapter->obj );\r
1950                         if( !p_adapter->packet_filter && (*(PULONG)set_oid.p_buf) )\r
1951                         {\r
1952                                 cl_qlist_insert_tail(\r
1953                                         &g_ipoib.adapter_list, &p_adapter->entry );\r
1954                                 /*\r
1955                                  * Filter was zero, now non-zero.  Register IP addresses\r
1956                                  * with SA.\r
1957                                  */\r
1958                                 ipoib_reg_addrs( p_adapter );\r
1959                         }\r
1960                         else if( p_adapter->packet_filter && !(*(PULONG)set_oid.p_buf) )\r
1961                         {\r
1962                                 /* Filter was non-zero, now zero.  Deregister IP addresses. */\r
1963                                 ipoib_dereg_addrs( p_adapter );\r
1964 \r
1965                                 ASSERT( cl_qlist_count( &g_ipoib.adapter_list ) );\r
1966                                 cl_qlist_remove_item(\r
1967                                         &g_ipoib.adapter_list, &p_adapter->entry );\r
1968                         }\r
1969                         p_adapter->packet_filter = *(PULONG)set_oid.p_buf;\r
1970 \r
1971                         cl_obj_unlock( &p_adapter->obj );\r
1972                         KeReleaseInStackQueuedSpinLock( &hdl );\r
1973 \r
1974                         NdisMSetInformationComplete( p_adapter->h_adapter, status );\r
1975                         break;\r
1976 \r
1977                 case OID_GEN_NETWORK_LAYER_ADDRESSES:\r
1978                         status = __ipoib_set_net_addr( p_adapter,\r
1979                                                                                    p_adapter->set_oid.p_buf,\r
1980                                                                                    p_adapter->set_oid.buf_len,\r
1981                                                                                    p_adapter->set_oid.p_bytes_used,\r
1982                                                                                    p_adapter->set_oid.p_bytes_needed );\r
1983                         if( status != NDIS_STATUS_PENDING )\r
1984                         {\r
1985                                 NdisMSetInformationComplete( p_adapter->h_adapter, status );\r
1986                         }\r
1987                         break;\r
1988 \r
1989                 default:\r
1990                         CL_ASSERT( set_oid.oid && 0 );\r
1991                         break;\r
1992                 }\r
1993         }\r
1994 \r
1995         IPOIB_EXIT( IPOIB_DBG_INIT );\r
1996 }\r
1997 \r
1998 \r
1999 static NDIS_STATUS\r
2000 __ipoib_set_net_addr(\r
2001         IN              ipoib_adapter_t *       p_adapter,\r
2002         IN              PVOID                           info_buf,\r
2003         IN              ULONG                           info_buf_len,\r
2004                 OUT     PULONG                          p_bytes_read,\r
2005                 OUT     PULONG                          p_bytes_needed )\r
2006 {\r
2007         NDIS_STATUS                             status;\r
2008         PNETWORK_ADDRESS_LIST   p_net_addrs;\r
2009         PNETWORK_ADDRESS                p_net_addr_oid;\r
2010         PNETWORK_ADDRESS_IP             p_ip_addr;\r
2011 \r
2012         net_address_item_t              *p_addr_item;\r
2013 \r
2014         cl_status_t                             cl_status;\r
2015 \r
2016         size_t                                  idx;\r
2017         LONG                                    i;\r
2018         ULONG                                   addr_size;\r
2019         ULONG                                   total_size;\r
2020 \r
2021         uint8_t                                 port_num;\r
2022 \r
2023         IPOIB_ENTER( IPOIB_DBG_OID );\r
2024 \r
2025         status = NDIS_STATUS_SUCCESS;\r
2026         port_num = p_adapter->guids.port_num;\r
2027 \r
2028         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
2029                 ("Port %d received set for OID_GEN_NETWORK_LAYER_ADDRESSES\n",\r
2030                 port_num) );\r
2031 \r
2032         if( !info_buf )\r
2033         {\r
2034                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2035                         ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
2036                         "NULL buffer\n", port_num) );\r
2037                 IPOIB_EXIT( IPOIB_DBG_OID );\r
2038                 return NDIS_STATUS_INVALID_DATA;\r
2039         }\r
2040 \r
2041         /*\r
2042          * Must use field offset because the structures define array's of size one\r
2043          * of a the incorrect type for what is really stored.\r
2044          */\r
2045         if( info_buf_len < FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) )\r
2046         {\r
2047                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
2048                         ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
2049                         "bad length of %d, not enough "\r
2050                         "for NETWORK_ADDRESS_LIST (%d)\n", port_num, info_buf_len,\r
2051                         FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address)) );\r
2052                 *p_bytes_needed = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address);\r
2053                 IPOIB_EXIT( IPOIB_DBG_OID );\r
2054                 return NDIS_STATUS_INVALID_LENGTH;\r
2055         }\r
2056 \r
2057         p_net_addrs = (PNETWORK_ADDRESS_LIST)info_buf;\r
2058         if( p_net_addrs->AddressCount == 0)\r
2059         {\r
2060                 if( p_net_addrs->AddressType == NDIS_PROTOCOL_ID_TCP_IP )\r
2061                 {\r
2062                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
2063                                 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
2064                                 "clear TCP/IP addresses\n", port_num) );\r
2065                 }\r
2066                 else\r
2067                 {\r
2068                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
2069                                 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
2070                                 "Non TCP/IP address type of 0x%.4X on clear\n",\r
2071                                 port_num, p_net_addrs->AddressType) );\r
2072                         IPOIB_EXIT( IPOIB_DBG_OID );\r
2073                         return NDIS_STATUS_SUCCESS;\r
2074                 }\r
2075         }\r
2076 \r
2077         addr_size = FIELD_OFFSET(NETWORK_ADDRESS, Address) +\r
2078                 NETWORK_ADDRESS_LENGTH_IP;\r
2079         total_size = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) +\r
2080                 addr_size * p_net_addrs->AddressCount;\r
2081 \r
2082         if( info_buf_len < total_size )\r
2083         {\r
2084                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2085                         ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
2086                         "bad length of %d, %d required for %d addresses\n",\r
2087                         port_num, info_buf_len, total_size, p_net_addrs->AddressCount) );\r
2088                 *p_bytes_needed = total_size;\r
2089                 IPOIB_EXIT( IPOIB_DBG_OID );\r
2090                 return NDIS_STATUS_INVALID_LENGTH;\r
2091         }\r
2092 \r
2093         /* Lock lists for duration since SA callbacks can occur on other CPUs */\r
2094         cl_obj_lock( &p_adapter->obj );\r
2095 \r
2096         /* Set the capacity of the vector to accomodate all assinged addresses. */\r
2097         cl_status = cl_vector_set_capacity(\r
2098                 &p_adapter->ip_vector, p_net_addrs->AddressCount );\r
2099         if( cl_status != CL_SUCCESS )\r
2100         {\r
2101                 cl_obj_unlock( &p_adapter->obj );\r
2102                 IPOIB_PRINT(TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2103                         ("Port %d - OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
2104                         "Failed to set IP vector capacity: %s\n", port_num,\r
2105                         CL_STATUS_MSG(cl_status)) );\r
2106                 IPOIB_EXIT( IPOIB_DBG_OID );\r
2107                 return NDIS_STATUS_RESOURCES;\r
2108         }\r
2109 \r
2110         *p_bytes_read = total_size;\r
2111 \r
2112         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
2113                 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - List contains %d addresses\n",\r
2114                         port_num, p_net_addrs->AddressCount));\r
2115 \r
2116         /* First look for addresses we had that should be removed */\r
2117         for( idx = 0; idx != cl_vector_get_size( &p_adapter->ip_vector ); idx++ )\r
2118         {\r
2119                 p_addr_item = (net_address_item_t*)\r
2120                         cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
2121                 p_net_addr_oid = (PNETWORK_ADDRESS)p_net_addrs->Address;\r
2122 \r
2123                 for( i = 0; i < p_net_addrs->AddressCount; ++i, p_net_addr_oid =\r
2124                         (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid +\r
2125                         FIELD_OFFSET(NETWORK_ADDRESS, Address) +\r
2126                         p_net_addr_oid->AddressLength) )\r
2127                 {\r
2128 \r
2129                         if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP )\r
2130                         {\r
2131                                 IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
2132                                         ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, "\r
2133                                                 "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType,\r
2134                                                 NDIS_PROTOCOL_ID_TCP_IP));\r
2135                                 continue;\r
2136                         }\r
2137 \r
2138                         if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP)\r
2139                         {\r
2140                                 IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
2141                                         ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, "\r
2142                                                 "should be %d\n", port_num, i, p_net_addr_oid->AddressLength,\r
2143                                                 NETWORK_ADDRESS_LENGTH_IP));\r
2144                                 continue;\r
2145                         }\r
2146 \r
2147                         p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address;\r
2148                         if( !cl_memcmp( &p_ip_addr->in_addr,\r
2149                                 &p_addr_item->address.as_ulong, sizeof(ULONG) ) )\r
2150                         {\r
2151                                 break;\r
2152                         }\r
2153                 }\r
2154 \r
2155                 if( i == p_net_addrs->AddressCount )\r
2156                 {\r
2157                         /* Didn't find a match, delete from SA */\r
2158                         IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
2159                                 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Deleting Address %d.%d.%d.%d\n",\r
2160                                         port_num,\r
2161                                         p_addr_item->address.as_bytes[0],\r
2162                                         p_addr_item->address.as_bytes[1],\r
2163                                         p_addr_item->address.as_bytes[2],\r
2164                                         p_addr_item->address.as_bytes[3]));\r
2165 \r
2166                         if( p_addr_item->p_reg )\r
2167                         {\r
2168                                 if( p_addr_item->p_reg->h_reg_svc )\r
2169                                 {\r
2170                                         p_adapter->p_ifc->dereg_svc(\r
2171                                                 p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
2172                                 }\r
2173                                 else\r
2174                                 {\r
2175                                         cl_free( p_addr_item->p_reg );\r
2176                                 }\r
2177                                 p_addr_item->p_reg = NULL;\r
2178                         }\r
2179                         p_addr_item->address.as_ulong = 0;\r
2180                 }\r
2181         }\r
2182 \r
2183         /* Now look for new addresses */\r
2184         p_net_addr_oid = (NETWORK_ADDRESS *)p_net_addrs->Address;\r
2185         idx = 0;\r
2186         for( i = 0; i < p_net_addrs->AddressCount; i++, p_net_addr_oid =\r
2187                 (PNETWORK_ADDRESS)((uint8_t *)p_net_addr_oid +\r
2188                 FIELD_OFFSET(NETWORK_ADDRESS, Address) + p_net_addr_oid->AddressLength) )\r
2189         {\r
2190 \r
2191                 if( p_net_addr_oid->AddressType != NDIS_PROTOCOL_ID_TCP_IP )\r
2192                 {\r
2193                         IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
2194                                 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong type of 0x%.4X, "\r
2195                                         "should be 0x%.4X\n", port_num, i, p_net_addr_oid->AddressType,\r
2196                                         NDIS_PROTOCOL_ID_TCP_IP));\r
2197                         continue;\r
2198                 }\r
2199 \r
2200                 if( p_net_addr_oid->AddressLength != NETWORK_ADDRESS_LENGTH_IP)\r
2201                 {\r
2202                         IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_OID,\r
2203                                 ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Address %d is wrong size of %d, "\r
2204                                         "should be %d\n", port_num, i, p_net_addr_oid->AddressLength,\r
2205                                         NETWORK_ADDRESS_LENGTH_IP));\r
2206                         continue;\r
2207                 }\r
2208 \r
2209                 p_ip_addr = (PNETWORK_ADDRESS_IP)p_net_addr_oid->Address;\r
2210 \r
2211                 /* Size the vector as needed. */\r
2212                 if( cl_vector_get_size( &p_adapter->ip_vector ) <= idx )\r
2213                         cl_vector_set_size( &p_adapter->ip_vector, idx + 1 );\r
2214 \r
2215                 p_addr_item = cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
2216                 if( !cl_memcmp( &p_ip_addr->in_addr, &p_addr_item->address.as_ulong,\r
2217                         sizeof(ULONG) ) )\r
2218                 {\r
2219                         idx++;\r
2220                         /* Already have this address - no change needed */\r
2221                         continue;\r
2222                 }\r
2223 \r
2224                 /*\r
2225                  * Copy the address information, but don't register yet - the port\r
2226                  * could be down.\r
2227                  */\r
2228                 if( p_addr_item->p_reg )\r
2229                 {\r
2230                         /* If in use by some other address, deregister. */\r
2231                         if( p_addr_item->p_reg->h_reg_svc )\r
2232                         {\r
2233                                 p_adapter->p_ifc->dereg_svc(\r
2234                                         p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
2235                         }\r
2236                         else\r
2237                         {\r
2238                                 cl_free( p_addr_item->p_reg );\r
2239                         }\r
2240                         p_addr_item->p_reg = NULL;\r
2241                 }\r
2242                 memcpy ((void *)&p_addr_item->address.as_ulong, (const void *)&p_ip_addr->in_addr, sizeof(ULONG) );\r
2243                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
2244                         ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Adding Address %d.%d.%d.%d\n",\r
2245                         port_num,\r
2246                         p_addr_item->address.as_bytes[0],\r
2247                         p_addr_item->address.as_bytes[1],\r
2248                         p_addr_item->address.as_bytes[2],\r
2249                         p_addr_item->address.as_bytes[3]) );\r
2250                 idx++;\r
2251         }\r
2252 \r
2253         /* Now clear any extra entries that shouldn't be there. */\r
2254         while( idx < cl_vector_get_size( &p_adapter->ip_vector ) )\r
2255         {\r
2256                 p_addr_item = (net_address_item_t*)\r
2257                         cl_vector_get_ptr( &p_adapter->ip_vector,\r
2258                         cl_vector_get_size( &p_adapter->ip_vector ) - 1 );\r
2259 \r
2260                 if( p_addr_item->p_reg )\r
2261                 {\r
2262                         if( p_addr_item->p_reg->h_reg_svc )\r
2263                         {\r
2264                                 p_adapter->p_ifc->dereg_svc(\r
2265                                         p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
2266                         }\r
2267                         else\r
2268                         {\r
2269                                 cl_free( p_addr_item->p_reg );\r
2270                         }\r
2271                         p_addr_item->p_reg = NULL;\r
2272                         p_addr_item->address.as_ulong = 0;\r
2273                 }\r
2274 \r
2275                 /* No need to check return value - shrinking always succeeds. */\r
2276                 cl_vector_set_size( &p_adapter->ip_vector,\r
2277                         cl_vector_get_size( &p_adapter->ip_vector ) - 1 );\r
2278         }\r
2279 \r
2280         if( p_adapter->state == IB_PNP_PORT_ACTIVE && p_adapter->packet_filter )\r
2281                 ipoib_reg_addrs( p_adapter );\r
2282 \r
2283         cl_obj_unlock( &p_adapter->obj );\r
2284 \r
2285         IPOIB_EXIT( IPOIB_DBG_OID );\r
2286         return NDIS_STATUS_SUCCESS;\r
2287 }\r
2288 \r
2289 \r
2290 /* Object lock is held when this function is called. */\r
2291 void\r
2292 ipoib_reg_addrs(\r
2293         IN                              ipoib_adapter_t* const          p_adapter )\r
2294 {\r
2295         net_address_item_t              *p_addr_item;\r
2296 \r
2297         size_t                                  idx;\r
2298 \r
2299         uint8_t                                 port_num;\r
2300 \r
2301         ib_api_status_t                 ib_status;\r
2302         ib_reg_svc_req_t                ib_service;\r
2303         ib_gid_t                                port_gid;\r
2304 \r
2305         IPOIB_ENTER( IPOIB_DBG_OID );\r
2306 \r
2307         port_num = p_adapter->guids.port_num;\r
2308 \r
2309         /* Setup our service call with things common to all calls */\r
2310         cl_memset( &ib_service, 0, sizeof(ib_service) );\r
2311 \r
2312         /* BUGBUG Only register local subnet GID prefix for now */\r
2313         ib_gid_set_default( &port_gid, p_adapter->guids.port_guid );\r
2314         ib_service.svc_rec.service_gid          = port_gid;\r
2315 \r
2316         ib_service.svc_rec.service_pkey         = IB_DEFAULT_PKEY;\r
2317         ib_service.svc_rec.service_lease        = IB_INFINITE_SERVICE_LEASE;\r
2318 \r
2319         /* Must cast here because the service name is an array of unsigned chars but\r
2320          * strcpy want a pointer to a signed char */\r
2321         strcpy( (char *)ib_service.svc_rec.service_name, ATS_NAME );\r
2322 \r
2323         /* IP Address in question will be put in below */\r
2324         ib_service.port_guid            = p_adapter->guids.port_guid;\r
2325         ib_service.timeout_ms           = p_adapter->params.sa_timeout;\r
2326         ib_service.retry_cnt            = p_adapter->params.sa_retry_cnt;\r
2327 \r
2328         /* Can't set IB_FLAGS_SYNC here because I can't wait at dispatch */\r
2329         ib_service.flags                        = 0;\r
2330 \r
2331         /* Service context will be put in below */\r
2332 \r
2333         ib_service.svc_data_mask        = IB_SR_COMPMASK_SID            |\r
2334                                                                   IB_SR_COMPMASK_SGID           |\r
2335                                                                   IB_SR_COMPMASK_SPKEY          |\r
2336                                                                   IB_SR_COMPMASK_SLEASE         |\r
2337                                                                   IB_SR_COMPMASK_SNAME          |\r
2338                                                                   IB_SR_COMPMASK_SDATA8_12      |\r
2339                                                                   IB_SR_COMPMASK_SDATA8_13      |\r
2340                                                                   IB_SR_COMPMASK_SDATA8_14      |\r
2341                                                                   IB_SR_COMPMASK_SDATA8_15;\r
2342         ib_service.pfn_reg_svc_cb = __ipoib_ats_reg_cb;\r
2343 \r
2344         for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ )\r
2345         {\r
2346                 p_addr_item = (net_address_item_t*)\r
2347                         cl_vector_get_ptr(  &p_adapter->ip_vector, idx );\r
2348 \r
2349                 if( p_addr_item->p_reg )\r
2350                         continue;\r
2351 \r
2352                 p_addr_item->p_reg = cl_zalloc( sizeof(ats_reg_t) );\r
2353                 if( !p_addr_item->p_reg )\r
2354                         break;\r
2355 \r
2356                 p_addr_item->p_reg->p_adapter = p_adapter;\r
2357 \r
2358                 ib_service.svc_context          = p_addr_item->p_reg;\r
2359 \r
2360                 ib_service.svc_rec.service_id =\r
2361                         ATS_SERVICE_ID & CL_HTON64(0xFFFFFFFFFFFFFF00);\r
2362                 /* ATS service IDs start at 0x10000CE100415453 */\r
2363                 ib_service.svc_rec.service_id |= ((uint64_t)(idx + 0x53)) << 56;\r
2364 \r
2365                 cl_memcpy( &ib_service.svc_rec.service_data8[ATS_IPV4_OFFSET],\r
2366                         p_addr_item->address.as_bytes, IPV4_ADDR_SIZE );\r
2367 \r
2368                 /* Take a reference for each service request. */\r
2369                 cl_obj_ref(&p_adapter->obj);\r
2370                 ib_status = p_adapter->p_ifc->reg_svc(\r
2371                         p_adapter->h_al, &ib_service, &p_addr_item->p_reg->h_reg_svc );\r
2372                 if( ib_status != IB_SUCCESS )\r
2373                 {\r
2374                         if( ib_status == IB_INVALID_GUID )\r
2375                         {\r
2376                                 /* If this occurs, we log the error but do not fail the OID yet */\r
2377                                 IPOIB_PRINT( TRACE_LEVEL_WARNING, IPOIB_DBG_OID,\r
2378                                         ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - "\r
2379                                         "Failed to register IP Address "\r
2380                                         "of %d.%d.%d.%d with error IB_INVALID_GUID\n",\r
2381                                         port_num,\r
2382                                         p_addr_item->address.as_bytes[0],\r
2383                                         p_addr_item->address.as_bytes[1],\r
2384                                         p_addr_item->address.as_bytes[2],\r
2385                                         p_addr_item->address.as_bytes[3]) );\r
2386                         }\r
2387                         else\r
2388                         {\r
2389                                 /* Fatal error. */\r
2390                                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
2391                                         ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address "\r
2392                                         "of %d.%d.%d.%d with error %s\n",\r
2393                                         port_num,\r
2394                                         p_addr_item->address.as_bytes[0],\r
2395                                         p_addr_item->address.as_bytes[1],\r
2396                                         p_addr_item->address.as_bytes[2],\r
2397                                         p_addr_item->address.as_bytes[3],\r
2398                                         p_adapter->p_ifc->get_err_str( ib_status )) );\r
2399                                 p_adapter->hung = TRUE;\r
2400                         }\r
2401                         cl_obj_deref(&p_adapter->obj);\r
2402                         cl_free( p_addr_item->p_reg );\r
2403                         p_addr_item->p_reg = NULL;\r
2404                 }\r
2405         }\r
2406 \r
2407         IPOIB_EXIT( IPOIB_DBG_OID );\r
2408 }\r
2409 \r
2410 \r
2411 /* Object lock is held when this function is called. */\r
2412 void\r
2413 ipoib_dereg_addrs(\r
2414         IN                              ipoib_adapter_t* const          p_adapter )\r
2415 {\r
2416         net_address_item_t              *p_addr_item;\r
2417 \r
2418         size_t                                  idx;\r
2419 \r
2420         IPOIB_ENTER( IPOIB_DBG_OID );\r
2421 \r
2422         for( idx = 0; idx < cl_vector_get_size( &p_adapter->ip_vector); idx++ )\r
2423         {\r
2424                 p_addr_item = (net_address_item_t*)\r
2425                         cl_vector_get_ptr( &p_adapter->ip_vector, idx );\r
2426 \r
2427                 if( !p_addr_item->p_reg )\r
2428                         continue;\r
2429 \r
2430                 if( p_addr_item->p_reg->h_reg_svc )\r
2431                 {\r
2432                         p_adapter->p_ifc->dereg_svc(\r
2433                                 p_addr_item->p_reg->h_reg_svc, __ipoib_ats_dereg_cb );\r
2434                 }\r
2435                 else\r
2436                 {\r
2437                         cl_free( p_addr_item->p_reg );\r
2438                 }\r
2439                 p_addr_item->p_reg = NULL;\r
2440         }\r
2441 \r
2442         IPOIB_EXIT( IPOIB_DBG_OID );\r
2443 }\r
2444 \r
2445 \r
2446 static void\r
2447 __ipoib_ats_reg_cb(\r
2448         IN                              ib_reg_svc_rec_t                        *p_reg_svc_rec )\r
2449 {\r
2450         ats_reg_t                               *p_reg;\r
2451         uint8_t                                 port_num;\r
2452 \r
2453         IPOIB_ENTER( IPOIB_DBG_OID );\r
2454 \r
2455         CL_ASSERT( p_reg_svc_rec );\r
2456         CL_ASSERT( p_reg_svc_rec->svc_context );\r
2457 \r
2458         p_reg = (ats_reg_t* __ptr64)p_reg_svc_rec->svc_context;\r
2459         port_num = p_reg->p_adapter->guids.port_num;\r
2460 \r
2461         cl_obj_lock( &p_reg->p_adapter->obj );\r
2462 \r
2463         if( p_reg_svc_rec->req_status == IB_SUCCESS &&\r
2464                 !p_reg_svc_rec->resp_status )\r
2465         {\r
2466                 IPOIB_PRINT( TRACE_LEVEL_INFORMATION,IPOIB_DBG_OID,\r
2467                                          ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Registered IP Address "\r
2468                                           "of %d.%d.%d.%d\n",\r
2469                                           port_num,\r
2470                                           p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET],\r
2471                                           p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1],\r
2472                                           p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2],\r
2473                                           p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3]) );\r
2474         }\r
2475         else if( p_reg_svc_rec->req_status != IB_CANCELED )\r
2476         {\r
2477                 IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_OID,\r
2478                                          ("Port %d OID_GEN_NETWORK_LAYER_ADDRESSES - Failed to register IP Address "\r
2479                                           "of %d.%d.%d.%d with error %s\n",\r
2480                                           port_num,\r
2481                                           p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET],\r
2482                                           p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+1],\r
2483                                           p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+2],\r
2484                                           p_reg_svc_rec->svc_rec.service_data8[ATS_IPV4_OFFSET+3],\r
2485                                           p_reg->p_adapter->p_ifc->get_err_str( p_reg_svc_rec->resp_status )) );\r
2486                 p_reg->p_adapter->hung = TRUE;\r
2487                 p_reg->h_reg_svc = NULL;\r
2488         }\r
2489 \r
2490         cl_obj_unlock( &p_reg->p_adapter->obj );\r
2491         cl_obj_deref(&p_reg->p_adapter->obj);\r
2492 \r
2493         IPOIB_EXIT( IPOIB_DBG_OID );\r
2494 }\r
2495 \r
2496 \r
2497 static void\r
2498 __ipoib_ats_dereg_cb(\r
2499         IN                              void                                            *context )\r
2500 {\r
2501         cl_free( context );\r
2502 }\r