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