[CORE] Expose vendor defined device in ibiou.
[mirror/winof/.git] / core / iou / kernel / iou_pnp.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 \r
33 \r
34 /*\r
35  * Implemenation of all PnP functionality for FDO (power policy owners).\r
36  */\r
37 \r
38 \r
39 #include "iou_driver.h"\r
40 #if defined(EVENT_TRACING)\r
41 #ifdef offsetof\r
42 #undef offsetof\r
43 #endif\r
44 #include "iou_pnp.tmh"\r
45 #endif\r
46 #include "iou_pnp.h"\r
47 #include "iou_ioc_mgr.h"\r
48 #include <complib/cl_memory.h>\r
49 #include <complib/cl_bus_ifc.h>\r
50 #include <initguid.h>\r
51 #include <iba/iou_ifc.h>\r
52 \r
53 \r
54 static NTSTATUS\r
55 fdo_start(\r
56         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
57         IN                                      IRP* const                              p_irp, \r
58                 OUT                             cl_irp_action_t* const  p_action );\r
59 \r
60 static void\r
61 fdo_release_resources(\r
62         IN                                      DEVICE_OBJECT* const    p_dev_obj );\r
63 \r
64 static NTSTATUS\r
65 fdo_query_remove(\r
66         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
67         IN                                      IRP* const                              p_irp, \r
68                 OUT                             cl_irp_action_t* const  p_action );\r
69 \r
70 static NTSTATUS\r
71 fdo_query_capabilities(\r
72         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
73         IN                                      IRP* const                              p_irp, \r
74                 OUT                             cl_irp_action_t* const  p_action );\r
75 \r
76 static NTSTATUS\r
77 fdo_query_iou_relations(\r
78         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
79         IN                                      IRP* const                              p_irp, \r
80                 OUT                             cl_irp_action_t* const  p_action );\r
81 \r
82 static NTSTATUS\r
83 fdo_query_interface(\r
84         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
85         IN                              IRP* const                                      p_irp, \r
86                 OUT                     cl_irp_action_t* const          p_action );\r
87 \r
88 static NTSTATUS\r
89 __fdo_query_power(\r
90         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
91         IN                              IRP* const                                      p_irp,\r
92                 OUT                     cl_irp_action_t* const          p_action );\r
93 \r
94 static NTSTATUS\r
95 __fdo_set_power(\r
96         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
97         IN                              IRP* const                                      p_irp,\r
98                 OUT                     cl_irp_action_t* const          p_action );\r
99 \r
100 \r
101 \r
102 /* Global virtual function pointer tables shared between all instances of FDO. */\r
103 static const cl_vfptr_pnp_po_t          vfptr_fdo_pnp = {\r
104         "IB IOU",\r
105         fdo_start,\r
106         cl_irp_skip,\r
107         cl_irp_skip,\r
108         cl_do_sync_pnp,\r
109         fdo_query_remove,\r
110         fdo_release_resources,\r
111         cl_do_remove,\r
112         cl_do_sync_pnp,\r
113         cl_irp_skip,\r
114         fdo_query_capabilities,\r
115         cl_irp_skip,\r
116         cl_irp_skip,\r
117         cl_do_sync_pnp,\r
118         fdo_query_iou_relations,\r
119         cl_irp_ignore,\r
120         cl_irp_ignore,\r
121         cl_irp_ignore,\r
122         cl_irp_ignore,\r
123         cl_irp_ignore,\r
124         cl_irp_ignore,\r
125         cl_irp_ignore,\r
126         cl_irp_ignore,                  /* QueryInterface */\r
127         cl_irp_ignore,\r
128         cl_irp_ignore,\r
129         cl_irp_ignore,\r
130         cl_irp_ignore,\r
131         __fdo_query_power,              /* QueryPower */\r
132         __fdo_set_power,                /* SetPower */\r
133         cl_irp_ignore,                  /* PowerSequence */\r
134         cl_irp_ignore                   /* WaitWake */\r
135 };\r
136 /*\r
137  * NOTE: The QueryInterface entry point is not used because we only enable/disable\r
138  * our interface so that user-mode AL can find a device to perform IOCTLs to.\r
139  */\r
140 \r
141 NTSTATUS\r
142 iou_add_device(\r
143         IN                              DRIVER_OBJECT                           *p_driver_obj,\r
144         IN                              DEVICE_OBJECT                           *p_pdo )\r
145 {\r
146         NTSTATUS                status;\r
147         DEVICE_OBJECT   *p_dev_obj, *p_next_do;\r
148         iou_fdo_ext_t   *p_ext;\r
149 \r
150         IOU_ENTER( IOU_DBG_PNP );\r
151 \r
152         /* Create the FDO device object to attach to the stack. */\r
153         status = IoCreateDevice( p_driver_obj, sizeof(iou_fdo_ext_t),\r
154                 NULL, FILE_DEVICE_BUS_EXTENDER,\r
155                 FILE_DEVICE_SECURE_OPEN, FALSE, &p_dev_obj );\r
156         if( !NT_SUCCESS(status) )\r
157         {\r
158                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
159                         ("Failed to create bus root FDO device.\n") );\r
160                 return status;\r
161         }\r
162 \r
163         p_ext = p_dev_obj->DeviceExtension;\r
164 \r
165         ioc_mgr_construct( &p_ext->ioc_mgr );\r
166 \r
167         p_next_do = IoAttachDeviceToDeviceStack( p_dev_obj, p_pdo );\r
168         if( !p_next_do )\r
169         {\r
170                 IoDeleteDevice( p_dev_obj );\r
171                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
172                         ("IoAttachToDeviceStack failed.\n") );\r
173                 return STATUS_NO_SUCH_DEVICE;\r
174         }\r
175 \r
176         cl_init_pnp_po_ext( p_dev_obj, p_next_do, p_pdo, g_iou_dbg_flags,\r
177                 &vfptr_fdo_pnp, NULL );\r
178 \r
179         IOU_EXIT( IOU_DBG_PNP );\r
180         return STATUS_SUCCESS;\r
181 }\r
182 \r
183 \r
184 static NTSTATUS\r
185 __get_iou_ifc(\r
186         IN                                      iou_fdo_ext_t* const    p_ext )\r
187 {\r
188         NTSTATUS                        status;\r
189         IO_STACK_LOCATION       io_stack;\r
190         ib_al_ifc_data_t        data;\r
191 \r
192         IOU_ENTER( IOU_DBG_PNP );\r
193 \r
194         data.type = &GUID_IOU_INTERFACE_DATA;\r
195         data.version = IOU_INTERFACE_DATA_VERSION;\r
196         data.size = sizeof(iou_ifc_data_t);\r
197         data.p_data = &p_ext->ioc_mgr.info;\r
198 \r
199         io_stack.MinorFunction = IRP_MN_QUERY_INTERFACE;\r
200         io_stack.Parameters.QueryInterface.Version = AL_INTERFACE_VERSION;\r
201         io_stack.Parameters.QueryInterface.Size = sizeof(ib_al_ifc_t);\r
202         io_stack.Parameters.QueryInterface.Interface =\r
203                 (INTERFACE*)&p_ext->ioc_mgr.ifc;\r
204         io_stack.Parameters.QueryInterface.InterfaceSpecificData =\r
205                 &data;\r
206         io_stack.Parameters.QueryInterface.InterfaceType = &GUID_IB_AL_INTERFACE;\r
207 \r
208         status = cl_fwd_query_ifc( p_ext->cl_ext.p_next_do, &io_stack );\r
209 \r
210         /*\r
211          * Dereference the interface now so that the bus driver doesn't fail a\r
212          * query remove IRP.  We will always get unloaded before the bus driver\r
213          * since we're a child device.\r
214          */\r
215         if( NT_SUCCESS( status ) )\r
216         {\r
217                 p_ext->ioc_mgr.ifc.wdm.InterfaceDereference(\r
218                         p_ext->ioc_mgr.ifc.wdm.Context );\r
219         }\r
220 \r
221         IOU_EXIT( IOU_DBG_PNP );\r
222         return status;\r
223 }\r
224 \r
225 \r
226 static NTSTATUS\r
227 fdo_start(\r
228         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
229         IN                                      IRP* const                              p_irp, \r
230                 OUT                             cl_irp_action_t* const  p_action )\r
231 {\r
232         NTSTATUS                status;\r
233         iou_fdo_ext_t   *p_ext;\r
234         ib_api_status_t ib_status;\r
235 \r
236         IOU_ENTER( IOU_DBG_PNP );\r
237 \r
238         p_ext = p_dev_obj->DeviceExtension;\r
239 \r
240         /* Handled on the way up. */\r
241         status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
242         if( !NT_SUCCESS( status ) )\r
243         {\r
244                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
245                         ("Lower drivers failed IRP_MN_START_DEVICE.\n") );\r
246                 return status;\r
247         }\r
248 \r
249         status = __get_iou_ifc( p_ext );\r
250         if( !NT_SUCCESS( status ) )\r
251         {\r
252                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
253                         ("Failed to get IOU interface.\n") );\r
254                 return status;\r
255         }\r
256 \r
257         /* Initialize the IOU manager. */\r
258         ib_status = ioc_mgr_init( &p_ext->ioc_mgr );\r
259         if( ib_status != IB_SUCCESS )\r
260         {\r
261                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
262                         ("ioc_mgr_init returned %s.\n",\r
263                         p_ext->ioc_mgr.ifc.get_err_str(ib_status)) );\r
264                 return STATUS_UNSUCCESSFUL;\r
265         }\r
266 \r
267         IOU_EXIT( IOU_DBG_PNP );\r
268         return status;\r
269 }\r
270 \r
271 \r
272 static NTSTATUS\r
273 fdo_query_remove(\r
274         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
275         IN                                      IRP* const                              p_irp, \r
276                 OUT                             cl_irp_action_t* const  p_action )\r
277 {\r
278         iou_fdo_ext_t   *p_ext;\r
279 \r
280         IOU_ENTER( IOU_DBG_PNP );\r
281 \r
282         p_ext = p_dev_obj->DeviceExtension;\r
283 \r
284         *p_action = IrpSkip;\r
285         /* The FDO driver must set the status even when passing down. */\r
286         p_irp->IoStatus.Status = STATUS_SUCCESS;\r
287         IOU_EXIT( IOU_DBG_PNP );\r
288         return STATUS_SUCCESS;\r
289 }\r
290 \r
291 static void _destroy_ca_ioc_maps(\r
292         IN                                      ioc_mgr_t       *p_ioc_mgr)\r
293 {\r
294         ca_ioc_map_t    *p_map = NULL;\r
295         cl_list_item_t  *list_item;\r
296 \r
297         cl_mutex_acquire( &iou_globals.list_mutex );\r
298 \r
299         list_item = cl_qlist_head( &iou_globals.ca_ioc_map_list );\r
300 \r
301         while( list_item != cl_qlist_end( &iou_globals.ca_ioc_map_list ) ) {\r
302                 p_map = ( ca_ioc_map_t  * ) list_item;\r
303                 list_item = cl_qlist_next( list_item ); // Get the next element before freeing it\r
304 \r
305                 if ( p_map->p_ioc_mgr == p_ioc_mgr ) {\r
306                         cl_qlist_remove_item( &iou_globals.ca_ioc_map_list, ( cl_list_item_t * )p_map );\r
307                         cl_free( p_map );\r
308                 }\r
309 \r
310         }\r
311 \r
312         cl_mutex_release( &iou_globals.list_mutex );\r
313 }\r
314 \r
315 /*\r
316  * This function gets called after releasing the remove lock and waiting\r
317  * for all other threads to release the lock.  No more modifications will\r
318  * occur to the PDO pointer vectors.\r
319  */\r
320 static void\r
321 fdo_release_resources(\r
322         IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
323 {\r
324         iou_fdo_ext_t   *p_ext;\r
325 \r
326         IOU_ENTER( IOU_DBG_PNP );\r
327 \r
328         p_ext = p_dev_obj->DeviceExtension;\r
329 \r
330         _destroy_ca_ioc_maps(&p_ext->ioc_mgr);\r
331 \r
332         //TODO: Fail outstanding I/O operations.\r
333         cl_obj_destroy( &p_ext->ioc_mgr.obj );\r
334 \r
335         IOU_EXIT( IOU_DBG_PNP );\r
336 }\r
337 \r
338 \r
339 static NTSTATUS\r
340 fdo_query_capabilities(\r
341         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
342         IN                                      IRP* const                              p_irp, \r
343                 OUT                             cl_irp_action_t* const  p_action )\r
344 {\r
345         NTSTATUS                        status;\r
346         iou_fdo_ext_t           *p_ext;\r
347         IO_STACK_LOCATION       *p_io_stack;\r
348 \r
349         IOU_ENTER( IOU_DBG_PNP );\r
350 \r
351         p_ext = p_dev_obj->DeviceExtension;\r
352 \r
353         /* Process on the way up. */\r
354         status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
355 \r
356         if( !NT_SUCCESS( status ) )\r
357         {\r
358                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
359                         ("cl_do_sync_pnp returned %08x.\n", status) );\r
360                 return status;\r
361         }\r
362 \r
363         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
364 \r
365         /*\r
366          * Store the device power maping into our extension since we're\r
367          * the power policy owner.  The mapping is used when handling\r
368          * IRP_MN_SET_POWER IRPs.\r
369          */\r
370         cl_memcpy( p_ext->po_state, \r
371                 p_io_stack->Parameters.DeviceCapabilities.Capabilities->DeviceState,\r
372                 sizeof( p_ext->po_state ) );\r
373 \r
374         IOU_EXIT( IOU_DBG_PNP );\r
375         return status;\r
376 }\r
377 \r
378 \r
379 static NTSTATUS\r
380 fdo_query_iou_relations(\r
381         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
382         IN                              IRP* const                                      p_irp, \r
383                 OUT                     cl_irp_action_t* const          p_action )\r
384 {\r
385         iou_fdo_ext_t   *p_ext;\r
386         NTSTATUS                status;\r
387 \r
388         IOU_ENTER( IOU_DBG_PNP );\r
389 \r
390         p_ext = p_dev_obj->DeviceExtension;\r
391 \r
392         status = ioc_mgr_get_iou_relations( &p_ext->ioc_mgr, p_irp );\r
393         switch( status )\r
394         {\r
395         case STATUS_NO_SUCH_DEVICE:\r
396                 *p_action = IrpSkip;\r
397                 status = STATUS_SUCCESS;\r
398                 break;\r
399 \r
400         case STATUS_SUCCESS:\r
401                 *p_action = IrpPassDown;\r
402                 break;\r
403 \r
404         default:\r
405                 *p_action = IrpComplete;\r
406                 break;\r
407         }\r
408 \r
409         IOU_EXIT( IOU_DBG_PNP );\r
410         return status;\r
411 }\r
412 \r
413 \r
414 static NTSTATUS\r
415 __fdo_query_power(\r
416         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
417         IN                              IRP* const                                      p_irp,\r
418                 OUT                     cl_irp_action_t* const          p_action )\r
419 {\r
420         NTSTATUS                        status = STATUS_SUCCESS;\r
421         IO_STACK_LOCATION       *p_io_stack;\r
422 \r
423         IOU_ENTER( IOU_DBG_POWER );\r
424 \r
425         UNUSED_PARAM( p_dev_obj );\r
426 \r
427         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
428 \r
429         switch( p_io_stack->Parameters.Power.Type )\r
430         {\r
431         case SystemPowerState:\r
432                 /* Fail any requests to hibernate or sleep the system. */\r
433                 switch( p_io_stack->Parameters.Power.State.SystemState )\r
434                 {\r
435                         case PowerSystemWorking:\r
436                         case PowerSystemShutdown:\r
437                                 /* We only support fully working and shutdown system states. */\r
438                                 break;\r
439 \r
440                         default:\r
441                                 status = STATUS_NOT_SUPPORTED;\r
442                 }\r
443                 break;\r
444 \r
445         case DevicePowerState:\r
446                 /* Fail any query for low power states. */\r
447                 switch( p_io_stack->Parameters.Power.State.DeviceState )\r
448                 {\r
449                 case PowerDeviceD0:\r
450                 case PowerDeviceD3:\r
451                         /* We only support fully powered or off power states. */\r
452                         break;\r
453 \r
454                 default:\r
455                         status = STATUS_NOT_SUPPORTED;\r
456                 }\r
457                 break;\r
458         }\r
459 \r
460         if( status == STATUS_NOT_SUPPORTED )\r
461                 *p_action = IrpComplete;\r
462         else\r
463                 *p_action = IrpSkip;\r
464 \r
465         IOU_EXIT( IOU_DBG_POWER );\r
466         return status;\r
467 }\r
468 \r
469 \r
470 static void\r
471 __request_power_completion(\r
472         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
473         IN                              UCHAR                                           minor_function,\r
474         IN                              POWER_STATE                                     power_state,\r
475         IN                              void                                            *context,\r
476         IN                              IO_STATUS_BLOCK                         *p_io_status )\r
477 {\r
478         IRP                                     *p_irp;\r
479         cl_pnp_po_ext_t         *p_ext;\r
480 \r
481         IOU_ENTER( IOU_DBG_PNP );\r
482 \r
483         UNUSED_PARAM( minor_function );\r
484         UNUSED_PARAM( power_state );\r
485 \r
486         p_irp = (IRP*)context;\r
487         p_ext = p_dev_obj->DeviceExtension;\r
488 \r
489         /* Propagate the device IRP status to the system IRP status. */\r
490         p_irp->IoStatus.Status = p_io_status->Status;\r
491 \r
492         /* Continue Power IRP processing. */\r
493         PoStartNextPowerIrp( p_irp );\r
494         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
495         IoReleaseRemoveLock( &p_ext->remove_lock, p_irp );\r
496         IOU_EXIT( IOU_DBG_PNP );\r
497 }\r
498 \r
499 \r
500 /*NOTE: Completion routines must NEVER be pageable. */\r
501 static NTSTATUS\r
502 __set_power_completion(\r
503         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
504         IN                              IRP                                                     *p_irp,\r
505         IN                              void                                            *context )\r
506 {\r
507         NTSTATUS                        status;\r
508         POWER_STATE                     state;\r
509         iou_fdo_ext_t           *p_ext;\r
510         IO_STACK_LOCATION       *p_io_stack;\r
511 \r
512         IOU_ENTER( IOU_DBG_PNP );\r
513 \r
514         UNUSED_PARAM( context );\r
515 \r
516         p_ext = p_dev_obj->DeviceExtension;\r
517         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
518 \r
519         if( !NT_SUCCESS( p_irp->IoStatus.Status ) )\r
520         {\r
521                 PoStartNextPowerIrp( p_irp );\r
522                 IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
523                 IOU_PRINT_EXIT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
524                         ("IRP_MN_SET_POWER for system failed by lower driver with %08x.\n",\r
525                         p_irp->IoStatus.Status) );\r
526                 return STATUS_SUCCESS;\r
527         }\r
528 \r
529         state.DeviceState = \r
530                 p_ext->po_state[p_io_stack->Parameters.Power.State.SystemState];\r
531 \r
532         /*\r
533          * Send a device power IRP to our devnode.  Using our device object will\r
534          * only work on win2k and other NT based systems.\r
535          */\r
536         status = PoRequestPowerIrp( p_dev_obj, IRP_MN_SET_POWER, state,\r
537                 __request_power_completion, p_irp, NULL );\r
538 \r
539         if( !NT_SUCCESS( p_irp->IoStatus.Status ) )\r
540         {\r
541                 PoStartNextPowerIrp( p_irp );\r
542                 /* Propagate the failure. */\r
543                 p_irp->IoStatus.Status = status;\r
544                 IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
545                 IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
546                 IOU_PRINT( TRACE_LEVEL_ERROR, IOU_DBG_ERROR,\r
547                         ("PoRequestPowerIrp returned %08x.\n", status) );\r
548         }\r
549 \r
550         IOU_EXIT( IOU_DBG_PNP );\r
551         return STATUS_MORE_PROCESSING_REQUIRED;\r
552 }\r
553 \r
554 \r
555 static NTSTATUS\r
556 __fdo_set_power(\r
557         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
558         IN                              IRP* const                                      p_irp,\r
559                 OUT                     cl_irp_action_t* const          p_action )\r
560 {\r
561         NTSTATUS                        status;\r
562         IO_STACK_LOCATION       *p_io_stack;\r
563         iou_fdo_ext_t           *p_ext;\r
564 \r
565         IOU_ENTER( IOU_DBG_POWER );\r
566 \r
567         p_ext = p_dev_obj->DeviceExtension;\r
568         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
569 \r
570         switch( p_io_stack->Parameters.Power.Type )\r
571         {\r
572         case SystemPowerState:\r
573                 /*\r
574                  * Process on the way up the stack.  We cannot block since the \r
575                  * power dispatch function can be called at elevated IRQL if the\r
576                  * device is in a paging/hibernation/crash dump path.\r
577                  */\r
578                 IoMarkIrpPending( p_irp );\r
579                 IoCopyCurrentIrpStackLocationToNext( p_irp );\r
580 #pragma warning( push, 3 )\r
581                 IoSetCompletionRoutine( p_irp, __set_power_completion, NULL, \r
582                         TRUE, TRUE, TRUE );\r
583 #pragma warning( pop )\r
584                 PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
585 \r
586                 *p_action = IrpDoNothing;\r
587                 status = STATUS_PENDING;\r
588                 break;\r
589 \r
590         case DevicePowerState:\r
591         default:\r
592                 /* Pass down and let the PDO driver handle it. */\r
593                 *p_action = IrpIgnore;\r
594                 status = STATUS_SUCCESS;\r
595                 break;\r
596         }\r
597 \r
598         IOU_EXIT( IOU_DBG_POWER );\r
599         return status;\r
600 }\r
601 \r
602 \r
603 void\r
604 update_relations(\r
605         IN                              cl_qlist_t*     const                   p_pdo_list,\r
606         IN      OUT                     DEVICE_RELATIONS* const         p_rel )\r
607 {\r
608         cl_list_item_t  *p_list_item;\r
609         iou_pdo_ext_t   *p_pdo_ext;\r
610 \r
611         IOU_ENTER( IOU_DBG_PNP );\r
612 \r
613         p_list_item = cl_qlist_head( p_pdo_list );\r
614         while( p_list_item != cl_qlist_end( p_pdo_list ) )\r
615         {\r
616                 p_pdo_ext = PARENT_STRUCT( p_list_item, iou_pdo_ext_t, list_item );\r
617 \r
618                 /* Move the list item to the next object. */\r
619                 p_list_item = cl_qlist_next( p_list_item );\r
620 \r
621                 if( !p_pdo_ext->b_present )\r
622                 {\r
623                         /*\r
624                          * We don't report a PDO that is no longer present.  This is how\r
625                          * the PDO will get cleaned up.\r
626                          */\r
627                         p_pdo_ext->b_reported_missing = TRUE;\r
628                         continue;\r
629                 }\r
630                 p_rel->Objects[p_rel->Count] = p_pdo_ext->cl_ext.p_pdo;\r
631                 ObReferenceObject( p_rel->Objects[p_rel->Count++] );\r
632         }\r
633 \r
634         IOU_EXIT( IOU_DBG_PNP );\r
635 }\r
636 \r
637 \r