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