?? usbfx2lk_selsusp.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_selsusp.cpp
//
// ABSTRACT:
//
// This file contains the routines that handle selective suspend
// 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_selsusp.tmh"
}
#endif
//
// Forward declarations
//
#ifndef WIN2K
VOID SSUsbIdleCallback(PVOID Context);
NTSTATUS SSIdleNotificationCompletionRoutine(PDEVICE_OBJECT DeviceObject,
PIRP Irp, PVOID Context);
#endif
VOID SSPowerUpCompleteUpdateSSState(PUSBFX2LK_EXT DevExt);
VOID SSSynchronousPowerIrpCompletionFunc(PDEVICE_OBJECT DeviceObject,
UCHAR MinorFunction,
POWER_STATE PowerState,
PVOID Context,
PIO_STATUS_BLOCK IoStatus);
VOID SSAsynchronousPowerUpIrpCompletionFunc(PDEVICE_OBJECT DeviceObject,
UCHAR MinorFunction,
POWER_STATE PowerState,
PVOID Context,
PIO_STATUS_BLOCK IoStatus);
///////////////////////////////////////////////////////////////////////////////
//
// EnableSelectiveSuspend
//
// Enables selective suspend on the device
//
// INPUTS:
//
// DevExt - One of our device extensions
//
// OUTPUTS:
//
// None
//
// RETURNS:
//
// An appropriate NTSTATUS value
//
// IRQL:
//
// IRQL == PASSIVE_LEVEL
//
// CONTEXT:
//
// Arbitrary
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID EnableSelectiveSuspend(PUSBFX2LK_EXT DevExt)
{
KIRQL oldIrql;
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
("EnableSelectiveSuspend: Entered.\n"));
//
// We're potentially going to change the state of the selective
// suspend members of our device extension, so we must acquire
// the selective suspend lock
//
KeAcquireSpinLock(&DevExt->SSLock,&oldIrql);
//
// ASSERT that we are not suspended or in the process of
// suspending. Our logic is written such that we assume that
// we are fully powered while enabling/disabling SS for the
// device. This is done by the calling function calling
// SSPowerDeviceIfSuspended before calling us
//
ASSERT(DevExt->SSState == SS_NOT_STARTED);
ASSERT(KeReadStateEvent(&DevExt->SSDeviceNotSuspendedEvent));
//
// If the user doesn't ever want selective suspend, then
// we can just get out of here
//
if (!DevExt->SSEnabledByUser) {
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
("EnableSelectiveSuspend: SS disabled by user. Exiting\n"));
KeReleaseSpinLock(&DevExt->SSLock,oldIrql);
return;
}
//
// See if we've already been here before. If so, we
// can just exit
//
if (DevExt->SSInitialized) {
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
("EnableSelectiveSuspend: SS already initialized. Exiting\n"));
KeReleaseSpinLock(&DevExt->SSLock,oldIrql);
return;
}
//
// Default to not allowing the device to suspend right
// now. Because we're called in this routine only as the
// result of an I/O request (either from the User or from
// the PnP manager) the I/O count is currently elevated.
// When it drops to 0, we will set this to TRUE
//
DevExt->SSDeviceCanNowSuspend = FALSE;
//
// We're ready to selectively suspend!
//
DevExt->SSInitialized = TRUE;
KeReleaseSpinLock(&DevExt->SSLock,oldIrql);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
("EnableSelectiveSuspend: Exit.\n"));
return;
}
///////////////////////////////////////////////////////////////////////////////
//
// DisableSelectiveSuspend
//
// Disables selective suspend on the device
//
// INPUTS:
//
// DevExt - One of our device extensions
//
// OUTPUTS:
//
// None
//
// RETURNS:
//
// An appropriate NTSTATUS value
//
// IRQL:
//
// IRQL == PASSIVE_LEVEL
//
// CONTEXT:
//
// Arbitrary
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID DisableSelectiveSuspend(PUSBFX2LK_EXT DevExt)
{
KIRQL oldIrql;
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
("DisableSelectiveSuspend: Entered.\n"));
//
// We're potentially going to change the state of the selective
// suspend members of our device extension, so we must acquire
// the selective suspend lock
//
KeAcquireSpinLock(&DevExt->SSLock,&oldIrql);
//
// ASSERT that we are not suspended or in the process of
// suspending. Our logic is written such that we assume that
// we are fully powered while enabling/disabling SS for the
// device. This is done by the calling function calling
// SSPowerDeviceIfSuspended before calling us
//
ASSERT(DevExt->SSState == SS_NOT_STARTED);
ASSERT(KeReadStateEvent(&DevExt->SSDeviceNotSuspendedEvent));
//
// Note that we're called here both when the user doesn't
// want SS anymore AND when SS just needs to be disabled
// so that the device can stop or be removed.
//
//
// See if we've already been here before. If so, we
// can just exit
//
if (!DevExt->SSInitialized) {
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
("DisableSelectiveSuspend: SS not initialized. Exiting\n"));
KeReleaseSpinLock(&DevExt->SSLock,oldIrql);
return;
}
//
// The device can't suspend right now...
//
DevExt->SSDeviceCanNowSuspend = FALSE;
//
// And it won't suspend in the future...
//
DevExt->SSInitialized = FALSE;
KeReleaseSpinLock(&DevExt->SSLock,oldIrql);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
("DisableSelectiveSuspend: Exit.\n"));
return;
}
///////////////////////////////////////////////////////////////////////////////
//
// SSPowerDeviceIfSuspended
//
// This routine synchronously powers the device up if it is
// suspended or in the process of being suspended
//
// INPUTS:
//
// DevExt - One of our device extensions
//
// OUTPUTS:
//
// None
//
// RETURNS:
//
// An appropriate NTSTATUS value
//
// IRQL:
//
// IRQL == PASSIVE_LEVEL
//
// CONTEXT:
//
// Arbitrary
//
// NOTES:
//
// This routine synchronously powers the device and therefore
// MUST be called at PASSIVE_LEVEL.
//
///////////////////////////////////////////////////////////////////////////////
VOID SSPowerDeviceIfSuspended(PUSBFX2LK_EXT DevExt)
{
PAGED_CODE();
//
// See if the device is currently suspended. If it
// is, this routine will attempt to asynchronously power
// the device back up and will return TRUE. In that
// case, we want to synchronously wait for the power up
// to occur.
//
// However, if this routine returns FALSE the device is
// already powered up and we can simply return
//
if (SSPowerDeviceIfSuspendedAsync(DevExt)) {
//
// Wait for the suspend to be over
//
(VOID)OsrWaitForSingleObject(&DevExt->SSDeviceNotSuspendedEvent);
}
return;
}
///////////////////////////////////////////////////////////////////////////////
//
// SSPowerDeviceIfSuspendedAsync
//
// This routine checks to see if the device is suspended or in the
// process of being suspsended and takes the appropriate action
// to get the device powered again.
//
// INPUTS:
//
// DevExt - One of our device extensions
//
// OUTPUTS:
//
// None
//
// RETURNS:
//
// TRUE if the device is suspended, FALSE if the device is
// fully powered
//
// IRQL:
//
// IRQL == PASSIVE_LEVEL
//
// CONTEXT:
//
// Arbitrary
//
// NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
BOOLEAN SSPowerDeviceIfSuspendedAsync(PUSBFX2LK_EXT DevExt)
{
BOOLEAN queuePowerUp = FALSE;
BOOLEAN powerUpQueued = FALSE;
KIRQL oldIrql;
#ifndef W2K
PIRP idleIrp = NULL;
#endif
PAGED_CODE();
//
// We'll need the SS lock for this
//
KeAcquireSpinLock(&DevExt->SSLock,&oldIrql);
//
// Only if SS is setup to we need to do any
// checks.
//
if (DevExt->SSInitialized) {
//
// Indicate that we do not want the device to suspend
// because we're about to send a request to it.
//
DevExt->SSDeviceCanNowSuspend = FALSE;
//
// Check the state.
//
switch (DevExt->SSState) {
case SS_SUSPENDED: {
DevExt->SSState = SS_PROCESSING;
//
// We'll be powering up...
//
queuePowerUp = TRUE;
break;
}
case SS_PROCESSING: {
powerUpQueued = TRUE;
#ifndef W2K
//
// On XP and later, we need to submit and idle
// notification IRP to the bus driver and wait
// to be called back in order to suspend. If we're
// on a hub with a device that is not suspending,
// this request may still be pending. If so, we
// need to cancel it before we can do anything
//
//
// Grab the idle IRP out of the extension
//
idleIrp = DevExt->SSIdleIrp;
//
// And set it to NULL. This is the clue to the
// completion routine that we will be freeing
// the IRP
//
DevExt->SSIdleIrp = NULL;
#endif
break;
}
case SS_NOT_STARTED: {
//
// Nothing to do here, we're powered up and active
// already
//
break;
}
default: {
//
// Shouldn't be here...
//
ASSERT(FALSE);
break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -