📄 usbfx2lk_power.cpp
字号:
///////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright 2005 OSR Open Systems Resources, Inc.
// Copyright (c) 2000 Microsoft Corporation
// All Rights Reserved
//
// This sofware is supplied for instructional purposes only.
//
// OSR Open Systems Resources, Inc. (OSR) expressly disclaims any warranty
// for this software. THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
// THE IMPLIED WARRANTIES OF MECHANTABILITY OR FITNESS FOR A PARTICULAR
// PURPOSE. THE ENTIRE RISK ARISING FROM THE USE OF THIS SOFTWARE REMAINS
// WITH YOU. OSR's entire liability and your exclusive remedy shall not
// exceed the price paid for this material. In no event shall OSR or its
// suppliers be liable for any damages whatsoever (including, without
// limitation, damages for loss of business profit, business interruption,
// loss of business information, or any other pecuniary loss) arising out
// of the use or inability to use this software, even if OSR has been
// advised of the possibility of such damages. Because some states/
// jurisdictions do not allow the exclusion or limitation of liability for
// consequential or incidental damages, the above limitation may not apply
// to you.
//
// OSR Open Systems Resources, Inc.
// 105 Route 101A Suite 19
// Amherst, NH 03031 (603) 595-6500 FAX: (603) 595-6503
// email bugs to: bugs@osr.com
//
//
// MODULE:
//
// USBFx2LK_Power.cpp
//
// ABSTRACT:
//
// This file contains the routines that handle IRP_MJ_POWER processing for the
// OSR USB FX2 Learning Kit Device
//
// AUTHOR(S):
//
// OSR Open Systems Resources, Inc.
//
///////////////////////////////////////////////////////////////////////////////
#include "usbfx2lk.h"
#ifdef WPP_TRACING
//
// Include the necessary tmh file - this is
// just a matter of course if you're using WPP tracing.
//
extern "C" {
#include "usbfx2lk_power.tmh"
}
#endif
//
// Forward Declarations
//
NTSTATUS OsrHandleSystemPowerIrp(PDEVICE_OBJECT DeviceObject,PIRP Irp);
NTSTATUS SystemPowerIoCompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp,
PVOID Context);
NTSTATUS OsrHandleDevicePowerIrp(PDEVICE_OBJECT DeviceObject,PIRP Irp);
NTSTATUS DevicePowerIoCompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp,
PVOID Context);
VOID DevicePowerRequestCompletionRoutine(PDEVICE_OBJECT DeviceObject,UCHAR MinorFunction,
POWER_STATE PowerState,PVOID Context,PIO_STATUS_BLOCK IoStatus);
VOID WaitWakeIrpCompletionFunc(PDEVICE_OBJECT DeviceObject,UCHAR MinorFunction,
POWER_STATE PowerState,PVOID Context,PIO_STATUS_BLOCK IoStatus);
VOID WaitWakeCallback(PDEVICE_OBJECT DeviceObject,UCHAR MinorFunction,POWER_STATE PowerState,
PVOID Context,PIO_STATUS_BLOCK IoStatus);
NTSTATUS WaitWakeCompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp,PUSBFX2LK_EXT DevExt);
///////////////////////////////////////////////////////////////////////////////
//
// UsbFx2LkPower
//
// This routine is called by the IO Manager to process a IRP_MJ_POWER
// Irp.
//
//
// INPUTS:
//
// DeviceObject - One of our Device Objects.
// Irp - The Irp to process.
//
// OUTPUTS:
//
// None
//
// RETURNS:
//
// None
//
// IRQL:
//
// IRQL == PASSIVE_LEVEL
//
// CONTEXT:
//
// User Context
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS UsbFx2LkPower(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
PUSBFX2LK_EXT devExt = (PUSBFX2LK_EXT)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
POWER_STATE_TYPE powerType;
NTSTATUS status;
KIRQL oldIrql;
//
// We're guaranteed to be called here at IRQL PASSIVE_LEVEL
//
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
//
// Increment the count of Outstanding IOs
//
OsrIncrementOutstandingIoCount(devExt,__FILE__,__LINE__);
if (ioStack->MinorFunction <= IRP_MN_QUERY_POWER) {
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO,
("OsrPower: Entered with Minor Function %s\n",
OsrMinorFunctionToString(ioStack->MajorFunction,
ioStack->MinorFunction)));
} else {
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO,
("OsrPower: Entered with unusual Minor Function 0x%x\n",
ioStack->MinorFunction));
}
//
// See what sort of state we're in. For our power policy, we have
// decided that we will not accept any power requests if we are not
// in STATE_STARTED.
//
// Why? Because as far as we can tell, it doesn't make any SENSE to handle
// them in any other state. If we're in REMOVE_PENDING and we process
// a power down, what do we do if we get a IRP_MN_CANCEL_REMOVE? Or, if
// we're in STOPPED we've already given up our resources so how
// do we tell our device to power down? In SURPRISE_REMOVED, what
// hardware are we going to power down??
//
KeAcquireSpinLock(&devExt->IoStateLock,&oldIrql);
if (devExt->DevicePnPState != STATE_STARTED &&
devExt->DevicePnPState != STATE_POWER_PROCESSING) {
KeReleaseSpinLock(&devExt->IoStateLock,oldIrql);
//
// We ALWAYS need to tell the system to start the next
// power IRP before we exit. Yes, even if we're failing
// the current request.
//
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
Irp->IoStatus.Information = 0;
//
// Complete the request here, without passing it down...
//
IoCompleteRequest(Irp, IO_NO_INCREMENT);
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO,
("OsrPower: Failing Power request due to Pnp State! Current PnP state - %s\n",
OsrPrintState(devExt)));
//
// We're done with this request
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO, ("OsrPower: Exiting...\n"));
return STATUS_INVALID_DEVICE_STATE;
}
KeReleaseSpinLock(&devExt->IoStateLock,oldIrql);
//
// Is this a system power Irp or a device power Irp?
//
powerType = ioStack->Parameters.Power.Type;
switch (powerType) {
case SystemPowerState:
//
// Transfer control to our SYSTEM power IRP routine...
//
status = OsrHandleSystemPowerIrp(DeviceObject, Irp);
//
// Don't release our remove lock!
//
break;
case DevicePowerState:
//
// Transfer control to our DEVICE power IRP routine...
//
status = OsrHandleDevicePowerIrp(DeviceObject, Irp);
//
// Don't release our remove lock!
//
break;
default:
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO,
("OsrPower: Not a device or system power request!?! Pass it along...\n"));
//
// Call PoStartNextPowerIrp to indicate that we're done
// processing this power IRP
//
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
//
// Pass the IRP down using PoCallDriver
//
status = PoCallDriver(devExt->DeviceToSendIrpsTo, Irp);
//
// We're done with this request
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
break;
}
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("OsrPower: Exiting...\n"));
return status;
}
///////////////////////////////////////////////////////////////////////////////
//
// OsrHandleSystemPowerIrp
//
// Entry point to handle SYSTEM power IRPs
//
// INPUTS:
//
// DeviceObject - Pointer to our device object.
// Irp - Address of the system power IRP.
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// STATUS_PENDING if we are going to handle the IRP,
// otherwise the NTSTATUS value of the driver below us
//
// IRQL:
//
// This routine is called at IRQL == PASSIVE_LEVEL
//
// CONTEXT:
//
// This routine is called in an arbitrary thread context
//
// NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS OsrHandleSystemPowerIrp(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
PUSBFX2LK_EXT devExt = (PUSBFX2LK_EXT)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
POWER_STATE powerState;
NTSTATUS status;
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("OsrHandleSystemPowerIrp: Entered...\n"));
//
// 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:
//
// The code below assumes that this device is the power
// policy owner. This is the norm for most FDO devices.
//
//
// There's a slightly annoying and unexpected side effect
// of being suspended while processing the S Query IRP.
//
// If we're going to a power state that is lower than
// what our device can wake the system from, the bus
// driver will allow the system suspend to the lower,
// unwakeable state. This means that the system will
// suspend, we'll have a Wait Wake IRP pending, but
// nothing we do will wake the system. However, if
// our device is powered up when we handle the S-IRP,
// then the bus driver will "do the right thing" and
// fail the S-IRP query for the power down. This will
// result in a new S-IRP coming in, hopefully with an
// S state that we can suspend from.
//
SSPowerDeviceIfSuspended(devExt);
//
// if this device is something like an industrial device,
// that will typically be used in an industrial or other
// fixed setting, then it may be desireable to avoid power
// downs while I/O requests are in progress. In this case
// the driver should keep some device state to indicate it is
// busy. For example this could be done by tracking open
// handles to the device. If the device is determined to be
// busy, the query to power down should be rejected. Something
// like following commented-out code could be used in this case.
//
//
//If(deviceBusy) {
// PoStartNextPowerIrp(Irp);
//
// Irp->IoStatus.Information = 0;
// Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
//
// //
// // Complete the request here, without passing it down...
// //
//
// IoCompleteRequest (Irp, IO_NO_INCREMENT);
//
// return STATUS_DEVICE_BUSY;
//}
//
// If the system is powering DOWN (numerically higher S-states
// are lower in power) and we support wait wake, submit
// a wait wake request
//
if((powerState.SystemState > devExt->SystemPowerState) && (devExt->WaitWakeEnable)) {
IssueWaitWake(devExt);
}
//
// Unless it's absolutely mission critical, you should agree
// to the request to power down your device. If one device
// on the system rejects the request, things could get ugly
// and the system might not properly shutdown in a timely
// manner (or even worse, not at all...).
//
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO,
("OsrHandleSystemPowerIrp: Querying for System state transition to %s\n",
OsrPrintSystemPowerState(powerState.SystemState)));
//
// mark the IRP pending
//
IoMarkIrpPending(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);
//
// Insert our completion routine into the system power IRP.
//
IoSetCompletionRoutine(Irp,
SystemPowerIoCompletionRoutine,
devExt,
TRUE,
TRUE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -