📄 usbfx2lk_power.cpp
字号:
//
// Which power state are we talking about?
//
powerState = ioStack->Parameters.Power.State;
//
// For ALL power IRPs, we are REQUIRED to:
//
// 1) call PoStartNextPowerIrp()
// 2) Pass the IRP down to the next lower driver, unless
// we complete the request with an error.
//
switch(ioStack->MinorFunction) {
case IRP_MN_QUERY_POWER:
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO,
("OsrHandleDevicePowerIrp: Querying Device state transition to %s\n",
OsrPrintDevicePowerState(powerState.DeviceState)));
//
// We will always accept the device QUERY_POWER
// for our device.
//
// A device may need to start queuing inbound I/O requests
// here. If a device does queue new requests on power down
// then it must have some method of restarting those requests
// when the device is returned to full power. When and where
// to start queuing requests is device specific and could
// possibly be postponed until the SET_POWER IRP arrives.
// However, it is typically when a QUERY_POWER IRP for the
// device is received that a driver starts queuing requests.
//
//
// Enter the POWER_PROCESSING state, all I/O
// requests will be queued
//
OsrUpdateDeviceState(devExt, STATE_POWER_PROCESSING);
//
// Setup our completion routine that just calls PoStartNextPowerIrp.
//
// See DevicePowerIoCompletionRoutine for an explanation
// of why we wait until the Irp comes back up to
// call PoStartNextPowerIrp...
//
IoMarkIrpPending(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
DevicePowerIoCompletionRoutine,
(PVOID)devExt,
TRUE,
TRUE,
TRUE);
//
// Pass the device power irp down using PoCallDriver!
// It is an error to use IoCallDriver here...Power irps
// must be passed down with PoCallDriver, since it
// will do some additional work to ensure proper
// synchronization of power Irps
//
(VOID)PoCallDriver(devExt->DeviceToSendIrpsTo,
Irp);
//
// We've registered an IO completion routine so we're not
// finished with this Irp...DON'T release our remove lock!
//
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("OsrHandleDevicePowerIrp: Exiting!\n"));
//
// We've marked the Irp pending so we MUST
// return STATUS_PENDING
//
return STATUS_PENDING;
case IRP_MN_SET_POWER:
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO,
("OsrHandleDevicePowerIrp: Setting Device state to %s\n",
OsrPrintDevicePowerState(powerState.DeviceState)));
//
// We need to determine if we are powering up, powering down, or if
// the device's power state is not changing.
//
if(devExt->DevicePowerState > powerState.DeviceState) {
//
// This is a power up, we send the IRP down so the PDO can power up
// first, then we finish our processing in an I/O completion routine.
//
IoMarkIrpPending(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
DevicePowerIoCompletionRoutine,
(PVOID)devExt,
TRUE,
TRUE,
TRUE);
//
// Pass the irp down using PoCallDriver! It is an
// error to use IoCallDriver here...Power irps
// must be passed down with PoCallDriver, since it
// will do some additional work to ensure proper
// synchronization of power Irps
//
(VOID)PoCallDriver(devExt->DeviceToSendIrpsTo,
Irp);
//
// We've registered an IO completion routine so we're not
// finished with this Irp...DON'T release our remove lock!
//
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("OsrHandleDevicePowerIrp: Exiting!\n"));
//
// The IRP is marked pending so we
// MUST return STATUS_PENDING here.
//
return STATUS_PENDING;
} else if (devExt->DevicePowerState < powerState.DeviceState) {
//
// Power down case. We handle it first and send the IRP to the bus
// with a completion routine that calls PoStartNextPowerIrp
//
// See DevicePowerIoCompletionRoutine for an explanation
// of why we wait until the Irp comes back up to
// call PoStartNextPowerIrp...
//
//
//
// Notify the power manager of our device power state change
//
PoSetPowerState(DeviceObject,
DevicePowerState,
powerState);
IoMarkIrpPending(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(
Irp,
DevicePowerIoCompletionRoutine,
(PVOID)devExt,
TRUE,
TRUE,
TRUE);
//
// Pass the irp down using PoCallDriver! It is an
// error to use IoCallDriver here...Power irps
// must be passed down with PoCallDriver, since it
// will do some additional work to ensure proper
// synchronization of power Irps
//
(VOID)PoCallDriver(devExt->DeviceToSendIrpsTo,
Irp);
//
// We've registered an IO completion routine so we're not
// finished with this Irp...DON'T release our remove lock!
//
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("OsrHandleDevicePowerIrp: Exiting!\n"));
//
// The IRP is marked pending so we
// MUST return STATUS_PENDING here.
//
return STATUS_PENDING;
} else {
//
// Else we're staying at the same power state.
// There's no reason to touch our hardware, so
// we're just going to set our completion routine
// and call PoStartNextPowerIrp in the completion routine.
//
// See DevicePowerIoCompletionRoutine for an explanation
// of why we wait until the Irp comes back up to
// call PoStartNextPowerIrp...
//
IoMarkIrpPending(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(
Irp,
DevicePowerIoCompletionRoutine,
(PVOID)devExt,
TRUE,
TRUE,
TRUE);
//
// Pass the irp down using PoCallDriver! It is an
// error to use IoCallDriver here...Power irps
// must be passed down with PoCallDriver, since it
// will do some additional work to ensure proper
// synchronization of power Irps
//
(VOID)PoCallDriver(devExt->DeviceToSendIrpsTo,
Irp);
//
// We've registered an IO completion routine so we're not
// finished with this Irp...DON'T release our remove lock!
//
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("OsrHandleDevicePowerIrp: Exiting!\n"));
//
// The IRP is marked pending so we
// MUST return STATUS_PENDING here.
//
return STATUS_PENDING;
}
//
// We never get here...
//
return STATUS_UNSUCCESSFUL;
case IRP_MN_WAIT_WAKE:
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO,
("OsrHandleDevicePowerIrp: IRP_MN_WAIT_WAKE received.\n"));
IoMarkIrpPending(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(
Irp,
(PIO_COMPLETION_ROUTINE)WaitWakeCompletionRoutine,
devExt,
TRUE,
TRUE,
TRUE);
PoStartNextPowerIrp(Irp);
status = PoCallDriver(devExt->DeviceToSendIrpsTo, Irp);
if(!NT_SUCCESS(status)) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_POWER_INFO,
("OsrHandleDevicePowerIrp: Lower drivers failed the wait-wake Irp\n"));
}
status = STATUS_PENDING;
//
// push back the count HERE and NOT in completion routine
// a pending Wait Wake Irp should not impede stopping the device
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("OsrHandleDevicePowerIrp: Exit..\n"));
return STATUS_PENDING;
case IRP_MN_BOGUS:
//
// Driver Verifier bogus minor function code
//
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO,
("OsrHandleDevicePowerIrp: Received IRP_MN_BOGUS: Just pass it along...\n"));
//
// Fall through...
//
case IRP_MN_POWER_SEQUENCE:
//
// This device does not support wake or power sequence so
// we just send the request down to the bus
//
//
// Fall through...
//
default:
//
// Unknown power code...
//
//
// No matter what we always must call
// PoStartNextPowerIrp...
//
// We must also always make this call BEFORE calling
// IoSkipCurrentIrpStackLocation. Why? Because
// PoStartNextPowerIrp lets another power Irp of
// the same kind that we're processing now through
// (System or Device). How does it know what kind
// of Irp we're handling? Why from the current
// stack location of course!
//
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
//
// Pass the irp down using PoCallDriver! It is an
// error to use IoCallDriver here...Power irps
// must be passed down with PoCallDriver, since it
// will do some additional work to ensure proper
// synchronization of power Irps
//
status = PoCallDriver(devExt->DeviceToSendIrpsTo, Irp);
//
// We're done with this request
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("OsrHandleDevicePowerIrp: Exiting!\n"));
return status;
}
//
// We never get here...
//
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_POWER_INFO,
("OsrHandleDevicePowerIrp: Should never reach the end! Breaking into the debugger if attached...\n"));
//
// Use KdBreakPoint instead of DbgBreakPoint so that
// we only break in the checked build...
//
KdBreakPoint();
return STATUS_UNSUCCESSFUL;
}
///////////////////////////////////////////////////////////////////////////////
//
// DevicePowerIoCompletionRoutine
//
// Our I/O completion routine for device power up IRPs.
//
// INPUTS:
//
// DeviceObject - Pointer to device object.
// Irp - Address of the DEVICE power IRP.
// Context - the device extension
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// NTSTATUS value signalling the I/O manager to continue processing IRP
// stack locations or not.
//
// IRQL:
//
// This routine is called at IRQL <= DISPATCH_LEVEL
//
// CONTEXT:
//
// This routine is called in an arbitrary thread context
//
// NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS DevicePowerIoCompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp,
PVOID Context)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -