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