[IBBUS,IPoIB] add debug prints. [mlnx: 4838]
[mirror/winof/.git] / core / bus / kernel / bus_pnp.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
4  *\r
5  * This software is available to you under the OpenIB.org BSD license\r
6  * below:\r
7  *\r
8  *     Redistribution and use in source and binary forms, with or\r
9  *     without modification, are permitted provided that the following\r
10  *     conditions are met:\r
11  *\r
12  *      - Redistributions of source code must retain the above\r
13  *        copyright notice, this list of conditions and the following\r
14  *        disclaimer.\r
15  *\r
16  *      - Redistributions in binary form must reproduce the above\r
17  *        copyright notice, this list of conditions and the following\r
18  *        disclaimer in the documentation and/or other materials\r
19  *        provided with the distribution.\r
20  *\r
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
28  * SOFTWARE.\r
29  *\r
30  * $Id$\r
31  */\r
32 \r
33 \r
34 \r
35 /*\r
36  * Implemenation of all PnP functionality for FDO (power policy owners).\r
37  */\r
38 \r
39 #include "bus_pnp.h"\r
40 #include "al_ca.h"\r
41 #include "al_init.h"\r
42 #include "al_dev.h"\r
43 #include "al_debug.h"\r
44 #include "bus_port_mgr.h"\r
45 #include "bus_iou_mgr.h"\r
46 #include "complib/cl_memory.h"\r
47 #include <initguid.h>\r
48 #include "iba/ib_ci_ifc.h"\r
49 #include "iba/ib_cm_ifc.h"\r
50 #include "al_cm_cep.h"\r
51 #include "al_mgr.h"\r
52 #include "bus_ev_log.h"\r
53 \r
54 \r
55 /* Interface names are generated by IoRegisterDeviceInterface. */\r
56 static UNICODE_STRING   al_ifc_name;\r
57 static UNICODE_STRING   ci_ifc_name;\r
58 static UNICODE_STRING   cm_ifc_name;\r
59 \r
60 KEVENT                                  g_ControlEvent;\r
61 ULONG                                   g_bfi_InstanceCount;\r
62 bus_filter_t                    g_bus_filters[MAX_BUS_FILTERS];\r
63 \r
64 extern PDEVICE_OBJECT   g_ControlDeviceObject;\r
65 extern UNICODE_STRING   g_CDO_dev_name, g_CDO_dos_name;\r
66 \r
67 \r
68 static NTSTATUS\r
69 fdo_start(\r
70         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
71         IN                                      IRP* const                              p_irp, \r
72                 OUT                             cl_irp_action_t* const  p_action );\r
73 \r
74 static void\r
75 fdo_release_resources(\r
76         IN                                      DEVICE_OBJECT* const    p_dev_obj );\r
77 \r
78 static NTSTATUS\r
79 fdo_query_remove(\r
80         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
81         IN                                      IRP* const                              p_irp, \r
82                 OUT                             cl_irp_action_t* const  p_action );\r
83 \r
84 static NTSTATUS\r
85 fdo_query_capabilities(\r
86         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
87         IN                                      IRP* const                              p_irp, \r
88                 OUT                             cl_irp_action_t* const  p_action );\r
89 \r
90 static NTSTATUS\r
91 fdo_query_bus_relations(\r
92         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
93         IN                                      IRP* const                              p_irp, \r
94                 OUT                             cl_irp_action_t* const  p_action );\r
95 \r
96 static NTSTATUS\r
97 __query_al_ifc(\r
98         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
99         IN                              IO_STACK_LOCATION* const        p_io_stack );\r
100 \r
101 static NTSTATUS\r
102 __get_relations(\r
103         IN              const   net64_t                                         ca_guid,\r
104         IN                              IRP* const                                      p_irp );\r
105 \r
106 static NTSTATUS\r
107 __query_ci_ifc(\r
108         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
109         IN                              IO_STACK_LOCATION* const        p_io_stack );\r
110 \r
111 static NTSTATUS\r
112 __query_cm_ifc(\r
113         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
114         IN                              IO_STACK_LOCATION* const        p_io_stack );\r
115 \r
116 static NTSTATUS\r
117 fdo_query_pnp_state(\r
118         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
119         IN                              IRP* const                                      p_irp, \r
120                 OUT                     cl_irp_action_t* const          p_action );\r
121 \r
122 \r
123 static NTSTATUS\r
124 fdo_query_interface(\r
125         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
126         IN                              IRP* const                                      p_irp, \r
127                 OUT                     cl_irp_action_t* const          p_action );\r
128 \r
129 static NTSTATUS\r
130 __fdo_query_power(\r
131         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
132         IN                              IRP* const                                      p_irp,\r
133                 OUT                     cl_irp_action_t* const          p_action );\r
134 \r
135 static NTSTATUS\r
136 __fdo_set_power(\r
137         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
138         IN                              IRP* const                                      p_irp,\r
139                 OUT                     cl_irp_action_t* const          p_action );\r
140 \r
141 static void\r
142 __set_ifc(\r
143                 OUT                     ib_al_ifc_t* const                      p_ifc );\r
144 \r
145 \r
146 \r
147 \r
148 /* Global virtual function pointer tables shared between all instances of FDO. */\r
149 static const cl_vfptr_pnp_po_t          vfptr_fdo_pnp = {\r
150         "IB Bus",\r
151         fdo_start,\r
152         cl_irp_skip,\r
153         cl_irp_skip,\r
154         cl_do_sync_pnp,\r
155         fdo_query_remove,\r
156         fdo_release_resources,\r
157         cl_do_remove,\r
158         cl_do_sync_pnp,\r
159         cl_irp_skip,\r
160         fdo_query_capabilities,\r
161         fdo_query_pnp_state,\r
162         cl_irp_skip,\r
163         cl_do_sync_pnp,\r
164         fdo_query_bus_relations,\r
165         cl_irp_ignore,\r
166         cl_irp_skip,\r
167         cl_irp_ignore,\r
168         cl_irp_ignore,\r
169         cl_irp_ignore,\r
170         cl_irp_ignore,\r
171         cl_irp_ignore,\r
172         fdo_query_interface,    /* QueryInterface */\r
173         cl_irp_ignore,\r
174         cl_irp_ignore,\r
175         cl_irp_ignore,\r
176         cl_irp_ignore,\r
177         __fdo_query_power,              /* QueryPower */\r
178         __fdo_set_power,                /* SetPower */\r
179         cl_irp_ignore,                  /* PowerSequence */\r
180         cl_irp_ignore                   /* WaitWake */\r
181 };\r
182 \r
183 \r
184 NTSTATUS\r
185 bus_add_device(\r
186         IN                              DRIVER_OBJECT                           *p_driver_obj,\r
187         IN                              DEVICE_OBJECT                           *p_pdo )\r
188 {\r
189         NTSTATUS                status;\r
190         DEVICE_OBJECT   *p_dev_obj, *p_next_do;\r
191         bus_fdo_ext_t   *p_ext=NULL;\r
192         bus_filter_t    *p_bfi;\r
193         int                             ic;\r
194 \r
195         BUS_ENTER( BUS_DBG_PNP );\r
196 \r
197         /* allocate a Bus Filter Instance */\r
198         p_bfi = alloc_bfi( p_driver_obj, &ic );\r
199         if ( !p_bfi )\r
200         {\r
201                 BUS_TRACE_EXIT( BUS_DBG_PNP,\r
202                         ("%s() Err - Exceeded MAX_BUS_FILTERS(%d)\n",MAX_BUS_FILTERS));\r
203                 return STATUS_UNSUCCESSFUL;\r
204         }\r
205 \r
206         /* if 1st Bus Filter Instance, then create device names for user ioctl */\r
207         if ( ic == 1  && !g_ControlDeviceObject)\r
208         {\r
209                 RtlInitUnicodeString( &g_CDO_dev_name, AL_DEVICE_NAME );\r
210                 RtlInitUnicodeString( &g_CDO_dos_name, L"\\DosDevices\\Global\\ibal" );\r
211         \r
212                 status = IoCreateDevice( p_driver_obj, sizeof(bus_fdo_ext_t),\r
213                         &g_CDO_dev_name, FILE_DEVICE_BUS_EXTENDER,\r
214                         FILE_DEVICE_SECURE_OPEN, FALSE, &g_ControlDeviceObject );\r
215                 if( !NT_SUCCESS(status) )\r
216                 {\r
217                         g_ControlDeviceObject = NULL;\r
218                         BUS_PRINT( BUS_DBG_ERROR, \r
219                                 ("Failed to create ControlDeviceObject, status %x.\n",status) );\r
220                         goto err1;\r
221                 }\r
222                 else {\r
223                         p_ext = g_ControlDeviceObject->DeviceExtension;\r
224                         RtlZeroMemory(p_ext, sizeof *p_ext);\r
225                         cl_init_pnp_po_ext( g_ControlDeviceObject, NULL, \r
226                                                                 NULL, bus_globals.dbg_lvl, NULL, NULL );\r
227 \r
228                         /* enable user-mode access to IB stack */\r
229                         BUS_PRINT( BUS_DBG_PNP, ("Remove-n-reCreate dos_name symlink\n") );\r
230                         IoDeleteSymbolicLink( &g_CDO_dos_name );\r
231                         status = IoCreateSymbolicLink( &g_CDO_dos_name, &g_CDO_dev_name );\r
232                         if( !NT_SUCCESS(status) )\r
233                         {\r
234                                 BUS_PRINT( BUS_DBG_ERROR,\r
235                                         ("Failed to create symlink for dos name.\n") );\r
236                                 IoDeleteDevice( g_ControlDeviceObject );\r
237                                 g_ControlDeviceObject = NULL;\r
238                                 goto err1;\r
239                         }\r
240                         BUS_TRACE( BUS_DBG_PNP, ("Created dos_name symlink\n") );\r
241                 }\r
242         }\r
243 \r
244         /* Create the FDO device object to attach to the stack. */\r
245         status = IoCreateDevice( p_driver_obj, sizeof(bus_fdo_ext_t),\r
246                                                          NULL, FILE_DEVICE_BUS_EXTENDER,\r
247                                                          FILE_DEVICE_SECURE_OPEN, FALSE, &p_dev_obj );\r
248         if( !NT_SUCCESS(status) )\r
249         {\r
250                 BUS_PRINT( BUS_DBG_ERROR, \r
251                         ("Failed to create bus root FDO device.\n") );\r
252                 goto err1;\r
253         }\r
254 \r
255         p_ext = p_dev_obj->DeviceExtension;\r
256         cl_memclr( p_ext, sizeof(bus_fdo_ext_t) );\r
257 \r
258         p_next_do = IoAttachDeviceToDeviceStack( p_dev_obj, p_pdo );\r
259         if( !p_next_do )\r
260         {\r
261                 BUS_PRINT( BUS_DBG_ERROR, ("IoAttachToDeviceStack failed.\n") );\r
262                 status = STATUS_NO_SUCH_DEVICE;\r
263                 goto err2;\r
264         }\r
265 \r
266         cl_init_pnp_po_ext( p_dev_obj, p_next_do, p_pdo, bus_globals.dbg_lvl,\r
267                                                 &vfptr_fdo_pnp, NULL );\r
268 \r
269         p_bfi->p_bus_ext = p_ext;\r
270         p_ext->bus_filter = p_bfi;\r
271 \r
272         /*\r
273          * if not 1st Bus Filter Instance, then finished...\r
274          */\r
275         if ( ic > 1 )\r
276                 goto adxit;\r
277 \r
278         /* Register the upper interface (the one used by clients). */\r
279         status = IoRegisterDeviceInterface( p_pdo, &GUID_IB_AL_INTERFACE, NULL,\r
280                                                                                 &al_ifc_name );\r
281         if( !NT_SUCCESS( status ) )\r
282         {\r
283                 BUS_PRINT( BUS_DBG_ERROR, \r
284                         ("IoRegisterDeviceInterface for upper interface returned %08x\n",\r
285                         status) );\r
286                 status = STATUS_NO_SUCH_DEVICE;\r
287                 goto err3;\r
288         }\r
289 \r
290         /* Register the lower (CI) interface (the one used by HCA VPDs). */\r
291         status = IoRegisterDeviceInterface( p_pdo, &GUID_IB_CI_INTERFACE, NULL,\r
292                                                                                 &ci_ifc_name );\r
293         if( !NT_SUCCESS( status ) )\r
294         {\r
295                 BUS_PRINT( BUS_DBG_ERROR, \r
296                         ("IoRegisterDeviceInterface for lower interface returned %08x\n",\r
297                         status) );\r
298                 status = STATUS_NO_SUCH_DEVICE;\r
299                 goto err3;\r
300         }\r
301 \r
302         status = IoRegisterDeviceInterface( p_pdo, &GUID_INFINIBAND_INTERFACE_CM, NULL,\r
303                                                                                 &cm_ifc_name );\r
304         if( !NT_SUCCESS( status ) )\r
305         {\r
306                 BUS_PRINT( BUS_DBG_ERROR, \r
307                         ("IoRegisterDeviceInterface for cm interface returned %08x\n",\r
308                         status) );\r
309                 status = STATUS_NO_SUCH_DEVICE;\r
310                 goto err3;\r
311         }\r
312 \r
313 adxit:\r
314         BUS_PRINT( BUS_DBG_PNP, ("%s exit status 0\n", p_bfi->whoami) );\r
315 \r
316         BUS_EXIT( BUS_DBG_PNP );\r
317         return STATUS_SUCCESS;\r
318 \r
319 err3:\r
320         IoDetachDevice( p_ext->cl_ext.p_next_do );\r
321 err2:\r
322         IoDeleteDevice( p_dev_obj );\r
323 err1:\r
324         BUS_PRINT( BUS_DBG_PNP, ("%s exit status 0x%x\n", p_bfi->whoami,status) );\r
325         ic = free_bfi(p_bfi);\r
326         BUS_EXIT( BUS_DBG_PNP );\r
327         return status;\r
328 }\r
329 \r
330 \r
331 /* Forwards the request to the HCA's FDO. */\r
332 static NTSTATUS\r
333 __get_ifc(\r
334         IN                              DEVICE_OBJECT* const            pDevObj,\r
335         IN              const   GUID* const                                     pGuid,\r
336         IN                              USHORT                                          size,\r
337         IN                              USHORT                                          Version,\r
338         IN OUT                  PVOID                                           InterfaceSpecificData,\r
339                 OUT                     PINTERFACE                                      pHcaIfc )\r
340 {\r
341         NTSTATUS                        status;\r
342         IRP                                     *pIrp;\r
343         IO_STATUS_BLOCK         ioStatus;\r
344         IO_STACK_LOCATION       *pIoStack;\r
345         DEVICE_OBJECT           *pDev;\r
346         KEVENT                          event;\r
347 \r
348         BUS_ENTER( BUS_DBG_PNP );\r
349 \r
350         CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
351 \r
352         pDev = IoGetAttachedDeviceReference( pDevObj );\r
353 \r
354         KeInitializeEvent( &event, NotificationEvent, FALSE );\r
355 \r
356         /* Build the IRP for the HCA. */\r
357         pIrp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, pDev,\r
358                 NULL, 0, NULL, &event, &ioStatus );\r
359         if( !pIrp )\r
360         {\r
361                 ObDereferenceObject( pDev );\r
362                 BUS_PRINT( BUS_DBG_PNP, \r
363                         ("IoBuildSynchronousFsdRequest failed.\n"));\r
364                 return STATUS_INSUFFICIENT_RESOURCES;\r
365         }\r
366 \r
367         /* Copy the request query parameters. */\r
368         pIoStack = IoGetNextIrpStackLocation( pIrp );\r
369         pIoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
370         pIoStack->Parameters.QueryInterface.Size = size;\r
371         pIoStack->Parameters.QueryInterface.Version = Version;\r
372         pIoStack->Parameters.QueryInterface.InterfaceType = pGuid;\r
373         pIoStack->Parameters.QueryInterface.Interface = (INTERFACE*)pHcaIfc;\r
374         pIoStack->Parameters.QueryInterface.InterfaceSpecificData = InterfaceSpecificData;\r
375 \r
376         pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
377 \r
378         /* Send the IRP. */\r
379         status = IoCallDriver( pDev, pIrp );\r
380         if( status == STATUS_PENDING )\r
381         {\r
382                 KeWaitForSingleObject( &event, Executive, KernelMode,\r
383                         FALSE, NULL );\r
384 \r
385                 status = ioStatus.Status;\r
386         }\r
387         ObDereferenceObject( pDev );\r
388 \r
389         BUS_EXIT( BUS_DBG_PNP );\r
390         return status;\r
391 }\r
392 \r
393 \r
394 static NTSTATUS\r
395 __register_ca(\r
396         IN                                      DEVICE_OBJECT* const    p_dev_obj\r
397         )\r
398 {\r
399         NTSTATUS                status;\r
400         bus_fdo_ext_t   *p_ext;\r
401         ib_api_status_t ib_status;\r
402         bus_filter_t    *p_bfi;\r
403 \r
404         BUS_ENTER( BUS_DBG_PNP );\r
405 \r
406         p_ext = p_dev_obj->DeviceExtension;\r
407         p_bfi = p_ext->bus_filter;\r
408 \r
409         /* get HCA verbs interface */\r
410         status = __get_ifc( p_dev_obj, &GUID_RDMA_INTERFACE_VERBS,\r
411                                                 sizeof(RDMA_INTERFACE_VERBS), \r
412                                                 VerbsVersion(VERBS_MAJOR_VER, VERBS_MINOR_VER), \r
413                                                 p_ext, (PINTERFACE)&p_ext->hca_ifc );\r
414         if( !NT_SUCCESS( status ) ) \r
415         {\r
416                 BUS_TRACE_EXIT(BUS_DBG_PNP,\r
417                         ("Getting MLX4 BUS interface failed: status=0x%x\n", status));\r
418                 return STATUS_UNSUCCESSFUL;\r
419         }\r
420         p_ext->hca_ifc_taken = TRUE;\r
421 \r
422         /* bind BFI to HCA by CA GUID. Have to be before ib_register_ca */\r
423         p_bfi->ca_guid = p_ext->hca_ifc.Verbs.guid;\r
424 \r
425         /* register HCA */\r
426         ib_status = ib_register_ca( &p_ext->hca_ifc.Verbs, p_ext->cl_ext.p_pdo, p_dev_obj );\r
427         if( ib_status != IB_SUCCESS )\r
428         {\r
429                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("ib_register_ca returned %s.\n",\r
430                         ib_get_err_str(ib_status)) );\r
431                 return STATUS_UNSUCCESSFUL;\r
432         }\r
433         BUS_TRACE_EXIT(BUS_DBG_PNP, ("%s bound to CA guid %I64x\n",\r
434                 p_bfi->whoami,p_bfi->ca_guid));\r
435 \r
436         p_ext->ca_registered = TRUE;\r
437         return status;\r
438 }\r
439 \r
440 static NTSTATUS\r
441 fdo_start(\r
442         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
443         IN                                      IRP* const                              p_irp, \r
444                 OUT                             cl_irp_action_t* const  p_action )\r
445 {\r
446         NTSTATUS                status;\r
447         bus_fdo_ext_t   *p_ext;\r
448         ib_api_status_t ib_status;\r
449         bus_filter_t    *p_bfi;\r
450         boolean_t               AL_init_here = FALSE;\r
451 \r
452         BUS_ENTER( BUS_DBG_PNP );\r
453 \r
454         p_ext = p_dev_obj->DeviceExtension;\r
455         p_bfi = p_ext->bus_filter;\r
456         ASSERT( !p_ext->ca_registered );\r
457 \r
458         /* Handled on the way up. */\r
459         status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
460         if( !NT_SUCCESS( status ) )\r
461         {\r
462                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
463                         ("Lower drivers failed IRP_MN_START_DEVICE.\n") );\r
464                 return status;\r
465         }\r
466         p_ext->device_power_state = PowerDeviceD0;\r
467 \r
468         lock_control_event();\r
469         if ( !gp_async_proc_mgr ) {\r
470                 /* Initialize AL */\r
471                 ib_status = al_initialize();\r
472                 if( ib_status != IB_SUCCESS )\r
473                 {\r
474                         al_cleanup();\r
475                         BUS_TRACE_EXIT( BUS_DBG_ERROR, ("al_initialize returned %s.\n",\r
476                                                         ib_get_err_str(ib_status)) );\r
477                         unlock_control_event();\r
478                         return STATUS_UNSUCCESSFUL;\r
479                 }\r
480                 AL_init_here = TRUE;\r
481                 BUS_TRACE( BUS_DBG_PNP, ("AL initialized\n"));\r
482         }\r
483         unlock_control_event();\r
484 \r
485         /* Initialize the port manager. */\r
486         ib_status = create_port_mgr( p_ext->bus_filter );\r
487         if( ib_status != IB_SUCCESS )\r
488         {\r
489                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("create_port_mgr returned %s.\n",\r
490                         ib_get_err_str(ib_status)) );\r
491                 return STATUS_UNSUCCESSFUL;\r
492         }\r
493 \r
494         /* Initialize the IOU manager. */\r
495         ib_status = create_iou_mgr( p_ext->bus_filter );\r
496         if( ib_status != IB_SUCCESS )\r
497         {\r
498                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("create_iou_mgr returned %s.\n",\r
499                         ib_get_err_str(ib_status)) );\r
500                 return STATUS_UNSUCCESSFUL;\r
501         }\r
502 \r
503         /* start IBAL */\r
504         status = __register_ca( p_dev_obj );\r
505         if( !NT_SUCCESS( status ) )\r
506                 return status;\r
507 \r
508         if ( AL_init_here ) {\r
509                 status = IoSetDeviceInterfaceState( &al_ifc_name, TRUE );\r
510                 ASSERT( NT_SUCCESS( status ) );\r
511 \r
512                 status = IoSetDeviceInterfaceState( &ci_ifc_name, TRUE );\r
513                 ASSERT( NT_SUCCESS( status ) );\r
514 \r
515                 status = IoSetDeviceInterfaceState( &cm_ifc_name, TRUE );\r
516                 ASSERT( NT_SUCCESS( status ) );\r
517         }\r
518 \r
519         BUS_TRACE( BUS_DBG_DRV, \r
520                 ("IBBUS started \n") );\r
521         CL_PRINT_TO_EVENT_LOG( p_dev_obj, EVENT_IBBUS_ANY_INFO,\r
522                 ("IBBUS started \n" ));\r
523 \r
524         return status;\r
525 }\r
526 \r
527 \r
528 static NTSTATUS\r
529 fdo_query_remove(\r
530         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
531         IN                                      IRP* const                              p_irp, \r
532                 OUT                             cl_irp_action_t* const  p_action )\r
533 {\r
534         bus_fdo_ext_t   *p_ext;\r
535 \r
536         BUS_ENTER( BUS_DBG_PNP );\r
537 \r
538         p_ext = p_dev_obj->DeviceExtension;\r
539 \r
540         CL_ASSERT(p_ext->bus_filter);\r
541         BUS_PRINT( BUS_DBG_PNP,\r
542                 ("IRP_MN_QUERY_REMOVE_DEVICE %s @ FDO %p refs(CI %d AL %d)\n"\r
543                 "   %s CA %I64x\n", \r
544                 p_ext->cl_ext.vfptr_pnp_po->identity, p_ext, p_ext->n_ci_ifc_ref,\r
545                 p_ext->n_al_ifc_ref,\r
546                 p_ext->bus_filter->whoami, p_ext->bus_filter->ca_guid) );\r
547 \r
548         if( p_ext->n_ci_ifc_ref )\r
549         {\r
550                 /*\r
551                  * Our interface is still being held by someone.\r
552                  * Rollback the PnP state that was changed in the cl_ext handler.\r
553                  */\r
554                 cl_rollback_pnp_state( &p_ext->cl_ext );\r
555 \r
556                 /* Fail the query. */\r
557                 *p_action = IrpComplete;\r
558                 BUS_TRACE_EXIT( BUS_DBG_PNP, \r
559                         ("Failing IRP_MN_QUERY_REMOVE_DEVICE:\n"\r
560                         "\tLowerInterface has %d references\n", \r
561                         p_ext->n_ci_ifc_ref ) );\r
562                 return STATUS_UNSUCCESSFUL;\r
563         }\r
564 \r
565         /* remove port & iou managers */        \r
566         CL_ASSERT( p_ext->bus_filter );\r
567 \r
568         //TODO: Fail outstanding I/O operations.\r
569 \r
570         *p_action = IrpSkip;\r
571         /* The FDO driver must set the status even when passing down. */\r
572         p_irp->IoStatus.Status = STATUS_SUCCESS;\r
573 \r
574         BUS_EXIT( BUS_DBG_PNP );\r
575         return STATUS_SUCCESS;\r
576 }\r
577 \r
578 \r
579 static void\r
580 __deregister_ca(\r
581         IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
582 {\r
583         bus_fdo_ext_t   *p_ext;\r
584         bus_filter_t    *p_bfi;\r
585         ib_api_status_t ib_status;\r
586 \r
587         BUS_ENTER( BUS_DBG_PNP );\r
588 \r
589         p_ext = p_dev_obj->DeviceExtension;\r
590         p_bfi = p_ext->bus_filter;\r
591 \r
592         if ( !p_ext->ca_registered )\r
593                 return;\r
594         p_ext->ca_registered = FALSE;\r
595 \r
596         //TODO: Fail outstanding I/O operations.\r
597 \r
598         ib_status = ib_deregister_ca( p_ext->hca_ifc.Verbs.guid );\r
599         if( ib_status != IB_SUCCESS ) {\r
600                 BUS_PRINT( BUS_DBG_ERROR, ("ib_deregister_ca returned %s.\n",\r
601                         ib_get_err_str(ib_status)) );\r
602         }\r
603 \r
604         if ( p_ext->hca_ifc_taken ) {\r
605                 p_ext->hca_ifc.InterfaceHeader.InterfaceDereference(\r
606                         p_ext->hca_ifc.InterfaceHeader.Context);\r
607                 p_ext->hca_ifc_taken = FALSE;\r
608         }\r
609 \r
610         BUS_EXIT( BUS_DBG_PNP );\r
611 }\r
612 \r
613 /*\r
614  * This function gets called after releasing the remove lock and waiting\r
615  * for all other threads to release the lock.  No more modifications will\r
616  * occur to the PDO pointer vectors.\r
617  */\r
618 static void\r
619 fdo_release_resources(\r
620         IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
621 {\r
622         bus_fdo_ext_t   *p_ext;\r
623         NTSTATUS                status;\r
624         bus_filter_t    *p_bfi;\r
625         int                             ic;\r
626 \r
627         BUS_ENTER( BUS_DBG_PNP );\r
628 \r
629         p_ext = p_dev_obj->DeviceExtension;\r
630         ic = get_bfi_count();\r
631 \r
632         p_bfi = p_ext->bus_filter;\r
633         CL_ASSERT( p_bfi );\r
634 \r
635         __deregister_ca( p_dev_obj );\r
636 \r
637         if ( p_bfi->p_port_mgr )\r
638                 cl_obj_destroy( p_bfi->p_port_mgr_obj );\r
639 \r
640         if ( p_bfi->p_iou_mgr )\r
641                 cl_obj_destroy( p_bfi->p_iou_mgr_obj );\r
642 \r
643 #if 0\r
644         // IBAL has no right to work with CA after it deregister.\r
645         // So there is no need to release interface only after IBAL cleanup\r
646 \r
647         /* if not last HCA then release IFC reference, otherwise release IFC after\r
648          * IBAL has shutdown; keep the HCA present until IBAL is terminated.\r
649          */\r
650         if ( ic > 1 && p_ext->hca_ifc_taken ) {\r
651                 p_ext->hca_ifc.InterfaceHeader.InterfaceDereference(\r
652                         p_ext->hca_ifc.InterfaceHeader.Context);\r
653                 p_ext->hca_ifc_taken = FALSE;\r
654         }\r
655 #endif  \r
656 \r
657         BUS_TRACE( BUS_DBG_PNP, ("Releasing BusFilter %s\n", p_bfi->whoami ));\r
658         if (p_bfi) {\r
659                 p_ext->bus_filter = NULL;\r
660                 p_bfi->p_bus_ext = NULL;\r
661         }\r
662 \r
663         ic = free_bfi( p_bfi );\r
664 \r
665         /* if not last Buf Filter Instance, then exit, otherwise cleanup/shutdown */\r
666         if ( ic > 0 ) {\r
667                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("%d remaining BusFilters\n", ic ));\r
668                 return;\r
669         }\r
670 \r
671         if (g_ControlDeviceObject)\r
672         {\r
673                 IoDeleteSymbolicLink( &g_CDO_dos_name );\r
674                 IoDeleteDevice(g_ControlDeviceObject);\r
675                 g_ControlDeviceObject = NULL; \r
676         }\r
677 \r
678         /* Disable any exported interfaces. */\r
679         status = IoSetDeviceInterfaceState( &al_ifc_name, FALSE );\r
680         ASSERT( NT_SUCCESS( status ) );\r
681         status = IoSetDeviceInterfaceState( &ci_ifc_name, FALSE );\r
682         ASSERT( NT_SUCCESS( status ) );\r
683         status = IoSetDeviceInterfaceState( &cm_ifc_name, FALSE );\r
684         ASSERT( NT_SUCCESS( status ) );\r
685 \r
686         /* Release the memory allocated for the interface symbolic names. */\r
687         RtlFreeUnicodeString( &cm_ifc_name );\r
688         RtlFreeUnicodeString( &ci_ifc_name );\r
689         RtlFreeUnicodeString( &al_ifc_name );\r
690 \r
691         al_cleanup();\r
692         cl_thread_suspend(50);  /* allow time for AL's async procs to run to exit */\r
693 \r
694         CL_ASSERT( !gp_async_proc_mgr && !gp_async_pnp_mgr && !gp_al_mgr );\r
695 \r
696 #if 0\r
697                 // IBAL has no right to work with CA after it deregister.\r
698                 // So there is no need to release interface only after IBAL cleanup\r
699         \r
700         /* AL needs the HCA to stick around until AL cleanup has completed.\r
701          * Now that it's done, let the HCA fade away.\r
702          */\r
703         if ( p_ext->hca_ifc_taken ) {\r
704                 p_ext->hca_ifc.InterfaceHeader.InterfaceDereference(\r
705                         p_ext->hca_ifc.InterfaceHeader.Context);\r
706                 p_ext->hca_ifc_taken = FALSE;\r
707         }\r
708 #endif  \r
709 \r
710         BUS_TRACE_EXIT( BUS_DBG_PNP, \r
711                 ("=====> IBBUS: fdo_release_resources exited \n") );\r
712 }\r
713 \r
714 \r
715 static NTSTATUS\r
716 fdo_query_capabilities(\r
717         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
718         IN                                      IRP* const                              p_irp, \r
719                 OUT                             cl_irp_action_t* const  p_action )\r
720 {\r
721         NTSTATUS                        status;\r
722         bus_fdo_ext_t           *p_ext;\r
723         IO_STACK_LOCATION       *p_io_stack;\r
724 \r
725         BUS_ENTER( BUS_DBG_PNP );\r
726 \r
727         p_ext = p_dev_obj->DeviceExtension;\r
728 \r
729         /* Process on the way up. */\r
730         status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
731 \r
732         if( !NT_SUCCESS( status ) )\r
733         {\r
734                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
735                         ("cl_do_sync_pnp returned %08x.\n", status) );\r
736                 return status;\r
737         }\r
738 \r
739         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
740 \r
741         /*\r
742          * Store the device power maping into our extension since we're\r
743          * the power policy owner.  The mapping is used when handling\r
744          * IRP_MN_SET_POWER IRPs.\r
745          */\r
746         cl_memcpy( p_ext->po_state, \r
747                 p_io_stack->Parameters.DeviceCapabilities.Capabilities->DeviceState,\r
748                 sizeof( p_ext->po_state ) );\r
749 \r
750         BUS_EXIT( BUS_DBG_PNP );\r
751         return status;\r
752 }\r
753 \r
754 \r
755 static NTSTATUS\r
756 fdo_query_bus_relations(\r
757         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
758         IN                                      IRP* const                              p_irp, \r
759                 OUT                             cl_irp_action_t* const  p_action )\r
760 {\r
761         NTSTATUS                        status = STATUS_SUCCESS; /*default to success*/\r
762         bus_fdo_ext_t           *p_ext;\r
763         bus_filter_t            *p_bfi;\r
764         int                                     waitLoop = 0;\r
765 \r
766         BUS_ENTER( BUS_DBG_PNP );\r
767 \r
768         p_ext = p_dev_obj->DeviceExtension;\r
769 \r
770         if ( !p_ext->bus_filter )\r
771         {\r
772                 /* BFI has already been released */\r
773                 *p_action = IrpComplete;\r
774                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("NULL BFI\n") );\r
775                 return STATUS_SUCCESS;\r
776         }\r
777 \r
778         p_bfi = p_ext->bus_filter;\r
779         CL_ASSERT( p_bfi->magic == BFI_MAGIC );\r
780 \r
781         while ( p_bfi->ca_guid == 0ULL )\r
782         {\r
783                 /* HCA not yet bound to a BFI slot (no PNP ADD event seen), no bus\r
784                  * relations yet.\r
785                  */\r
786                 BUS_PRINT(BUS_DBG_ERROR, ("%s ca_guid %I64x\n",p_bfi->whoami,\r
787                                                                 p_bfi->ca_guid));\r
788                 cl_thread_suspend( 100 );       /* suspend for 100 ms */\r
789                 waitLoop++;\r
790                 if(waitLoop>50) break;\r
791         }\r
792         if ( p_bfi->ca_guid != 0ULL )\r
793         {\r
794                 status = port_mgr_get_bus_relations( p_bfi->ca_guid, p_irp );\r
795                 if( status == STATUS_SUCCESS || \r
796                         status == STATUS_NO_SUCH_DEVICE )\r
797                 {\r
798                         status = iou_mgr_get_bus_relations( p_bfi->ca_guid, p_irp );\r
799                 }\r
800                 if( status == STATUS_NO_SUCH_DEVICE )\r
801                         status = STATUS_SUCCESS;\r
802         }\r
803 \r
804         switch( status )\r
805         {\r
806         case STATUS_NO_SUCH_DEVICE:\r
807                 *p_action = IrpSkip;\r
808                 status = STATUS_SUCCESS;\r
809                 break;\r
810 \r
811         case STATUS_SUCCESS:\r
812                 *p_action = IrpPassDown;\r
813                 break;\r
814 \r
815         default:\r
816                 *p_action = IrpComplete;\r
817                 break;\r
818         }\r
819 \r
820         BUS_EXIT( BUS_DBG_PNP );\r
821         return status;\r
822 }\r
823 \r
824 \r
825 void\r
826 al_ref_ifc(\r
827         IN                              DEVICE_OBJECT*                          p_dev_obj )\r
828 {\r
829         bus_fdo_ext_t   *p_ext;\r
830 \r
831         BUS_ENTER( BUS_DBG_PNP );\r
832 \r
833         p_ext = p_dev_obj->DeviceExtension;\r
834 \r
835         CL_ASSERT( p_ext->n_al_ifc_ref >= 0 );\r
836 \r
837         cl_atomic_inc( &p_ext->n_al_ifc_ref );\r
838         ObReferenceObject( p_dev_obj );\r
839 \r
840         BUS_EXIT( BUS_DBG_PNP );\r
841 }\r
842 \r
843 \r
844 void\r
845 al_deref_ifc(\r
846         IN                              DEVICE_OBJECT*                          p_dev_obj )\r
847 {\r
848         bus_fdo_ext_t   *p_ext;\r
849 \r
850         BUS_ENTER( BUS_DBG_PNP );\r
851 \r
852         p_ext = p_dev_obj->DeviceExtension;\r
853 \r
854         CL_ASSERT( p_ext->n_al_ifc_ref > 0 );\r
855         cl_atomic_dec( &p_ext->n_al_ifc_ref );\r
856         ObDereferenceObject( p_dev_obj );\r
857 \r
858         BUS_EXIT( BUS_DBG_PNP );\r
859 }\r
860 \r
861 \r
862 void\r
863 al_ref_ci_ifc(\r
864         IN                              DEVICE_OBJECT*                          p_dev_obj )\r
865 {\r
866         bus_fdo_ext_t   *p_ext;\r
867 \r
868         BUS_ENTER( BUS_DBG_PNP );\r
869 \r
870         p_ext = p_dev_obj->DeviceExtension;\r
871 \r
872         CL_ASSERT( p_ext->n_ci_ifc_ref >= 0 );\r
873         cl_atomic_inc( &p_ext->n_ci_ifc_ref );\r
874         ObReferenceObject( p_dev_obj );\r
875 \r
876         BUS_EXIT( BUS_DBG_PNP );\r
877 }\r
878 \r
879 \r
880 void\r
881 al_deref_ci_ifc(\r
882         IN                              DEVICE_OBJECT*                          p_dev_obj )\r
883 {\r
884         bus_fdo_ext_t   *p_ext;\r
885 \r
886         BUS_ENTER( BUS_DBG_PNP );\r
887 \r
888         p_ext = p_dev_obj->DeviceExtension;\r
889 \r
890         CL_ASSERT( p_ext->n_ci_ifc_ref > 0 );\r
891 \r
892         cl_atomic_dec( &p_ext->n_ci_ifc_ref );\r
893         ObDereferenceObject( p_dev_obj );\r
894 \r
895 \r
896         BUS_EXIT( BUS_DBG_PNP );\r
897 }\r
898 \r
899 \r
900 static NTSTATUS\r
901 __query_al_ifc(\r
902         IN                                      DEVICE_OBJECT* const            p_dev_obj,\r
903         IN                                      IO_STACK_LOCATION* const        p_io_stack )\r
904 {\r
905         ib_al_ifc_t             *p_ifc;\r
906 \r
907         BUS_ENTER( BUS_DBG_PNP );\r
908 \r
909         if( p_io_stack->Parameters.QueryInterface.Version != \r
910                 AL_INTERFACE_VERSION )\r
911         {\r
912                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Incorrect interface version (%d)\n",\r
913                         p_io_stack->Parameters.QueryInterface.Version ) );\r
914                 return STATUS_NOT_SUPPORTED;\r
915         }\r
916 \r
917         if( p_io_stack->Parameters.QueryInterface.Size < sizeof(ib_al_ifc_t) )\r
918         {\r
919                 BUS_TRACE_EXIT( BUS_DBG_PNP, \r
920                         ("Buffer too small (%d given, %d required).\n",\r
921                         p_io_stack->Parameters.QueryInterface.Size, sizeof(ib_al_ifc_t)) );\r
922                 return STATUS_BUFFER_TOO_SMALL;\r
923         }\r
924 \r
925         // Copy the interface.\r
926         p_ifc = (ib_al_ifc_t*)p_io_stack->Parameters.QueryInterface.Interface;\r
927 \r
928         p_ifc->wdm.Size = sizeof(ib_al_ifc_t);\r
929         p_ifc->wdm.Version = AL_INTERFACE_VERSION;\r
930         p_ifc->wdm.Context = p_dev_obj;\r
931         p_ifc->wdm.InterfaceReference = al_ref_ifc;\r
932         p_ifc->wdm.InterfaceDereference = al_deref_ifc;\r
933 \r
934         __set_ifc( p_ifc );\r
935 \r
936         // take the reference before returning.\r
937         al_ref_ifc( p_dev_obj );\r
938         BUS_EXIT( BUS_DBG_PNP );\r
939         return STATUS_SUCCESS;\r
940 }\r
941 \r
942 static void\r
943 __set_ifc(\r
944                 OUT                     ib_al_ifc_t* const                      p_ifc )\r
945 {\r
946         BUS_ENTER( BUS_DBG_PNP );\r
947 \r
948         p_ifc->wdm.Size = sizeof(ib_al_ifc_t);\r
949         p_ifc->wdm.InterfaceReference = al_ref_ifc;\r
950         p_ifc->wdm.InterfaceDereference = al_deref_ifc;\r
951 \r
952         p_ifc->sync_destroy = ib_sync_destroy;\r
953         p_ifc->open_ca = ib_open_ca;\r
954         p_ifc->query_ca = ib_query_ca;\r
955         p_ifc->get_dev = get_ca_dev;\r
956         p_ifc->close_ca = ib_close_ca;\r
957         p_ifc->alloc_pd = ib_alloc_pd;\r
958         p_ifc->dealloc_pd = ib_dealloc_pd;\r
959         p_ifc->create_av = ib_create_av;\r
960         p_ifc->query_av = ib_query_av;\r
961         p_ifc->modify_av = ib_modify_av;\r
962         p_ifc->destroy_av = ib_destroy_av;\r
963         p_ifc->create_qp = ib_create_qp;\r
964         p_ifc->get_spl_qp = ib_get_spl_qp;\r
965         p_ifc->query_qp = ib_query_qp;\r
966         p_ifc->modify_qp = ib_modify_qp;\r
967         p_ifc->destroy_qp = ib_destroy_qp;\r
968         p_ifc->create_cq = ib_create_cq;\r
969         p_ifc->modify_cq = ib_modify_cq;\r
970         p_ifc->query_cq = ib_query_cq;\r
971         p_ifc->destroy_cq = ib_destroy_cq;\r
972         p_ifc->reg_mem = ib_reg_mem;\r
973         p_ifc->reg_phys = ib_reg_phys;\r
974         p_ifc->query_mr = ib_query_mr;\r
975         p_ifc->rereg_mem = ib_rereg_mem;\r
976         p_ifc->reg_shmid = ib_reg_shmid;\r
977         p_ifc->dereg_mr = ib_dereg_mr;\r
978         p_ifc->create_mw = ib_create_mw;\r
979         p_ifc->query_mw = ib_query_mw;\r
980         p_ifc->bind_mw = ib_bind_mw;\r
981         p_ifc->destroy_mw = ib_destroy_mw;\r
982         p_ifc->post_send = ib_post_send;\r
983         p_ifc->post_recv = ib_post_recv;\r
984         p_ifc->send_mad = ib_send_mad;\r
985         p_ifc->cancel_mad = ib_cancel_mad;\r
986         p_ifc->poll_cq = ib_poll_cq;\r
987         p_ifc->rearm_cq = ib_rearm_cq;\r
988         p_ifc->join_mcast = ib_join_mcast;\r
989         p_ifc->leave_mcast = ib_leave_mcast;\r
990         p_ifc->local_mad = ib_local_mad;\r
991         p_ifc->cm_listen = ib_cm_listen;\r
992         p_ifc->cm_cancel = ib_cm_cancel;\r
993         p_ifc->cm_req = ib_cm_req;\r
994         p_ifc->cm_rep = ib_cm_rep;\r
995         p_ifc->cm_rtu = ib_cm_rtu;\r
996         p_ifc->cm_rej = ib_cm_rej;\r
997         p_ifc->cm_mra = ib_cm_mra;\r
998         p_ifc->cm_lap = ib_cm_lap;\r
999         p_ifc->cm_apr = ib_cm_apr;\r
1000         p_ifc->force_apm = ib_force_apm;\r
1001         p_ifc->cm_dreq = ib_cm_dreq;\r
1002         p_ifc->cm_drep = ib_cm_drep;\r
1003         p_ifc->cm_handoff = ib_cm_handoff;\r
1004         p_ifc->create_ioc = ib_create_ioc;\r
1005         p_ifc->destroy_ioc = ib_destroy_ioc;\r
1006         p_ifc->reg_ioc = ib_reg_ioc;\r
1007         p_ifc->add_svc_entry = ib_add_svc_entry;\r
1008         p_ifc->remove_svc_entry = ib_remove_svc_entry;\r
1009         p_ifc->get_ca_guids = ib_get_ca_guids;\r
1010         p_ifc->get_ca_by_gid = ib_get_ca_by_gid;\r
1011         p_ifc->get_port_by_gid = ib_get_port_by_gid;\r
1012         p_ifc->create_mad_pool = ib_create_mad_pool;\r
1013         p_ifc->destroy_mad_pool = ib_destroy_mad_pool;\r
1014         p_ifc->reg_mad_pool = ib_reg_mad_pool;\r
1015         p_ifc->dereg_mad_pool = ib_dereg_mad_pool;\r
1016         p_ifc->get_mad = ib_get_mad;\r
1017         p_ifc->put_mad = ib_put_mad;\r
1018         p_ifc->init_dgrm_svc = ib_init_dgrm_svc;\r
1019         p_ifc->reg_mad_svc = ib_reg_mad_svc;\r
1020         p_ifc->reg_svc = ib_reg_svc;\r
1021         p_ifc->dereg_svc = ib_dereg_svc;\r
1022         p_ifc->query = ib_query;\r
1023         p_ifc->cancel_query = ib_cancel_query;\r
1024         p_ifc->reg_pnp = ib_reg_pnp;\r
1025         p_ifc->dereg_pnp = ib_dereg_pnp;\r
1026         p_ifc->subscribe = ib_subscribe;\r
1027         p_ifc->unsubscribe = ib_unsubscribe;\r
1028         p_ifc->reject_ioc = ib_reject_ioc;\r
1029         p_ifc->ci_call = ib_ci_call;\r
1030         p_ifc->open_al = ib_open_al;\r
1031         p_ifc->close_al = ib_close_al;\r
1032         p_ifc->get_err_str = ib_get_err_str;\r
1033         p_ifc->get_wc_status_str = ib_get_wc_status_str;\r
1034         p_ifc->create_mlnx_fmr = mlnx_create_fmr;\r
1035         p_ifc->map_phys_mlnx_fmr = mlnx_map_phys_fmr;\r
1036         p_ifc->unmap_mlnx_fmr = mlnx_unmap_fmr;\r
1037         p_ifc->destroy_mlnx_fmr = mlnx_destroy_fmr;\r
1038         p_ifc->create_mlnx_fmr_pool = mlnx_create_fmr_pool;\r
1039         p_ifc->destroy_mlnx_fmr_pool = mlnx_destroy_fmr_pool;\r
1040         p_ifc->map_phys_mlnx_fmr_pool = mlnx_map_phys_fmr_pool;\r
1041         p_ifc->unmap_mlnx_fmr_pool = mlnx_unmap_fmr_pool;\r
1042         p_ifc->flush_mlnx_fmr_pool = mlnx_flush_fmr_pool;\r
1043         p_ifc->create_srq = ib_create_srq;\r
1044         p_ifc->modify_srq = ib_modify_srq;\r
1045         p_ifc->query_srq = ib_query_srq;\r
1046         p_ifc->destroy_srq = ib_destroy_srq;\r
1047         p_ifc->post_srq_recv = ib_post_srq_recv;\r
1048 \r
1049         BUS_EXIT( BUS_DBG_PNP );\r
1050 }\r
1051 \r
1052 \r
1053 static NTSTATUS\r
1054 __get_relations(\r
1055         IN              const   net64_t                                         ca_guid,\r
1056         IN                              IRP* const                                      p_irp )\r
1057 {\r
1058         UNUSED_PARAM( ca_guid );\r
1059         UNUSED_PARAM( p_irp );\r
1060 \r
1061         BUS_ENTER( BUS_DBG_PNP );\r
1062 \r
1063         /*\r
1064          * Now that ibbus is in the same device stack as the HCA driver, skip\r
1065          * returning relations here as ibbus has already done the deed.\r
1066          * This interface remains to minimize changes to HCA drivers for now.\r
1067          */\r
1068 \r
1069         BUS_EXIT( BUS_DBG_PNP );\r
1070         return STATUS_SUCCESS;\r
1071 }\r
1072 \r
1073 \r
1074 static NTSTATUS\r
1075 __query_ci_ifc(\r
1076         IN                                      DEVICE_OBJECT* const            p_dev_obj,\r
1077         IN                                      IO_STACK_LOCATION* const        p_io_stack )\r
1078 {\r
1079         ib_ci_ifc_t             *p_ifc;\r
1080 \r
1081         BUS_ENTER( BUS_DBG_PNP );\r
1082 \r
1083         if( p_io_stack->Parameters.QueryInterface.Version != \r
1084                 IB_CI_INTERFACE_VERSION )\r
1085         {\r
1086                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Incorrect interface version (%d)\n",\r
1087                         p_io_stack->Parameters.QueryInterface.Version ) );\r
1088                 return STATUS_NOT_SUPPORTED;\r
1089         }\r
1090 \r
1091         if( p_io_stack->Parameters.QueryInterface.Size < sizeof(ib_ci_ifc_t) )\r
1092         {\r
1093                 BUS_TRACE_EXIT( BUS_DBG_PNP, \r
1094                         ("Buffer too small (%d given, %d required).\n",\r
1095                         p_io_stack->Parameters.QueryInterface.Size, sizeof(ib_ci_ifc_t)) );\r
1096                 return STATUS_BUFFER_TOO_SMALL;\r
1097         }\r
1098 \r
1099         /* Copy the interface. */\r
1100         p_ifc = (ib_ci_ifc_t*)p_io_stack->Parameters.QueryInterface.Interface;\r
1101 \r
1102         p_ifc->wdm.Size = sizeof(ib_ci_ifc_t);\r
1103         p_ifc->wdm.Version = IB_CI_INTERFACE_VERSION;\r
1104         p_ifc->wdm.Context = p_dev_obj;\r
1105         p_ifc->wdm.InterfaceReference = al_ref_ci_ifc;\r
1106         p_ifc->wdm.InterfaceDereference = al_deref_ci_ifc;\r
1107 \r
1108         /* Set the entry points. */\r
1109         p_ifc->register_ca = ib_register_ca;\r
1110         p_ifc->deregister_ca = ib_deregister_ca;\r
1111         p_ifc->get_relations = __get_relations;\r
1112         p_ifc->get_err_str = ib_get_err_str;\r
1113 \r
1114         /* take the reference before returning. */\r
1115         al_ref_ci_ifc( p_dev_obj );\r
1116         BUS_EXIT( BUS_DBG_PNP );\r
1117         return STATUS_SUCCESS;\r
1118 }\r
1119 \r
1120 \r
1121 static NTSTATUS\r
1122 __query_cm_ifc(\r
1123         IN                                      DEVICE_OBJECT* const            p_dev_obj,\r
1124         IN                                      IO_STACK_LOCATION* const        p_io_stack )\r
1125 {\r
1126         INFINIBAND_INTERFACE_CM *p_ifc;\r
1127 \r
1128         BUS_ENTER( BUS_DBG_PNP );\r
1129 \r
1130         if( p_io_stack->Parameters.QueryInterface.Version != IbaCmVersion(1, 0) )\r
1131         {\r
1132                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Incorrect interface version (%d)\n",\r
1133                         p_io_stack->Parameters.QueryInterface.Version ) );\r
1134                 return STATUS_NOT_SUPPORTED;\r
1135         }\r
1136 \r
1137         if( p_io_stack->Parameters.QueryInterface.Size < sizeof(INFINIBAND_INTERFACE_CM) )\r
1138         {\r
1139                 BUS_TRACE_EXIT( BUS_DBG_PNP, \r
1140                         ("Buffer too small (%d given, %d required).\n",\r
1141                         p_io_stack->Parameters.QueryInterface.Size, sizeof(INFINIBAND_INTERFACE_CM)) );\r
1142                 return STATUS_BUFFER_TOO_SMALL;\r
1143         }\r
1144 \r
1145         /* Copy the interface. */\r
1146         p_ifc = (INFINIBAND_INTERFACE_CM*)p_io_stack->Parameters.QueryInterface.Interface;\r
1147 \r
1148         p_ifc->InterfaceHeader.Size = sizeof(INFINIBAND_INTERFACE_CM);\r
1149         p_ifc->InterfaceHeader.Version = IbaCmVersion(1, 0);\r
1150         p_ifc->InterfaceHeader.Context = p_dev_obj;\r
1151         p_ifc->InterfaceHeader.InterfaceReference = al_ref_ifc;\r
1152         p_ifc->InterfaceHeader.InterfaceDereference = al_deref_ifc;\r
1153         cm_get_interface(&p_ifc->CM);\r
1154 \r
1155         /* take the reference before returning. */\r
1156         al_ref_ifc( p_dev_obj );\r
1157         BUS_EXIT( BUS_DBG_PNP );\r
1158         return STATUS_SUCCESS;\r
1159 }\r
1160 \r
1161 static NTSTATUS\r
1162 fdo_query_pnp_state(\r
1163         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1164         IN                              IRP* const                                      p_irp, \r
1165                 OUT                     cl_irp_action_t* const          p_action )\r
1166 {\r
1167         bus_fdo_ext_t           *p_ext;\r
1168 \r
1169         BUS_ENTER( BUS_DBG_PNP );\r
1170 \r
1171         p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;\r
1172 \r
1173         p_irp->IoStatus.Information |= p_ext->pnp_state;\r
1174 \r
1175         *p_action = IrpSkip;\r
1176 \r
1177         BUS_EXIT( BUS_DBG_PNP );\r
1178         return STATUS_SUCCESS;;\r
1179 }\r
1180 \r
1181 \r
1182 static NTSTATUS\r
1183 fdo_query_interface(\r
1184         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1185         IN                                      IRP* const                              p_irp, \r
1186                 OUT                             cl_irp_action_t* const  p_action )\r
1187 {\r
1188         NTSTATUS                        status;\r
1189         IO_STACK_LOCATION       *p_io_stack;\r
1190 \r
1191         BUS_ENTER( BUS_DBG_PNP );\r
1192 \r
1193         PAGED_CODE();\r
1194 \r
1195         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1196         \r
1197         /* Compare requested GUID with our supported interface GUIDs. */\r
1198         if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
1199                 &GUID_IB_AL_INTERFACE ) )\r
1200         {\r
1201                 status = __query_al_ifc( p_dev_obj, p_io_stack );\r
1202         }\r
1203         else if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
1204                 &GUID_IB_CI_INTERFACE ) )\r
1205         {\r
1206                 status = __query_ci_ifc( p_dev_obj, p_io_stack );\r
1207         }\r
1208         else if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
1209                 &GUID_INFINIBAND_INTERFACE_CM ) )\r
1210         {\r
1211                 status = __query_cm_ifc( p_dev_obj, p_io_stack );\r
1212         }\r
1213         else\r
1214         {\r
1215                 status = p_irp->IoStatus.Status;\r
1216         }\r
1217 \r
1218         if( NT_SUCCESS( status ) )\r
1219                 *p_action = IrpSkip;\r
1220         else if( status == STATUS_BUFFER_TOO_SMALL )\r
1221                 *p_action = IrpComplete;\r
1222         else\r
1223                 *p_action = IrpIgnore;\r
1224 \r
1225         BUS_EXIT( BUS_DBG_PNP );\r
1226         return status;\r
1227 }\r
1228 \r
1229 \r
1230 static NTSTATUS\r
1231 __fdo_query_power(\r
1232         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1233         IN                              IRP* const                                      p_irp,\r
1234                 OUT                     cl_irp_action_t* const          p_action )\r
1235 {\r
1236         NTSTATUS                        status = STATUS_SUCCESS;\r
1237         IO_STACK_LOCATION       *p_io_stack;\r
1238 \r
1239         BUS_ENTER( BUS_DBG_POWER );\r
1240 \r
1241         UNUSED_PARAM( p_dev_obj );\r
1242 \r
1243         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1244 \r
1245         switch( p_io_stack->Parameters.Power.Type )\r
1246         {\r
1247         case SystemPowerState:\r
1248                 /* Fail any requests to hibernate or sleep the system. */\r
1249                 switch( p_io_stack->Parameters.Power.State.SystemState )\r
1250                 {\r
1251                         case PowerSystemHibernate:\r
1252                         case PowerSystemSleeping1:      // STANDBY support\r
1253                         case PowerSystemSleeping2:      // STANDBY support\r
1254                         case PowerSystemSleeping3:      // STANDBY support\r
1255                         case PowerSystemWorking:\r
1256                         case PowerSystemShutdown:\r
1257                                 break;\r
1258 \r
1259                         default:\r
1260                                 status = STATUS_NOT_SUPPORTED;\r
1261                 }\r
1262                 break;\r
1263 \r
1264         case DevicePowerState:\r
1265                 /* Fail any query for low power states. */\r
1266                 switch( p_io_stack->Parameters.Power.State.DeviceState )\r
1267                 {\r
1268                 case PowerDeviceD0:\r
1269                 case PowerDeviceD3:\r
1270                         /* We only support fully powered or off power states. */\r
1271                         break;\r
1272 \r
1273                 default:\r
1274                         status = STATUS_NOT_SUPPORTED;\r
1275                 }\r
1276                 break;\r
1277         }\r
1278 \r
1279         if( status == STATUS_NOT_SUPPORTED )\r
1280                 *p_action = IrpComplete;\r
1281         else\r
1282                 *p_action = IrpSkip;\r
1283 \r
1284         BUS_EXIT( BUS_DBG_POWER );\r
1285         return status;\r
1286 }\r
1287 \r
1288 \r
1289 \r
1290 /* Work item callback to handle DevicePowerD0 IRPs at passive level. */\r
1291 \r
1292 static void\r
1293 __device_power_up_completion_workItem(\r
1294         IN                              DEVICE_OBJECT*                          p_dev_obj,\r
1295         IN                              void*                                           context )\r
1296 {\r
1297         NTSTATUS                        status;\r
1298         IO_STACK_LOCATION       *p_io_stack;\r
1299         bus_fdo_ext_t           *p_ext;\r
1300         IRP                                     *p_irp;\r
1301         POWER_STATE                     power_state;\r
1302 \r
1303         BUS_ENTER( BUS_DBG_POWER );\r
1304 \r
1305         p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;\r
1306         p_irp = (IRP*)context;\r
1307         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1308 \r
1309         IoFreeWorkItem( p_ext->p_po_work_item );\r
1310         p_ext->p_po_work_item = NULL;\r
1311 \r
1312         /* re-register CA */\r
1313         BUS_PRINT( BUS_DBG_POWER, \r
1314                 ("***** re-register CA, IRQL %d\n", KeGetCurrentIrql()));\r
1315 \r
1316         status = __register_ca( p_dev_obj );\r
1317         if( !NT_SUCCESS( status ) ) {\r
1318                 BUS_PRINT( BUS_DBG_POWER, \r
1319                         ("!!! __register_ca failed (%#x) \n", status));\r
1320                 goto err_fdo_start;\r
1321         }\r
1322 \r
1323         p_ext->device_power_state = p_io_stack->Parameters.Power.State.DeviceState;\r
1324         power_state = PoSetPowerState( p_dev_obj, DevicePowerState,\r
1325                 p_io_stack->Parameters.Power.State );\r
1326 \r
1327         BUS_PRINT( BUS_DBG_POWER, \r
1328                 ("PoSetPowerState: old state %d, new state to %d\n", \r
1329                 power_state.DeviceState, p_ext->device_power_state ));\r
1330 \r
1331         CL_PRINT_TO_EVENT_LOG( p_dev_obj, EVENT_IBBUS_ANY_WARN,\r
1332                 ("Power increased to: device %d, system %d.\n",\r
1333                 (int)p_ext->device_power_state, (int)p_ext->system_power_state));\r
1334 \r
1335         goto exit;\r
1336 \r
1337 err_fdo_start:\r
1338         /* Flag device as having failed. */\r
1339         p_ext->pnp_state |= PNP_DEVICE_FAILED;\r
1340         IoInvalidateDeviceState( p_ext->cl_ext.p_pdo );\r
1341 exit:\r
1342         PoStartNextPowerIrp( p_irp );\r
1343         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
1344         IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
1345         BUS_EXIT( BUS_DBG_POWER );\r
1346 }\r
1347 \r
1348 \r
1349 /*NOTE: Completion routines must NEVER be pageable. */\r
1350 static NTSTATUS\r
1351 __device_power_up_completion(\r
1352         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
1353         IN                              IRP                                                     *p_irp,\r
1354         IN                              void                                            *context )\r
1355 {\r
1356         NTSTATUS                        status = STATUS_SUCCESS;\r
1357         bus_fdo_ext_t           *p_ext;\r
1358         IO_STACK_LOCATION       *p_io_stack;\r
1359 \r
1360         BUS_ENTER( BUS_DBG_POWER );\r
1361 \r
1362         UNUSED_PARAM( context );\r
1363 \r
1364         p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;\r
1365         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1366 \r
1367         if( !NT_SUCCESS( p_irp->IoStatus.Status ) ) {\r
1368                 BUS_PRINT( BUS_DBG_POWER, \r
1369                         ("IRP_MN_SET_POWER for device failed by lower driver with %08x.\n",\r
1370                         p_irp->IoStatus.Status));\r
1371                 status =  STATUS_SUCCESS;\r
1372                 PoStartNextPowerIrp( p_irp );\r
1373                 goto release;\r
1374         }\r
1375 \r
1376         /* Process in a work item to allow blocking. */\r
1377         ASSERT( !p_ext->p_po_work_item );\r
1378         p_ext->p_po_work_item = IoAllocateWorkItem( p_dev_obj );\r
1379         if( !p_ext->p_po_work_item ) {\r
1380                 BUS_PRINT( BUS_DBG_POWER, \r
1381                         ("Failed to allocate work item.\n" ));\r
1382                 status = STATUS_SUCCESS;\r
1383                 p_ext->pnp_state |= PNP_DEVICE_FAILED;\r
1384                 IoInvalidateDeviceState( p_ext->cl_ext.p_pdo );\r
1385                 PoStartNextPowerIrp( p_irp );\r
1386                 goto release;\r
1387         }\r
1388 \r
1389         /* Process in work item callback. */\r
1390         IoMarkIrpPending( p_irp );\r
1391         IoQueueWorkItem( p_ext->p_po_work_item, \r
1392                 __device_power_up_completion_workItem, DelayedWorkQueue, p_irp );\r
1393         status = STATUS_MORE_PROCESSING_REQUIRED;\r
1394         goto exit;\r
1395 \r
1396 release:        \r
1397         IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
1398 exit:   \r
1399         BUS_EXIT( BUS_DBG_POWER );\r
1400         return status;\r
1401 }\r
1402 \r
1403 \r
1404 static NTSTATUS __device_power_down_workItem_completion(\r
1405         IN                              DEVICE_OBJECT   *p_dev_obj,\r
1406         IN                              IRP                             *p_irp,\r
1407         IN                              void                            *context )\r
1408 {\r
1409         bus_fdo_ext_t           *p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;\r
1410         UNUSED_PARAM( context );\r
1411 \r
1412         BUS_ENTER( BUS_DBG_POWER );\r
1413 \r
1414         PoStartNextPowerIrp( p_irp );\r
1415         IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
1416 \r
1417         BUS_EXIT( BUS_DBG_POWER );\r
1418         return STATUS_SUCCESS;\r
1419 }\r
1420 \r
1421 /* Work item callback to handle DevicePowerD3 IRPs at passive level. */\r
1422 static void\r
1423 __device_power_down_workItem(\r
1424         IN                              DEVICE_OBJECT*                          p_dev_obj,\r
1425         IN                              void*                                           context )\r
1426 {\r
1427         IO_STACK_LOCATION       *p_io_stack;\r
1428         bus_fdo_ext_t           *p_ext;\r
1429         IRP                                     *p_irp;\r
1430         POWER_STATE                     power_state;\r
1431 \r
1432         BUS_ENTER( BUS_DBG_POWER );\r
1433 \r
1434         p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;\r
1435         p_irp = (IRP*)context;\r
1436         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1437 \r
1438         IoFreeWorkItem( p_ext->p_po_work_item );\r
1439         p_ext->p_po_work_item = NULL;\r
1440 \r
1441         p_ext->device_power_state = p_io_stack->Parameters.Power.State.DeviceState;\r
1442         power_state = PoSetPowerState( p_dev_obj, DevicePowerState,\r
1443                 p_io_stack->Parameters.Power.State );\r
1444 \r
1445         BUS_PRINT( BUS_DBG_POWER, \r
1446                 ("PoSetPowerState: old state %d, new state to %d, IRQL %d\n", \r
1447                 power_state.DeviceState, p_ext->device_power_state, KeGetCurrentIrql() ));\r
1448 \r
1449         CL_PRINT_TO_EVENT_LOG( p_dev_obj, EVENT_IBBUS_ANY_WARN,\r
1450                 ("Power decreased to: device %d, system %d.\n",\r
1451                 (int)p_ext->device_power_state, (int)p_ext->system_power_state));\r
1452 \r
1453         BUS_PRINT( BUS_DBG_POWER, \r
1454                 ("***** deregister CA \n"));\r
1455 \r
1456         __deregister_ca( p_dev_obj );\r
1457 \r
1458         IoCopyCurrentIrpStackLocationToNext( p_irp );\r
1459 #pragma warning( push, 3 )\r
1460         IoSetCompletionRoutine( p_irp, __device_power_down_workItem_completion,\r
1461                 NULL, TRUE, TRUE, TRUE );\r
1462 #pragma warning( pop )\r
1463         PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
1464 \r
1465         BUS_EXIT( BUS_DBG_POWER );\r
1466 }\r
1467 \r
1468 \r
1469 \r
1470 static NTSTATUS\r
1471 __fdo_set_power(\r
1472         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1473         IN                              IRP* const                                      p_irp,\r
1474                 OUT                     cl_irp_action_t* const          p_action )\r
1475 {\r
1476         NTSTATUS                        status;\r
1477         IO_STACK_LOCATION       *p_io_stack;\r
1478         bus_fdo_ext_t           *p_ext;\r
1479 \r
1480         BUS_ENTER( BUS_DBG_POWER );\r
1481 \r
1482         p_ext = p_dev_obj->DeviceExtension;\r
1483         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1484 \r
1485         BUS_TRACE( BUS_DBG_POWER, \r
1486                 ("SET_POWER for FDO %p (ext %p): type %s, state %d, action %d, IRQL %d  \n",\r
1487                 p_dev_obj, p_ext,\r
1488                 (p_io_stack->Parameters.Power.Type)\r
1489                         ? "DevicePowerState" : "SystemPowerState",\r
1490                 p_io_stack->Parameters.Power.State.DeviceState, \r
1491                 p_io_stack->Parameters.Power.ShutdownType, KeGetCurrentIrql() ));\r
1492 \r
1493         switch( p_io_stack->Parameters.Power.Type )\r
1494         {\r
1495         case SystemPowerState:\r
1496                 /* Pass down and let the PDO driver handle it. */\r
1497                 p_ext->system_power_state = p_io_stack->Parameters.Power.State.SystemState;\r
1498                 *p_action = IrpIgnore;\r
1499                 status = STATUS_SUCCESS;\r
1500                 break;\r
1501 \r
1502         case DevicePowerState:\r
1503                 IoMarkIrpPending( p_irp );\r
1504                 if( p_io_stack->Parameters.Power.State.DeviceState == PowerDeviceD0 && \r
1505                         p_ext->system_power_state == PowerSystemWorking)\r
1506                 { /* power up */\r
1507                         /* If we're already powered up, just pass down. */\r
1508                         if( p_ext->device_power_state == PowerDeviceD0 )\r
1509                         {\r
1510                                 status = STATUS_SUCCESS;\r
1511                                 *p_action = IrpIgnore;\r
1512                                 break;\r
1513                         }\r
1514 \r
1515                         /* Process in I/O completion callback. */\r
1516                         IoCopyCurrentIrpStackLocationToNext( p_irp );\r
1517 #pragma warning( push, 3 )\r
1518                         IoSetCompletionRoutine( p_irp, __device_power_up_completion, NULL, \r
1519                                 TRUE, TRUE, TRUE );\r
1520 #pragma warning( pop )\r
1521                         PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
1522                 }\r
1523                 else\r
1524                 { /* power down */\r
1525 \r
1526                         /* Process in a work item - deregister_ca and HcaDeinit block. */\r
1527                         ASSERT( !p_ext->p_po_work_item );\r
1528                         p_ext->p_po_work_item = IoAllocateWorkItem( p_dev_obj );\r
1529                         if( !p_ext->p_po_work_item )\r
1530                         {\r
1531                                 status = STATUS_INSUFFICIENT_RESOURCES;\r
1532                                 break;\r
1533                         }\r
1534 \r
1535                         /* Process in work item callback. */\r
1536                         IoQueueWorkItem(\r
1537                                 p_ext->p_po_work_item, __device_power_down_workItem, DelayedWorkQueue, p_irp );\r
1538                 }\r
1539                 *p_action = IrpDoNothing;\r
1540                 status = STATUS_PENDING;\r
1541                 break;\r
1542 \r
1543         default:\r
1544                 /* Pass down and let the PDO driver handle it. */\r
1545                 *p_action = IrpIgnore;\r
1546                 status = STATUS_SUCCESS;\r
1547                 break;\r
1548         }\r
1549 \r
1550         if( !NT_SUCCESS( status ) )\r
1551                 *p_action = IrpComplete;\r
1552 \r
1553         BUS_EXIT( BUS_DBG_POWER );\r
1554         return status;\r
1555 }\r
1556 \r
1557 \r
1558 /*\r
1559  * A CA GUID of zero means that all devices should be reported.\r
1560  */\r
1561 NTSTATUS\r
1562 bus_get_relations(\r
1563         IN                              cl_qlist_t*     const                   p_pdo_list,\r
1564         IN              const   net64_t                                         ca_guid,\r
1565         IN                              IRP* const                                      p_irp )\r
1566 {\r
1567         NTSTATUS                        status;\r
1568         DEVICE_RELATIONS        *p_rel;\r
1569         cl_list_item_t          *p_list_item;\r
1570         bus_pdo_ext_t           *p_pdo_ext;\r
1571         size_t                          n_devs = 0;\r
1572 \r
1573         BUS_ENTER( BUS_DBG_PNP );\r
1574 \r
1575         /* Count the number of child devices. */\r
1576         for( p_list_item = cl_qlist_head( p_pdo_list );\r
1577                 p_list_item != cl_qlist_end( p_pdo_list );\r
1578                 p_list_item = cl_qlist_next( p_list_item ) )\r
1579         {\r
1580                 p_pdo_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
1581 \r
1582                 if( !p_pdo_ext->b_present )\r
1583                 {\r
1584                         // mark it missing to be removed in port_remove\r
1585                         p_pdo_ext->b_reported_missing = TRUE;\r
1586                         /*\r
1587                          * We don't report a PDO that is no longer present.  This is how\r
1588                          * the PDO will get cleaned up.\r
1589                          */\r
1590                         BUS_TRACE( BUS_DBG_PNP, ("Don't report PDO! %s: PDO %p, ext %p, "\r
1591                                 "present %d, missing %d .\n",\r
1592                                 p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
1593                                 p_pdo_ext->cl_ext.p_self_do, p_pdo_ext, p_pdo_ext->b_present,\r
1594                                 p_pdo_ext->b_reported_missing ) );\r
1595                         continue;\r
1596                 }\r
1597                 \r
1598                 if( ca_guid && p_pdo_ext->ca_guid != ca_guid )\r
1599                         continue;\r
1600 \r
1601                 n_devs++;\r
1602         }\r
1603 \r
1604         if( !n_devs )\r
1605         {\r
1606                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Found 0 PDOs ca_guid %I64x\n", ca_guid));\r
1607                 return STATUS_NO_SUCH_DEVICE;\r
1608         }\r
1609 \r
1610         BUS_TRACE( BUS_DBG_PNP, ("Found %d PDOs ca_guid %I64x\n", n_devs, ca_guid));\r
1611 \r
1612         /* Add space for our child IOUs. */\r
1613         status = cl_alloc_relations( p_irp, n_devs );\r
1614         if( !NT_SUCCESS( status ) )\r
1615         {\r
1616                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1617                         ("cl_alloc_relations returned %08x.\n", status) );\r
1618                 return status;\r
1619         }\r
1620 \r
1621         p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
1622 \r
1623         for( p_list_item = cl_qlist_head( p_pdo_list );\r
1624                 p_list_item != cl_qlist_end( p_pdo_list );\r
1625                 p_list_item = cl_qlist_next( p_list_item ) )\r
1626         {\r
1627                 p_pdo_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
1628 \r
1629                 if( !p_pdo_ext->b_present )\r
1630                         continue;\r
1631 \r
1632                 if( ca_guid && p_pdo_ext->ca_guid != ca_guid )\r
1633                         continue;\r
1634 \r
1635                 BUS_TRACE( BUS_DBG_PNP, ("Reported PDO %p(=%p), ext %p\n", \r
1636                         p_pdo_ext->cl_ext.p_self_do, p_pdo_ext->cl_ext.p_pdo, p_pdo_ext ));\r
1637                 \r
1638                 p_rel->Objects[p_rel->Count] = p_pdo_ext->cl_ext.p_pdo;\r
1639                 ObReferenceObject( p_rel->Objects[p_rel->Count++] );\r
1640         }\r
1641 \r
1642         BUS_EXIT( BUS_DBG_PNP );\r
1643         return STATUS_SUCCESS;\r
1644 }\r
1645 \r
1646 \r
1647 /*\r
1648  * find a bus filter instance (p_bfi) given an *cl_obj: port_mgr or iou_mgr. \r
1649  */\r
1650 \r
1651 bus_filter_t *\r
1652 get_bfi_by_obj(IN int obj_type, IN cl_obj_t *p_obj )\r
1653 {\r
1654         bus_filter_t    *p_bfi;\r
1655         bus_filter_t    *matched=NULL;\r
1656 \r
1657         CL_ASSERT((obj_type == BFI_PORT_MGR_OBJ) || (obj_type == BFI_IOU_MGR_OBJ));\r
1658 \r
1659         lock_control_event();\r
1660 \r
1661         for(p_bfi=g_bus_filters; p_bfi < &g_bus_filters[MAX_BUS_FILTERS]; p_bfi++) {\r
1662 \r
1663                 if ( !p_bfi->p_bus_ext )\r
1664                         continue;\r
1665 \r
1666                 if ( obj_type == BFI_PORT_MGR_OBJ ) {\r
1667                         if ( p_obj == p_bfi->p_port_mgr_obj ) {\r
1668                                 matched = p_bfi;\r
1669                                 break;\r
1670                         }\r
1671                 }\r
1672                 else {\r
1673                         if ( p_obj == p_bfi->p_iou_mgr_obj ) {\r
1674                                 matched = p_bfi;\r
1675                                 break;\r
1676                         }\r
1677                 }\r
1678         }\r
1679         unlock_control_event();\r
1680 \r
1681         BUS_TRACE( BUS_DBG_PNP,\r
1682                                 ("cl_obj %p type %s_MGR_OBJ --> bfi[%d] %p\n", p_obj,\r
1683                                 (obj_type == BFI_PORT_MGR_OBJ ? "PORT": "IOU"),\r
1684                                 (matched ? (matched - g_bus_filters) : (-1)), matched ) );\r
1685 \r
1686         return matched;\r
1687 }\r
1688 \r
1689 /*\r
1690  * find a bus filter instance given an HCA guid.\r
1691  * BFIs are bound to GUIDs in fdo_start().\r
1692  */\r
1693 \r
1694 bus_filter_t *\r
1695 get_bfi_by_ca_guid( IN net64_t ca_guid )\r
1696 {\r
1697         bus_filter_t    *p_bfi;\r
1698         bus_filter_t    *matched=NULL;\r
1699 \r
1700         if ( ca_guid == 0ULL )\r
1701         {\r
1702                 matched = g_bus_filters;\r
1703                 BUS_TRACE( BUS_DBG_PNP, ("ERR guid %I64x -> bfi[0] %p\n",\r
1704                                                                 ca_guid, matched) );\r
1705                 CL_ASSERT( ca_guid );\r
1706                 return matched;\r
1707         }\r
1708 \r
1709         lock_control_event();\r
1710 \r
1711         for(p_bfi=g_bus_filters; p_bfi < &g_bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
1712         {\r
1713                 if ( !p_bfi->p_bus_ext )\r
1714                         continue;\r
1715 \r
1716                 if ( ca_guid == p_bfi->ca_guid )\r
1717                 {\r
1718                         matched = p_bfi;\r
1719                         break;\r
1720                 }\r
1721         }\r
1722         unlock_control_event();\r
1723 \r
1724 #if DBG\r
1725         if ( !matched )\r
1726         {\r
1727                 BUS_PRINT( BUS_DBG_PNP, ("No Match ca_guid 0x%I64x -> bfi[%d] %p\n",\r
1728                                                                         ca_guid, -1, matched ) );\r
1729         }\r
1730 #endif\r
1731         return matched;\r
1732 }\r
1733 \r
1734 \r
1735 bus_filter_t *\r
1736 alloc_bfi( IN DRIVER_OBJECT  *p_driver_obj, OUT int *p_instance_count )\r
1737 {\r
1738         bus_filter_t    *p_bfi;\r
1739         bus_filter_t    *matched=NULL;\r
1740 \r
1741     /* Using unsafe function so that the IRQL remains at PASSIVE_LEVEL.\r
1742      * IoCreateDeviceSecure & IoCreateSymbolicLink must be called at\r
1743      * PASSIVE_LEVEL.\r
1744          */\r
1745         lock_control_event();\r
1746 \r
1747         // find 1st unused bfi slot.\r
1748         for(p_bfi=g_bus_filters; p_bfi < &g_bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
1749         {\r
1750                 if ( !p_bfi->p_bus_ext )\r
1751                 {\r
1752                         /* temp setting until 'real' p_bus_ext is alloc; see bus_add_device.\r
1753                          * If p_bus_ext is ! 0, then bfi slot is allocated, although it\r
1754                          * may not yet have a bound CA guid; set set_get_\r
1755                          */\r
1756                         p_bfi->p_bus_ext = (bus_fdo_ext_t*)p_driver_obj;\r
1757                         matched = p_bfi;\r
1758                         *p_instance_count = ++g_bfi_InstanceCount; // record in-use\r
1759                         break;\r
1760                 }\r
1761         }\r
1762         unlock_control_event();\r
1763 \r
1764 #if DBG\r
1765         RtlStringCbPrintfA ( p_bfi->whoami,\r
1766                                                  sizeof(p_bfi->whoami),\r
1767                                                  "bfi-%d",\r
1768                                                  (g_bfi_InstanceCount - 1) );\r
1769 \r
1770         p_bfi->magic = BFI_MAGIC;\r
1771 #endif\r
1772 \r
1773         BUS_TRACE( BUS_DBG_PNP, ("%s %p\n",\r
1774                                 (matched ? matched->whoami:"Nobody"), matched) );\r
1775 \r
1776         return matched;\r
1777 }\r
1778 \r
1779 \r
1780 int\r
1781 free_bfi( IN  bus_filter_t  *p_bfi )\r
1782 {\r
1783         int     remaining;\r
1784 \r
1785         lock_control_event();\r
1786         p_bfi->p_bus_ext = NULL;\r
1787         p_bfi->ca_guid = 0ULL;\r
1788         remaining = --g_bfi_InstanceCount; // one less bfi in-use\r
1789         unlock_control_event();\r
1790         \r
1791         return remaining;\r
1792 }\r
1793 \r
1794 int\r
1795 get_bfi_count( void )\r
1796 {\r
1797         int     ic;\r
1798 \r
1799         lock_control_event();\r
1800         ic = g_bfi_InstanceCount;\r
1801         unlock_control_event();\r
1802         \r
1803         return ic;\r
1804 }\r
1805 \r
1806 #if DBG\r
1807 char *get_obj_state_str(cl_state_t state)\r
1808 {\r
1809         switch( state ) {\r
1810           case CL_UNINITIALIZED:\r
1811                 return "UNINITIALIZED";\r
1812           case CL_INITIALIZED:\r
1813                 return "INITIALIZED";\r
1814           case CL_DESTROYING:\r
1815                 return "DESTROYING";\r
1816           case CL_DESTROYED:\r
1817                 return "DESTROYED";\r
1818           default:\r
1819                 break;\r
1820         }\r
1821         return "Err - Bad obj state";\r
1822 }\r
1823 #endif\r
1824 \r