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");
122 PC_ASSERT(DeviceExt
);
124 // FIXME more cleanup */
125 if (DeviceExt
->resources
)
127 // free resource list */
128 DeviceExt
->resources
->Release();
131 DeviceExt
->resources
= NULL
;
135 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
137 return PcCompleteIrp(DeviceObject
, Irp
, Status
);
139 case IRP_MN_QUERY_INTERFACE
:
140 DPRINT("IRP_MN_QUERY_INTERFACE\n");
141 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
142 return PcCompleteIrp(DeviceObject
, Irp
, Status
);
143 case IRP_MN_QUERY_DEVICE_RELATIONS
:
144 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
145 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
146 return PcCompleteIrp(DeviceObject
, Irp
, Status
);
147 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
148 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
149 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
150 return PcCompleteIrp(DeviceObject
, Irp
, Status
);
151 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
152 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
153 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
154 return PcCompleteIrp(DeviceObject
, Irp
, Status
);
155 case IRP_MN_READ_CONFIG
:
156 DPRINT("IRP_MN_READ_CONFIG\n");
157 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
158 return PcCompleteIrp(DeviceObject
, Irp
, Status
);
161 DPRINT("unhandled function %u\n", IoStack
->MinorFunction
);
163 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
164 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
165 return STATUS_UNSUCCESSFUL
;
170 PwrCompletionFunction(
171 IN PDEVICE_OBJECT DeviceObject
,
172 IN UCHAR MinorFunction
,
173 IN POWER_STATE PowerState
,
175 IN PIO_STATUS_BLOCK IoStatus
)
178 PQUERY_POWER_CONTEXT PwrContext
= (PQUERY_POWER_CONTEXT
)Context
;
180 if (NT_SUCCESS(IoStatus
->Status
))
182 // forward request to lower device object
183 Status
= PcForwardIrpSynchronous(PwrContext
->DeviceObject
, PwrContext
->Irp
);
188 Status
= IoStatus
->Status
;
191 // start next power irp
192 PoStartNextPowerIrp(PwrContext
->Irp
);
195 PwrContext
->Irp
->IoStatus
.Status
= Status
;
196 IoCompleteRequest(PwrContext
->Irp
, IO_NO_INCREMENT
);
199 FreeItem(PwrContext
, TAG_PORTCLASS
);
206 IN PDEVICE_OBJECT DeviceObject
,
209 PIO_STACK_LOCATION IoStack
;
210 PPCLASS_DEVICE_EXTENSION DeviceExtension
;
211 PQUERY_POWER_CONTEXT PwrContext
;
212 POWER_STATE PowerState
;
213 NTSTATUS Status
= STATUS_SUCCESS
;
215 DPRINT("PortClsPower called\n");
217 // get currrent stack location
218 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
220 if (IoStack
->MinorFunction
!= IRP_MN_SET_POWER
&& IoStack
->MinorFunction
!= IRP_MN_QUERY_POWER
)
222 // just forward the request
223 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
225 // start next power irp
226 PoStartNextPowerIrp(Irp
);
229 Irp
->IoStatus
.Status
= Status
;
230 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
237 // get device extension
238 DeviceExtension
= (PPCLASS_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
240 // get current request type
241 if (IoStack
->Parameters
.Power
.Type
== DevicePowerState
)
243 // request for device power state
244 if (DeviceExtension
->DevicePowerState
== IoStack
->Parameters
.Power
.State
.DeviceState
)
246 // nothing has changed
247 if (IoStack
->MinorFunction
== IRP_MN_QUERY_POWER
)
249 // only forward query requests
250 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
253 // start next power irp
254 PoStartNextPowerIrp(Irp
);
257 Irp
->IoStatus
.Status
= Status
;
258 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
264 if (IoStack
->MinorFunction
== IRP_MN_QUERY_POWER
)
266 // check if there is a registered adapter power management
267 if (DeviceExtension
->AdapterPowerManagement
)
269 // it is query if the change can be changed
270 PowerState
= *((POWER_STATE
*)&IoStack
->Parameters
.Power
.State
.DeviceState
);
271 Status
= DeviceExtension
->AdapterPowerManagement
->QueryPowerChangeState(PowerState
);
274 PC_ASSERT(Status
== STATUS_SUCCESS
);
277 // only forward query requests
278 PcForwardIrpSynchronous(DeviceObject
, Irp
);
280 // start next power irp
281 PoStartNextPowerIrp(Irp
);
284 Irp
->IoStatus
.Status
= Status
;
285 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
293 PowerState
= *((POWER_STATE
*)&IoStack
->Parameters
.Power
.State
.DeviceState
);
294 PoSetPowerState(DeviceObject
, DevicePowerState
, PowerState
);
296 // check if there is a registered adapter power management
297 if (DeviceExtension
->AdapterPowerManagement
)
299 // notify of a power change state
300 DeviceExtension
->AdapterPowerManagement
->PowerChangeState(PowerState
);
303 // FIXME call all registered IPowerNotify interfaces via ISubdevice interface
305 // store new power state
306 DeviceExtension
->DevicePowerState
= IoStack
->Parameters
.Power
.State
.DeviceState
;
309 Irp
->IoStatus
.Status
= Status
;
310 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
319 PC_ASSERT(IoStack
->Parameters
.Power
.Type
== SystemPowerState
);
321 if (IoStack
->MinorFunction
== IRP_MN_QUERY_POWER
)
323 // mark irp as pending
324 IoMarkIrpPending(Irp
);
326 // allocate power completion context
327 PwrContext
= (PQUERY_POWER_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(QUERY_POWER_CONTEXT
), TAG_PORTCLASS
);
332 PoStartNextPowerIrp(Irp
);
334 // complete and forget
335 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
336 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
342 // setup power context
343 PwrContext
->Irp
= Irp
;
344 PwrContext
->DeviceObject
= DeviceObject
;
347 PowerState
= *((POWER_STATE
*)IoStack
->Parameters
.Power
.State
.SystemState
);
348 Status
= PoRequestPowerIrp(DeviceExtension
->PhysicalDeviceObject
, IoStack
->MinorFunction
, PowerState
, PwrCompletionFunction
, (PVOID
)PwrContext
, NULL
);
351 if (!NT_SUCCESS(Status
))
354 Irp
->IoStatus
.Status
= Status
;
355 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
362 return STATUS_PENDING
;
367 DeviceExtension
->SystemPowerState
= IoStack
->Parameters
.Power
.State
.SystemState
;
369 // only forward query requests
370 Status
= PcForwardIrpSynchronous(DeviceObject
, Irp
);
372 // start next power irp
373 PoStartNextPowerIrp(Irp
);
376 Irp
->IoStatus
.Status
= Status
;
377 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
388 IN PDEVICE_OBJECT DeviceObject
,
391 DPRINT("PortClsSysControl called\n");
395 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
396 Irp
->IoStatus
.Information
= 0;
397 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
399 return STATUS_SUCCESS
;
405 IN PDEVICE_OBJECT DeviceObject
,
408 PPCLASS_DEVICE_EXTENSION DeviceExtension
;
409 DPRINT("PortClsShutdown called\n");
411 // get device extension
412 DeviceExtension
= (PPCLASS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
414 if (DeviceExtension
->AdapterPowerManagement
)
416 // release adapter power management
417 DPRINT("Power %u\n", DeviceExtension
->AdapterPowerManagement
->Release());
420 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
421 Irp
->IoStatus
.Information
= 0;
422 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
424 return STATUS_SUCCESS
;
430 IN PDEVICE_OBJECT DeviceObject
,
433 PIO_STACK_LOCATION IoStack
;
435 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
437 DPRINT("PcDispatchIrp called - handling IRP in PortCls MajorFunction %x MinorFunction %x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
439 switch ( IoStack
->MajorFunction
)
443 return PortClsCreate(DeviceObject
, Irp
);
446 return PortClsPnp(DeviceObject
, Irp
);
449 return PortClsPower(DeviceObject
, Irp
);
451 case IRP_MJ_DEVICE_CONTROL
:
452 return KsDispatchIrp(DeviceObject
, Irp
);
455 return KsDispatchIrp(DeviceObject
, Irp
);
457 case IRP_MJ_SYSTEM_CONTROL
:
458 return PortClsSysControl(DeviceObject
, Irp
);
460 case IRP_MJ_SHUTDOWN
:
461 return PortClsShutdown(DeviceObject
, Irp
);
464 DPRINT("Unhandled function %x\n", IoStack
->MajorFunction
);
468 // If we reach here, we just complete the IRP
469 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
470 Irp
->IoStatus
.Information
= 0;
471 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
473 return STATUS_SUCCESS
;
480 IN PDEVICE_OBJECT DeviceObject
,
485 PC_ASSERT(DeviceObject
);
487 PC_ASSERT(Status
!= STATUS_PENDING
);
490 Irp
->IoStatus
.Status
= Status
;
491 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
499 IN PDEVICE_OBJECT DeviceObject
,
503 if (Irp
->PendingReturned
== TRUE
)
505 KeSetEvent ((PKEVENT
) Context
, IO_NO_INCREMENT
, FALSE
);
507 return STATUS_MORE_PROCESSING_REQUIRED
;
510 #undef IoSetCompletionRoutine
511 #define IoSetCompletionRoutine(_Irp, \
512 _CompletionRoutine, \
518 PIO_STACK_LOCATION _IrpSp; \
519 _IrpSp = IoGetNextIrpStackLocation(_Irp); \
520 _IrpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)(_CompletionRoutine); \
521 _IrpSp->Context = (_Context); \
522 _IrpSp->Control = 0; \
523 if (_InvokeOnSuccess) _IrpSp->Control = SL_INVOKE_ON_SUCCESS; \
524 if (_InvokeOnError) _IrpSp->Control |= SL_INVOKE_ON_ERROR; \
525 if (_InvokeOnCancel) _IrpSp->Control |= SL_INVOKE_ON_CANCEL; \
532 PcForwardIrpSynchronous(
533 IN PDEVICE_OBJECT DeviceObject
,
537 PPCLASS_DEVICE_EXTENSION DeviceExt
;
540 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
542 DeviceExt
= (PPCLASS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
544 // initialize the notification event
545 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
547 IoCopyCurrentIrpStackLocationToNext(Irp
);
549 IoSetCompletionRoutine(Irp
, CompletionRoutine
, (PVOID
)&Event
, TRUE
, TRUE
, TRUE
);
551 // now call the driver
552 Status
= IoCallDriver(DeviceExt
->PrevDeviceObject
, Irp
);
553 // did the request complete yet
554 if (Status
== STATUS_PENDING
)
556 // not yet, lets wait a bit
557 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
558 Status
= Irp
->IoStatus
.Status
;