mlx4: fix line endings to windows format
[mirror/winof/.git] / hw / mlx4 / kernel / hca / drv.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 1996-2003 Intel Corporation. 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: al.c 1611 2006-08-20 14:48:55Z sleybo $\r
31  */\r
32 \r
33 #include "precomp.h"\r
34 #include <initguid.h>\r
35 #include <wdmguid.h>\r
36 \r
37 #if defined(EVENT_TRACING)\r
38 #ifdef offsetof\r
39 #undef offsetof\r
40 #endif\r
41 #include "drv.tmh"\r
42 #endif \r
43 \r
44 #define DRV_VERSION     "1.0"\r
45 #define DRV_RELDATE     "02/01/2008"\r
46 \r
47 GLOBALS g;\r
48 \r
49 /*\r
50  * UVP name does not include file extension.  For debug builds, UAL\r
51  * will append "d.dll".  For release builds, UAL will append ".dll"\r
52  */\r
53 char                    mlnx_uvp_lib_name[MAX_LIB_NAME] = {"mlx4u"};\r
54 \r
55 \r
56 static void\r
57 __put_ifc(\r
58                 IN      PINTERFACE              p_ifc )\r
59 {\r
60         HCA_ENTER( HCA_DBG_PNP );\r
61         p_ifc->InterfaceDereference( p_ifc->Context );\r
62         HCA_EXIT( HCA_DBG_PNP );\r
63 }\r
64 \r
65 static int __get_dev_info(PFDO_DEVICE_DATA p_fdo, __be64 *node_guid, u32 *hw_id)\r
66 {\r
67         struct ib_device_attr device_attr;\r
68         struct ib_device *p_ibdev = p_fdo->bus_ib_ifc.p_ibdev;\r
69         int err;\r
70 \r
71         HCA_ENTER( HCA_DBG_PNP );\r
72         if ( hca_is_livefish(p_fdo) ) {\r
73                 *node_guid = cl_hton64((uint64_t)(ULONG_PTR)p_ibdev);\r
74                 p_ibdev->node_guid = *node_guid;\r
75                 *hw_id = 0;\r
76                 return 0;\r
77         }\r
78 \r
79         err = (p_ibdev->query_device)( p_ibdev, &device_attr );\r
80         if (err)\r
81                 return err;\r
82 \r
83         *node_guid = p_ibdev->node_guid;\r
84         *hw_id = device_attr.hw_ver;\r
85         HCA_EXIT( HCA_DBG_PNP );\r
86         return 0;\r
87 }\r
88 \r
89 #ifndef USE_WDM_FRAMEWORK\r
90 \r
91 //\r
92 // TODO: add support for Hibernate/Standby as in WDM version below\r
93 //\r
94 \r
95 #ifdef ALLOC_PRAGMA\r
96 #pragma alloc_text (INIT, DriverEntry)\r
97 #pragma alloc_text (PAGE, EvtDeviceAdd)\r
98 #pragma alloc_text (PAGE, EvtDriverUnload)\r
99 #pragma alloc_text (PAGE, EvtDeviceD0Entry)\r
100 #pragma alloc_text (PAGE, EvtDeviceD0Exit)\r
101 #pragma alloc_text (PAGE, EvtPrepareHardware)\r
102 #pragma alloc_text (PAGE, EvtReleaseHardware)\r
103 #endif\r
104 \r
105 static NTSTATUS\r
106 __get_ci_interface(\r
107         IN                                      PFDO_DEVICE_DATA                                p_fdo )\r
108 {\r
109         NTSTATUS                        status;\r
110         IRP                                     *p_irp;\r
111         IO_STATUS_BLOCK         ioStatus;\r
112         IO_STACK_LOCATION       *pIoStack;\r
113         KEVENT                          event;\r
114 \r
115         HCA_ENTER( HCA_DBG_PNP );\r
116 \r
117         KeInitializeEvent( &event, NotificationEvent, FALSE );\r
118 \r
119         /* Query for the verbs interface. */\r
120         p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_fdo->p_al_dev,\r
121                 NULL, 0, NULL, &event, &ioStatus );\r
122         if( !p_irp )\r
123         {\r
124                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
125                         ("IoBuildSynchronousFsdRequest failed.\n"));\r
126                 return STATUS_INSUFFICIENT_RESOURCES;\r
127         }\r
128 \r
129         /* Format the IRP. */\r
130         pIoStack = IoGetNextIrpStackLocation( p_irp );\r
131         pIoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
132         pIoStack->Parameters.QueryInterface.Version = IB_CI_INTERFACE_VERSION;\r
133         pIoStack->Parameters.QueryInterface.Size = sizeof(ib_ci_ifc_t);\r
134         pIoStack->Parameters.QueryInterface.Interface = \r
135                 (INTERFACE*)&p_fdo->ci_ifc;\r
136         pIoStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;\r
137         pIoStack->Parameters.QueryInterface.InterfaceType = \r
138                 &GUID_IB_CI_INTERFACE;\r
139         p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
140 \r
141         /* Send the IRP. */\r
142         status = IoCallDriver( p_fdo->p_al_dev, p_irp );\r
143         if( status == STATUS_PENDING )\r
144         {\r
145                 KeWaitForSingleObject( &event, Executive, KernelMode, \r
146                         FALSE, NULL );\r
147 \r
148                 status = ioStatus.Status;\r
149         }\r
150 \r
151         if( !NT_SUCCESS( status ) )\r
152         {\r
153                 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP, \r
154                         ("Query interface for verbs returned %08x.\n", status));\r
155                 return status;\r
156         }\r
157 \r
158         HCA_EXIT( HCA_DBG_PNP );\r
159         return status;\r
160 }\r
161 \r
162 \r
163 static NTSTATUS\r
164 __pnp_notify_target(\r
165         IN                              void                                            *pNotifyStruct,\r
166         IN                              void                                            *context )\r
167 {\r
168         NTSTATUS                                                        status = STATUS_SUCCESS;\r
169         PFDO_DEVICE_DATA                                                p_fdo = context;\r
170         PDEVICE_OBJECT p_dev_obj = WdfDeviceWdmGetDeviceObject(p_fdo->FdoDevice);\r
171         TARGET_DEVICE_REMOVAL_NOTIFICATION      *pNotify;\r
172 \r
173         HCA_ENTER( HCA_DBG_PNP );\r
174 \r
175         pNotify = (TARGET_DEVICE_REMOVAL_NOTIFICATION*)pNotifyStruct;\r
176 \r
177         if( IsEqualGUID( &pNotify->Event, &GUID_TARGET_DEVICE_QUERY_REMOVE ) )\r
178         {\r
179                 if ( p_fdo->state == HCA_REGISTERED) {\r
180                         /* Release AL's CI interface. */\r
181                         p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );\r
182                         p_fdo->state = HCA_IFC_DEREFERENCED;\r
183                 }\r
184 \r
185                 /* Release AL's file object so that it can unload. */\r
186                 CL_ASSERT( p_fdo->p_al_dev );\r
187                 CL_ASSERT( p_fdo->p_al_file_obj );\r
188                 CL_ASSERT( p_fdo->p_al_file_obj == pNotify->FileObject );\r
189                 if( p_fdo->p_al_file_obj ) {\r
190                         ObDereferenceObject( p_fdo->p_al_file_obj );\r
191                         p_fdo->p_al_file_obj = NULL;\r
192                         p_fdo->p_al_dev = NULL;\r
193                 }\r
194         }\r
195         else if( IsEqualGUID( &pNotify->Event, \r
196                 &GUID_TARGET_DEVICE_REMOVE_COMPLETE ) )\r
197         {\r
198                 if (p_fdo->ci_ifc.deregister_ca) {\r
199                         /* Notify AL that the CA is being removed. */\r
200                         p_fdo->ci_ifc.deregister_ca( p_fdo->hca.guid );\r
201                         p_fdo->ci_ifc.deregister_ca = NULL;\r
202                 }\r
203 \r
204                 if ( p_fdo->state == HCA_REGISTERED) {\r
205                         /* Release AL's CI interface. */\r
206                         p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );\r
207                 }\r
208                 p_fdo->state = HCA_STARTED;\r
209 \r
210                 /* Release AL's file object so that it can unload. */\r
211                 if( p_fdo->p_al_file_obj )\r
212                 {\r
213                         ObDereferenceObject( p_fdo->p_al_file_obj );\r
214                         p_fdo->p_al_file_obj = NULL;\r
215                         p_fdo->p_al_dev = NULL;\r
216                 }\r
217 \r
218                 /* Cancel our target device change registration. */\r
219                 if (p_fdo->pnp_target_entry) {\r
220                         IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );\r
221                         p_fdo->pnp_target_entry = NULL;\r
222                 }\r
223 \r
224         }\r
225         else if( IsEqualGUID( &pNotify->Event, \r
226                 &GUID_TARGET_DEVICE_REMOVE_CANCELLED ) )\r
227         {\r
228                 /* Cancel our target device change registration. */\r
229                 if (p_fdo->pnp_target_entry) {\r
230                         IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );\r
231                         p_fdo->pnp_target_entry = NULL;\r
232                 }\r
233 \r
234                 /* Get the device object pointer for the AL. */\r
235                 CL_ASSERT( !p_fdo->p_al_file_obj );\r
236                 CL_ASSERT( !p_fdo->p_al_dev );\r
237                 /* Get the AL device object. */\r
238                 HCA_PRINT( TRACE_LEVEL_INFORMATION      ,HCA_DBG_SHIM  ,("Calling IoGetDeviceObjectPointer.\n"));\r
239                 status = IoGetDeviceObjectPointer( &p_fdo->al_sym_name,\r
240                         FILE_ALL_ACCESS, &p_fdo->p_al_file_obj, &p_fdo->p_al_dev );\r
241                 if( !NT_SUCCESS( status ) )\r
242                 {\r
243                         HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_SHIM, \r
244                                 ("IoGetDeviceObjectPointer returned %08x.\n", status ));\r
245                         return STATUS_SUCCESS;\r
246                 }\r
247 \r
248                 /* Register for removal notification of the IB Fabric root device. */\r
249                 status = IoRegisterPlugPlayNotification( \r
250                         EventCategoryTargetDeviceChange, 0, p_fdo->p_al_file_obj, \r
251                         p_dev_obj->DriverObject, __pnp_notify_target, p_fdo, \r
252                         &p_fdo->pnp_target_entry );\r
253                 if( !NT_SUCCESS( status ) )\r
254                 {\r
255                         HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
256                                 ("IoRegisterPlugPlayNotification returned %08x.\n", status));\r
257                         return status;\r
258                 }\r
259 \r
260                 CL_ASSERT( p_fdo->state == HCA_IFC_DEREFERENCED );\r
261                 if ( p_fdo->state == HCA_IFC_DEREFERENCED) {\r
262                         /* Release AL's CI interface. */\r
263                         p_fdo->ci_ifc.wdm.InterfaceReference( p_fdo->ci_ifc.wdm.Context );\r
264                         p_fdo->state = HCA_REGISTERED;\r
265                 }\r
266         }\r
267 \r
268         HCA_EXIT( HCA_DBG_PNP );\r
269         return status;\r
270 }\r
271 \r
272 \r
273 static ci_interface_t*\r
274 __alloc_hca_ifc(\r
275         IN                              PFDO_DEVICE_DATA const          p_fdo )\r
276 {\r
277         ci_interface_t  *pIfc;\r
278 \r
279         HCA_ENTER( HCA_DBG_PNP );\r
280 \r
281         pIfc =\r
282                 (ci_interface_t*)ExAllocatePoolWithTag( PagedPool, sizeof(ci_interface_t), MT_TAG_KERNEL );\r
283         if( !pIfc )\r
284         {\r
285                 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP, \r
286                         ("Failed to allocate ci_interface_t (%d bytes).\n",\r
287                         sizeof(ci_interface_t)));\r
288                 return NULL;\r
289         }\r
290 \r
291         setup_ci_interface( p_fdo->hca.guid, !!hca_is_livefish(p_fdo), pIfc );\r
292 \r
293         pIfc->p_hca_dev = WdfDeviceWdmGetPhysicalDevice(p_fdo->FdoDevice);\r
294         pIfc->vend_id = (uint32_t)p_fdo->bus_ib_ifc.pdev->ven_id;\r
295         pIfc->dev_id = (uint16_t)p_fdo->bus_ib_ifc.pdev->dev_id;\r
296         pIfc->dev_revision = (uint16_t)p_fdo->hca.hw_ver;\r
297 \r
298         HCA_EXIT( HCA_DBG_PNP );\r
299         return pIfc;\r
300 }\r
301 \r
302 static void\r
303 __hca_deregister(\r
304         IN                              PFDO_DEVICE_DATA                                p_fdo )\r
305 {\r
306         HCA_ENTER( HCA_DBG_PNP );\r
307         \r
308         if ( p_fdo->state == HCA_REGISTERED) {\r
309                 if (p_fdo->ci_ifc.deregister_ca) {\r
310                         /* Notify AL that the CA is being removed. */\r
311                         p_fdo->ci_ifc.deregister_ca( p_fdo->hca.guid );\r
312                         p_fdo->ci_ifc.deregister_ca = NULL;\r
313                         /* Release AL's CI interface. */\r
314                         p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );\r
315                         p_fdo->state = HCA_STARTED;\r
316                         HCA_PRINT( TRACE_LEVEL_INFORMATION      ,HCA_DBG_PNP,\r
317                                 ("***** HCA deregistered \n"));\r
318                 }\r
319         }\r
320 \r
321         HCA_EXIT( HCA_DBG_PNP );\r
322 }\r
323 \r
324 static NTSTATUS\r
325 __hca_register(\r
326         IN                              PFDO_DEVICE_DATA                                p_fdo )\r
327 {\r
328         NTSTATUS                                status;\r
329         ib_api_status_t                 ib_status;\r
330         ci_interface_t                  *p_hca_ifc;\r
331 \r
332         HCA_ENTER( HCA_DBG_PNP );\r
333         \r
334         ASSERT( p_fdo->state == HCA_STARTED );\r
335         ASSERT( p_fdo->p_al_dev );\r
336 \r
337         /* Get the AL's lower interface. */\r
338         status = __get_ci_interface( p_fdo );\r
339         if( !NT_SUCCESS( status ) )\r
340         {\r
341                 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP, \r
342                         ("__get_ci_interface returned %08x.\n", status));\r
343                 goto exit;\r
344         }\r
345 \r
346         /* Allocate and populate our HCA interface structure. */\r
347         p_hca_ifc = __alloc_hca_ifc( p_fdo );\r
348         if( !p_hca_ifc )\r
349         {\r
350                 HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_PNP  ,("__alloc_hca_ifc failed.\n"));\r
351                 status = STATUS_NO_MEMORY;\r
352                 goto exit;\r
353         }\r
354 \r
355         /* Notify AL that we're available... */\r
356         ib_status = p_fdo->ci_ifc.register_ca( p_hca_ifc );\r
357         ExFreePool( p_hca_ifc );\r
358         if( ib_status != IB_SUCCESS )\r
359         {\r
360                 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );\r
361                 status = STATUS_INSUFFICIENT_RESOURCES;\r
362                 goto exit;\r
363         }\r
364 \r
365         p_fdo->state = HCA_REGISTERED;\r
366         HCA_PRINT( TRACE_LEVEL_INFORMATION  ,HCA_DBG_PNP,\r
367                 ("***** HCA registered \n"));\r
368 exit:\r
369         HCA_EXIT( HCA_DBG_PNP );\r
370         return status;\r
371 }\r
372 \r
373 static NTSTATUS\r
374 __pnp_notify_ifc(\r
375         IN                              void                                            *pNotifyStruct,\r
376         IN                              void                                            *context )\r
377 {\r
378         NTSTATUS                                                                status = STATUS_SUCCESS;\r
379         DEVICE_INTERFACE_CHANGE_NOTIFICATION    *pNotify;\r
380         PFDO_DEVICE_DATA                                                p_fdo = context;\r
381         PDEVICE_OBJECT p_dev_obj = WdfDeviceWdmGetDeviceObject(p_fdo->FdoDevice);\r
382 \r
383         HCA_ENTER( HCA_DBG_PNP );\r
384 \r
385         pNotify = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)pNotifyStruct;\r
386 \r
387         if( !IsEqualGUID( &pNotify->Event, &GUID_DEVICE_INTERFACE_ARRIVAL ) )\r
388                 goto done;\r
389 \r
390         /*\r
391          * Sanity check.  We should only be getting notifications of the \r
392          * CI interface exported by AL.\r
393          */\r
394         ASSERT( \r
395                 IsEqualGUID( &pNotify->InterfaceClassGuid, &GUID_IB_CI_INTERFACE ) );\r
396 \r
397         if( p_fdo->state != HCA_STARTED )\r
398         {\r
399                 HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_PNP  ,("Invalid state: %d\n", p_fdo->state));\r
400                 goto done;\r
401         }\r
402 \r
403         /* save symbolic name of IBAL for a case of cancelled IBAL removal */\r
404         if (!p_fdo->al_sym_name.Buffer) {\r
405                 p_fdo->al_sym_name.Length = pNotify->SymbolicLinkName->Length;\r
406                 p_fdo->al_sym_name.MaximumLength = pNotify->SymbolicLinkName->MaximumLength;\r
407                 p_fdo->al_sym_name.Buffer = ExAllocatePoolWithTag( NonPagedPool, \r
408                         p_fdo->al_sym_name.MaximumLength * sizeof(wchar_t), MT_TAG_KERNEL );\r
409                 if (!p_fdo->al_sym_name.Buffer)\r
410                 {\r
411                         HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_PNP  ,("allocation of sym IBAL name failed.\n"));\r
412                         goto done;\r
413                 }\r
414                 RtlCopyUnicodeString( &p_fdo->al_sym_name, pNotify->SymbolicLinkName );\r
415         }\r
416 \r
417         ASSERT( !p_fdo->p_al_dev );\r
418         ASSERT( !p_fdo->p_al_file_obj );\r
419 \r
420         /* Get the AL device object. */\r
421         HCA_PRINT( TRACE_LEVEL_INFORMATION  ,HCA_DBG_PNP  ,("Calling IoGetDeviceObjectPointer.\n"));\r
422         status = IoGetDeviceObjectPointer( pNotify->SymbolicLinkName,\r
423                 FILE_ALL_ACCESS, &p_fdo->p_al_file_obj, &p_fdo->p_al_dev );\r
424         if( !NT_SUCCESS( status ) )\r
425         {\r
426                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
427                         ("IoGetDeviceObjectPointer returned %08x.\n", status ));\r
428                 goto done;\r
429         }\r
430 \r
431         /* Register for removal notification of the IB Fabric root device. */\r
432         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, \r
433                 ("Registering for target notifications.\n"));\r
434         status = IoRegisterPlugPlayNotification( \r
435                 EventCategoryTargetDeviceChange, 0, p_fdo->p_al_file_obj, \r
436                 p_dev_obj->DriverObject, __pnp_notify_target, p_fdo, \r
437                 &p_fdo->pnp_target_entry );\r
438         if( !NT_SUCCESS( status ) )\r
439         {\r
440                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
441                         ("IoRegisterPlugPlayNotification returned %08x.\n", status));\r
442                 goto err_reg_notify;\r
443         }\r
444 \r
445         status = __hca_register( p_fdo );\r
446         if( !NT_SUCCESS( status ) )\r
447         {\r
448                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
449                         ("__get_ci_interface returned %08x.\n", status));\r
450                 goto err_reg_hca;\r
451         }\r
452         goto done;\r
453         \r
454 err_reg_hca:\r
455         IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );\r
456         p_fdo->pnp_target_entry = NULL;\r
457 err_reg_notify:\r
458         ObDereferenceObject( p_fdo->p_al_file_obj );\r
459         p_fdo->p_al_file_obj = NULL;\r
460         p_fdo->p_al_dev = NULL;\r
461 done:\r
462         HCA_EXIT( HCA_DBG_PNP );\r
463         return status;\r
464 }\r
465 \r
466 /* Forwards the request to the HCA's PDO. */\r
467 static NTSTATUS\r
468 __get_ifc(\r
469         IN                              WDFDEVICE const                 FdoDevice,\r
470         IN              const   GUID* const                             p_guid,\r
471         IN                              USHORT                                  size,\r
472         IN                              USHORT                                  Version,\r
473         IN OUT                  PVOID                                   InterfaceSpecificData,\r
474         OUT                             PINTERFACE                              p_ifc )\r
475 {\r
476         NTSTATUS status;\r
477 \r
478         HCA_ENTER( HCA_DBG_PNP );\r
479         \r
480         status = WdfFdoQueryForInterface( FdoDevice, p_guid, p_ifc,\r
481                 size, Version, InterfaceSpecificData );\r
482 \r
483         HCA_EXIT( HCA_DBG_PNP );\r
484         return status;\r
485 }\r
486 \r
487 static void\r
488 __unmap_hca_memory(\r
489         IN                              PFDO_DEVICE_DATA const p_fdo )\r
490 {\r
491         struct pci_dev *pdev = p_fdo->bus_ib_ifc.pdev;\r
492         int                             i;\r
493 \r
494         HCA_ENTER( HCA_DBG_PNP );\r
495 \r
496         for( i = 0; i < HCA_BAR_TYPE_MAX; i++ ) {\r
497                 if (pdev->bar[i].virt) {\r
498                         MmUnmapIoSpace( pdev->bar[i].virt, pdev->bar[i].size );\r
499                         cl_memclr( &pdev->bar[i], sizeof(hca_bar_t) );\r
500                 }\r
501         }\r
502 \r
503         HCA_EXIT( HCA_DBG_PNP );\r
504 }\r
505 \r
506 /* release the resources, allocated in hca_start */\r
507 static void\r
508 __hca_release_resources(\r
509         IN      WDFDEVICE  Device )\r
510 {\r
511         PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);\r
512 \r
513         HCA_ENTER( HCA_DBG_PNP );\r
514 \r
515         switch( p_fdo->state )\r
516         {\r
517         case HCA_REGISTERED:\r
518                 __hca_deregister( p_fdo );\r
519 \r
520                 /* Fall through. */\r
521         case HCA_STARTED:\r
522                 /* dequeue HCA  */\r
523                 mlnx_hca_remove( &p_fdo->hca );\r
524         }\r
525 \r
526         if (p_fdo->al_sym_name.Buffer) {\r
527                 ExFreePool( p_fdo->al_sym_name.Buffer );\r
528                 p_fdo->al_sym_name.Buffer = NULL;\r
529         }\r
530         \r
531         if( p_fdo->pnp_target_entry )\r
532         {\r
533                 ASSERT( p_fdo->pnp_ifc_entry );\r
534                 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );\r
535                 p_fdo->pnp_target_entry = NULL;\r
536         }\r
537 \r
538         if( p_fdo->pnp_ifc_entry ) {\r
539                 IoUnregisterPlugPlayNotification( p_fdo->pnp_ifc_entry );\r
540                 p_fdo->pnp_ifc_entry = NULL;\r
541         }\r
542 \r
543         if( p_fdo->p_al_file_obj ) {\r
544                 ObDereferenceObject( p_fdo->p_al_file_obj );\r
545                 p_fdo->p_al_file_obj = NULL;\r
546         }\r
547 \r
548         __unmap_hca_memory( p_fdo );\r
549 \r
550         p_fdo->state = HCA_ADDED;\r
551 \r
552         HCA_EXIT( HCA_DBG_PNP );\r
553 }\r
554 \r
555 NTSTATUS\r
556 EvtDeviceD0Entry(\r
557         IN WDFDEVICE  Device,\r
558         IN WDF_POWER_DEVICE_STATE  PreviousState\r
559         )\r
560 {\r
561         PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);\r
562         NTSTATUS status = STATUS_SUCCESS;\r
563 \r
564         UNUSED_PARAM(PreviousState);\r
565         HCA_ENTER( HCA_DBG_PNP );\r
566 \r
567         HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceD0Entry: PreviousState 0x%x\n", PreviousState));\r
568 \r
569         /* Connect to IBAL */\r
570         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
571                 ("***** Connect to IBAL, IRQL %d\n", KeGetCurrentIrql()));\r
572 \r
573         if( p_fdo->p_al_dev && p_fdo->state == HCA_STARTED) {\r
574                 status = __hca_register( p_fdo );\r
575                 if( !NT_SUCCESS( status ) ) {\r
576                         HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO, \r
577                                 ("!!! __hca_register failed (%#x) \n", status));\r
578                         status = STATUS_UNSUCCESSFUL;\r
579                 }\r
580         }\r
581 \r
582         HCA_EXIT( HCA_DBG_PNP );\r
583         return STATUS_SUCCESS;\r
584 }\r
585 \r
586 NTSTATUS\r
587 EvtDeviceD0Exit(\r
588         IN WDFDEVICE  Device,\r
589         IN WDF_POWER_DEVICE_STATE  TargetState\r
590         )\r
591 {\r
592         NTSTATUS status;\r
593         PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);\r
594 \r
595         HCA_ENTER( HCA_DBG_PNP );\r
596 \r
597         HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceD0Exit: TargetState 0x%x\n", TargetState));\r
598 \r
599         switch (TargetState) {\r
600         case WdfPowerDeviceD1:  /* hopefully, it is STANDBY state */\r
601         case WdfPowerDevicePrepareForHibernation:\r
602                 if (atomic_read(&p_fdo->usecnt)) {\r
603                         status = STATUS_UNSUCCESSFUL;\r
604                         break;\r
605                 }\r
606                 /* Fall through. */\r
607         default:\r
608                 __hca_deregister( p_fdo );\r
609                 status = STATUS_SUCCESS;\r
610                 break;\r
611         }\r
612 \r
613         HCA_EXIT( HCA_DBG_PNP );\r
614         return status;\r
615 }\r
616 \r
617 NTSTATUS\r
618 EvtDevicePrepareHardware(\r
619         IN WDFDEVICE  Device,\r
620         IN WDFCMRESLIST  ResourcesRaw,\r
621         IN WDFCMRESLIST  ResourcesTranslated\r
622         )\r
623 {\r
624         int err;\r
625         NTSTATUS status;\r
626         PFDO_DEVICE_DATA p_fdo  = FdoGetData(Device);\r
627         PDEVICE_OBJECT p_dev_obj = WdfDeviceWdmGetDeviceObject(Device);\r
628         BUS_INTERFACE_STANDARD  bus_pci_ifc;\r
629                 \r
630         UNUSED_PARAM(ResourcesRaw);\r
631         UNUSED_PARAM(ResourcesTranslated);\r
632 \r
633         HCA_ENTER( HCA_DBG_PNP );\r
634         \r
635         HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtPrepareHardware: \n"));\r
636 \r
637         ASSERT(p_dev_obj);\r
638 \r
639         /* get PCI BUS interface */\r
640         status = __get_ifc( Device, &GUID_BUS_INTERFACE_STANDARD,\r
641                 sizeof(BUS_INTERFACE_STANDARD), 1, NULL, (PINTERFACE)&bus_pci_ifc);\r
642         if( !NT_SUCCESS( status ) ) {\r
643                 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting PCI BUS interface failed: status=0x%x\n", status));\r
644                 return status;\r
645         }\r
646         RtlCopyMemory( &p_fdo->bus_pci_ifc, &bus_pci_ifc, sizeof(BUS_INTERFACE_STANDARD) );\r
647         p_fdo->bus_pci_ifc_taken = TRUE;\r
648         \r
649         /* get MLX4_BUS IB interface */\r
650         status = __get_ifc( Device, &MLX4_BUS_IB_INTERFACE_GUID,\r
651                 sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL, (PINTERFACE)&p_fdo->bus_ib_ifc);\r
652         if( !NT_SUCCESS( status ) ) {\r
653                 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));\r
654                 return status;\r
655         }\r
656         p_fdo->bus_ib_ifc_taken = TRUE;\r
657         p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;\r
658 \r
659         InitializeListHead(&p_fdo->hca.event_list);\r
660         KeInitializeSpinLock(&p_fdo->hca.event_list_lock);\r
661 \r
662         /* get node GUID */\r
663         err = __get_dev_info( p_fdo, &p_fdo->hca.guid, &p_fdo->hca.hw_ver );\r
664         if (err) {\r
665 \r
666                 HCA_PRINT(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,\r
667                         ("can't get guid - ib_query_device() failed (%08X)\n", err ));\r
668                 //TODO: no cleanup on error\r
669                 return STATUS_INSUFFICIENT_RESOURCES;\r
670         }\r
671 \r
672         /* queue HCA  */\r
673         mlnx_hca_insert( &p_fdo->hca );\r
674 \r
675         /*\r
676          * Change the state since the PnP callback can happen\r
677          * before the callback returns.\r
678          */\r
679         p_fdo->state = HCA_STARTED;\r
680         \r
681         /* Register for interface arrival of the IB_AL device. */\r
682         status = IoRegisterPlugPlayNotification(\r
683                 EventCategoryDeviceInterfaceChange,\r
684                 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,\r
685                 (void*)&GUID_IB_CI_INTERFACE, p_dev_obj->DriverObject,\r
686                 __pnp_notify_ifc, p_fdo, &p_fdo->pnp_ifc_entry );\r
687         if( !NT_SUCCESS( status ) )\r
688         {\r
689                 p_fdo->state = HCA_ADDED;\r
690                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,\r
691                         ("IoRegisterPlugPlayNotification returned %08x.\n", status));\r
692         }\r
693 \r
694         HCA_EXIT( HCA_DBG_PNP );\r
695         return status;\r
696 }\r
697 \r
698 \r
699 NTSTATUS\r
700 EvtDeviceReleaseHardware(\r
701         IN WDFDEVICE  Device,\r
702         IN WDFCMRESLIST  ResourcesTranslated\r
703         )\r
704 {\r
705         PFDO_DEVICE_DATA p_fdo  = FdoGetData(Device);\r
706 \r
707         UNUSED_PARAM(ResourcesTranslated);\r
708 \r
709         HCA_ENTER( HCA_DBG_PNP );\r
710 \r
711         HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtReleaseHardware: FdoData=0x%p\n", p_fdo));\r
712 \r
713         // release IBBUS resources\r
714         __hca_release_resources(Device);\r
715 \r
716         // release MLX4_BUS resources\r
717         if(p_fdo->bus_ib_ifc_taken) {\r
718                 p_fdo->bus_ib_ifc_taken = FALSE;\r
719                 __put_ifc( (PINTERFACE)&p_fdo->bus_ib_ifc );\r
720         }\r
721 \r
722         // release PCI BUS resources\r
723         if(p_fdo->bus_pci_ifc_taken) {\r
724                 p_fdo->bus_pci_ifc_taken = FALSE;\r
725                 __put_ifc( (PINTERFACE)&p_fdo->bus_pci_ifc );\r
726         }\r
727 \r
728         HCA_EXIT( HCA_DBG_PNP );\r
729         return STATUS_SUCCESS;\r
730 }\r
731 \r
732 NTSTATUS\r
733 EvtDeviceQueryRemove(\r
734         IN WDFDEVICE  Device\r
735         )\r
736 {\r
737         PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);\r
738         HCA_ENTER( HCA_DBG_PNP );\r
739         if (atomic_read(&p_fdo->usecnt)) {\r
740                 DbgPrint( "MLX4: Can't get unloaded. %d applications are still in work\n", p_fdo->usecnt);\r
741                 return STATUS_UNSUCCESSFUL;\r
742         }\r
743         HCA_EXIT( HCA_DBG_PNP );\r
744         return STATUS_SUCCESS;\r
745 }\r
746 \r
747 \r
748 NTSTATUS\r
749 EvtDeviceAdd(\r
750         IN WDFDRIVER        Driver,\r
751         IN PWDFDEVICE_INIT  DeviceInit\r
752         )\r
753 /*++\r
754 Routine Description:\r
755 \r
756         EvtDeviceAdd is called by the framework in response to AddDevice\r
757         call from the PnP manager. We create and initialize a device object to\r
758         represent a new instance of mxe bus.\r
759 \r
760 Arguments:\r
761 \r
762         Driver - Handle to a framework driver object created in DriverEntry\r
763 \r
764         DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.\r
765 \r
766 Return Value:\r
767 \r
768         NTSTATUS\r
769 \r
770 --*/\r
771 {\r
772         WDF_OBJECT_ATTRIBUTES                   attributes;\r
773         NTSTATUS                                                status;\r
774         WDFDEVICE                                               device;\r
775         PFDO_DEVICE_DATA                                p_fdo;\r
776         WDF_PNPPOWER_EVENT_CALLBACKS    Callbacks;\r
777 \r
778         UNREFERENCED_PARAMETER(Driver);\r
779 \r
780         PAGED_CODE ();\r
781         \r
782         HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceAdd: 0x%p\n", Driver));\r
783         //\r
784         // register PnP & Power stuff\r
785         //\r
786         WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&Callbacks);\r
787         Callbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware;\r
788         Callbacks.EvtDeviceReleaseHardware = EvtDeviceReleaseHardware;\r
789         Callbacks.EvtDeviceQueryRemove  = EvtDeviceQueryRemove;\r
790         Callbacks.EvtDeviceD0Entry = EvtDeviceD0Entry;\r
791         Callbacks.EvtDeviceD0Exit = EvtDeviceD0Exit;\r
792 \r
793         WdfDeviceInitSetPnpPowerEventCallbacks( DeviceInit, &Callbacks );\r
794         \r
795         //\r
796         // Initialize all the properties specific to the device.\r
797         // Framework has default values for the one that are not\r
798         // set explicitly here. So please read the doc and make sure\r
799         // you are okay with the defaults.\r
800         //\r
801         WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_INFINIBAND);\r
802         WdfDeviceInitSetExclusive(DeviceInit, FALSE);\r
803 \r
804         //\r
805         // Initialize attributes structure to specify size and accessor function\r
806         // for storing device context.\r
807         //\r
808         WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FDO_DEVICE_DATA);\r
809 \r
810         //\r
811         // Create a framework device object. In response to this call, framework\r
812         // creates a WDM deviceobject.\r
813         //\r
814         status = WdfDeviceCreate(&DeviceInit, &attributes, &device);\r
815         if (!NT_SUCCESS(status)) {\r
816                 HCA_PRINT(TRACE_LEVEL_VERBOSE, HCA_DBG_PNP, ("EvtDeviceAdd: WdfDeviceCreate failed with 0x%x\n", status));\r
817                 goto end;\r
818         }\r
819 \r
820         //\r
821         // Init device context.\r
822         //\r
823         p_fdo = FdoGetData(device);\r
824         RtlZeroMemory(p_fdo, sizeof(FDO_DEVICE_DATA));\r
825         p_fdo->FdoDevice = device;\r
826         spin_lock_init( &p_fdo->uctx_lock );\r
827         cl_qlist_init( &p_fdo->uctx_list );\r
828         atomic_set(&p_fdo->usecnt, 0);\r
829         p_fdo->state = HCA_ADDED;\r
830 \r
831         //\r
832         // WMI\r
833         //\r
834         status = WmiRegistration(device);\r
835         if (!NT_SUCCESS(status)) {\r
836                 return status;\r
837         }\r
838 \r
839         status = STATUS_SUCCESS;\r
840 \r
841 end:    \r
842         HCA_EXIT( HCA_DBG_PNP );\r
843         return status;\r
844 }\r
845 \r
846 \r
847 void\r
848 EvtDriverUnload(\r
849         IN              WDFDRIVER  Driver\r
850         )\r
851 {\r
852         HCA_ENTER( HCA_DBG_PNP );\r
853 \r
854         UNUSED_PARAM( Driver );\r
855 \r
856         HCA_EXIT( HCA_DBG_PNP );\r
857 #if defined(EVENT_TRACING)\r
858         WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver));\r
859 #endif\r
860 }\r
861 \r
862 NTSTATUS\r
863 DriverEntry(\r
864         IN PDRIVER_OBJECT DriverObject,\r
865         IN PUNICODE_STRING RegistryPath\r
866         )\r
867 /*++\r
868 Routine Description:\r
869 \r
870         Initialize the call backs structure of Driver Framework.\r
871 \r
872 Arguments:\r
873 \r
874         DriverObject - pointer to the driver object\r
875 \r
876         RegistryPath - pointer to a unicode string representing the path,\r
877                                         to driver-specific key in the registry.\r
878 \r
879 Return Value:\r
880 \r
881         NT Status Code\r
882 \r
883 --*/\r
884 {\r
885         WDF_DRIVER_CONFIG   config;\r
886         NTSTATUS            status;\r
887         WDFDRIVER hDriver;\r
888 \r
889 #if defined(EVENT_TRACING)\r
890         WPP_INIT_TRACING(DriverObject, RegistryPath);\r
891 #endif\r
892 \r
893         // global initializations\r
894         g.DebugPrintLevel = TRACE_LEVEL_VERBOSE;\r
895         g.DebugPrintFlags = 0xffff;\r
896         HCA_ENTER( HCA_DBG_PNP );\r
897         HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, \r
898                 ("Built %s %s, Version %s, RelDate %s\n", \r
899                 __DATE__, __TIME__, DRV_VERSION, DRV_RELDATE));\r
900         status = mlnx_hcas_init();\r
901         if( status  != STATUS_SUCCESS ) {\r
902                 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,\r
903                         ("mlnx_hcas_init returned %#x.\n", status));\r
904                 goto end;\r
905         }\r
906 \r
907         //\r
908         // Initiialize driver config to control the attributes that\r
909         // are global to the driver. Note that framework by default\r
910         // provides a driver unload routine. If you create any resources\r
911         // in the DriverEntry and want to be cleaned in driver unload,\r
912         // you can override that by specifing one in the Config structure.\r
913         //\r
914 \r
915         WDF_DRIVER_CONFIG_INIT(\r
916                 &config, EvtDeviceAdd );\r
917         config.EvtDriverUnload = EvtDriverUnload;\r
918 \r
919         //\r
920         // Create a framework driver object to represent our driver.\r
921         //\r
922         status = WdfDriverCreate(DriverObject,\r
923                 RegistryPath, WDF_NO_OBJECT_ATTRIBUTES,\r
924                 &config, &hDriver);\r
925 \r
926         if (!NT_SUCCESS(status)) {\r
927                 HCA_PRINT(TRACE_LEVEL_VERBOSE, HCA_DBG_PNP, ("WdfDriverCreate failed with status 0x%x\n", status));\r
928                 goto end;\r
929         }\r
930 \r
931         //\r
932         // read registry parameters\r
933         //\r
934         {\r
935                 DECLARE_CONST_UNICODE_STRING(valueName0, L"DebugLevel");\r
936                 DECLARE_CONST_UNICODE_STRING(valueName1, L"DebugFlags");\r
937                 ULONG value;\r
938                 WDFKEY hKey = NULL;\r
939 \r
940                 status = WdfDriverOpenParametersRegistryKey( hDriver,\r
941                         STANDARD_RIGHTS_ALL, WDF_NO_OBJECT_ATTRIBUTES, &hKey );\r
942 \r
943                 if (NT_SUCCESS (status)) {\r
944 \r
945                         status = WdfRegistryQueryULong(hKey, &valueName0, &value);\r
946                         if (NT_SUCCESS (status)) g.DebugPrintLevel = value;\r
947                         \r
948                         status = WdfRegistryQueryULong(hKey, &valueName1, &value);\r
949                         if (NT_SUCCESS (status)) g.DebugPrintFlags = value;\r
950                         \r
951                         WdfRegistryClose(hKey);\r
952                 }\r
953 \r
954                 // we don't matter the failure in the work with Registry\r
955                 status = STATUS_SUCCESS;\r
956         }\r
957 \r
958 end:\r
959         HCA_EXIT( HCA_DBG_PNP );\r
960         return status;\r
961 \r
962 }\r
963 \r
964 #else\r
965 \r
966 \r
967 UNICODE_STRING                          g_param_path;\r
968 static cl_vfptr_pnp_po_t        vfptrHcaPnp;\r
969 \r
970 NTSTATUS\r
971 DriverEntry(\r
972         IN                              PDRIVER_OBJECT                          p_driver_obj,\r
973         IN                              PUNICODE_STRING                         p_registry_path );\r
974 \r
975 static NTSTATUS\r
976 __read_registry(\r
977         IN                              UNICODE_STRING* const           p_Param_Path );\r
978 \r
979 static void\r
980 hca_drv_unload(\r
981         IN                              PDRIVER_OBJECT                          p_driver_obj );\r
982 \r
983 static NTSTATUS\r
984 hca_sysctl(\r
985         IN                              PDEVICE_OBJECT                          p_dev_obj,\r
986         IN                              PIRP                                            p_irp );\r
987 \r
988 NTSTATUS\r
989 hca_add_device(\r
990         IN                              PDRIVER_OBJECT                          pDriverObj,\r
991         IN                              PDEVICE_OBJECT                          pPdo );\r
992 \r
993 static NTSTATUS\r
994 hca_start(\r
995         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
996         IN                              IRP* const                                      p_irp, \r
997                 OUT                     cl_irp_action_t* const          p_action );\r
998 \r
999 static NTSTATUS\r
1000 hca_query_stop(\r
1001         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1002         IN                              IRP* const                                      p_irp, \r
1003                 OUT                     cl_irp_action_t* const          p_action );\r
1004 \r
1005 static NTSTATUS\r
1006 hca_stop(\r
1007         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1008         IN                              IRP* const                                      p_irp, \r
1009                 OUT                     cl_irp_action_t* const          p_action );\r
1010 \r
1011 static NTSTATUS\r
1012 hca_cancel_stop(\r
1013         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1014         IN                              IRP* const                                      p_irp, \r
1015                 OUT                     cl_irp_action_t* const          p_action );\r
1016 \r
1017 static NTSTATUS\r
1018 hca_query_remove(\r
1019         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1020         IN                              IRP* const                                      p_irp, \r
1021                 OUT                     cl_irp_action_t* const          p_action );\r
1022 \r
1023 static void\r
1024 hca_release_resources(\r
1025         IN                              DEVICE_OBJECT* const            p_dev_obj );\r
1026 \r
1027 static NTSTATUS\r
1028 hca_cancel_remove(\r
1029         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1030         IN                              IRP* const                                      p_irp, \r
1031                 OUT                     cl_irp_action_t* const          p_action );\r
1032 \r
1033 static NTSTATUS\r
1034 hca_surprise_remove(\r
1035         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1036         IN                              IRP* const                                      p_irp, \r
1037                 OUT                     cl_irp_action_t* const          p_action );\r
1038 \r
1039 static NTSTATUS\r
1040 hca_query_capabilities(\r
1041         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1042         IN                              IRP* const                                      p_irp, \r
1043                 OUT                     cl_irp_action_t* const          p_action );\r
1044 \r
1045 static NTSTATUS\r
1046 hca_query_pnp_state(\r
1047         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1048         IN                              IRP* const                                      p_irp, \r
1049                 OUT                     cl_irp_action_t* const          p_action );\r
1050 \r
1051 static NTSTATUS\r
1052 hca_query_bus_relations(\r
1053         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1054         IN                              IRP* const                                      p_irp, \r
1055                 OUT                     cl_irp_action_t* const          p_action );\r
1056 \r
1057 static NTSTATUS\r
1058 hca_query_removal_relations(\r
1059         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1060         IN                              IRP* const                                      p_irp, \r
1061                 OUT                     cl_irp_action_t* const          p_action );\r
1062 \r
1063 static NTSTATUS\r
1064 hca_query_power(\r
1065         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1066         IN                              IRP* const                                      p_irp,\r
1067                 OUT                     cl_irp_action_t* const          p_action );\r
1068 \r
1069 static NTSTATUS\r
1070 hca_set_power(\r
1071         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1072         IN                              IRP* const                                      p_irp, \r
1073                 OUT                     cl_irp_action_t* const          p_action );\r
1074 \r
1075 static ci_interface_t*\r
1076 __alloc_hca_ifc(\r
1077         IN                              FDO_DEVICE_DATA* const          p_fdo );\r
1078 \r
1079 static NTSTATUS\r
1080 __get_ci_interface(\r
1081         IN                              DEVICE_OBJECT* const            p_dev_obj );\r
1082 \r
1083 static void\r
1084 __hca_deregister(\r
1085         IN                              FDO_DEVICE_DATA                 *p_fdo );\r
1086 \r
1087 static NTSTATUS\r
1088 __hca_register(\r
1089         IN                              DEVICE_OBJECT                           *p_dev_obj );\r
1090 \r
1091 static NTSTATUS\r
1092 __pnp_notify_target(\r
1093         IN                              void                                            *pNotifyStruct,\r
1094         IN                              void                                            *context );\r
1095 \r
1096 static NTSTATUS\r
1097 __pnp_notify_ifc(\r
1098         IN                              void                                            *pNotifyStruct,\r
1099         IN                              void                                            *context );\r
1100 \r
1101 \r
1102 #ifdef ALLOC_PRAGMA\r
1103 #pragma alloc_text (INIT, DriverEntry)\r
1104 #pragma alloc_text (INIT, __read_registry)\r
1105 #pragma alloc_text (PAGE, hca_drv_unload)\r
1106 #pragma alloc_text (PAGE, hca_sysctl)\r
1107 #pragma alloc_text (PAGE, hca_add_device)\r
1108 #pragma alloc_text (PAGE, hca_start)\r
1109 #pragma alloc_text (PAGE, hca_query_stop)\r
1110 #pragma alloc_text (PAGE, hca_stop)\r
1111 #pragma alloc_text (PAGE, hca_cancel_stop)\r
1112 #pragma alloc_text (PAGE, hca_query_remove)\r
1113 #pragma alloc_text (PAGE, hca_release_resources)\r
1114 #pragma alloc_text (PAGE, hca_cancel_remove)\r
1115 #pragma alloc_text (PAGE, hca_surprise_remove)\r
1116 #pragma alloc_text (PAGE, hca_query_capabilities)\r
1117 #pragma alloc_text (PAGE, hca_query_pnp_state)\r
1118 #pragma alloc_text (PAGE, hca_query_bus_relations)\r
1119 #pragma alloc_text (PAGE, hca_query_removal_relations)\r
1120 #pragma alloc_text (PAGE, hca_set_power)\r
1121 #pragma alloc_text (PAGE, __alloc_hca_ifc)\r
1122 #pragma alloc_text (PAGE, __get_ci_interface)\r
1123 #pragma alloc_text (PAGE, __hca_register)\r
1124 #pragma alloc_text (PAGE, __pnp_notify_target)\r
1125 #pragma alloc_text (PAGE, __pnp_notify_ifc)\r
1126 #endif\r
1127 \r
1128 \r
1129 NTSTATUS\r
1130 hca_add_device(\r
1131         IN                              PDRIVER_OBJECT                          pDriverObj,\r
1132         IN                              PDEVICE_OBJECT                          pPdo )\r
1133 {\r
1134         NTSTATUS                        status;\r
1135         DEVICE_OBJECT           *p_dev_obj, *pNextDevObj;\r
1136         PFDO_DEVICE_DATA        p_fdo;\r
1137 \r
1138         HCA_ENTER(HCA_DBG_PNP);\r
1139 \r
1140         /*\r
1141          * Create the device so that we have a device extension to store stuff in.\r
1142          */\r
1143         status = IoCreateDevice( pDriverObj, sizeof(FDO_DEVICE_DATA),\r
1144                 NULL, FILE_DEVICE_INFINIBAND, FILE_DEVICE_SECURE_OPEN,\r
1145                 FALSE, &p_dev_obj );\r
1146         if( !NT_SUCCESS( status ) )\r
1147         {\r
1148                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
1149                         ("IoCreateDevice returned 0x%08X.\n", status));\r
1150                 return status;\r
1151         }\r
1152 \r
1153         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
1154         cl_memclr( p_fdo, sizeof(FDO_DEVICE_DATA) );\r
1155         cl_spinlock_init( &p_fdo->uctx_lock );\r
1156         cl_qlist_init( &p_fdo->uctx_list );\r
1157         atomic_set(&p_fdo->usecnt, 0);\r
1158 \r
1159         /* Attach to the device stack. */\r
1160         pNextDevObj = IoAttachDeviceToDeviceStack( p_dev_obj, pPdo );\r
1161         if( !pNextDevObj )\r
1162         {\r
1163                 //cl_event_destroy( &p_fdo->mutex );\r
1164                 IoDeleteDevice( p_dev_obj );\r
1165                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
1166                         ("IoAttachDeviceToDeviceStack failed.\n"));\r
1167                 return STATUS_NO_SUCH_DEVICE;\r
1168         }\r
1169 \r
1170         /* Inititalize the complib extension. */\r
1171         cl_init_pnp_po_ext( p_dev_obj, pNextDevObj, pPdo, 0,\r
1172                 &vfptrHcaPnp, NULL );\r
1173 \r
1174         p_fdo->state = HCA_ADDED;\r
1175 \r
1176         HCA_EXIT(HCA_DBG_PNP);\r
1177         return status;\r
1178 }\r
1179 \r
1180 /* Forwards the request to the HCA's PDO. */\r
1181 static NTSTATUS\r
1182 __get_ifc(\r
1183         IN                              DEVICE_OBJECT* const            pDevObj,\r
1184         IN              const   GUID* const                                     pGuid,\r
1185         IN                              USHORT                                          size,\r
1186         IN                              USHORT                                          Version,\r
1187         IN OUT                  PVOID                                           InterfaceSpecificData,\r
1188                 OUT                     PINTERFACE                                      pBusIfc )\r
1189 {\r
1190         NTSTATUS                        status;\r
1191         IRP                                     *pIrp;\r
1192         IO_STATUS_BLOCK         ioStatus;\r
1193         IO_STACK_LOCATION       *pIoStack;\r
1194         DEVICE_OBJECT           *pDev;\r
1195         KEVENT                          event;\r
1196 \r
1197         HCA_ENTER( HCA_DBG_PNP );\r
1198 \r
1199         CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
1200 \r
1201         pDev = IoGetAttachedDeviceReference( pDevObj );\r
1202 \r
1203         KeInitializeEvent( &event, NotificationEvent, FALSE );\r
1204 \r
1205         /* Build the IRP for the HCA. */\r
1206         pIrp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, pDev,\r
1207                 NULL, 0, NULL, &event, &ioStatus );\r
1208         if( !pIrp )\r
1209         {\r
1210                 ObDereferenceObject( pDev );\r
1211                 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP, \r
1212                         ("IoBuildSynchronousFsdRequest failed.\n"));\r
1213                 return STATUS_INSUFFICIENT_RESOURCES;\r
1214         }\r
1215 \r
1216         /* Copy the request query parameters. */\r
1217         pIoStack = IoGetNextIrpStackLocation( pIrp );\r
1218         pIoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
1219         pIoStack->Parameters.QueryInterface.Size = size;\r
1220         pIoStack->Parameters.QueryInterface.Version = Version;\r
1221         pIoStack->Parameters.QueryInterface.InterfaceType = pGuid;\r
1222         pIoStack->Parameters.QueryInterface.Interface = (INTERFACE*)pBusIfc;\r
1223         pIoStack->Parameters.QueryInterface.InterfaceSpecificData = InterfaceSpecificData;\r
1224 \r
1225         pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
1226 \r
1227         /* Send the IRP. */\r
1228         status = IoCallDriver( pDev, pIrp );\r
1229         if( status == STATUS_PENDING )\r
1230         {\r
1231                 KeWaitForSingleObject( &event, Executive, KernelMode,\r
1232                         FALSE, NULL );\r
1233 \r
1234                 status = ioStatus.Status;\r
1235         }\r
1236         ObDereferenceObject( pDev );\r
1237 \r
1238         HCA_EXIT( HCA_DBG_PNP );\r
1239         return status;\r
1240 }\r
1241 \r
1242 static NTSTATUS\r
1243 __get_ci_interface(\r
1244         IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
1245 {\r
1246         NTSTATUS                        status;\r
1247         IRP                                     *p_irp;\r
1248         PFDO_DEVICE_DATA        p_fdo;\r
1249         IO_STATUS_BLOCK         ioStatus;\r
1250         IO_STACK_LOCATION       *pIoStack;\r
1251         KEVENT                          event;\r
1252 \r
1253         HCA_ENTER( HCA_DBG_PNP );\r
1254 \r
1255         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
1256 \r
1257         KeInitializeEvent( &event, NotificationEvent, FALSE );\r
1258 \r
1259         /* Query for the verbs interface. */\r
1260         p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_fdo->p_al_dev,\r
1261                 NULL, 0, NULL, &event, &ioStatus );\r
1262         if( !p_irp )\r
1263         {\r
1264                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
1265                         ("IoBuildSynchronousFsdRequest failed.\n"));\r
1266                 return STATUS_INSUFFICIENT_RESOURCES;\r
1267         }\r
1268 \r
1269         /* Format the IRP. */\r
1270         pIoStack = IoGetNextIrpStackLocation( p_irp );\r
1271         pIoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
1272         pIoStack->Parameters.QueryInterface.Version = IB_CI_INTERFACE_VERSION;\r
1273         pIoStack->Parameters.QueryInterface.Size = sizeof(ib_ci_ifc_t);\r
1274         pIoStack->Parameters.QueryInterface.Interface = \r
1275                 (INTERFACE*)&p_fdo->ci_ifc;\r
1276         pIoStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;\r
1277         pIoStack->Parameters.QueryInterface.InterfaceType = \r
1278                 &GUID_IB_CI_INTERFACE;\r
1279         p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
1280 \r
1281         /* Send the IRP. */\r
1282         status = IoCallDriver( p_fdo->p_al_dev, p_irp );\r
1283         if( status == STATUS_PENDING )\r
1284         {\r
1285                 KeWaitForSingleObject( &event, Executive, KernelMode, \r
1286                         FALSE, NULL );\r
1287 \r
1288                 status = ioStatus.Status;\r
1289         }\r
1290 \r
1291         if( !NT_SUCCESS( status ) )\r
1292         {\r
1293                 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP, \r
1294                         ("Query interface for verbs returned %08x.\n", status));\r
1295                 return status;\r
1296         }\r
1297 \r
1298         HCA_EXIT( HCA_DBG_PNP );\r
1299         return status;\r
1300 }\r
1301 \r
1302 \r
1303 static NTSTATUS\r
1304 __pnp_notify_target(\r
1305         IN                              void                                            *pNotifyStruct,\r
1306         IN                              void                                            *context )\r
1307 {\r
1308         NTSTATUS                                                        status = STATUS_SUCCESS;\r
1309         DEVICE_OBJECT                                           *p_dev_obj;\r
1310         PFDO_DEVICE_DATA                                        p_fdo;\r
1311         TARGET_DEVICE_REMOVAL_NOTIFICATION      *pNotify;\r
1312 \r
1313         HCA_ENTER( HCA_DBG_PNP );\r
1314 \r
1315         pNotify = (TARGET_DEVICE_REMOVAL_NOTIFICATION*)pNotifyStruct;\r
1316         p_dev_obj = (DEVICE_OBJECT*)context;\r
1317         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
1318 \r
1319         if( IsEqualGUID( &pNotify->Event, &GUID_TARGET_DEVICE_QUERY_REMOVE ) )\r
1320         {\r
1321                 if ( p_fdo->state == HCA_REGISTERED) {\r
1322                         /* Release AL's CI interface. */\r
1323                         p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );\r
1324                         p_fdo->state = HCA_IFC_DEREFERENCED;\r
1325                 }\r
1326 \r
1327                 /* Release AL's file object so that it can unload. */\r
1328                 CL_ASSERT( p_fdo->p_al_dev );\r
1329                 CL_ASSERT( p_fdo->p_al_file_obj );\r
1330                 CL_ASSERT( p_fdo->p_al_file_obj == pNotify->FileObject );\r
1331                 if( p_fdo->p_al_file_obj ) {\r
1332                         ObDereferenceObject( p_fdo->p_al_file_obj );\r
1333                         p_fdo->p_al_file_obj = NULL;\r
1334                         p_fdo->p_al_dev = NULL;\r
1335                 }\r
1336         }\r
1337         else if( IsEqualGUID( &pNotify->Event, \r
1338                 &GUID_TARGET_DEVICE_REMOVE_COMPLETE ) )\r
1339         {\r
1340                 if (p_fdo->ci_ifc.deregister_ca) {\r
1341                         /* Notify AL that the CA is being removed. */\r
1342                         p_fdo->ci_ifc.deregister_ca( p_fdo->hca.guid );\r
1343                         p_fdo->ci_ifc.deregister_ca = NULL;\r
1344                 }\r
1345 \r
1346                 if ( p_fdo->state == HCA_REGISTERED) {\r
1347                         /* Release AL's CI interface. */\r
1348                         p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );\r
1349                 }\r
1350                 p_fdo->state = HCA_STARTED;\r
1351 \r
1352                 /* Release AL's file object so that it can unload. */\r
1353                 if( p_fdo->p_al_file_obj )\r
1354                 {\r
1355                         ObDereferenceObject( p_fdo->p_al_file_obj );\r
1356                         p_fdo->p_al_file_obj = NULL;\r
1357                         p_fdo->p_al_dev = NULL;\r
1358                 }\r
1359 \r
1360                 /* Cancel our target device change registration. */\r
1361                 if (p_fdo->pnp_target_entry) {\r
1362                         IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );\r
1363                         p_fdo->pnp_target_entry = NULL;\r
1364                 }\r
1365 \r
1366         }\r
1367         else if( IsEqualGUID( &pNotify->Event, \r
1368                 &GUID_TARGET_DEVICE_REMOVE_CANCELLED ) )\r
1369         {\r
1370                 /* Cancel our target device change registration. */\r
1371                 if (p_fdo->pnp_target_entry) {\r
1372                         IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );\r
1373                         p_fdo->pnp_target_entry = NULL;\r
1374                 }\r
1375 \r
1376                 /* Get the device object pointer for the AL. */\r
1377                 CL_ASSERT( !p_fdo->p_al_file_obj );\r
1378                 CL_ASSERT( !p_fdo->p_al_dev );\r
1379                 /* Get the AL device object. */\r
1380                 HCA_PRINT( TRACE_LEVEL_INFORMATION      ,HCA_DBG_SHIM  ,("Calling IoGetDeviceObjectPointer.\n"));\r
1381                 status = IoGetDeviceObjectPointer( &p_fdo->al_sym_name,\r
1382                         FILE_ALL_ACCESS, &p_fdo->p_al_file_obj, &p_fdo->p_al_dev );\r
1383                 if( !NT_SUCCESS( status ) )\r
1384                 {\r
1385                         HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_SHIM, \r
1386                                 ("IoGetDeviceObjectPointer returned %08x.\n", status ));\r
1387                         return STATUS_SUCCESS;\r
1388                 }\r
1389 \r
1390                 /* Register for removal notification of the IB Fabric root device. */\r
1391                 status = IoRegisterPlugPlayNotification( \r
1392                         EventCategoryTargetDeviceChange, 0, p_fdo->p_al_file_obj, \r
1393                         p_dev_obj->DriverObject, __pnp_notify_target, p_dev_obj, \r
1394                         &p_fdo->pnp_target_entry );\r
1395                 if( !NT_SUCCESS( status ) )\r
1396                 {\r
1397                         HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
1398                                 ("IoRegisterPlugPlayNotification returned %08x.\n", status));\r
1399                         return status;\r
1400                 }\r
1401 \r
1402                 CL_ASSERT( p_fdo->state == HCA_IFC_DEREFERENCED );\r
1403                 if ( p_fdo->state == HCA_IFC_DEREFERENCED) {\r
1404                         /* Release AL's CI interface. */\r
1405                         p_fdo->ci_ifc.wdm.InterfaceReference( p_fdo->ci_ifc.wdm.Context );\r
1406                         p_fdo->state = HCA_REGISTERED;\r
1407                 }\r
1408         }\r
1409 \r
1410         HCA_EXIT( HCA_DBG_PNP );\r
1411         return status;\r
1412 }\r
1413 \r
1414 static ci_interface_t*\r
1415 __alloc_hca_ifc(\r
1416         IN                              PFDO_DEVICE_DATA const          p_fdo )\r
1417 {\r
1418         ci_interface_t  *pIfc;\r
1419 \r
1420         HCA_ENTER( HCA_DBG_PNP );\r
1421 \r
1422         pIfc = (ci_interface_t*)ExAllocatePoolWithTag( PagedPool,\r
1423                 sizeof(ci_interface_t), MT_TAG_KERNEL );\r
1424         if( !pIfc )\r
1425         {\r
1426                 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP, \r
1427                         ("Failed to allocate ci_interface_t (%d bytes).\n",\r
1428                         sizeof(ci_interface_t)));\r
1429                 return NULL;\r
1430         }\r
1431 \r
1432         setup_ci_interface( p_fdo->hca.guid, !!hca_is_livefish(p_fdo), pIfc );\r
1433 \r
1434         pIfc->p_hca_dev = p_fdo->cl_ext.p_pdo;\r
1435         pIfc->vend_id = (uint32_t)p_fdo->bus_ib_ifc.pdev->ven_id;\r
1436         pIfc->dev_id = (uint16_t)p_fdo->bus_ib_ifc.pdev->dev_id;\r
1437         pIfc->dev_revision = (uint16_t)p_fdo->hca.hw_ver;\r
1438 \r
1439         HCA_EXIT( HCA_DBG_PNP );\r
1440         return pIfc;\r
1441 }\r
1442 \r
1443 static void\r
1444 __hca_deregister(\r
1445         IN                              PFDO_DEVICE_DATA                        p_fdo )\r
1446 {\r
1447         HCA_ENTER( HCA_DBG_PNP );\r
1448         \r
1449         if ( p_fdo->state == HCA_REGISTERED) {\r
1450                 if (p_fdo->ci_ifc.deregister_ca) {\r
1451                         /* Notify AL that the CA is being removed. */\r
1452                         p_fdo->ci_ifc.deregister_ca( p_fdo->hca.guid );\r
1453                         p_fdo->ci_ifc.deregister_ca = NULL;\r
1454                         /* Release AL's CI interface. */\r
1455                         p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );\r
1456                         p_fdo->state = HCA_STARTED;\r
1457                         HCA_PRINT( TRACE_LEVEL_INFORMATION      ,HCA_DBG_PNP,\r
1458                                 ("***** HCA deregistered \n"));\r
1459                 }\r
1460         }\r
1461 \r
1462         HCA_EXIT( HCA_DBG_PNP );\r
1463 }\r
1464 \r
1465 static NTSTATUS\r
1466 __hca_register(\r
1467         IN                              DEVICE_OBJECT                           *p_dev_obj )\r
1468 {\r
1469         PFDO_DEVICE_DATA                p_fdo;\r
1470         NTSTATUS                                status;\r
1471         ib_api_status_t                 ib_status;\r
1472         ci_interface_t                  *p_hca_ifc;\r
1473 \r
1474         HCA_ENTER( HCA_DBG_PNP );\r
1475         \r
1476         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
1477 \r
1478         ASSERT( p_fdo->state == HCA_STARTED );\r
1479         ASSERT( p_fdo->p_al_dev );\r
1480 \r
1481         /* Get the AL's lower interface. */\r
1482         status = __get_ci_interface( p_dev_obj );\r
1483         if( !NT_SUCCESS( status ) )\r
1484         {\r
1485                 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP, \r
1486                         ("__get_ci_interface returned %08x.\n", status));\r
1487                 goto exit;\r
1488         }\r
1489 \r
1490         /* Allocate and populate our HCA interface structure. */\r
1491         p_hca_ifc = __alloc_hca_ifc( p_fdo );\r
1492         if( !p_hca_ifc )\r
1493         {\r
1494                 HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_PNP  ,("__alloc_hca_ifc failed.\n"));\r
1495                 status = STATUS_NO_MEMORY;\r
1496                 goto exit;\r
1497         }\r
1498 \r
1499         /* Notify AL that we're available... */\r
1500         ib_status = p_fdo->ci_ifc.register_ca( p_hca_ifc );\r
1501         ExFreePool( p_hca_ifc );\r
1502         if( ib_status != IB_SUCCESS )\r
1503         {\r
1504                 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );\r
1505                 status = STATUS_INSUFFICIENT_RESOURCES;\r
1506                 goto exit;\r
1507         }\r
1508 \r
1509         p_fdo->state = HCA_REGISTERED;\r
1510         HCA_PRINT( TRACE_LEVEL_INFORMATION  ,HCA_DBG_PNP,\r
1511                 ("***** HCA registered \n"));\r
1512 exit:\r
1513         HCA_EXIT( HCA_DBG_PNP );\r
1514         return status;\r
1515 }\r
1516 \r
1517 \r
1518 static NTSTATUS\r
1519 __pnp_notify_ifc(\r
1520         IN                              void                                            *pNotifyStruct,\r
1521         IN                              void                                            *context )\r
1522 {\r
1523         NTSTATUS                                                                status = STATUS_SUCCESS;\r
1524         DEVICE_OBJECT                                                   *p_dev_obj;\r
1525         PFDO_DEVICE_DATA                                                p_fdo;\r
1526         DEVICE_INTERFACE_CHANGE_NOTIFICATION    *pNotify;\r
1527 \r
1528         HCA_ENTER( HCA_DBG_PNP );\r
1529 \r
1530         pNotify = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)pNotifyStruct;\r
1531         p_dev_obj = (DEVICE_OBJECT*)context;\r
1532         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
1533 \r
1534         if( !IsEqualGUID( &pNotify->Event, &GUID_DEVICE_INTERFACE_ARRIVAL ) )\r
1535                 goto done;\r
1536 \r
1537         /*\r
1538          * Sanity check.  We should only be getting notifications of the \r
1539          * CI interface exported by AL.\r
1540          */\r
1541         ASSERT( \r
1542                 IsEqualGUID( &pNotify->InterfaceClassGuid, &GUID_IB_CI_INTERFACE ) );\r
1543 \r
1544         if( p_fdo->state != HCA_STARTED )\r
1545         {\r
1546                 HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_PNP  ,("Invalid state: %d\n", p_fdo->state));\r
1547                 goto done;\r
1548         }\r
1549 \r
1550         /* save symbolic name of IBAL for a case of cancelled IBAL removal */\r
1551         if (!p_fdo->al_sym_name.Buffer) {\r
1552                 p_fdo->al_sym_name.Length = pNotify->SymbolicLinkName->Length;\r
1553                 p_fdo->al_sym_name.MaximumLength = pNotify->SymbolicLinkName->MaximumLength;\r
1554                 p_fdo->al_sym_name.Buffer = ExAllocatePoolWithTag( NonPagedPool, \r
1555                            p_fdo->al_sym_name.MaximumLength * sizeof(wchar_t),\r
1556                            'cfin' );\r
1557                 if (!p_fdo->al_sym_name.Buffer)\r
1558                 {\r
1559                         HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_PNP  ,("allocation of sym IBAL name failed.\n"));\r
1560                         goto done;\r
1561                 }\r
1562                 RtlCopyUnicodeString( &p_fdo->al_sym_name, pNotify->SymbolicLinkName );\r
1563         }\r
1564 \r
1565         ASSERT( !p_fdo->p_al_dev );\r
1566         ASSERT( !p_fdo->p_al_file_obj );\r
1567 \r
1568         /* Get the AL device object. */\r
1569         HCA_PRINT( TRACE_LEVEL_INFORMATION  ,HCA_DBG_PNP  ,("Calling IoGetDeviceObjectPointer.\n"));\r
1570         status = IoGetDeviceObjectPointer( pNotify->SymbolicLinkName,\r
1571                 FILE_ALL_ACCESS, &p_fdo->p_al_file_obj, &p_fdo->p_al_dev );\r
1572         if( !NT_SUCCESS( status ) )\r
1573         {\r
1574                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
1575                         ("IoGetDeviceObjectPointer returned %08x.\n", status ));\r
1576                 goto done;\r
1577         }\r
1578 \r
1579         /* Register for removal notification of the IB Fabric root device. */\r
1580         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, \r
1581                 ("Registering for target notifications.\n"));\r
1582         status = IoRegisterPlugPlayNotification( \r
1583                 EventCategoryTargetDeviceChange, 0, p_fdo->p_al_file_obj, \r
1584                 p_dev_obj->DriverObject, __pnp_notify_target, p_dev_obj, \r
1585                 &p_fdo->pnp_target_entry );\r
1586         if( !NT_SUCCESS( status ) )\r
1587         {\r
1588                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
1589                         ("IoRegisterPlugPlayNotification returned %08x.\n", status));\r
1590                 goto err_reg_notify;\r
1591         }\r
1592 \r
1593         status = __hca_register( p_dev_obj );\r
1594         if( !NT_SUCCESS( status ) )\r
1595         {\r
1596                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
1597                         ("__get_ci_interface returned %08x.\n", status));\r
1598                 goto err_reg_hca;\r
1599         }\r
1600         goto done;\r
1601         \r
1602 err_reg_hca:\r
1603         IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );\r
1604         p_fdo->pnp_target_entry = NULL;\r
1605 err_reg_notify:\r
1606         ObDereferenceObject( p_fdo->p_al_file_obj );\r
1607         p_fdo->p_al_file_obj = NULL;\r
1608         p_fdo->p_al_dev = NULL;\r
1609 done:\r
1610         HCA_EXIT( HCA_DBG_PNP );\r
1611         return status;\r
1612 }\r
1613 \r
1614 \r
1615 static void\r
1616 __unmap_hca_memory(\r
1617         IN                              PFDO_DEVICE_DATA const p_fdo )\r
1618 {\r
1619         struct pci_dev *pdev = p_fdo->bus_ib_ifc.pdev;\r
1620         int                             i;\r
1621 \r
1622         HCA_ENTER( HCA_DBG_PNP );\r
1623 \r
1624         if ( pdev )\r
1625                 for( i = 0; i < HCA_BAR_TYPE_MAX; i++ ) {\r
1626                         if (pdev->bar[i].virt) {\r
1627                                 MmUnmapIoSpace( pdev->bar[i].virt, pdev->bar[i].size );\r
1628                                 cl_memclr( &pdev->bar[i], sizeof(hca_bar_t) );\r
1629                         }\r
1630                 }\r
1631 \r
1632         HCA_EXIT( HCA_DBG_PNP );\r
1633 }\r
1634 \r
1635 \r
1636 /* release the resources, allocated in hca_start */\r
1637 static void\r
1638 __hca_release_resources(\r
1639         IN                              DEVICE_OBJECT* const            p_dev_obj )\r
1640 {\r
1641         PFDO_DEVICE_DATA                p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
1642 \r
1643         HCA_ENTER( HCA_DBG_PNP );\r
1644 \r
1645         switch( p_fdo->state )\r
1646         {\r
1647         case HCA_REGISTERED:\r
1648                 __hca_deregister( p_fdo );\r
1649 \r
1650                 /* Fall through. */\r
1651         case HCA_STARTED:\r
1652                 /* dequeue HCA  */\r
1653                 mlnx_hca_remove( &p_fdo->hca );\r
1654         }\r
1655 \r
1656         if (p_fdo->al_sym_name.Buffer) {\r
1657                 ExFreePool( p_fdo->al_sym_name.Buffer );\r
1658                 p_fdo->al_sym_name.Buffer = NULL;\r
1659         }\r
1660         \r
1661         if( p_fdo->pnp_target_entry )\r
1662         {\r
1663                 ASSERT( p_fdo->pnp_ifc_entry );\r
1664                 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );\r
1665                 p_fdo->pnp_target_entry = NULL;\r
1666         }\r
1667 \r
1668         if( p_fdo->pnp_ifc_entry ) {\r
1669                 IoUnregisterPlugPlayNotification( p_fdo->pnp_ifc_entry );\r
1670                 p_fdo->pnp_ifc_entry = NULL;\r
1671         }\r
1672 \r
1673         if( p_fdo->p_al_file_obj ) {\r
1674                 ObDereferenceObject( p_fdo->p_al_file_obj );\r
1675                 p_fdo->p_al_file_obj = NULL;\r
1676         }\r
1677 \r
1678         // release MLX4_BUS resources\r
1679         if(p_fdo->bus_ib_ifc_taken) {\r
1680                 p_fdo->bus_ib_ifc_taken = FALSE;\r
1681                 __put_ifc( (PINTERFACE)&p_fdo->bus_ib_ifc );\r
1682         }\r
1683 \r
1684         // release PCI BUS resources\r
1685         if(p_fdo->bus_pci_ifc_taken) {\r
1686                 p_fdo->bus_pci_ifc_taken = FALSE;\r
1687                 __put_ifc( (PINTERFACE)&p_fdo->bus_pci_ifc );\r
1688         }\r
1689 \r
1690         __unmap_hca_memory( p_fdo );\r
1691 \r
1692         p_fdo->state = HCA_ADDED;\r
1693 \r
1694         HCA_EXIT( HCA_DBG_PNP );\r
1695 }\r
1696 \r
1697 \r
1698 static void\r
1699 hca_release_resources(\r
1700         IN                              DEVICE_OBJECT* const            p_dev_obj )\r
1701 {\r
1702         PFDO_DEVICE_DATA                p_fdo;\r
1703         POWER_STATE             powerState;\r
1704 \r
1705         HCA_ENTER( HCA_DBG_PNP );\r
1706 \r
1707         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
1708 \r
1709         /* release all the resources, allocated in hca_start */\r
1710         __hca_release_resources(p_dev_obj);\r
1711 \r
1712         /* Notify the power manager that the device is powered down. */\r
1713         p_fdo->DevicePowerState = PowerDeviceD3;\r
1714         powerState.DeviceState = PowerDeviceD3;\r
1715         powerState = PoSetPowerState ( p_fdo->cl_ext.p_self_do, DevicePowerState, powerState );\r
1716 \r
1717         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, \r
1718                 ("PoSetPowerState: old state %d, new state to %d\n", \r
1719                 powerState.DeviceState, p_fdo->DevicePowerState ));\r
1720 \r
1721         /* Clear the PnP state in case we get restarted. */\r
1722         p_fdo->pnpState = 0;\r
1723 \r
1724         HCA_EXIT( HCA_DBG_PNP );\r
1725 }\r
1726 \r
1727 static NTSTATUS\r
1728 hca_start(\r
1729         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1730         IN                              IRP* const                                      p_irp, \r
1731                 OUT                     cl_irp_action_t* const          p_action )\r
1732 {\r
1733         int                                     err;\r
1734         NTSTATUS                        status;\r
1735         PFDO_DEVICE_DATA        p_fdo;\r
1736         IO_STACK_LOCATION       *pIoStack;\r
1737         POWER_STATE                     powerState;\r
1738         BUS_INTERFACE_STANDARD  bus_pci_ifc;\r
1739 \r
1740         HCA_ENTER( HCA_DBG_PNP );\r
1741 \r
1742         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
1743 \r
1744         /* Handled on the way up. */\r
1745         status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
1746         if( !NT_SUCCESS( status ) )\r
1747         {\r
1748                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
1749                         ("Lower drivers failed IRP_MN_START_DEVICE (%#x).\n", status));\r
1750                 goto end;\r
1751         }\r
1752 \r
1753         pIoStack = IoGetCurrentIrpStackLocation( p_irp );\r
1754 \r
1755         /* get PCI BUS interface */\r
1756         status = __get_ifc( p_dev_obj, &GUID_BUS_INTERFACE_STANDARD,\r
1757                 sizeof(BUS_INTERFACE_STANDARD), 1, NULL, (PINTERFACE)&bus_pci_ifc);\r
1758         if( !NT_SUCCESS( status ) ) {\r
1759                 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting PCI BUS interface failed: status=0x%x\n", status));\r
1760                 goto end;\r
1761         }\r
1762         RtlCopyMemory( &p_fdo->bus_pci_ifc, &bus_pci_ifc, sizeof(BUS_INTERFACE_STANDARD) );\r
1763         p_fdo->bus_pci_ifc_taken = TRUE;\r
1764         \r
1765         /* get MLX4_BUS IB interface */\r
1766         status = __get_ifc( p_dev_obj, &MLX4_BUS_IB_INTERFACE_GUID,\r
1767                 sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL, (PINTERFACE)&p_fdo->bus_ib_ifc);\r
1768         if( !NT_SUCCESS( status ) ) {\r
1769                 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));\r
1770                 goto end;\r
1771         }\r
1772         p_fdo->bus_ib_ifc_taken = TRUE;\r
1773         p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;\r
1774         \r
1775 \r
1776         /* get node GUID */\r
1777         err = __get_dev_info( p_fdo, &p_fdo->hca.guid, &p_fdo->hca.hw_ver );\r
1778         if (err) {\r
1779 \r
1780                 HCA_PRINT(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,\r
1781                         ("can't get guid - ib_query_device() failed (%08X)\n", err ));\r
1782                 //TODO: no cleanup on error\r
1783                 return STATUS_INSUFFICIENT_RESOURCES;\r
1784         }\r
1785 \r
1786         /* queue HCA  */\r
1787         mlnx_hca_insert( &p_fdo->hca );\r
1788 \r
1789         /*\r
1790          * Change the state since the PnP callback can happen\r
1791          * before the callback returns.\r
1792          */\r
1793         p_fdo->state = HCA_STARTED;\r
1794         \r
1795         /* Register for interface arrival of the IB_AL device. */\r
1796         status = IoRegisterPlugPlayNotification(\r
1797                 EventCategoryDeviceInterfaceChange,\r
1798                 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,\r
1799                 (void*)&GUID_IB_CI_INTERFACE, p_dev_obj->DriverObject,\r
1800                 __pnp_notify_ifc, p_dev_obj, &p_fdo->pnp_ifc_entry );\r
1801         if( !NT_SUCCESS( status ) )\r
1802         {\r
1803                 p_fdo->state = HCA_ADDED;\r
1804                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,\r
1805                         ("IoRegisterPlugPlayNotification returned %08x.\n", status));\r
1806         }\r
1807 \r
1808         /* We get started fully powered. */\r
1809         p_fdo->DevicePowerState = PowerDeviceD0;\r
1810         powerState.DeviceState = PowerDeviceD0;\r
1811         powerState = PoSetPowerState ( p_fdo->cl_ext.p_self_do, DevicePowerState, powerState );\r
1812         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, \r
1813                 ("PoSetPowerState: old state %d, new state to %d\n", \r
1814                 powerState.DeviceState, p_fdo->DevicePowerState ));\r
1815 \r
1816 end:\r
1817         HCA_EXIT( HCA_DBG_PNP );\r
1818         return status;\r
1819 }\r
1820 \r
1821 \r
1822 static NTSTATUS\r
1823 hca_query_removal_relations(\r
1824         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1825         IN                                      IRP* const                              p_irp, \r
1826                 OUT                             cl_irp_action_t* const  p_action )\r
1827 {\r
1828         NTSTATUS        status;\r
1829         PFDO_DEVICE_DATA        p_fdo;\r
1830 \r
1831         HCA_ENTER( HCA_DBG_PNP );\r
1832 \r
1833         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
1834 \r
1835         if( p_fdo->state == HCA_REGISTERED )\r
1836         {\r
1837                 status = p_fdo->ci_ifc.get_relations( p_fdo->hca.guid, p_irp );\r
1838                 if( !NT_SUCCESS( status ) )\r
1839                 {\r
1840                         *p_action = IrpComplete;\r
1841                         HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
1842                                 ("AL get_relations returned %08x.\n", status));\r
1843                         return status;\r
1844                 }\r
1845         }\r
1846 \r
1847         *p_action = IrpPassDown;\r
1848         HCA_EXIT( HCA_DBG_PNP );\r
1849         return STATUS_SUCCESS;\r
1850 }\r
1851 \r
1852 \r
1853 static NTSTATUS\r
1854 hca_query_bus_relations(\r
1855         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1856         IN                                      IRP* const                              p_irp, \r
1857                 OUT                             cl_irp_action_t* const  p_action )\r
1858 {\r
1859         NTSTATUS                        status;\r
1860         DEVICE_RELATIONS        *p_rel;\r
1861         PFDO_DEVICE_DATA        p_fdo;\r
1862 \r
1863         HCA_ENTER( HCA_DBG_PNP );\r
1864 \r
1865         p_fdo = p_dev_obj->DeviceExtension;\r
1866 \r
1867         //cl_event_wait_on( &p_fdo->mutex, EVENT_NO_TIMEOUT, FALSE );\r
1868         if( p_fdo->state == HCA_REGISTERED )\r
1869         {\r
1870                 status = p_fdo->ci_ifc.get_relations( p_fdo->hca.guid, p_irp );\r
1871                 if( !NT_SUCCESS( status ) )\r
1872                 {\r
1873                         //cl_event_signal( &p_fdo->mutex );\r
1874                         *p_action = IrpComplete;\r
1875                         HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
1876                                 ("AL get_relations returned %08x.\n", status));\r
1877                         return status;\r
1878                 }\r
1879         }\r
1880         else\r
1881         {\r
1882                 status = cl_alloc_relations( p_irp, 1 );\r
1883                 if( !NT_SUCCESS( status ) )\r
1884                 {\r
1885                         HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
1886                                 ("cl_alloc_relations returned %08x.\n", status));\r
1887                         return status;\r
1888                 }\r
1889 \r
1890                 p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
1891                 p_rel->Count = 0;\r
1892                 p_rel->Objects[0] = NULL;\r
1893         }\r
1894 \r
1895         //cl_event_signal( &p_fdo->mutex );\r
1896 \r
1897         *p_action = IrpPassDown;\r
1898         HCA_EXIT( HCA_DBG_PNP );\r
1899         return STATUS_SUCCESS;\r
1900 }\r
1901 \r
1902 \r
1903 static NTSTATUS\r
1904 hca_query_stop(\r
1905         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1906         IN                              IRP* const                                      p_irp, \r
1907                 OUT                     cl_irp_action_t* const          p_action )\r
1908 {\r
1909         /* All kernel clients will get notified through the device hierarchy. */\r
1910 \r
1911         /* TODO: set a flag to fail creation of any new IB resources. */\r
1912         return cl_irp_skip( p_dev_obj, p_irp, p_action );\r
1913 }\r
1914 \r
1915 \r
1916 static NTSTATUS\r
1917 hca_stop(\r
1918         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1919         IN                              IRP* const                                      p_irp, \r
1920                 OUT                     cl_irp_action_t* const          p_action )\r
1921 {\r
1922         /*\r
1923          * Must disable everything.  Complib framework will\r
1924          * call ReleaseResources handler.\r
1925          */\r
1926         return cl_irp_skip( p_dev_obj, p_irp, p_action );\r
1927 }\r
1928 \r
1929 \r
1930 static NTSTATUS\r
1931 hca_cancel_stop(\r
1932         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1933         IN                              IRP* const                                      p_irp, \r
1934                 OUT                     cl_irp_action_t* const          p_action )\r
1935 {\r
1936         /* Handled on the way up. */\r
1937         return cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
1938 }\r
1939 \r
1940 \r
1941 static NTSTATUS\r
1942 hca_query_remove(\r
1943         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1944         IN                              IRP* const                                      p_irp, \r
1945                 OUT                     cl_irp_action_t* const          p_action )\r
1946 {\r
1947         PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
1948         if (atomic_read(&p_fdo->usecnt)) {\r
1949                 DbgPrint( "MTHCA: Can't get unloaded. %d applications are still in work\n", p_fdo->usecnt);\r
1950                 p_irp->IoStatus.Status = STATUS_UNSUCCESSFUL;\r
1951                 return cl_irp_complete( p_dev_obj, p_irp, p_action );\r
1952         }\r
1953         /* TODO: set a flag to fail creation of any new IB resources. */\r
1954         return cl_irp_skip( p_dev_obj, p_irp, p_action );\r
1955 }\r
1956 \r
1957 \r
1958 static NTSTATUS\r
1959 hca_cancel_remove(\r
1960         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1961         IN                              IRP* const                                      p_irp, \r
1962                 OUT                     cl_irp_action_t* const          p_action )\r
1963 {\r
1964         /* Handled on the way up. */\r
1965         return cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
1966 }\r
1967 \r
1968 \r
1969 static NTSTATUS\r
1970 hca_surprise_remove(\r
1971         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1972         IN                              IRP* const                                      p_irp, \r
1973                 OUT                     cl_irp_action_t* const          p_action )\r
1974 {\r
1975         /*\r
1976          * TODO: Set state so that all further requests\r
1977          * automatically succeed/fail as needed.\r
1978          */\r
1979         return cl_irp_skip( p_dev_obj, p_irp, p_action );\r
1980 }\r
1981 \r
1982 \r
1983 static NTSTATUS\r
1984 hca_query_capabilities(\r
1985         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1986         IN                              IRP* const                                      p_irp, \r
1987                 OUT                     cl_irp_action_t* const          p_action )\r
1988 {\r
1989         NTSTATUS                        status;\r
1990         PFDO_DEVICE_DATA        p_fdo;\r
1991         IO_STACK_LOCATION       *pIoStack;\r
1992         DEVICE_CAPABILITIES     *pCaps;\r
1993 \r
1994         HCA_ENTER( HCA_DBG_PNP );\r
1995 \r
1996         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
1997 \r
1998         /* Process on the way up. */\r
1999         status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
2000         if( !NT_SUCCESS( status ) )\r
2001         {\r
2002                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
2003                         ("cl_do_sync_pnp returned %08X.\n", status));\r
2004                 return status;\r
2005         }\r
2006 \r
2007         pIoStack = IoGetCurrentIrpStackLocation( p_irp );\r
2008         pCaps = pIoStack->Parameters.DeviceCapabilities.Capabilities;\r
2009 \r
2010         /*\r
2011          * Store the device power mapping into our extension since we're\r
2012          * the power policy owner.  The mapping is used when handling\r
2013          * IRP_MN_SET_POWER IRPs.\r
2014          */\r
2015         cl_memcpy(\r
2016                 p_fdo->DevicePower, pCaps->DeviceState, sizeof(p_fdo->DevicePower) );\r
2017 \r
2018         if( pCaps->DeviceD1 )\r
2019         {\r
2020                 HCA_PRINT( TRACE_LEVEL_WARNING ,HCA_DBG_PNP,\r
2021                         ("WARNING: Device reports support for DeviceD1 power state.\n"));\r
2022                 pCaps->DeviceD1 = FALSE;\r
2023         }\r
2024 \r
2025         if( pCaps->DeviceD2 )\r
2026         {\r
2027                 HCA_PRINT( TRACE_LEVEL_WARNING,HCA_DBG_PNP,\r
2028                         ("WARNING: Device reports support for DeviceD2 power state.\n"));\r
2029                 pCaps->DeviceD2 = FALSE;\r
2030         }\r
2031 \r
2032         if( pCaps->SystemWake != PowerSystemUnspecified )\r
2033         {\r
2034                 HCA_PRINT( TRACE_LEVEL_WARNING ,HCA_DBG_PNP,\r
2035                         ("WARNING: Device reports support for system wake.\n"));\r
2036                 pCaps->SystemWake = PowerSystemUnspecified;\r
2037         }\r
2038 \r
2039         if( pCaps->DeviceWake != PowerDeviceUnspecified )\r
2040         {\r
2041                 HCA_PRINT( TRACE_LEVEL_WARNING, HCA_DBG_PNP,\r
2042                         ("WARNING: Device reports support for device wake.\n"));\r
2043                 pCaps->DeviceWake = PowerDeviceUnspecified;\r
2044         }\r
2045 \r
2046         HCA_EXIT( HCA_DBG_PNP );\r
2047         return status;\r
2048 }\r
2049 \r
2050 \r
2051 static NTSTATUS\r
2052 hca_query_pnp_state(\r
2053         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
2054         IN                              IRP* const                                      p_irp, \r
2055                 OUT                     cl_irp_action_t* const          p_action )\r
2056 {\r
2057         PFDO_DEVICE_DATA                p_fdo;\r
2058 \r
2059         HCA_ENTER( HCA_DBG_PNP );\r
2060 \r
2061         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
2062 \r
2063         p_irp->IoStatus.Information |= p_fdo->pnpState;\r
2064 \r
2065         *p_action = IrpSkip;\r
2066 \r
2067         HCA_EXIT( HCA_DBG_PNP );\r
2068         return STATUS_SUCCESS;;\r
2069 }\r
2070 \r
2071 static NTSTATUS\r
2072 hca_query_power(\r
2073         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
2074         IN                              IRP* const                                      p_irp,\r
2075                 OUT                     cl_irp_action_t* const          p_action )\r
2076 {\r
2077         NTSTATUS                        status = STATUS_SUCCESS;\r
2078         IO_STACK_LOCATION       *pIoStack;\r
2079 \r
2080         HCA_ENTER(HCA_DBG_PO);\r
2081 \r
2082         UNUSED_PARAM( p_dev_obj );\r
2083 \r
2084         pIoStack = IoGetCurrentIrpStackLocation( p_irp );\r
2085 \r
2086         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
2087                 ("QUERY_POWER for FDO %p: type %s, state %d, action %d, IRQL %d, IRP %p\n",\r
2088                 p_dev_obj, \r
2089                 (pIoStack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",\r
2090                 pIoStack->Parameters.Power.State.DeviceState, \r
2091                 pIoStack->Parameters.Power.ShutdownType, KeGetCurrentIrql(), p_irp ));\r
2092 \r
2093         switch( pIoStack->Parameters.Power.Type )\r
2094         {\r
2095         case SystemPowerState:\r
2096                 /* Fail any requests to hibernate or sleep the system. */\r
2097                 switch( pIoStack->Parameters.Power.State.SystemState )\r
2098                 {\r
2099                         case PowerSystemSleeping1:      // STANDBY support\r
2100                         case PowerSystemHibernate:\r
2101                         {\r
2102                                 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
2103                                 if (atomic_read(&p_fdo->usecnt)) \r
2104                                         status = STATUS_UNSUCCESSFUL;\r
2105                                 break;\r
2106                         }\r
2107 \r
2108                         case PowerSystemWorking:\r
2109                         case PowerSystemShutdown:\r
2110                                 break;\r
2111 \r
2112                         default:\r
2113                                 status = STATUS_NOT_SUPPORTED;\r
2114                 }\r
2115                 break;\r
2116 \r
2117         case DevicePowerState:\r
2118                 /* Fail any query for low power states. */\r
2119                 switch( pIoStack->Parameters.Power.State.DeviceState )\r
2120                 {\r
2121                 case PowerDeviceD0:\r
2122                 case PowerDeviceD3:\r
2123                         /* We only support fully powered or off power states. */\r
2124                         break;\r
2125 \r
2126                 default:\r
2127                         status = STATUS_NOT_SUPPORTED;\r
2128                 }\r
2129                 break;\r
2130         }\r
2131 \r
2132         if( status == STATUS_SUCCESS )\r
2133                 *p_action = IrpSkip;\r
2134         else\r
2135                 *p_action = IrpComplete;\r
2136 \r
2137         HCA_EXIT( HCA_DBG_PO );\r
2138         return status;\r
2139 }\r
2140 \r
2141 \r
2142 static void\r
2143 __RequestPowerCompletion(\r
2144         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
2145         IN                              UCHAR                                           minorFunction,\r
2146         IN                              POWER_STATE                                     powerState,\r
2147         IN                              void                                            *context,\r
2148         IN                              IO_STATUS_BLOCK                         *pIoStatus )\r
2149 {\r
2150         IRP                                     *p_irp;\r
2151         cl_pnp_po_ext_t         *p_fdo;\r
2152 \r
2153         HCA_ENTER( HCA_DBG_PO );\r
2154 \r
2155         UNUSED_PARAM( minorFunction );\r
2156         UNUSED_PARAM( powerState );\r
2157 \r
2158         p_irp = (IRP*)context;\r
2159         p_fdo = (cl_pnp_po_ext_t*)p_dev_obj->DeviceExtension;\r
2160 \r
2161         /* Propagate the device IRP status to the system IRP status. */\r
2162         p_irp->IoStatus.Status = pIoStatus->Status;\r
2163 \r
2164         /* Continue Power IRP processing. */\r
2165         PoStartNextPowerIrp( p_irp );\r
2166         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
2167         IoReleaseRemoveLock( &p_fdo->remove_lock, p_irp );\r
2168         HCA_EXIT( HCA_DBG_PO );\r
2169 }\r
2170 \r
2171 \r
2172 /*NOTE: Completion routines must NEVER be pageable. */\r
2173 static NTSTATUS\r
2174 __SystemPowerCompletion(\r
2175         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
2176         IN                              IRP                                                     *p_irp,\r
2177         IN                              void                                            *context )\r
2178 {\r
2179         NTSTATUS                        status;\r
2180         POWER_STATE                     state;\r
2181         PFDO_DEVICE_DATA        p_fdo;\r
2182         IO_STACK_LOCATION       *pIoStack;\r
2183 \r
2184         HCA_ENTER( HCA_DBG_PO );\r
2185 \r
2186         UNUSED_PARAM( context );\r
2187 \r
2188         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
2189         pIoStack = IoGetCurrentIrpStackLocation( p_irp );\r
2190 \r
2191         if( !NT_SUCCESS( p_irp->IoStatus.Status ) )\r
2192         {\r
2193                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO, \r
2194                         ("IRP_MN_SET_POWER for system failed by lower driver with %08x.\n",\r
2195                         p_irp->IoStatus.Status));\r
2196                 status = STATUS_SUCCESS;\r
2197                 PoStartNextPowerIrp( p_irp );\r
2198                 goto release;\r
2199         }\r
2200 \r
2201         state.DeviceState = \r
2202                 p_fdo->DevicePower[pIoStack->Parameters.Power.State.SystemState];\r
2203 \r
2204         /*\r
2205          * Send a device power IRP to our devnode.  Using our device object will\r
2206          * only work on win2k and other NT based systems.\r
2207          */\r
2208         status = PoRequestPowerIrp( p_dev_obj, IRP_MN_SET_POWER, state,\r
2209                 __RequestPowerCompletion, p_irp, NULL );\r
2210 \r
2211         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
2212                 ("PoRequestPowerIrp: SET_POWER 'PowerDeviceD%d', status %#x\n", \r
2213                 state.DeviceState - 1, status ));\r
2214 \r
2215         if( status != STATUS_PENDING ) {\r
2216                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,\r
2217                         ("PoRequestPowerIrp returned %08x.\n", status));\r
2218                 p_irp->IoStatus.Status = status;        /* Propagate the failure. */\r
2219                 PoStartNextPowerIrp( p_irp );\r
2220                 IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
2221                 goto release;\r
2222         }\r
2223 \r
2224         status = STATUS_MORE_PROCESSING_REQUIRED;\r
2225         goto exit;\r
2226 \r
2227 release:        \r
2228         IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );\r
2229 exit:\r
2230         HCA_EXIT( HCA_DBG_PO );\r
2231         return status;\r
2232 }\r
2233 \r
2234 \r
2235 /* Work item callback to handle DevicePowerD0 IRPs at passive level. */\r
2236 static void\r
2237 __DevicePowerUpCompletionWorkItem(\r
2238         IN                              DEVICE_OBJECT*                          p_dev_obj,\r
2239         IN                              void*                                           context )\r
2240 {\r
2241         int                                     err;\r
2242         NTSTATUS                        status;\r
2243         IO_STACK_LOCATION       *pIoStack;\r
2244         PFDO_DEVICE_DATA        p_fdo;\r
2245         IRP                                     *p_irp;\r
2246         POWER_STATE powerState;\r
2247 \r
2248         HCA_ENTER( HCA_DBG_PO );\r
2249 \r
2250         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
2251         p_irp = (IRP*)context;\r
2252         pIoStack = IoGetCurrentIrpStackLocation( p_irp );\r
2253 \r
2254         IoFreeWorkItem( p_fdo->pPoWorkItem );\r
2255         p_fdo->pPoWorkItem = NULL;\r
2256 \r
2257         /* restart the HCA */\r
2258         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
2259                 ("***** Restart the HCA, IRQL %d\n", KeGetCurrentIrql()));\r
2260 \r
2261         /* get MLX4_BUS IB interface */\r
2262         status = __get_ifc( p_dev_obj, &MLX4_BUS_IB_INTERFACE_GUID,\r
2263                 sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL, (PINTERFACE)&p_fdo->bus_ib_ifc);\r
2264         if( !NT_SUCCESS( status ) ) {\r
2265                 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));\r
2266                 goto err_hca_reg;\r
2267         }\r
2268         p_fdo->bus_ib_ifc_taken = TRUE;\r
2269         p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;\r
2270 \r
2271         /* get node GUID */\r
2272         err = __get_dev_info( p_fdo, &p_fdo->hca.guid, &p_fdo->hca.hw_ver );\r
2273         if (err) {\r
2274 \r
2275                 HCA_PRINT(TRACE_LEVEL_ERROR   ,HCA_DBG_LOW   ,\r
2276                         ("can't get guid - ib_query_device() failed (%08X)\n", err ));\r
2277                 //TODO: no cleanup on error\r
2278                 goto err_hca_reg;\r
2279         }\r
2280 \r
2281         if( p_fdo->p_al_dev ) {\r
2282                 status = __hca_register( p_dev_obj );\r
2283                 if( !NT_SUCCESS( status ) ) {\r
2284                         HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO, \r
2285                                 ("!!! __hca_register failed (%#x) \n", status));\r
2286                         goto err_hca_reg;\r
2287                 }\r
2288         }\r
2289 \r
2290         p_fdo->DevicePowerState = pIoStack->Parameters.Power.State.DeviceState;\r
2291         powerState = PoSetPowerState( p_dev_obj, DevicePowerState,\r
2292                 pIoStack->Parameters.Power.State );\r
2293 \r
2294         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
2295                 ("PoSetPowerState: old state %d, new state to %d\n", \r
2296                 powerState.DeviceState, p_fdo->DevicePowerState ));\r
2297 \r
2298         goto exit;\r
2299 \r
2300 err_hca_reg:\r
2301         /* Flag device as having failed. */\r
2302         p_fdo->pnpState |= PNP_DEVICE_FAILED;\r
2303         IoInvalidateDeviceState( p_fdo->cl_ext.p_pdo );\r
2304 exit:\r
2305         PoStartNextPowerIrp( p_irp );\r
2306         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
2307         IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );\r
2308         HCA_EXIT( HCA_DBG_PO );\r
2309 }\r
2310 \r
2311 /*NOTE: Completion routines must NEVER be pageable. */\r
2312 static NTSTATUS\r
2313 __DevicePowerUpCompletion(\r
2314         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
2315         IN                              IRP                                                     *p_irp,\r
2316         IN                              void                                            *context )\r
2317 {\r
2318         NTSTATUS                        status = STATUS_SUCCESS;\r
2319         PFDO_DEVICE_DATA        p_fdo;\r
2320         IO_STACK_LOCATION       *pIoStack;\r
2321 \r
2322         HCA_ENTER( HCA_DBG_PO );\r
2323 \r
2324         UNUSED_PARAM( context );\r
2325 \r
2326         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
2327         pIoStack = IoGetCurrentIrpStackLocation( p_irp );\r
2328 \r
2329         if( !NT_SUCCESS( p_irp->IoStatus.Status ) ) {\r
2330                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO, \r
2331                         ("IRP_MN_SET_POWER for device failed by lower driver with %08x.\n",\r
2332                         p_irp->IoStatus.Status));\r
2333                 status =  STATUS_SUCCESS;\r
2334                 PoStartNextPowerIrp( p_irp );\r
2335                 goto release;\r
2336         }\r
2337 \r
2338         /* Process in a work item - mthca_start blocks. */\r
2339         ASSERT( !p_fdo->pPoWorkItem );\r
2340         p_fdo->pPoWorkItem = IoAllocateWorkItem( p_dev_obj );\r
2341         if( !p_fdo->pPoWorkItem ) {\r
2342                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO, \r
2343                         ("Failed to allocate work item.\n" ));\r
2344                 status = STATUS_SUCCESS;\r
2345                 p_fdo->pnpState |= PNP_DEVICE_FAILED;\r
2346                 IoInvalidateDeviceState( p_fdo->cl_ext.p_pdo );\r
2347                 PoStartNextPowerIrp( p_irp );\r
2348                 goto release;\r
2349         }\r
2350 \r
2351         /* Process in work item callback. */\r
2352         IoMarkIrpPending( p_irp );\r
2353         IoQueueWorkItem( p_fdo->pPoWorkItem, \r
2354                 __DevicePowerUpCompletionWorkItem, DelayedWorkQueue, p_irp );\r
2355         status = STATUS_MORE_PROCESSING_REQUIRED;\r
2356         goto exit;\r
2357 \r
2358 release:        \r
2359         IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );\r
2360 exit:   \r
2361         HCA_EXIT( HCA_DBG_PO );\r
2362         return status;\r
2363 }\r
2364 \r
2365 static NTSTATUS __DevicePowerDownWorkItemCompletion(\r
2366         IN                              DEVICE_OBJECT   *p_dev_obj,\r
2367         IN                              IRP                             *p_irp,\r
2368         IN                              void                            *context )\r
2369 {\r
2370         PFDO_DEVICE_DATA  p_fdo  = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
2371         UNUSED_PARAM( context );\r
2372 \r
2373         HCA_ENTER( HCA_DBG_PO );\r
2374 \r
2375         PoStartNextPowerIrp( p_irp );\r
2376         IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );\r
2377 \r
2378         HCA_EXIT( HCA_DBG_PO );\r
2379         return STATUS_SUCCESS;\r
2380 }\r
2381 \r
2382 /* Work item callback to handle DevicePowerD3 IRPs at passive level. */\r
2383 static void\r
2384 __DevicePowerDownWorkItem(\r
2385         IN                              DEVICE_OBJECT*                          p_dev_obj,\r
2386         IN                              void*                                           context )\r
2387 {\r
2388         IO_STACK_LOCATION       *pIoStack;\r
2389         PFDO_DEVICE_DATA        p_fdo;\r
2390         IRP                                     *p_irp;\r
2391         POWER_STATE powerState;\r
2392 \r
2393         HCA_ENTER( HCA_DBG_PO );\r
2394 \r
2395         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
2396         p_irp = (IRP*)context;\r
2397         pIoStack = IoGetCurrentIrpStackLocation( p_irp );\r
2398 \r
2399         IoFreeWorkItem( p_fdo->pPoWorkItem );\r
2400         p_fdo->pPoWorkItem = NULL;\r
2401 \r
2402         p_fdo->DevicePowerState = pIoStack->Parameters.Power.State.DeviceState;\r
2403         powerState = PoSetPowerState( p_dev_obj, DevicePowerState,\r
2404                 pIoStack->Parameters.Power.State );\r
2405 \r
2406         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
2407                 ("PoSetPowerState: old state %d, new state to %d, IRQL %d\n", \r
2408                 powerState.DeviceState, p_fdo->DevicePowerState, KeGetCurrentIrql() ));\r
2409 \r
2410         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
2411                 ("***** Remove the HCA \n"));\r
2412 \r
2413         {\r
2414                 __hca_deregister( p_fdo );\r
2415 \r
2416                 // release MLX4_BUS resources\r
2417                 if(p_fdo->bus_ib_ifc_taken) {\r
2418                         p_fdo->bus_ib_ifc_taken = FALSE;\r
2419                         __put_ifc( (PINTERFACE)&p_fdo->bus_ib_ifc );\r
2420                 }\r
2421         }\r
2422 \r
2423         IoCopyCurrentIrpStackLocationToNext( p_irp );\r
2424 #pragma warning( push, 3 )\r
2425         IoSetCompletionRoutine( p_irp, __DevicePowerDownWorkItemCompletion,\r
2426                 NULL, TRUE, TRUE, TRUE );\r
2427 #pragma warning( pop )\r
2428         PoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );\r
2429 \r
2430         HCA_EXIT( HCA_DBG_PO );\r
2431 }\r
2432 \r
2433 \r
2434 static NTSTATUS\r
2435 hca_set_power(\r
2436         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
2437         IN                              IRP* const                                      p_irp,\r
2438                 OUT                     cl_irp_action_t* const          p_action )\r
2439 {\r
2440         NTSTATUS                        status;\r
2441         IO_STACK_LOCATION       *pIoStack;\r
2442         PFDO_DEVICE_DATA        p_fdo;\r
2443 \r
2444         HCA_ENTER( HCA_DBG_PO );\r
2445 \r
2446         p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;\r
2447         pIoStack = IoGetCurrentIrpStackLocation( p_irp );\r
2448 \r
2449         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
2450                 ("SET_POWER for FDO %p (ext %p): type %s, state %d, action %d, IRQL %d \n",\r
2451                 p_dev_obj, p_fdo,\r
2452                 (pIoStack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",\r
2453                 pIoStack->Parameters.Power.State.DeviceState, \r
2454                 pIoStack->Parameters.Power.ShutdownType, KeGetCurrentIrql() ));\r
2455 \r
2456         switch( pIoStack->Parameters.Power.Type )\r
2457         {\r
2458         case SystemPowerState:\r
2459                 p_fdo->SystemPowerState = pIoStack->Parameters.Power.State.SystemState;\r
2460                 \r
2461                 /*\r
2462                  * Process on the way up the stack.  We cannot block since the \r
2463                  * power dispatch function can be called at elevated IRQL if the\r
2464                  * device is in a paging/hibernation/crash dump path.\r
2465                  */\r
2466                 IoMarkIrpPending( p_irp );\r
2467                 IoCopyCurrentIrpStackLocationToNext( p_irp );\r
2468 #pragma warning( push, 3 )\r
2469                 IoSetCompletionRoutine( p_irp, __SystemPowerCompletion, NULL, \r
2470                         TRUE, TRUE, TRUE );\r
2471 #pragma warning( pop )\r
2472                 PoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );\r
2473 \r
2474                 *p_action = IrpDoNothing;\r
2475                 status = STATUS_PENDING;\r
2476                 break;\r
2477 \r
2478         case DevicePowerState:\r
2479                 IoMarkIrpPending( p_irp );\r
2480                 if( pIoStack->Parameters.Power.State.DeviceState == PowerDeviceD0 && \r
2481                         p_fdo->SystemPowerState == PowerSystemWorking)\r
2482                 { /* power up */\r
2483                         /* If we're already powered up, just pass down. */\r
2484                         if( p_fdo->DevicePowerState == PowerDeviceD0 )\r
2485                         {\r
2486                                 status = STATUS_SUCCESS;\r
2487                                 *p_action = IrpIgnore;\r
2488                                 break;\r
2489                         }\r
2490 \r
2491                         /* Process in I/O completion callback. */\r
2492                         IoCopyCurrentIrpStackLocationToNext( p_irp );\r
2493 #pragma warning( push, 3 )\r
2494                         IoSetCompletionRoutine( p_irp, __DevicePowerUpCompletion, NULL, \r
2495                                 TRUE, TRUE, TRUE );\r
2496 #pragma warning( pop )\r
2497                         PoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );\r
2498                 }\r
2499                 else\r
2500                 { /* power down */\r
2501 \r
2502                         /* Process in a work item - deregister_ca and HcaDeinit block. */\r
2503                         ASSERT( !p_fdo->pPoWorkItem );\r
2504                         p_fdo->pPoWorkItem = IoAllocateWorkItem( p_dev_obj );\r
2505                         if( !p_fdo->pPoWorkItem )\r
2506                         {\r
2507                                 status = STATUS_INSUFFICIENT_RESOURCES;\r
2508                                 break;\r
2509                         }\r
2510 \r
2511                         /* Process in work item callback. */\r
2512                         IoQueueWorkItem(\r
2513                                 p_fdo->pPoWorkItem, __DevicePowerDownWorkItem, DelayedWorkQueue, p_irp );\r
2514                 }\r
2515                 *p_action = IrpDoNothing;\r
2516                 status = STATUS_PENDING;\r
2517                 break;\r
2518 \r
2519         default:\r
2520                 /* Pass down and let the PDO driver handle it. */\r
2521                 *p_action = IrpIgnore;\r
2522                 status = STATUS_SUCCESS;\r
2523                 break;\r
2524         }\r
2525 \r
2526         if( !NT_SUCCESS( status ) )\r
2527                 *p_action = IrpComplete;\r
2528 \r
2529         HCA_EXIT( HCA_DBG_PNP );\r
2530         return status;\r
2531 }\r
2532 \r
2533 void\r
2534 hca_init_vfptr( void )\r
2535 {\r
2536         vfptrHcaPnp.identity = "MLX4_HCA driver";\r
2537         vfptrHcaPnp.pfn_start = hca_start;\r
2538         vfptrHcaPnp.pfn_query_stop = hca_query_stop;\r
2539         vfptrHcaPnp.pfn_stop = hca_stop;\r
2540         vfptrHcaPnp.pfn_cancel_stop = hca_cancel_stop;\r
2541         vfptrHcaPnp.pfn_query_remove = hca_query_remove;\r
2542         vfptrHcaPnp.pfn_release_resources = hca_release_resources;\r
2543         vfptrHcaPnp.pfn_remove = cl_do_remove;\r
2544         vfptrHcaPnp.pfn_cancel_remove = hca_cancel_remove;\r
2545         vfptrHcaPnp.pfn_surprise_remove = hca_surprise_remove;\r
2546         vfptrHcaPnp.pfn_query_capabilities = hca_query_capabilities;\r
2547         vfptrHcaPnp.pfn_query_pnp_state = hca_query_pnp_state;\r
2548         vfptrHcaPnp.pfn_filter_res_req = cl_irp_skip;\r
2549         vfptrHcaPnp.pfn_dev_usage_notification = cl_do_sync_pnp;\r
2550         vfptrHcaPnp.pfn_query_bus_relations = hca_query_bus_relations;\r
2551         vfptrHcaPnp.pfn_query_ejection_relations = cl_irp_ignore;\r
2552         vfptrHcaPnp.pfn_query_removal_relations = hca_query_removal_relations;\r
2553         vfptrHcaPnp.pfn_query_target_relations = cl_irp_ignore;\r
2554         vfptrHcaPnp.pfn_unknown = cl_irp_ignore;\r
2555         vfptrHcaPnp.pfn_query_resources = cl_irp_ignore;\r
2556         vfptrHcaPnp.pfn_query_res_req = cl_irp_ignore;\r
2557         vfptrHcaPnp.pfn_query_bus_info = cl_irp_ignore;\r
2558         vfptrHcaPnp.pfn_query_interface = cl_irp_ignore;\r
2559         vfptrHcaPnp.pfn_read_config = cl_irp_ignore;\r
2560         vfptrHcaPnp.pfn_write_config = cl_irp_ignore;\r
2561         vfptrHcaPnp.pfn_eject = cl_irp_ignore;\r
2562         vfptrHcaPnp.pfn_set_lock = cl_irp_ignore;\r
2563         vfptrHcaPnp.pfn_query_power = hca_query_power;\r
2564         vfptrHcaPnp.pfn_set_power = hca_set_power;\r
2565         vfptrHcaPnp.pfn_power_sequence = cl_irp_ignore;\r
2566         vfptrHcaPnp.pfn_wait_wake = cl_irp_ignore;\r
2567 }\r
2568 \r
2569 static NTSTATUS\r
2570 __read_registry(\r
2571         IN                              UNICODE_STRING* const   p_registry_path )\r
2572 {\r
2573         NTSTATUS                                        status;\r
2574         /* Remember the terminating entry in the table below. */\r
2575         RTL_QUERY_REGISTRY_TABLE        table[3];\r
2576 \r
2577         HCA_ENTER( HCA_DBG_PNP );\r
2578 \r
2579         RtlInitUnicodeString( &g_param_path, NULL );\r
2580         g_param_path.MaximumLength = p_registry_path->Length + \r
2581                 sizeof(L"\\Parameters");\r
2582         g_param_path.Buffer = cl_zalloc( g_param_path.MaximumLength );\r
2583         if( !g_param_path.Buffer )\r
2584         {\r
2585                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
2586                         ("Failed to allocate parameters path buffer.\n"));\r
2587                 return STATUS_INSUFFICIENT_RESOURCES;\r
2588         }\r
2589 \r
2590         RtlAppendUnicodeStringToString( &g_param_path, p_registry_path );\r
2591         RtlAppendUnicodeToString( &g_param_path, L"\\Parameters" );\r
2592 \r
2593         /*\r
2594          * Clear the table.  This clears all the query callback pointers,\r
2595          * and sets up the terminating table entry.\r
2596          */\r
2597         cl_memclr( table, sizeof(table) );\r
2598 \r
2599         /* Setup the table entries. */\r
2600         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
2601         table[0].Name = L"DebugLevel";\r
2602         table[0].EntryContext = &g.DebugPrintLevel;\r
2603         table[0].DefaultType = REG_DWORD;\r
2604         table[0].DefaultData = &g.DebugPrintLevel;\r
2605         table[0].DefaultLength = sizeof(ULONG);\r
2606 \r
2607         \r
2608         table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
2609         table[1].Name = L"DebugFlags";\r
2610         table[1].EntryContext = &g.DebugPrintFlags;\r
2611         table[1].DefaultType = REG_DWORD;\r
2612         table[1].DefaultData = &g.DebugPrintFlags;\r
2613         table[1].DefaultLength = sizeof(ULONG);\r
2614 \r
2615 \r
2616         /* Have at it! */\r
2617         status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
2618                 g_param_path.Buffer, table, NULL, NULL );\r
2619 \r
2620         HCA_EXIT( HCA_DBG_PNP );\r
2621         return status;\r
2622 }\r
2623 \r
2624 static void\r
2625 hca_drv_unload(\r
2626         IN                              PDRIVER_OBJECT                  p_driver_obj )\r
2627 {\r
2628         HCA_ENTER( HCA_DBG_PNP );\r
2629 \r
2630         UNUSED_PARAM( p_driver_obj );\r
2631 \r
2632         cl_free( g_param_path.Buffer );\r
2633         \r
2634         HCA_EXIT( HCA_DBG_PNP );\r
2635 #if defined(EVENT_TRACING)\r
2636         WPP_CLEANUP(p_driver_obj);\r
2637 #endif\r
2638 \r
2639 }\r
2640 \r
2641 static NTSTATUS\r
2642 hca_sysctl(\r
2643         IN                              PDEVICE_OBJECT                          p_dev_obj,\r
2644         IN                              PIRP                                            p_irp )\r
2645 {\r
2646         NTSTATUS                status;\r
2647         PFDO_DEVICE_DATA        p_fdo;\r
2648 \r
2649         HCA_ENTER( HCA_DBG_PNP );\r
2650 \r
2651         p_fdo = p_dev_obj->DeviceExtension;\r
2652 \r
2653         IoSkipCurrentIrpStackLocation( p_irp );\r
2654         status = IoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );\r
2655 \r
2656         HCA_EXIT( HCA_DBG_PNP );\r
2657         return status;\r
2658 }\r
2659 \r
2660 \r
2661 NTSTATUS\r
2662 DriverEntry(\r
2663         IN                              PDRIVER_OBJECT                  p_driver_obj,\r
2664         IN                              PUNICODE_STRING                 p_registry_path )\r
2665 {\r
2666         NTSTATUS                        status;\r
2667 #if defined(EVENT_TRACING)\r
2668         WPP_INIT_TRACING(p_driver_obj ,p_registry_path);\r
2669 #endif\r
2670         // global initializations\r
2671         g.DebugPrintLevel = TRACE_LEVEL_VERBOSE;\r
2672         g.DebugPrintFlags = 0xffff;\r
2673 \r
2674         HCA_ENTER( HCA_DBG_PNP );\r
2675         HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, \r
2676                 ("Built %s %s, Version %s, RelDate %s\n", \r
2677                 __DATE__, __TIME__, DRV_VERSION, DRV_RELDATE));\r
2678 \r
2679         status = mlnx_hcas_init();\r
2680         if( status  != STATUS_SUCCESS ) {\r
2681                 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,\r
2682                         ("mlnx_hcas_init returned %#x.\n", status));\r
2683                 goto end;\r
2684         }\r
2685 \r
2686         status = __read_registry( p_registry_path );\r
2687         if( !NT_SUCCESS( status ) )\r
2688         {\r
2689                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
2690                         ("__read_registry_path returned 0x%X.\n", status));\r
2691                 return status;\r
2692         }\r
2693 \r
2694         /*leo:  init function table */\r
2695         hca_init_vfptr();\r
2696         \r
2697         p_driver_obj->MajorFunction[IRP_MJ_PNP] = cl_pnp;\r
2698         p_driver_obj->MajorFunction[IRP_MJ_POWER] = cl_power;\r
2699         p_driver_obj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = hca_sysctl;\r
2700         p_driver_obj->DriverUnload = hca_drv_unload;\r
2701         p_driver_obj->DriverExtension->AddDevice = hca_add_device;\r
2702 \r
2703 end:\r
2704         HCA_EXIT( HCA_DBG_PNP );\r
2705         return STATUS_SUCCESS;\r
2706 }\r
2707 \r
2708 #endif\r