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