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