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
);
144 case IRP_MN_READ_CONFIG
:
145 DPRINT("IRP_MN_READ_CONFIG\n");
146 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
147 return PcCompleteIrp(DeviceObject
, Irp
, Status
);
150 DPRINT("unhandled function %u\n", IoStack
->MinorFunction
);
152 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
153 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
154 return STATUS_UNSUCCESSFUL
;
159 PwrCompletionFunction(
160 IN PDEVICE_OBJECT DeviceObject
,
161 IN UCHAR MinorFunction
,
162 IN POWER_STATE PowerState
,
164 IN PIO_STATUS_BLOCK IoStatus
)
167 PQUERY_POWER_CONTEXT PwrContext
= (PQUERY_POWER_CONTEXT
)Context
;
169 if (NT_SUCCESS(IoStatus
->Status
))
171 // forward request to lower device object
172 Status
= PcForwardIrpSynchronous(PwrContext
->DeviceObject
, PwrContext
->Irp
);
177 Status
= IoStatus
->Status
;
180 // start next power irp
181 PoStartNextPowerIrp(PwrContext
->Irp
);
184 PwrContext
->Irp
->IoStatus
.Status
= Status
;
185 IoCompleteRequest(PwrContext
->Irp
, IO_NO_INCREMENT
);
188 FreeItem(PwrContext
, TAG_PORTCLASS
);
195 IN PDEVICE_OBJECT DeviceObject
,
198 PIO_STACK_LOCATION IoStack
;
199 PPCLASS_DEVICE_EXTENSION DeviceExtension
;
200 PQUERY_POWER_CONTEXT PwrContext
;
201 POWER_STATE PowerState
;
202 NTSTATUS Status
= STATUS_SUCCESS
;
204 DPRINT("PortClsPower called\n");
206 // get currrent stack location
207 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
209 if (IoStack
->MinorFunction
!= IRP_MN_SET_POWER
&& IoStack
->MinorFunction
!= IRP_MN_QUERY_POWER
)
211 // just forward the request
212 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
214 // start next power irp
215 PoStartNextPowerIrp(Irp
);
218 Irp
->IoStatus
.Status
= Status
;
219 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
226 // get device extension
227 DeviceExtension
= (PPCLASS_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
229 // get current request type
230 if (IoStack
->Parameters
.Power
.Type
== DevicePowerState
)
232 // request for device power state
233 if (DeviceExtension
->DevicePowerState
== IoStack
->Parameters
.Power
.State
.DeviceState
)
235 // nothing has changed
236 if (IoStack
->MinorFunction
== IRP_MN_QUERY_POWER
)
238 // only forward query requests
239 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
242 // start next power irp
243 PoStartNextPowerIrp(Irp
);
246 Irp
->IoStatus
.Status
= Status
;
247 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
253 if (IoStack
->MinorFunction
== IRP_MN_QUERY_POWER
)
255 // check if there is a registered adapter power management
256 if (DeviceExtension
->AdapterPowerManagement
)
258 // it is query if the change can be changed
259 PowerState
= *((POWER_STATE
*)&IoStack
->Parameters
.Power
.State
.DeviceState
);
260 Status
= DeviceExtension
->AdapterPowerManagement
->QueryPowerChangeState(PowerState
);
263 PC_ASSERT(Status
== STATUS_SUCCESS
);
266 // only forward query requests
267 PcForwardIrpSynchronous(DeviceObject
, Irp
);
269 // start next power irp
270 PoStartNextPowerIrp(Irp
);
273 Irp
->IoStatus
.Status
= Status
;
274 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
282 PowerState
= *((POWER_STATE
*)&IoStack
->Parameters
.Power
.State
.DeviceState
);
283 PoSetPowerState(DeviceObject
, DevicePowerState
, PowerState
);
285 // check if there is a registered adapter power management
286 if (DeviceExtension
->AdapterPowerManagement
)
288 // notify of a power change state
289 DeviceExtension
->AdapterPowerManagement
->PowerChangeState(PowerState
);
292 // FIXME call all registered IPowerNotify interfaces via ISubdevice interface
294 // store new power state
295 DeviceExtension
->DevicePowerState
= IoStack
->Parameters
.Power
.State
.DeviceState
;
298 Irp
->IoStatus
.Status
= Status
;
299 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
308 PC_ASSERT(IoStack
->Parameters
.Power
.Type
== SystemPowerState
);
310 if (IoStack
->MinorFunction
== IRP_MN_QUERY_POWER
)
312 // mark irp as pending
313 IoMarkIrpPending(Irp
);
315 // allocate power completion context
316 PwrContext
= (PQUERY_POWER_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(QUERY_POWER_CONTEXT
), TAG_PORTCLASS
);
321 PoStartNextPowerIrp(Irp
);
323 // complete and forget
324 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
325 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
331 // setup power context
332 PwrContext
->Irp
= Irp
;
333 PwrContext
->DeviceObject
= DeviceObject
;
336 PowerState
= *((POWER_STATE
*)IoStack
->Parameters
.Power
.State
.SystemState
);
337 Status
= PoRequestPowerIrp(DeviceExtension
->PhysicalDeviceObject
, IoStack
->MinorFunction
, PowerState
, PwrCompletionFunction
, (PVOID
)PwrContext
, NULL
);
340 if (!NT_SUCCESS(Status
))
343 Irp
->IoStatus
.Status
= Status
;
344 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
351 return STATUS_PENDING
;
356 DeviceExtension
->SystemPowerState
= IoStack
->Parameters
.Power
.State
.SystemState
;
358 // only forward query requests
359 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
361 // start next power irp
362 PoStartNextPowerIrp(Irp
);
365 Irp
->IoStatus
.Status
= Status
;
366 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
377 IN PDEVICE_OBJECT DeviceObject
,
380 DPRINT("PortClsSysControl called\n");
384 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
385 Irp
->IoStatus
.Information
= 0;
386 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
388 return STATUS_SUCCESS
;
394 IN PDEVICE_OBJECT DeviceObject
,
397 PPCLASS_DEVICE_EXTENSION DeviceExtension
;
398 DPRINT("PortClsShutdown called\n");
400 // get device extension
401 DeviceExtension
= (PPCLASS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
403 if (DeviceExtension
->AdapterPowerManagement
)
405 // release adapter power management
406 DPRINT("Power %u\n", DeviceExtension
->AdapterPowerManagement
->Release());
409 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
410 Irp
->IoStatus
.Information
= 0;
411 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
413 return STATUS_SUCCESS
;
419 IN PDEVICE_OBJECT DeviceObject
,
422 PIO_STACK_LOCATION IoStack
;
424 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
426 DPRINT("PcDispatchIrp called - handling IRP in PortCls MajorFunction %x MinorFunction %x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
428 switch ( IoStack
->MajorFunction
)
432 return PortClsCreate(DeviceObject
, Irp
);
435 return PortClsPnp(DeviceObject
, Irp
);
438 return PortClsPower(DeviceObject
, Irp
);
440 case IRP_MJ_DEVICE_CONTROL
:
441 return KsDispatchIrp(DeviceObject
, Irp
);
444 return KsDispatchIrp(DeviceObject
, Irp
);
446 case IRP_MJ_SYSTEM_CONTROL
:
447 return PortClsSysControl(DeviceObject
, Irp
);
449 case IRP_MJ_SHUTDOWN
:
450 return PortClsShutdown(DeviceObject
, Irp
);
453 DPRINT("Unhandled function %x\n", IoStack
->MajorFunction
);
457 // If we reach here, we just complete the IRP
458 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
459 Irp
->IoStatus
.Information
= 0;
460 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
462 return STATUS_SUCCESS
;
469 IN PDEVICE_OBJECT DeviceObject
,
474 PC_ASSERT(DeviceObject
);
476 PC_ASSERT(Status
!= STATUS_PENDING
);
479 Irp
->IoStatus
.Status
= Status
;
480 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
488 IN PDEVICE_OBJECT DeviceObject
,
492 if (Irp
->PendingReturned
== TRUE
)
494 KeSetEvent ((PKEVENT
) Context
, IO_NO_INCREMENT
, FALSE
);
496 return STATUS_MORE_PROCESSING_REQUIRED
;
499 #undef IoSetCompletionRoutine
500 #define IoSetCompletionRoutine(_Irp, \
501 _CompletionRoutine, \
507 PIO_STACK_LOCATION _IrpSp; \
508 _IrpSp = IoGetNextIrpStackLocation(_Irp); \
509 _IrpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)(_CompletionRoutine); \
510 _IrpSp->Context = (_Context); \
511 _IrpSp->Control = 0; \
512 if (_InvokeOnSuccess) _IrpSp->Control = SL_INVOKE_ON_SUCCESS; \
513 if (_InvokeOnError) _IrpSp->Control |= SL_INVOKE_ON_ERROR; \
514 if (_InvokeOnCancel) _IrpSp->Control |= SL_INVOKE_ON_CANCEL; \
521 PcForwardIrpSynchronous(
522 IN PDEVICE_OBJECT DeviceObject
,
526 PPCLASS_DEVICE_EXTENSION DeviceExt
;
529 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
531 DeviceExt
= (PPCLASS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
533 // initialize the notification event
534 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
536 IoCopyCurrentIrpStackLocationToNext(Irp
);
538 IoSetCompletionRoutine(Irp
, CompletionRoutine
, (PVOID
)&Event
, TRUE
, TRUE
, TRUE
);
540 // now call the driver
541 Status
= IoCallDriver(DeviceExt
->PrevDeviceObject
, Irp
);
542 // did the request complete yet
543 if (Status
== STATUS_PENDING
)
545 // not yet, lets wait a bit
546 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
547 Status
= Irp
->IoStatus
.Status
;