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