a7703665d617d7f8161456defd33ccbdfbe3a220
[mirror/winof/.git] / ulp / ipoib_NDIS6_CM / kernel / ipoib_ibat.c
1 /*\r
2  * Copyright (c) 2005 Mellanox Technologies.  All rights reserved.\r
3  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
4  * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
5  *\r
6  * This software is available to you under the OpenIB.org BSD license\r
7  * below:\r
8  *\r
9  *     Redistribution and use in source and binary forms, with or\r
10  *     without modification, are permitted provided that the following\r
11  *     conditions are met:\r
12  *\r
13  *      - Redistributions of source code must retain the above\r
14  *        copyright notice, this list of conditions and the following\r
15  *        disclaimer.\r
16  *\r
17  *      - Redistributions in binary form must reproduce the above\r
18  *        copyright notice, this list of conditions and the following\r
19  *        disclaimer in the documentation and/or other materials\r
20  *        provided with the distribution.\r
21  *\r
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
29  * SOFTWARE.\r
30  *\r
31  * $Id: ipoib_ibat.c 4494 2009-06-22 14:31:08Z xalex $\r
32  */\r
33 \r
34 \r
35 #include "ipoib_driver.h"\r
36 #include "ipoib_adapter.h"\r
37 #include "ipoib_port.h"\r
38 #include "ipoib_debug.h"\r
39 #if defined(EVENT_TRACING)\r
40 #ifdef offsetof\r
41 #undef offsetof\r
42 #endif\r
43 #include "ipoib_ibat.tmh"\r
44 #endif\r
45 #include <iba/ib_at_ioctl.h>\r
46 \r
47 extern PDRIVER_OBJECT                           g_p_drv_obj;\r
48 \r
49 static NTSTATUS\r
50 __ipoib_create(\r
51         IN                              DEVICE_OBJECT* const            pDevObj,\r
52         IN                              IRP* const                                      pIrp );\r
53 \r
54 static NTSTATUS\r
55 __ipoib_cleanup(\r
56         IN                              DEVICE_OBJECT* const            pDevObj,\r
57         IN                              IRP* const                                      pIrp );\r
58 \r
59 static NTSTATUS\r
60 __ipoib_close(\r
61         IN                              DEVICE_OBJECT* const            pDevObj,\r
62         IN                              IRP* const                                      pIrp );\r
63 \r
64 static NTSTATUS\r
65 __ipoib_dispatch(\r
66         IN                              DEVICE_OBJECT* const            pDevObj,\r
67         IN                              IRP* const                                      pIrp );\r
68 \r
69 \r
70 static NTSTATUS\r
71 __ibat_get_ports(\r
72         IN                              IRP                                                     *pIrp,\r
73         IN                              IO_STACK_LOCATION                       *pIoStack )\r
74 {\r
75         IOCTL_IBAT_PORTS_IN             *pIn;\r
76         IOCTL_IBAT_PORTS_OUT    *pOut;\r
77         KLOCK_QUEUE_HANDLE              hdl;\r
78         cl_list_item_t                  *pItem;\r
79         ipoib_adapter_t                 *pAdapter;\r
80         LONG                                    nPorts;\r
81 \r
82         IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
83 \r
84         if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
85                 sizeof(IOCTL_IBAT_PORTS_IN) )\r
86         {\r
87                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
88                         ("Invalid input buffer size.\n") );\r
89                 return STATUS_INVALID_PARAMETER;\r
90         }\r
91         \r
92         if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength <\r
93                 sizeof(IOCTL_IBAT_PORTS_OUT) )\r
94         {\r
95                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
96                         ("Invalid output buffer size.\n") );\r
97                 return STATUS_INVALID_PARAMETER;\r
98         }\r
99 \r
100         pIn = pIrp->AssociatedIrp.SystemBuffer;\r
101         pOut = pIrp->AssociatedIrp.SystemBuffer;\r
102 \r
103         if( pIn->Version != IBAT_IOCTL_VERSION )\r
104         {\r
105                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
106                         ("Invalid version.\n") );\r
107                 return STATUS_INVALID_PARAMETER;\r
108         }\r
109 \r
110         KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
111         nPorts = (LONG)cl_qlist_count( &g_ipoib.adapter_list );\r
112         switch( nPorts )\r
113         {\r
114         case 0:\r
115                 cl_memclr( pOut->Ports, sizeof(pOut->Ports) );\r
116                 /* Fall through */\r
117         case 1:\r
118                 pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT);\r
119                 break;\r
120 \r
121         default:\r
122                 pOut->Size = sizeof(IOCTL_IBAT_PORTS_OUT) + \r
123                         (sizeof(IBAT_PORT_RECORD) * (nPorts - 1));\r
124                 break;\r
125         }\r
126 \r
127         pIrp->IoStatus.Information = pOut->Size;\r
128 \r
129         if( pOut->Size > pIoStack->Parameters.DeviceIoControl.OutputBufferLength )\r
130         {\r
131                 nPorts = 1 +\r
132                         (pIoStack->Parameters.DeviceIoControl.OutputBufferLength -\r
133                         sizeof(IOCTL_IBAT_PORTS_OUT)) / sizeof(IBAT_PORT_RECORD);\r
134 \r
135                 pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_PORTS_OUT) +\r
136                         ((nPorts - 1) * sizeof(IBAT_PORT_RECORD));\r
137         }\r
138 \r
139         pOut->NumPorts = 0;\r
140         pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
141         while( pOut->NumPorts != nPorts )\r
142         {\r
143                 pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
144                 pOut->Ports[pOut->NumPorts].CaGuid = pAdapter->guids.ca_guid;\r
145                 pOut->Ports[pOut->NumPorts].PortGuid = pAdapter->guids.port_guid.guid;\r
146                 pOut->Ports[pOut->NumPorts].PKey = IB_DEFAULT_PKEY;\r
147                 pOut->Ports[pOut->NumPorts].PortNum = pAdapter->guids.port_num;\r
148                 pOut->NumPorts++;\r
149 \r
150                 pItem = cl_qlist_next( pItem );\r
151         }\r
152 \r
153         KeReleaseInStackQueuedSpinLock( &hdl );\r
154         IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
155         return STATUS_SUCCESS;\r
156 }\r
157 \r
158 \r
159 static NTSTATUS\r
160 __ibat_get_ips(\r
161         IN                              IRP                                                     *pIrp,\r
162         IN                              IO_STACK_LOCATION                       *pIoStack )\r
163 {\r
164         IOCTL_IBAT_IP_ADDRESSES_IN      *pIn;\r
165         IOCTL_IBAT_IP_ADDRESSES_OUT     *pOut;\r
166         KLOCK_QUEUE_HANDLE                      hdl;\r
167         cl_list_item_t                          *pItem;\r
168         ipoib_adapter_t                         *pAdapter;\r
169         LONG                                            nIps, maxIps;\r
170         size_t                                          idx;\r
171         net_address_item_t                      *pAddr;\r
172         UINT64                                          PortGuid;\r
173 \r
174         IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
175 \r
176         if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
177                 sizeof(IOCTL_IBAT_IP_ADDRESSES_IN) )\r
178         {\r
179                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
180                         ("Invalid input buffer size.\n") );\r
181                 return STATUS_INVALID_PARAMETER;\r
182         }\r
183         \r
184         if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength <\r
185                 sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT) )\r
186         {\r
187                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
188                         ("Invalid output buffer size.\n") );\r
189                 return STATUS_INVALID_PARAMETER;\r
190         }\r
191 \r
192         pIn = pIrp->AssociatedIrp.SystemBuffer;\r
193         pOut = pIrp->AssociatedIrp.SystemBuffer;\r
194 \r
195         if( pIn->Version != IBAT_IOCTL_VERSION )\r
196         {\r
197                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
198                         ("Invalid version.\n") );\r
199                 return STATUS_INVALID_PARAMETER;\r
200         }\r
201 \r
202         PortGuid = pIn->PortGuid;\r
203 \r
204         nIps = 0;\r
205         pOut->AddressCount = 0;\r
206         maxIps = 1 +\r
207                 ((pIoStack->Parameters.DeviceIoControl.OutputBufferLength -\r
208                 sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT)) / sizeof(IP_ADDRESS));\r
209 \r
210         KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
211         for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
212                 pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
213                 pItem = cl_qlist_next( pItem ) )\r
214         {\r
215                 pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
216                 if( PortGuid && pAdapter->guids.port_guid.guid != PortGuid )\r
217                         continue;\r
218 \r
219                 cl_obj_lock( &pAdapter->obj );\r
220                 nIps += (LONG)cl_vector_get_size( &pAdapter->ip_vector );\r
221 \r
222                 for( idx = 0;\r
223                         idx < cl_vector_get_size( &pAdapter->ip_vector );\r
224                         idx++ )\r
225                 {\r
226                         if( pOut->AddressCount == maxIps )\r
227                                 break;\r
228 \r
229                         pAddr = (net_address_item_t*)\r
230                                 cl_vector_get_ptr( &pAdapter->ip_vector, idx );\r
231 \r
232                         pOut->Address[pOut->AddressCount].IpVersion = 4;\r
233                         cl_memclr( &pOut->Address[pOut->AddressCount].Address,\r
234                                 sizeof(IP_ADDRESS) );\r
235                         cl_memcpy( &pOut->Address[pOut->AddressCount].Address[12],\r
236                                 pAddr->address.as_bytes, IPV4_ADDR_SIZE );\r
237 \r
238                         pOut->AddressCount++;\r
239                 }\r
240                 cl_obj_unlock( &pAdapter->obj );\r
241         }\r
242 \r
243         pOut->Size = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);\r
244         if( --nIps )\r
245                 pOut->Size += sizeof(IP_ADDRESS) * nIps;\r
246 \r
247         pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);\r
248         if( --maxIps < nIps )\r
249                 pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * maxIps);\r
250         else\r
251                 pIrp->IoStatus.Information += (sizeof(IP_ADDRESS) * nIps);\r
252 \r
253         KeReleaseInStackQueuedSpinLock( &hdl );\r
254         IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
255         return STATUS_SUCCESS;\r
256 }\r
257 \r
258 \r
259 static NTSTATUS\r
260 __ibat_mac_to_gid(\r
261         IN                              IRP                                                     *pIrp,\r
262         IN                              IO_STACK_LOCATION                       *pIoStack )\r
263 {\r
264         NTSTATUS                                        status = STATUS_INVALID_PARAMETER;\r
265         IOCTL_IBAT_MAC_TO_GID_IN        *pIn;\r
266         IOCTL_IBAT_MAC_TO_GID_OUT       *pOut;\r
267         KLOCK_QUEUE_HANDLE                      hdl;\r
268         cl_list_item_t                          *pItem;\r
269         ipoib_adapter_t                         *pAdapter;\r
270 \r
271         IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
272 \r
273         if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
274                 sizeof(IOCTL_IBAT_MAC_TO_GID_IN) )\r
275         {\r
276                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
277                         ("Invalid input buffer size.\n") );\r
278                 return STATUS_INVALID_PARAMETER;\r
279         }\r
280         \r
281         if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
282                 sizeof(IOCTL_IBAT_MAC_TO_GID_OUT) )\r
283         {\r
284                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
285                         ("Invalid output buffer size.\n") );\r
286                 return STATUS_INVALID_PARAMETER;\r
287         }\r
288 \r
289         pIn = pIrp->AssociatedIrp.SystemBuffer;\r
290         pOut = pIrp->AssociatedIrp.SystemBuffer;\r
291 \r
292         if( pIn->Version != IBAT_IOCTL_VERSION )\r
293         {\r
294                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
295                         ("Invalid version.\n") );\r
296                 return STATUS_INVALID_PARAMETER;\r
297         }\r
298 \r
299         KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
300 \r
301         for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
302                 pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
303                 pItem = cl_qlist_next( pItem ) )\r
304         {\r
305                 pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
306                 if( pIn->PortGuid != pAdapter->guids.port_guid.guid )\r
307                         continue;\r
308 \r
309                 /* Found the port - lookup the MAC. */\r
310                 cl_obj_lock( &pAdapter->obj );\r
311                 if( pAdapter->p_port )\r
312                 {\r
313                         status = ipoib_mac_to_gid(\r
314                                 pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->DestGid );\r
315                         if( NT_SUCCESS( status ) )\r
316                         {\r
317                                 pIrp->IoStatus.Information =\r
318                                         sizeof(IOCTL_IBAT_MAC_TO_GID_OUT);\r
319                         }\r
320                 }\r
321                 cl_obj_unlock( &pAdapter->obj );\r
322                 break;\r
323         }\r
324 \r
325         KeReleaseInStackQueuedSpinLock( &hdl );\r
326 \r
327         IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
328         return status;\r
329 }\r
330 \r
331 \r
332 static NTSTATUS\r
333 __ibat_mac_to_path(\r
334         IN                              IRP                                                     *pIrp,\r
335         IN                              IO_STACK_LOCATION                       *pIoStack )\r
336 {\r
337         NTSTATUS                                        status = STATUS_INVALID_PARAMETER;\r
338         IOCTL_IBAT_MAC_TO_PATH_IN       *pIn;\r
339         IOCTL_IBAT_MAC_TO_PATH_OUT      *pOut;\r
340         KLOCK_QUEUE_HANDLE                      hdl;\r
341         cl_list_item_t                          *pItem;\r
342         ipoib_adapter_t                         *pAdapter;\r
343 \r
344         IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
345 \r
346         if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
347                 sizeof(IOCTL_IBAT_MAC_TO_PATH_IN) )\r
348         {\r
349                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
350                         ("Invalid input buffer size.\n") );\r
351                 return STATUS_INVALID_PARAMETER;\r
352         }\r
353         \r
354         if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
355                 sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT) )\r
356         {\r
357                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
358                         ("Invalid output buffer size.\n") );\r
359                 return STATUS_INVALID_PARAMETER;\r
360         }\r
361 \r
362         pIn = pIrp->AssociatedIrp.SystemBuffer;\r
363         pOut = pIrp->AssociatedIrp.SystemBuffer;\r
364 \r
365         if( pIn->Version != IBAT_IOCTL_VERSION )\r
366         {\r
367                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
368                         ("Invalid version.\n") );\r
369                 return STATUS_INVALID_PARAMETER;\r
370         }\r
371 \r
372         KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
373 \r
374         for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
375                 pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
376                 pItem = cl_qlist_next( pItem ) )\r
377         {\r
378                 pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
379                 if( pIn->PortGuid != pAdapter->guids.port_guid.guid )\r
380                         continue;\r
381 \r
382                 /* Found the port - lookup the MAC. */\r
383                 cl_obj_lock( &pAdapter->obj );\r
384                 if( pAdapter->p_port )\r
385                 {\r
386                         status = ipoib_mac_to_path(\r
387                                 pAdapter->p_port, *(mac_addr_t*)pIn->DestMac, &pOut->Path );\r
388 \r
389                         if( NT_SUCCESS( status ) )\r
390                         {\r
391                                 pIrp->IoStatus.Information =\r
392                                         sizeof(IOCTL_IBAT_MAC_TO_PATH_OUT);\r
393                         }\r
394                 }\r
395                 cl_obj_unlock( &pAdapter->obj );\r
396                 break;\r
397         }\r
398 \r
399         KeReleaseInStackQueuedSpinLock( &hdl );\r
400 \r
401         IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
402         return status;\r
403 }\r
404 \r
405 \r
406 static NTSTATUS\r
407 __ibat_ip_to_port(\r
408         IN                              IRP                                                     *pIrp,\r
409         IN                              IO_STACK_LOCATION                       *pIoStack )\r
410 {\r
411         IOCTL_IBAT_IP_TO_PORT_IN        *pIn;\r
412         IOCTL_IBAT_IP_TO_PORT_OUT       *pOut;\r
413         KLOCK_QUEUE_HANDLE                      hdl;\r
414         cl_list_item_t                                  *pItem;\r
415         ipoib_adapter_t                         *pAdapter;\r
416         size_t                                          idx;\r
417         net_address_item_t                      *pAddr;\r
418         NTSTATUS status = STATUS_NOT_FOUND;\r
419 \r
420         IPOIB_ENTER(IPOIB_DBG_IOCTL);\r
421 \r
422         if( pIoStack->Parameters.DeviceIoControl.InputBufferLength !=\r
423                 sizeof(IOCTL_IBAT_IP_TO_PORT_IN) )\r
424         {\r
425                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
426                         ("Invalid input buffer size.\n") );\r
427                 return STATUS_INVALID_PARAMETER;\r
428         }\r
429         \r
430         if( pIoStack->Parameters.DeviceIoControl.OutputBufferLength !=\r
431                 sizeof(IOCTL_IBAT_IP_TO_PORT_OUT) )\r
432         {\r
433                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
434                         ("Invalid output buffer size.\n") );\r
435                 return STATUS_INVALID_PARAMETER;\r
436         }\r
437 \r
438         pIn = pIrp->AssociatedIrp.SystemBuffer;\r
439         pOut = pIrp->AssociatedIrp.SystemBuffer;\r
440 \r
441         if( pIn->Version != IBAT_IOCTL_VERSION )\r
442         {\r
443                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
444                         ("Invalid version.\n") );\r
445                 return STATUS_INVALID_PARAMETER;\r
446         }\r
447 \r
448         if (pIn->Address.IpVersion != 4)\r
449         {\r
450                 IPOIB_PRINT_EXIT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR,\r
451                         ("Invalid IP version (%d). Supported only 4\n", pIn->Address.IpVersion) );\r
452                 return STATUS_INVALID_PARAMETER;\r
453         }\r
454 \r
455         KeAcquireInStackQueuedSpinLock( &g_ipoib.lock, &hdl );\r
456         for( pItem = cl_qlist_head( &g_ipoib.adapter_list );\r
457                 pItem != cl_qlist_end( &g_ipoib.adapter_list );\r
458                 pItem = cl_qlist_next( pItem ) )\r
459         {\r
460                 pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
461 \r
462                 cl_obj_lock( &pAdapter->obj );\r
463 \r
464                 for( idx = 0;\r
465                         idx < cl_vector_get_size( &pAdapter->ip_vector );\r
466                         idx++ )\r
467                 {\r
468                         pAddr = (net_address_item_t*)\r
469                                 cl_vector_get_ptr( &pAdapter->ip_vector, idx );\r
470 \r
471                         if (!memcmp( &pIn->Address.Address[12], pAddr->address.as_bytes, IPV4_ADDR_SIZE))\r
472                         {\r
473                                 pOut->Port.CaGuid = pAdapter->guids.ca_guid;\r
474                                 pOut->Port.PortGuid = pAdapter->guids.port_guid.guid;\r
475                                 pOut->Port.PKey = IB_DEFAULT_PKEY;\r
476                                 pOut->Port.PortNum = pAdapter->guids.port_num;\r
477                                 pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_TO_PORT_OUT);\r
478                                 status = STATUS_SUCCESS;\r
479                                 break;\r
480                         }\r
481                 }\r
482                 cl_obj_unlock( &pAdapter->obj );\r
483                 if (status == STATUS_SUCCESS)\r
484                         break;\r
485         }\r
486 \r
487         KeReleaseInStackQueuedSpinLock( &hdl );\r
488         IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
489         return status;\r
490 }\r
491 \r
492 void\r
493 ipoib_ref_ibat()\r
494 {\r
495         UNICODE_STRING      DeviceName;\r
496     UNICODE_STRING      DeviceLinkUnicodeString;\r
497     NDIS_DEVICE_OBJECT_ATTRIBUTES   DeviceObjectAttributes;\r
498     PDRIVER_DISPATCH    DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];\r
499 \r
500         NDIS_STATUS         Status = NDIS_STATUS_SUCCESS;\r
501 \r
502         IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
503 \r
504         if( InterlockedIncrement( &g_ipoib.ibat_ref ) == 1 )\r
505         {\r
506 \r
507                 NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH));\r
508                                 \r
509                 DispatchTable[IRP_MJ_CREATE]                                    = __ipoib_create;\r
510                 DispatchTable[IRP_MJ_CLEANUP]                                   = __ipoib_cleanup;\r
511                 DispatchTable[IRP_MJ_CLOSE]                                             = __ipoib_close;\r
512                 DispatchTable[IRP_MJ_DEVICE_CONTROL]                    = __ipoib_dispatch;\r
513                 DispatchTable[IRP_MJ_INTERNAL_DEVICE_CONTROL]   = __ipoib_dispatch;             \r
514                 \r
515                                 \r
516                 NdisInitUnicodeString( &DeviceName, IBAT_DEV_NAME );\r
517                 NdisInitUnicodeString( &DeviceLinkUnicodeString, IBAT_DOS_DEV_NAME );\r
518                                 \r
519                 \r
520                 NdisZeroMemory(&DeviceObjectAttributes, sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES));\r
521                 \r
522                 DeviceObjectAttributes.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; // type implicit from the context\r
523                 DeviceObjectAttributes.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;\r
524                 DeviceObjectAttributes.Header.Size = sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES);\r
525                 DeviceObjectAttributes.DeviceName = &DeviceName;\r
526                 DeviceObjectAttributes.SymbolicName = &DeviceLinkUnicodeString;\r
527                 DeviceObjectAttributes.MajorFunctions = &DispatchTable[0];\r
528                 DeviceObjectAttributes.ExtensionSize = 0;\r
529                 DeviceObjectAttributes.DefaultSDDLString = NULL;\r
530                 DeviceObjectAttributes.DeviceClassGuid = 0;\r
531                 \r
532                 Status = NdisRegisterDeviceEx(\r
533                                                         g_IpoibMiniportDriverHandle,\r
534                                                         &DeviceObjectAttributes,\r
535                                                         &g_ipoib.h_ibat_dev,\r
536                                                         &g_ipoib.h_ibat_dev_handle);\r
537 \r
538 \r
539         \r
540                 if( Status != NDIS_STATUS_SUCCESS )\r
541                 {\r
542                         IPOIB_PRINT( TRACE_LEVEL_ERROR, IPOIB_DBG_ERROR, \r
543                                 ("NdisRegisterDeviceEx failed with status of %d\n", Status) );\r
544                 }\r
545         }\r
546 \r
547         IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
548 }\r
549 \r
550 \r
551 void\r
552 ipoib_deref_ibat()\r
553 {\r
554         IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
555 \r
556         if( InterlockedDecrement( &g_ipoib.ibat_ref ) )\r
557         {\r
558                 IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
559                 return;\r
560         }\r
561 \r
562         if( g_ipoib.h_ibat_dev )\r
563         {\r
564                 NdisDeregisterDeviceEx( g_ipoib.h_ibat_dev_handle );\r
565                 g_ipoib.h_ibat_dev = NULL;\r
566                 g_ipoib.h_ibat_dev_handle = NULL; //TODO set here INVALID_HANDLE_VALUE\r
567         }\r
568 \r
569         IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
570 }\r
571 \r
572 \r
573 static NTSTATUS\r
574 __ipoib_create(\r
575         IN                              DEVICE_OBJECT* const            pDevObj,\r
576         IN                              IRP* const                                      pIrp )\r
577 {\r
578         IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
579 \r
580         UNREFERENCED_PARAMETER( pDevObj );\r
581 \r
582         ipoib_ref_ibat();\r
583 \r
584         pIrp->IoStatus.Status = STATUS_SUCCESS;\r
585         pIrp->IoStatus.Information = 0;\r
586         IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
587 \r
588         IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
589         return STATUS_SUCCESS;\r
590 }\r
591 \r
592 \r
593 static NTSTATUS\r
594 __ipoib_cleanup(\r
595         IN                              DEVICE_OBJECT* const            pDevObj,\r
596         IN                              IRP* const                                      pIrp )\r
597 {\r
598         IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
599 \r
600         UNREFERENCED_PARAMETER( pDevObj );\r
601 \r
602         ipoib_deref_ibat();\r
603 \r
604         pIrp->IoStatus.Status = STATUS_SUCCESS;\r
605         pIrp->IoStatus.Information = 0;\r
606         IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
607 \r
608         IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
609         return STATUS_SUCCESS;\r
610 }\r
611 \r
612 \r
613 static NTSTATUS\r
614 __ipoib_close(\r
615         IN                              DEVICE_OBJECT* const            pDevObj,\r
616         IN                              IRP* const                                      pIrp )\r
617 {\r
618         IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
619 \r
620         UNREFERENCED_PARAMETER( pDevObj );\r
621 \r
622         pIrp->IoStatus.Status = STATUS_SUCCESS;\r
623         pIrp->IoStatus.Information = 0;\r
624         IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
625 \r
626         IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
627         return STATUS_SUCCESS;\r
628 }\r
629 \r
630 \r
631 static NTSTATUS\r
632 __ipoib_dispatch(\r
633         IN                              DEVICE_OBJECT* const            pDevObj,\r
634         IN                              IRP* const                                      pIrp )\r
635 {\r
636         IO_STACK_LOCATION       *pIoStack;\r
637         NTSTATUS                        status = STATUS_SUCCESS;\r
638 \r
639         IPOIB_ENTER( IPOIB_DBG_IOCTL );\r
640 \r
641         UNREFERENCED_PARAMETER( pDevObj );\r
642 \r
643         pIoStack = IoGetCurrentIrpStackLocation( pIrp );\r
644 \r
645         pIrp->IoStatus.Information = 0;\r
646 \r
647         switch( pIoStack->Parameters.DeviceIoControl.IoControlCode )\r
648         {\r
649         case IOCTL_IBAT_PORTS:\r
650                 IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
651                         ("IOCTL_IBAT_PORTS received\n") );\r
652                 status = __ibat_get_ports( pIrp, pIoStack );\r
653                 break;\r
654 \r
655         case IOCTL_IBAT_IP_ADDRESSES:\r
656                 IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
657                         ("IOCTL_IBAT_IP_ADDRESSES received\n" ));\r
658                 status = __ibat_get_ips( pIrp, pIoStack );\r
659                 break;\r
660 \r
661         case IOCTL_IBAT_MAC_TO_GID:\r
662                 IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
663                         ("IOCTL_IBAT_MAC_TO_GID received\n" ));\r
664                 status = __ibat_mac_to_gid( pIrp, pIoStack );\r
665                 break;\r
666 \r
667         case IOCTL_IBAT_IP_TO_PORT:\r
668                 IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
669                         ("IOCTL_IBAT_IP_TO_PORT received\n" ));\r
670                 status = __ibat_ip_to_port( pIrp, pIoStack );\r
671                 break;\r
672 \r
673         case IOCTL_IBAT_MAC_TO_PATH:\r
674                 IPOIB_PRINT(TRACE_LEVEL_INFORMATION, IPOIB_DBG_IOCTL,\r
675                         ("IOCTL_IBAT_MAC_TO_PATH received\n" ));\r
676                 status = __ibat_mac_to_path( pIrp, pIoStack );\r
677                 break;\r
678 \r
679         default:\r
680                 IPOIB_PRINT( TRACE_LEVEL_VERBOSE, IPOIB_DBG_IOCTL,\r
681                         ("unknow IOCTL code = 0x%x\n",\r
682                         pIoStack->Parameters.DeviceIoControl.IoControlCode) );\r
683                 status = STATUS_INVALID_PARAMETER;\r
684         }\r
685 \r
686         pIrp->IoStatus.Status = status;\r
687         IoCompleteRequest( pIrp, IO_NO_INCREMENT );\r
688 \r
689         IPOIB_EXIT( IPOIB_DBG_IOCTL );\r
690         return status;\r
691 }\r
692 \r
693 \r