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