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