📄 pwr.c
字号:
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = ntS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DPRINT(("HandleDeviceSetPower::"));
DevIoDecrement(deviceExtension);
return ntS;
} else {
goto HandleDeviceSetPower_Exit;
}
} else if(PowerDeviceD0 == oldDevState && PowerDeviceD0 == newDevState) {
//
// D0 -> D0
// unblock the queue which may have been blocked processing
// query irp
//
DPRINT(("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);
ntS = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
if(!NT_SUCCESS(ntS)) {
DPRINT(("Lower drivers failed a power Irp\n"));
}
}
HandleDeviceSetPower_Exit:
DPRINT(("HandleDeviceSetPower - ends\n"));
return STATUS_PENDING;
}
/*++
Routine Description:
The power dispatch routine.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT status code
--*/
NTSTATUS BulkUsb_DispatchPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
NTSTATUS ntS;
PIO_STACK_LOCATION irpStack;
DEVICE_EXTENSION * deviceExtension;
//
// initialize the variables
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
deviceExtension = (DEVICE_EXTENSION *)DeviceObject->DeviceExtension;
//
// We don't queue power Irps, we'll only check if the
// device was removed, otherwise we'll take appropriate
// action and send it to the next lower driver. In general
// drivers should not cause long delays while handling power
// IRPs. If a driver cannot handle a power IRP in a brief time,
// it should return STATUS_PENDING and queue all incoming
// IRPs until the IRP completes.
//
if(Removed == deviceExtension->DeviceState) {
//
// Even if a driver fails the IRP, it must nevertheless call
// PoStartNextPowerIrp to inform the Power Manager that it
// is ready to handle another power IRP.
//
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = ntS = STATUS_DELETE_PENDING;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return ntS;
}
if(NotStarted == deviceExtension->DeviceState) {
//
// if the device is not started yet, pass it down
//
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
}
DPRINT(("BulkUsb_DispatchPower::"));
DevIoIncrement(deviceExtension);
switch (irpStack->MinorFunction) {
case IRP_MN_SET_POWER:
//
// The Power Manager sends this IRP for one of the
// following reasons:
// 1) To notify drivers of a change to the system power state.
// 2) To change the power state of a device for which
// the Power Manager is performing idle detection.
// A driver sends IRP_MN_SET_POWER to change the power
// state of its device if it's a power policy owner for the
// device.
//
IoMarkIrpPending(Irp);
switch(irpStack->Parameters.Power.Type) {
case SystemPowerState:
HandleSystemSetPower(DeviceObject, Irp);
ntS = STATUS_PENDING;
break;
case DevicePowerState:
HandleDeviceSetPower(DeviceObject, Irp);
ntS = STATUS_PENDING;
break;
}
break;
case IRP_MN_QUERY_POWER:
//
// The Power Manager sends a power IRP with the minor
// IRP code IRP_MN_QUERY_POWER to determine whether it
// can safely change to the specified system power state
// (S1-S5) and to allow drivers to prepare for such a change.
// If a driver can put its device in the requested state,
// it sets status to STATUS_SUCCESS and passes the IRP down.
//
IoMarkIrpPending(Irp);
switch(irpStack->Parameters.Power.Type) {
case SystemPowerState:
HandleSystemQueryPower(DeviceObject, Irp);
ntS = STATUS_PENDING;
break;
case DevicePowerState:
HandleDeviceQueryPower(DeviceObject, Irp);
ntS = STATUS_PENDING;
break;
}
break;
case IRP_MN_WAIT_WAKE:
//
// The minor power IRP code IRP_MN_WAIT_WAKE provides
// for waking a device or waking the system. Drivers
// of devices that can wake themselves or the system
// send IRP_MN_WAIT_WAKE. The system sends IRP_MN_WAIT_WAKE
// only to devices that always wake the system, such as
// the power-on switch.
//
IoMarkIrpPending(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)WaitWakeCompletionRoutine,
deviceExtension, TRUE, TRUE, TRUE);
PoStartNextPowerIrp(Irp);
ntS = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
if(!NT_SUCCESS(ntS)) {
DPRINT(("Lower drivers failed the wait-wake Irp"));
}
ntS = STATUS_PENDING;
//
// push back the count HERE and NOT in completion routine
// a pending Wait Wake Irp should not impede stopping the device
//
DPRINT(("IRP_MN_WAIT_WAKE::"));
DevIoDecrement(deviceExtension);
break;
case IRP_MN_POWER_SEQUENCE:
//
// A driver sends this IRP as an optimization to determine
// whether its device actually entered a specific power state.
// This IRP is optional. Power Manager cannot send this IRP.
//
default:
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
ntS = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
if(!NT_SUCCESS(ntS)) {
DPRINT(("Lower drivers failed this Irp"));
}
DPRINT(("BulkUsb_DispatchPower::"));
DevIoDecrement(deviceExtension);
break;
}
return ntS;
}
/*********************************************************************
Routine Description:
This routine removes the irp from the queue and completes it with
STATUS_CANCELLED
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
Return Value:
None.
--*/
VOID CancelQueued(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) {
DEVICE_EXTENSION * deviceExtension;
KIRQL oldIrql;
//
// initialize variables
//
deviceExtension = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
oldIrql = Irp->CancelIrql;
DPRINT(("CancelQueued - begins\n"));
//
// Release the cancel spin lock
//
IoReleaseCancelSpinLock(Irp->CancelIrql);
//
// Acquire the queue lock
//
KeAcquireSpinLockAtDpcLevel(&deviceExtension->QueueLock);
//
// Remove the cancelled Irp from queue and release the lock
//
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);
//
// complete with STATUS_CANCELLED
//
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DPRINT(("CancelQueued - ends\n"));
return;
}
/*********************************************************************
*
* Routine Description:
* Queue the Irp in the device queue
*
* Arguments:
* DeviceExtension - pointer to device extension
* Irp - I/O request packet.
*
* Return Value:
* NT status value
*/
NTSTATUS QueueRequest( IN OUT DEVICE_EXTENSION * DeviceExtension, IN PIRP Irp ) {
KIRQL oldIrql;
NTSTATUS ntS;
//
// initialize variables
//
ntS = STATUS_PENDING;
DPRINT(("QueueRequests - begins\n"));
ASSERT(HoldRequests == DeviceExtension->QueueState);
KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);
InsertTailList(&DeviceExtension->NewRequestsQueue, &Irp->Tail.Overlay.ListEntry);
IoMarkIrpPending(Irp);
//
// Set the cancel routine
//
IoSetCancelRoutine(Irp, CancelQueued);
KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
DPRINT(("QueueRequests - ends\n"));
return ntS;
}
/*++
Routine Description:
This routine cancels the Wait Wake request.
Arguments:
DeviceExtension - pointer to the device extension
Return Value:
None.
--*/
VOID CancelWaitWake(IN DEVICE_EXTENSION * DeviceExtension) {
PIRP Irp;
DPRINT(("CancelWaitWake - begins\n"));
Irp = (PIRP) InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, NULL);
if(Irp) {
IoCancelIrp(Irp);
if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1)) {
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}
DPRINT(("CancelWaitWake - ends\n"));
}
/*********************************************************************
*
* WWIrpCompletionFunc
*
* Function description
* ???
*/
void WWIrpCompletionFunc(IN PDEVICE_OBJECT pDevObj, IN UCHAR MinorFunction,
IN POWER_STATE PowerState, IN void* pContext, IN PIO_STATUS_BLOCK IoStatus)
{
DEVICE_EXTENSION * pDevExt = (DEVICE_EXTENSION*) pContext;
DevIoDecrement(pDevExt);
return;
}
/*++
Routine Description:
This is the PoRequest completion routine for the wait wake irp.
Arguments:
DeviceObject - pointer to device object
MinorFunction - irp minor function
PowerState - power state of the irp.
Context - context passed to the completion routine.
IoStatus - status block.
Return Value:
None
--*/
VOID WaitWakeCallback(IN PDEVICE_OBJECT DeviceObject,IN UCHAR MinorFunction,
IN POWER_STATE PowerState,IN PVOID Context,IN PIO_STATUS_BLOCK IoStatus) {
NTSTATUS ntS;
POWER_STATE powerState;
DEVICE_EXTENSION * deviceExtension;
DPRINT(("WaitWakeCallback - begins\n"));
deviceExtension = (DEVICE_EXTENSION *) Context;
InterlockedExchange(&deviceExtension->FlagWWOutstanding, 0);
if(!NT_SUCCESS(IoStatus->Status)) {
return;
}
//
// wake up the device
//
if(deviceExtension->DevPower == PowerDeviceD0) {
DPRINT(("device already powered up...\n"));
return;
}
DPRINT(("WaitWakeCallback::"));
DevIoIncrement(deviceExtension);
powerState.DeviceState = PowerDeviceD0;
ntS = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState,
WWIrpCompletionFunc, deviceExtension, NULL);
if(deviceExtension->WaitWakeEnable) {
IssueWaitWake(deviceExtension);
}
DPRINT(("WaitWakeCallback - ends\n"));
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -