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