📄 intpwr.c
字号:
KdPrint( ("SysPoCompletionRoutine - begins\n"));
//
// lower drivers failed this Irp
//
if(!NT_SUCCESS(ntStatus)) {
PoStartNextPowerIrp(Irp);
KdPrint( ("SysPoCompletionRoutine::"));
IntUsb_IoDecrement(DeviceExtension);
return STATUS_SUCCESS;
}
//
// ..otherwise update the cached system power state (IRP_MN_SET_POWER)
//
if(irpStack->MinorFunction == IRP_MN_SET_POWER) {
DeviceExtension->SysPower = irpStack->Parameters.Power.State.SystemState;
}
//
// queue device irp and return STATUS_MORE_PROCESSING_REQUIRED
//
SendDeviceIrp(DeviceObject, Irp);
KdPrint( ("SysPoCompletionRoutine - ends\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
VOID
SendDeviceIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP SIrp
)
/*++
Routine Description:
This routine is invoked from the completion routine of the system power
irp. This routine will PoRequest a device power irp. The system irp is
passed as a context to the the device power irp.
Arguments:
DeviceObject - pointer to device object
SIrp - system power irp.
Return Value:
None
--*/
{
NTSTATUS ntStatus;
POWER_STATE powState;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
SYSTEM_POWER_STATE systemState;
DEVICE_POWER_STATE devState;
PPOWER_COMPLETION_CONTEXT powerContext;
//
// initialize variables
//
irpStack = IoGetCurrentIrpStackLocation(SIrp);
systemState = irpStack->Parameters.Power.State.SystemState;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
KdPrint( ("SendDeviceIrp - begins\n"));
//
// Read out the D-IRP out of the S->D mapping array captured in QueryCap's.
// we can choose deeper sleep states than our mapping but never choose
// lighter ones.
//
devState = deviceExtension->DeviceCapabilities.DeviceState[systemState];
powState.DeviceState = devState;
powerContext = (PPOWER_COMPLETION_CONTEXT)
ExAllocatePool(NonPagedPool,
sizeof(POWER_COMPLETION_CONTEXT));
if(!powerContext) {
KdPrint( ("Failed to alloc memory for powerContext\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
else {
powerContext->DeviceObject = DeviceObject;
powerContext->SIrp = SIrp;
//
// in win2k PoRequestPowerIrp can take fdo or pdo.
//
ntStatus = PoRequestPowerIrp(
deviceExtension->PhysicalDeviceObject,
irpStack->MinorFunction,
powState,
(PREQUEST_POWER_COMPLETE)DevPoCompletionRoutine,
powerContext,
NULL);
}
if(!NT_SUCCESS(ntStatus)) {
if(powerContext) {
ExFreePool(powerContext);
}
PoStartNextPowerIrp(SIrp);
SIrp->IoStatus.Status = ntStatus;
SIrp->IoStatus.Information = 0;
IoCompleteRequest(SIrp, IO_NO_INCREMENT);
KdPrint( ("SendDeviceIrp::"));
IntUsb_IoDecrement(deviceExtension);
}
KdPrint( ("SendDeviceIrp - ends\n"));
}
VOID
DevPoCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
/*++
Routine Description:
This is the PoRequest - completion routine for the device power irp.
This routine is responsible for completing the system power irp,
received as a context.
Arguments:
DeviceObject - pointer to device object
MinorFunction - minor function of the irp.
PowerState - power state of the irp.
Context - context passed to the completion routine.
IoStatus - status of the device power irp.
Return Value:
None
--*/
{
PIRP sIrp;
PDEVICE_EXTENSION deviceExtension;
PPOWER_COMPLETION_CONTEXT powerContext;
//
// initialize variables
//
powerContext = (PPOWER_COMPLETION_CONTEXT) Context;
sIrp = powerContext->SIrp;
deviceExtension = powerContext->DeviceObject->DeviceExtension;
KdPrint( ("DevPoCompletionRoutine - begins\n"));
//
// copy the D-Irp status into S-Irp
//
sIrp->IoStatus.Status = IoStatus->Status;
//
// complete the system Irp
//
PoStartNextPowerIrp(sIrp);
sIrp->IoStatus.Information = 0;
IoCompleteRequest(sIrp, IO_NO_INCREMENT);
//
// cleanup
//
KdPrint( ("DevPoCompletionRoutine::"));
IntUsb_IoDecrement(deviceExtension);
ExFreePool(powerContext);
KdPrint( ("DevPoCompletionRoutine - ends\n"));
}
NTSTATUS
HandleDeviceSetPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine services irps of minor type IRP_MN_SET_POWER
for the device power state
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet sent by the power manager
Return Value:
NT status value
--*/
{
KIRQL oldIrql;
NTSTATUS ntStatus;
POWER_STATE newState;
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
DEVICE_POWER_STATE newDevState,
oldDevState;
KdPrint( ("HandleDeviceSetPower - begins\n"));
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
oldDevState = deviceExtension->DevPower;
newState = irpStack->Parameters.Power.State;
newDevState = newState.DeviceState;
KdPrint( ("Set request for device power state D%X\n"
"Current device power state D%X\n",
newDevState - 1,
deviceExtension->DevPower - 1));
if(newDevState < oldDevState) {
//
// adding power
//
KdPrint( ("Adding power to the device\n"));
//
// send the power IRP to the next driver in the stack
//
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(
Irp,
(PIO_COMPLETION_ROUTINE)FinishDevPoUpIrp,
deviceExtension,
TRUE,
TRUE,
TRUE);
ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
}
else {
//
// newDevState >= oldDevState
//
// hold I/O if transition from D0 -> DX (X = 1, 2, 3)
// if transition from D1 or D2 to deeper sleep states,
// I/O queue is already on hold.
//
if(PowerDeviceD0 == oldDevState && newDevState > oldDevState) {
//
// D0 -> DX transition
//
KdPrint( ("Removing power from the device\n"));
ntStatus = HoldIoRequests(DeviceObject, Irp);
if(!NT_SUCCESS(ntStatus)) {
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KdPrint( ("HandleDeviceSetPower::"));
IntUsb_IoDecrement(deviceExtension);
return ntStatus;
}
else {
goto HandleDeviceSetPower_Exit;
}
}
else if(PowerDeviceD0 == oldDevState && PowerDeviceD0 == newDevState) {
//
// D0 -> D0
// unblock the queue which may have been blocked processing
// query irp
//
KdPrint( ("A SetD0 request\n"));
KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
deviceExtension->QueueState = AllowRequests;
KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
ProcessQueuedRequests(deviceExtension);
}
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(
Irp,
(PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp,
deviceExtension,
TRUE,
TRUE,
TRUE);
ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
if(!NT_SUCCESS(ntStatus)) {
KdPrint( ("Lower drivers failed a power Irp\n"));
}
}
HandleDeviceSetPower_Exit:
KdPrint( ("HandleDeviceSetPower - ends\n"));
return STATUS_PENDING;
}
NTSTATUS
FinishDevPoUpIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
completion routine for the device power UP irp with minor function
IRP_MN_SET_POWER.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
DeviceExtension - pointer to device extension
Return Value:
NT status value
--*/
{
NTSTATUS ntStatus;
//
// initialize variables
//
ntStatus = Irp->IoStatus.Status;
KdPrint( ("FinishDevPoUpIrp - begins\n"));
if(Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
if(!NT_SUCCESS(ntStatus)) {
PoStartNextPowerIrp(Irp);
KdPrint( ("FinishDevPoUpIrp::"));
IntUsb_IoDecrement(DeviceExtension);
return STATUS_SUCCESS;
}
SetDeviceFunctional(DeviceObject, Irp, DeviceExtension);
KdPrint( ("FinishDevPoUpIrp - ends\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
SetDeviceFunctional(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
This routine processes queue of pending irps.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
DeviceExtension - pointer to device extension
Return Value:
NT status value
--*/
{
KIRQL oldIrql;
NTSTATUS ntStatus;
POWER_STATE newState;
PIO_STACK_LOCATION irpStack;
DEVICE_POWER_STATE newDevState,
oldDevState;
//
// initialize variables
//
ntStatus = Irp->IoStatus.Status;
irpStack = IoGetCurrentIrpStackLocation(Irp);
newState = irpStack->Parameters.Power.State;
newDevState = newState.DeviceState;
oldDevState = DeviceExtension->DevPower;
KdPrint( ("SetDeviceFunctional - begins\n"));
//
// update the cached state
//
DeviceExtension->DevPower = newDevState;
//
// restore appropriate amount of state to our h/w
// this driver does not implement partial context
// save/restore.
//
PoSetPowerState(DeviceObject, DevicePowerState, newState);
if(PowerDeviceD0 == newDevState) {
//
// empty existing queue of all pending irps.
//
KeAcquireSpinLock(&DeviceExtension->DevStateLock, &oldIrql);
DeviceExtension->QueueState = AllowRequests;
KeReleaseSpinLock(&DeviceExtension->DevStateLock, oldIrql);
ProcessQueuedRequests(DeviceExtension);
}
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KdPrint( ("SetDeviceFunctional::"));
IntUsb_IoDecrement(DeviceExtension);
KdPrint( ("SetDeviceFunctional - ends\n"));
return STATUS_SUCCESS;
}
NTSTATUS
FinishDevPoDnIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
This routine is the completion routine for device power DOWN irp.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
DeviceExtension - pointer to device extension
Return Value:
NT status value
--*/
{
NTSTATUS ntStatus;
POWER_STATE newState;
PIO_STACK_LOCATION irpStack;
//
// initialize variables
//
ntStatus = Irp->IoStatus.Status;
irpStack = IoGetCurrentIrpStackLocation(Irp);
newState = irpStack->Parameters.Power.State;
KdPrint( ("FinishDevPoDnIrp - begins\n"));
if(NT_SUCCESS(ntStatus) && irpStack->MinorFunction == IRP_MN_SET_POWER) {
//
// update the cache;
//
KdPrint( ("updating cache..\n"));
DeviceExtension->DevPower = newState.DeviceState;
PoSetPowerState(DeviceObject, DevicePowerState, newState);
}
PoStartNextPowerIrp(Irp);
KdPrint( ("FinishDevPoDnIrp::"));
IntUsb_IoDecrement(DeviceExtension);
KdPrint( ("FinishDevPoDnIrp - ends\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -