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