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