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