2 * COPYRIGHT: See COPYING in the top level directory
4 * FILE: drivers/wdm/audio/backpln/portcls/irp.cpp
5 * PURPOSE: Port Class driver / IRP Handling
6 * PROGRAMMER: Andrew Greenwood
13 #include "private.hpp"
18 PDEVICE_OBJECT DeviceObject
;
19 }QUERY_POWER_CONTEXT
, *PQUERY_POWER_CONTEXT
;
25 IN PDEVICE_OBJECT DeviceObject
,
28 DPRINT("PortClsCreate called\n");
30 return KsDispatchIrp(DeviceObject
, Irp
);
37 IN PDEVICE_OBJECT DeviceObject
,
41 PPCLASS_DEVICE_EXTENSION DeviceExt
;
42 PIO_STACK_LOCATION IoStack
;
43 POWER_STATE PowerState
;
44 IResourceList
* resource_list
= NULL
;
46 //PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor, UnPartialDescriptor;
48 DeviceExt
= (PPCLASS_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
49 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
52 DPRINT("PortClsPnp called %u\n", IoStack
->MinorFunction
);
54 //PC_ASSERT(DeviceExt);
56 switch (IoStack
->MinorFunction
)
58 case IRP_MN_START_DEVICE
:
59 DPRINT("IRP_MN_START_DEVICE\n");
61 // Create the resource list
62 Status
= PcNewResourceList(
66 IoStack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
,
67 IoStack
->Parameters
.StartDevice
.AllocatedResources
);
68 if (!NT_SUCCESS(Status
))
70 DPRINT("PcNewResourceList failed [0x%8x]\n", Status
);
71 Irp
->IoStatus
.Status
= Status
;
72 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
76 // forward irp to lower device object
77 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
79 if (!NT_SUCCESS(Status
))
81 // lower device object failed to start
82 resource_list
->Release();
83 // complete the request
84 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
90 //PC_ASSERT(DeviceExt->StartDevice);
91 // Call the StartDevice routine
92 DPRINT("Calling StartDevice at 0x%8p\n", DeviceExt
->StartDevice
);
93 Status
= DeviceExt
->StartDevice(DeviceObject
, Irp
, resource_list
);
94 if (!NT_SUCCESS(Status
))
96 DPRINT("StartDevice returned a failure code [0x%8x]\n", Status
);
97 Irp
->IoStatus
.Status
= Status
;
98 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
102 // Assign the resource list to our extension
103 DeviceExt
->resources
= resource_list
;
105 // store device power state
106 DeviceExt
->DevicePowerState
= PowerDeviceD0
;
107 DeviceExt
->SystemPowerState
= PowerSystemWorking
;
109 // notify power manager of current state
110 PowerState
= *((POWER_STATE
*)&DeviceExt
->DevicePowerState
);
111 PoSetPowerState(DeviceObject
, DevicePowerState
, PowerState
);
113 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
114 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
117 case IRP_MN_REMOVE_DEVICE
:
119 DPRINT("IRP_MN_REMOVE_DEVICE\n");
121 DeviceExt
->resources
->Release();
122 IoDeleteDevice(DeviceObject
);
125 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
126 return PcCompleteIrp(DeviceObject
, Irp
, Status
);
128 case IRP_MN_QUERY_INTERFACE
:
129 DPRINT("IRP_MN_QUERY_INTERFACE\n");
130 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
131 return PcCompleteIrp(DeviceObject
, Irp
, Status
);
132 case IRP_MN_QUERY_DEVICE_RELATIONS
:
133 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
134 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
135 return PcCompleteIrp(DeviceObject
, Irp
, Status
);
136 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
137 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
138 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
139 return PcCompleteIrp(DeviceObject
, Irp
, Status
);
140 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
141 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
142 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
143 return PcCompleteIrp(DeviceObject
, Irp
, Status
);
146 DPRINT("unhandled function %u\n", IoStack
->MinorFunction
);
148 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
149 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
150 return STATUS_UNSUCCESSFUL
;
155 PwrCompletionFunction(
156 IN PDEVICE_OBJECT DeviceObject
,
157 IN UCHAR MinorFunction
,
158 IN POWER_STATE PowerState
,
160 IN PIO_STATUS_BLOCK IoStatus
)
163 PQUERY_POWER_CONTEXT PwrContext
= (PQUERY_POWER_CONTEXT
)Context
;
165 if (NT_SUCCESS(IoStatus
->Status
))
167 // forward request to lower device object
168 Status
= PcForwardIrpSynchronous(PwrContext
->DeviceObject
, PwrContext
->Irp
);
173 Status
= IoStatus
->Status
;
176 // start next power irp
177 PoStartNextPowerIrp(PwrContext
->Irp
);
180 PwrContext
->Irp
->IoStatus
.Status
= Status
;
181 IoCompleteRequest(PwrContext
->Irp
, IO_NO_INCREMENT
);
184 FreeItem(PwrContext
, TAG_PORTCLASS
);
191 IN PDEVICE_OBJECT DeviceObject
,
194 PIO_STACK_LOCATION IoStack
;
195 PPCLASS_DEVICE_EXTENSION DeviceExtension
;
196 PQUERY_POWER_CONTEXT PwrContext
;
197 POWER_STATE PowerState
;
198 NTSTATUS Status
= STATUS_SUCCESS
;
200 DPRINT("PortClsPower called\n");
202 // get currrent stack location
203 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
205 if (IoStack
->MinorFunction
!= IRP_MN_SET_POWER
&& IoStack
->MinorFunction
!= IRP_MN_QUERY_POWER
)
207 // just forward the request
208 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
210 // start next power irp
211 PoStartNextPowerIrp(Irp
);
214 Irp
->IoStatus
.Status
= Status
;
215 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
222 // get device extension
223 DeviceExtension
= (PPCLASS_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
225 // get current request type
226 if (IoStack
->Parameters
.Power
.Type
== DevicePowerState
)
228 // request for device power state
229 if (DeviceExtension
->DevicePowerState
== IoStack
->Parameters
.Power
.State
.DeviceState
)
231 // nothing has changed
232 if (IoStack
->MinorFunction
== IRP_MN_QUERY_POWER
)
234 // only forward query requests
235 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
238 // start next power irp
239 PoStartNextPowerIrp(Irp
);
242 Irp
->IoStatus
.Status
= Status
;
243 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
249 if (IoStack
->MinorFunction
== IRP_MN_QUERY_POWER
)
251 // check if there is a registered adapter power management
252 if (DeviceExtension
->AdapterPowerManagement
)
254 // it is query if the change can be changed
255 PowerState
= *((POWER_STATE
*)&IoStack
->Parameters
.Power
.State
.DeviceState
);
256 Status
= DeviceExtension
->AdapterPowerManagement
->QueryPowerChangeState(PowerState
);
259 PC_ASSERT(Status
== STATUS_SUCCESS
);
262 // only forward query requests
263 PcForwardIrpSynchronous(DeviceObject
, Irp
);
265 // start next power irp
266 PoStartNextPowerIrp(Irp
);
269 Irp
->IoStatus
.Status
= Status
;
270 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
278 PowerState
= *((POWER_STATE
*)&IoStack
->Parameters
.Power
.State
.DeviceState
);
279 PoSetPowerState(DeviceObject
, DevicePowerState
, PowerState
);
281 // check if there is a registered adapter power management
282 if (DeviceExtension
->AdapterPowerManagement
)
284 // notify of a power change state
285 DeviceExtension
->AdapterPowerManagement
->PowerChangeState(PowerState
);
288 // FIXME call all registered IPowerNotify interfaces via ISubdevice interface
290 // store new power state
291 DeviceExtension
->DevicePowerState
= IoStack
->Parameters
.Power
.State
.DeviceState
;
294 Irp
->IoStatus
.Status
= Status
;
295 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
304 PC_ASSERT(IoStack
->Parameters
.Power
.Type
== SystemPowerState
);
306 if (IoStack
->MinorFunction
== IRP_MN_QUERY_POWER
)
308 // mark irp as pending
309 IoMarkIrpPending(Irp
);
311 // allocate power completion context
312 PwrContext
= (PQUERY_POWER_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(QUERY_POWER_CONTEXT
), TAG_PORTCLASS
);
317 PoStartNextPowerIrp(Irp
);
319 // complete and forget
320 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
321 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
327 // setup power context
328 PwrContext
->Irp
= Irp
;
329 PwrContext
->DeviceObject
= DeviceObject
;
332 PowerState
= *((POWER_STATE
*)IoStack
->Parameters
.Power
.State
.SystemState
);
333 Status
= PoRequestPowerIrp(DeviceExtension
->PhysicalDeviceObject
, IoStack
->MinorFunction
, PowerState
, PwrCompletionFunction
, (PVOID
)PwrContext
, NULL
);
336 if (!NT_SUCCESS(Status
))
339 Irp
->IoStatus
.Status
= Status
;
340 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
347 return STATUS_PENDING
;
352 DeviceExtension
->SystemPowerState
= IoStack
->Parameters
.Power
.State
.SystemState
;
354 // only forward query requests
355 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
357 // start next power irp
358 PoStartNextPowerIrp(Irp
);
361 Irp
->IoStatus
.Status
= Status
;
362 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
373 IN PDEVICE_OBJECT DeviceObject
,
376 DPRINT("PortClsSysControl called\n");
380 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
381 Irp
->IoStatus
.Information
= 0;
382 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
384 return STATUS_SUCCESS
;
390 IN PDEVICE_OBJECT DeviceObject
,
393 PPCLASS_DEVICE_EXTENSION DeviceExtension
;
394 DPRINT("PortClsShutdown called\n");
396 // get device extension
397 DeviceExtension
= (PPCLASS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
399 if (DeviceExtension
->AdapterPowerManagement
)
401 // release adapter power management
402 DPRINT("Power %u\n", DeviceExtension
->AdapterPowerManagement
->Release());
405 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
406 Irp
->IoStatus
.Information
= 0;
407 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
409 return STATUS_SUCCESS
;
415 IN PDEVICE_OBJECT DeviceObject
,
418 PIO_STACK_LOCATION IoStack
;
420 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
422 DPRINT("PcDispatchIrp called - handling IRP in PortCls MajorFunction %x MinorFunction %x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
424 switch ( IoStack
->MajorFunction
)
428 return PortClsCreate(DeviceObject
, Irp
);
431 return PortClsPnp(DeviceObject
, Irp
);
434 return PortClsPower(DeviceObject
, Irp
);
436 case IRP_MJ_DEVICE_CONTROL
:
437 return KsDispatchIrp(DeviceObject
, Irp
);
440 return KsDispatchIrp(DeviceObject
, Irp
);
442 case IRP_MJ_SYSTEM_CONTROL
:
443 return PortClsSysControl(DeviceObject
, Irp
);
445 case IRP_MJ_SHUTDOWN
:
446 return PortClsShutdown(DeviceObject
, Irp
);
449 DPRINT("Unhandled function %x\n", IoStack
->MajorFunction
);
453 // If we reach here, we just complete the IRP
454 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
455 Irp
->IoStatus
.Information
= 0;
456 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
458 return STATUS_SUCCESS
;
465 IN PDEVICE_OBJECT DeviceObject
,
470 PC_ASSERT(DeviceObject
);
472 PC_ASSERT(Status
!= STATUS_PENDING
);
475 Irp
->IoStatus
.Status
= Status
;
476 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
484 IN PDEVICE_OBJECT DeviceObject
,
488 if (Irp
->PendingReturned
== TRUE
)
490 KeSetEvent ((PKEVENT
) Context
, IO_NO_INCREMENT
, FALSE
);
492 return STATUS_MORE_PROCESSING_REQUIRED
;
495 #undef IoSetCompletionRoutine
496 #define IoSetCompletionRoutine(_Irp, \
497 _CompletionRoutine, \
503 PIO_STACK_LOCATION _IrpSp; \
504 _IrpSp = IoGetNextIrpStackLocation(_Irp); \
505 _IrpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)(_CompletionRoutine); \
506 _IrpSp->Context = (_Context); \
507 _IrpSp->Control = 0; \
508 if (_InvokeOnSuccess) _IrpSp->Control = SL_INVOKE_ON_SUCCESS; \
509 if (_InvokeOnError) _IrpSp->Control |= SL_INVOKE_ON_ERROR; \
510 if (_InvokeOnCancel) _IrpSp->Control |= SL_INVOKE_ON_CANCEL; \
517 PcForwardIrpSynchronous(
518 IN PDEVICE_OBJECT DeviceObject
,
522 PPCLASS_DEVICE_EXTENSION DeviceExt
;
525 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
527 DeviceExt
= (PPCLASS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
529 // initialize the notification event
530 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
532 IoCopyCurrentIrpStackLocationToNext(Irp
);
534 IoSetCompletionRoutine(Irp
, CompletionRoutine
, (PVOID
)&Event
, TRUE
, TRUE
, TRUE
);
536 // now call the driver
537 Status
= IoCallDriver(DeviceExt
->PrevDeviceObject
, Irp
);
538 // did the request complete yet
539 if (Status
== STATUS_PENDING
)
541 // not yet, lets wait a bit
542 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
543 Status
= Irp
->IoStatus
.Status
;