You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
694 lines
18 KiB
694 lines
18 KiB
/*++
|
|
|
|
Copyright (c) 2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
wake.c
|
|
|
|
Abstract:
|
|
|
|
This module contains code to handle
|
|
IRP_MJ_POWER dispatches for SD controllers
|
|
|
|
Authors:
|
|
|
|
Neil Sandlin (neilsa) Jan 1, 2002
|
|
|
|
Environment:
|
|
|
|
Kernel mode only
|
|
|
|
Notes:
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
|
|
//
|
|
// Internal References
|
|
//
|
|
|
|
|
|
NTSTATUS
|
|
SdbusFdoWaitWakeIoCompletion(
|
|
IN PDEVICE_OBJECT Fdo,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
);
|
|
|
|
VOID
|
|
SdbusPdoWaitWakeCancelRoutine(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN OUT PIRP Irp
|
|
);
|
|
|
|
/**************************************************************************
|
|
|
|
FDO ROUTINES
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
NTSTATUS
|
|
SdbusFdoWaitWake(
|
|
IN PDEVICE_OBJECT Fdo,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
|
|
Routine Description
|
|
|
|
Handles WAIT_WAKE for the given sd controller
|
|
|
|
Arguments
|
|
|
|
Pdo - Pointer to the functional device object for the sd controller
|
|
Irp - The IRP_MN_WAIT_WAKE Irp
|
|
|
|
Return Value
|
|
|
|
STATUS_PENDING - Wait wake is pending
|
|
STATUS_SUCCESS - Wake is already asserted, wait wake IRP is completed
|
|
in this case
|
|
Any other status - Error
|
|
--*/
|
|
|
|
{
|
|
PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension;
|
|
WAKESTATE oldWakeState;
|
|
|
|
//
|
|
// Record the wait wake Irp..
|
|
//
|
|
fdoExtension->WaitWakeIrp = Irp;
|
|
|
|
oldWakeState = InterlockedCompareExchange(&fdoExtension->WaitWakeState,
|
|
WAKESTATE_ARMED, WAKESTATE_WAITING);
|
|
|
|
DebugPrint((SDBUS_DEBUG_POWER, "fdo %x irp %x WaitWake: prevState %s\n",
|
|
Fdo, Irp, WAKESTATE_STRING(oldWakeState)));
|
|
|
|
if (oldWakeState == WAKESTATE_WAITING_CANCELLED) {
|
|
fdoExtension->WaitWakeState = WAKESTATE_COMPLETING;
|
|
|
|
Irp->IoStatus.Status = STATUS_CANCELLED;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_CANCELLED;
|
|
}
|
|
|
|
IoMarkIrpPending(Irp);
|
|
|
|
IoCopyCurrentIrpStackLocationToNext (Irp);
|
|
//
|
|
// Set our completion routine in the Irp..
|
|
//
|
|
IoSetCompletionRoutine(Irp,
|
|
SdbusFdoWaitWakeIoCompletion,
|
|
Fdo,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
//
|
|
// now pass this down to the lower driver..
|
|
//
|
|
PoCallDriver(fdoExtension->LowerDevice, Irp);
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SdbusFdoWaitWakeIoCompletion(
|
|
IN PDEVICE_OBJECT Fdo,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Completion routine for the IRP_MN_WAIT_WAKE request for this
|
|
sd controller. This is called when the WAIT_WAKE IRP is
|
|
completed by the lower driver (PCI/ACPI) indicating either that
|
|
1. SD bus controller asserted wake
|
|
2. WAIT_WAKE was cancelled
|
|
3. Lower driver returned an error for some reason
|
|
|
|
Arguments:
|
|
Fdo - Pointer to Functional device object for the sd controller
|
|
Irp - Pointer to the IRP for the power request (IRP_MN_WAIT_WAKE)
|
|
Context - Not used
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - WAIT_WAKE was completed with success
|
|
Any other status - Wake could be not be accomplished.
|
|
|
|
--*/
|
|
{
|
|
PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension;
|
|
PPDO_EXTENSION pdoExtension;
|
|
PDEVICE_OBJECT pdo;
|
|
WAKESTATE oldWakeState;
|
|
|
|
UNREFERENCED_PARAMETER(Context);
|
|
|
|
oldWakeState = InterlockedExchange(&fdoExtension->WaitWakeState, WAKESTATE_COMPLETING);
|
|
|
|
DebugPrint((SDBUS_DEBUG_POWER, "fdo %x irp %x WW IoComp: prev=%s\n",
|
|
Fdo, Irp, WAKESTATE_STRING(oldWakeState)));
|
|
|
|
if (oldWakeState != WAKESTATE_ARMED) {
|
|
ASSERT(oldWakeState == WAKESTATE_ARMING_CANCELLED);
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
}
|
|
|
|
|
|
if (IsDeviceFlagSet(fdoExtension, SDBUS_FDO_WAKE_BY_CD)) {
|
|
POWER_STATE powerState;
|
|
|
|
ResetDeviceFlag(fdoExtension, SDBUS_FDO_WAKE_BY_CD);
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
powerState.DeviceState = PowerDeviceD0;
|
|
PoRequestPowerIrp(fdoExtension->DeviceObject, IRP_MN_SET_POWER, powerState, NULL, NULL, NULL);
|
|
|
|
} else {
|
|
// NOTE:
|
|
// At this point we do NOT know how to distinguish which function
|
|
// in a multifunction device has asserted wake.
|
|
// So we go through the entire list of PDOs hanging off this FDO
|
|
// and complete all the outstanding WAIT_WAKE Irps for every PDO that
|
|
// that's waiting. We leave it up to the FDO for the device to figure
|
|
// if it asserted wake
|
|
//
|
|
|
|
for (pdo = fdoExtension->PdoList; pdo != NULL ; pdo = pdoExtension->NextPdoInFdoChain) {
|
|
|
|
pdoExtension = pdo->DeviceExtension;
|
|
|
|
if (IsDeviceLogicallyRemoved(pdoExtension) ||
|
|
IsDevicePhysicallyRemoved(pdoExtension)) {
|
|
//
|
|
// This pdo is about to be removed ..
|
|
// skip it
|
|
//
|
|
continue;
|
|
}
|
|
|
|
if (pdoExtension->WaitWakeIrp != NULL) {
|
|
PIRP finishedIrp;
|
|
//
|
|
// Ah.. this is a possible candidate to have asserted the wake
|
|
//
|
|
//
|
|
// Make sure this IRP will not be completed again or cancelled
|
|
//
|
|
finishedIrp = pdoExtension->WaitWakeIrp;
|
|
|
|
DebugPrint((SDBUS_DEBUG_POWER, "fdo %x WW IoComp: irp %08x for pdo %08x\n",
|
|
Fdo, finishedIrp, pdo));
|
|
|
|
|
|
IoSetCancelRoutine(finishedIrp, NULL);
|
|
//
|
|
// Propagate parent's status to child
|
|
//
|
|
PoStartNextPowerIrp(finishedIrp);
|
|
finishedIrp->IoStatus.Status = Irp->IoStatus.Status;
|
|
|
|
//
|
|
// Since we didn't pass this IRP down, call our own completion routine
|
|
//
|
|
// SdbusPdoWaitWakeCompletion(pdo, finishedIrp, pdoExtension);
|
|
IoCompleteRequest(finishedIrp, IO_NO_INCREMENT);
|
|
}
|
|
}
|
|
PoStartNextPowerIrp(Irp);
|
|
}
|
|
|
|
return Irp->IoStatus.Status;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
SdbusFdoWaitWakePoCompletion(
|
|
IN PDEVICE_OBJECT Fdo,
|
|
IN UCHAR MinorFunction,
|
|
IN POWER_STATE PowerState,
|
|
IN PVOID Context,
|
|
IN PIO_STATUS_BLOCK IoStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
This routine is called on completion of a D irp generated by an S irp.
|
|
|
|
Parameters
|
|
|
|
DeviceObject - Pointer to the Fdo for the SDBUS controller
|
|
MinorFunction - Minor function of the IRP_MJ_POWER request
|
|
PowerState - Power state requested
|
|
Context - Context passed in to the completion routine
|
|
IoStatus - Pointer to the status block which will contain
|
|
the returned status
|
|
Return Value
|
|
|
|
Status
|
|
|
|
--*/
|
|
{
|
|
PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension;
|
|
|
|
DebugPrint((SDBUS_DEBUG_POWER, "fdo %x irp %x WaitWakePoCompletion: prevState %s\n",
|
|
Fdo, fdoExtension->WaitWakeIrp,
|
|
WAKESTATE_STRING(fdoExtension->WaitWakeState)));
|
|
|
|
ASSERT (fdoExtension->WaitWakeIrp);
|
|
fdoExtension->WaitWakeIrp = NULL;
|
|
ASSERT (fdoExtension->WaitWakeState == WAKESTATE_COMPLETING);
|
|
fdoExtension->WaitWakeState = WAKESTATE_DISARMED;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
SdbusFdoArmForWake(
|
|
PFDO_EXTENSION FdoExtension
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to enable the controller for wake. It is called by the Pdo
|
|
wake routines when a wake-enabled controller gets a wait-wake irp, and also by
|
|
the idle routine to arm for wake from D3 by card insertion.
|
|
|
|
Arguments:
|
|
|
|
FdoExtension - device extension of the controller
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_PENDING;
|
|
PIO_STACK_LOCATION irpStack;
|
|
PIRP irp;
|
|
LONG oldWakeState;
|
|
POWER_STATE powerState;
|
|
|
|
oldWakeState = InterlockedCompareExchange(&FdoExtension->WaitWakeState,
|
|
WAKESTATE_WAITING, WAKESTATE_DISARMED);
|
|
|
|
DebugPrint((SDBUS_DEBUG_POWER, "fdo %x ArmForWake: prevState %s\n",
|
|
FdoExtension->DeviceObject, WAKESTATE_STRING(oldWakeState)));
|
|
|
|
if ((oldWakeState == WAKESTATE_ARMED) || (oldWakeState == WAKESTATE_WAITING)) {
|
|
return STATUS_SUCCESS;
|
|
}
|
|
if (oldWakeState != WAKESTATE_DISARMED) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
|
|
|
|
powerState.SystemState = FdoExtension->DeviceCapabilities.SystemWake;
|
|
|
|
status = PoRequestPowerIrp(FdoExtension->DeviceObject,
|
|
IRP_MN_WAIT_WAKE,
|
|
powerState,
|
|
SdbusFdoWaitWakePoCompletion,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
FdoExtension->WaitWakeState = WAKESTATE_DISARMED;
|
|
|
|
DebugPrint((SDBUS_DEBUG_POWER, "WaitWake to FDO, expecting STATUS_PENDING, got %08X\n", status));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
SdbusFdoDisarmWake(
|
|
PFDO_EXTENSION FdoExtension
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to disable the controller for wake.
|
|
|
|
Arguments:
|
|
|
|
FdoExtension - device extension of the controller
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
WAKESTATE oldWakeState;
|
|
|
|
oldWakeState = InterlockedCompareExchange(&FdoExtension->WaitWakeState,
|
|
WAKESTATE_WAITING_CANCELLED, WAKESTATE_WAITING);
|
|
|
|
DebugPrint((SDBUS_DEBUG_POWER, "fdo %x DisarmWake: prevState %s\n",
|
|
FdoExtension->DeviceObject, WAKESTATE_STRING(oldWakeState)));
|
|
|
|
if (oldWakeState != WAKESTATE_WAITING) {
|
|
|
|
oldWakeState = InterlockedCompareExchange(&FdoExtension->WaitWakeState,
|
|
WAKESTATE_ARMING_CANCELLED, WAKESTATE_ARMED);
|
|
|
|
if (oldWakeState != WAKESTATE_ARMED) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
if (oldWakeState == WAKESTATE_ARMED) {
|
|
IoCancelIrp(FdoExtension->WaitWakeIrp);
|
|
|
|
//
|
|
// Now that we've cancelled the IRP, try to give back ownership
|
|
// to the completion routine by restoring the WAKESTATE_ARMED state
|
|
//
|
|
oldWakeState = InterlockedCompareExchange(&FdoExtension->WaitWakeState,
|
|
WAKESTATE_ARMED, WAKESTATE_ARMING_CANCELLED);
|
|
|
|
if (oldWakeState == WAKESTATE_COMPLETING) {
|
|
//
|
|
// We didn't give control back of the IRP in time, we we own it now
|
|
//
|
|
IoCompleteRequest(FdoExtension->WaitWakeIrp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
SdbusFdoCheckForIdle(
|
|
IN PFDO_EXTENSION FdoExtension
|
|
)
|
|
{
|
|
POWER_STATE powerState;
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Make sure all sockets are empty
|
|
//
|
|
|
|
#if 0
|
|
for (socket = FdoExtension->SocketList; socket != NULL; socket = socket->NextSocket) {
|
|
if (IsCardInSocket(socket)) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Arm for wakeup
|
|
//
|
|
|
|
status = SdbusFdoArmForWake(FdoExtension);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return status;
|
|
}
|
|
|
|
SetDeviceFlag(FdoExtension, SDBUS_FDO_WAKE_BY_CD);
|
|
|
|
powerState.DeviceState = PowerDeviceD3;
|
|
PoRequestPowerIrp(FdoExtension->DeviceObject, IRP_MN_SET_POWER, powerState, NULL, NULL, NULL);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
PDO ROUTINES
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
NTSTATUS
|
|
SdbusPdoWaitWake(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN PIRP Irp,
|
|
OUT BOOLEAN *CompleteIrp
|
|
)
|
|
/*++
|
|
|
|
|
|
Routine Description
|
|
|
|
Handles WAIT_WAKE for the given pc-card.
|
|
|
|
Arguments
|
|
|
|
Pdo - Pointer to the device object for the pc-card
|
|
Irp - The IRP_MN_WAIT_WAKE Irp
|
|
CompleteIrp - This routine will set this to TRUE if the IRP should be
|
|
completed after this is called and FALSE if it should not be
|
|
touched
|
|
|
|
Return Value
|
|
|
|
STATUS_PENDING - Wait wake is pending
|
|
STATUS_SUCCESS - Wake is already asserted, wait wake IRP is completed
|
|
in this case
|
|
Any other status - Error
|
|
--*/
|
|
{
|
|
|
|
PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
|
|
PFDO_EXTENSION fdoExtension = pdoExtension->FdoExtension;
|
|
NTSTATUS status;
|
|
|
|
*CompleteIrp = FALSE;
|
|
|
|
if ((pdoExtension->DeviceCapabilities.DeviceWake == PowerDeviceUnspecified) ||
|
|
(pdoExtension->DeviceCapabilities.DeviceWake < pdoExtension->DevicePowerState)) {
|
|
//
|
|
// Either we don't support wake at all OR the current device power state
|
|
// of the PC-Card doesn't support wake
|
|
//
|
|
return STATUS_INVALID_DEVICE_STATE;
|
|
}
|
|
|
|
if (pdoExtension->Flags & SDBUS_DEVICE_WAKE_PENDING) {
|
|
//
|
|
// A WAKE is already pending
|
|
//
|
|
return STATUS_DEVICE_BUSY;
|
|
}
|
|
|
|
status = SdbusFdoArmForWake(fdoExtension);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return status;
|
|
}
|
|
|
|
//for the time being, expect STATUS_PENDING from FdoArmForWake
|
|
ASSERT(status == STATUS_PENDING);
|
|
|
|
//
|
|
// Parent has one (more) waiter..
|
|
//
|
|
InterlockedIncrement(&fdoExtension->ChildWaitWakeCount);
|
|
//for testing, make sure there is only one waiter
|
|
ASSERT (fdoExtension->ChildWaitWakeCount == 1);
|
|
|
|
|
|
pdoExtension->WaitWakeIrp = Irp;
|
|
pdoExtension->Flags |= SDBUS_DEVICE_WAKE_PENDING;
|
|
|
|
//
|
|
// Set Ring enable/cstschg for the card here..
|
|
//
|
|
// (*socket->SocketFnPtr->PCBEnableDisableWakeupEvent)(socket, pdoExtension, TRUE);
|
|
|
|
//
|
|
// PCI currently does not do anything with a WW irp for a cardbus PDO. So we hack around
|
|
// this here by not passing the irp down. Instead it is held pending here, so we can
|
|
// set a cancel routine just like the read PDO driver would. If PCI were to do something
|
|
// with the irp, we could code something like the following:
|
|
//
|
|
// if (IsCardBusCard(pdoExtension)) {
|
|
// IoSetCompletionRoutine(Irp, SdbusPdoWaitWakeCompletion, pdoExtension,TRUE,TRUE,TRUE);
|
|
// IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
// status = IoCallDriver (pdoExtension->LowerDevice, Irp);
|
|
// ASSERT (status == STATUS_PENDING);
|
|
// return status;
|
|
// }
|
|
|
|
|
|
IoMarkIrpPending(Irp);
|
|
|
|
//
|
|
// Allow IRP to be cancelled..
|
|
//
|
|
IoSetCancelRoutine(Irp, SdbusPdoWaitWakeCancelRoutine);
|
|
|
|
IoSetCompletionRoutine(Irp,
|
|
SdbusPdoWaitWakeCompletion,
|
|
pdoExtension,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
SdbusPdoWaitWakeCompletion(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN PIRP Irp,
|
|
IN PPDO_EXTENSION PdoExtension
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Completion routine called when a pending IRP_MN_WAIT_WAKE Irp completes
|
|
|
|
Arguments
|
|
|
|
Pdo - Pointer to the physical device object for the pc-card
|
|
Irp - Pointer to the wait wake IRP
|
|
PdoExtension - Pointer to the device extension for the Pdo
|
|
|
|
Return Value
|
|
|
|
Status from the IRP
|
|
|
|
--*/
|
|
{
|
|
PFDO_EXTENSION fdoExtension = PdoExtension->FdoExtension;
|
|
|
|
DebugPrint((SDBUS_DEBUG_POWER, "pdo %08x irp %08x --> WaitWakeCompletion\n", Pdo, Irp));
|
|
|
|
ASSERT (PdoExtension->Flags & SDBUS_DEVICE_WAKE_PENDING);
|
|
|
|
PdoExtension->Flags &= ~SDBUS_DEVICE_WAKE_PENDING;
|
|
PdoExtension->WaitWakeIrp = NULL;
|
|
//
|
|
// Reset ring enable/cstschg
|
|
//
|
|
|
|
// (*socket->SocketFnPtr->PCBEnableDisableWakeupEvent)(socket, PdoExtension, FALSE);
|
|
|
|
ASSERT (fdoExtension->ChildWaitWakeCount > 0);
|
|
InterlockedDecrement(&fdoExtension->ChildWaitWakeCount);
|
|
//
|
|
// Wake completed
|
|
//
|
|
|
|
InterlockedDecrement(&PdoExtension->DeletionLock);
|
|
return Irp->IoStatus.Status;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
SdbusPdoWaitWakeCancelRoutine(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN OUT PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Cancel an outstanding (pending) WAIT_WAKE Irp.
|
|
Note: The CancelSpinLock is held on entry
|
|
|
|
Arguments:
|
|
|
|
Pdo - Pointer to the physical device object for the pc-card
|
|
on which the WAKE is pending
|
|
Irp - Pointer to the WAIT_WAKE Irp to be cancelled
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
|
|
PFDO_EXTENSION fdoExtension = pdoExtension->FdoExtension;
|
|
|
|
DebugPrint((SDBUS_DEBUG_POWER, "pdo %08x irp %08x --> WaitWakeCancelRoutine\n", Pdo, Irp));
|
|
|
|
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
|
|
|
if (pdoExtension->WaitWakeIrp == NULL) {
|
|
//
|
|
// Wait wake already completed/cancelled
|
|
//
|
|
return;
|
|
}
|
|
|
|
pdoExtension->Flags &= ~SDBUS_DEVICE_WAKE_PENDING;
|
|
pdoExtension->WaitWakeIrp = NULL;
|
|
|
|
//
|
|
// Reset ring enable, disabling wake..
|
|
//
|
|
// (*socket->SocketFnPtr->PCBEnableDisableWakeupEvent)(socket, pdoExtension, FALSE);
|
|
|
|
//
|
|
// Since this is cancelled, see if parent's wait wake
|
|
// needs to be cancelled too.
|
|
// First, decrement the number of child waiters..
|
|
//
|
|
|
|
ASSERT (fdoExtension->ChildWaitWakeCount > 0);
|
|
if (InterlockedDecrement(&fdoExtension->ChildWaitWakeCount) == 0) {
|
|
//
|
|
// No more waiters.. cancel the parent's wake IRP
|
|
//
|
|
ASSERT(fdoExtension->WaitWakeIrp);
|
|
|
|
if (fdoExtension->WaitWakeIrp) {
|
|
IoCancelIrp(fdoExtension->WaitWakeIrp);
|
|
}
|
|
}
|
|
|
|
|
|
InterlockedDecrement(&pdoExtension->DeletionLock);
|
|
//
|
|
// Complete the IRP
|
|
//
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
//
|
|
// Is this necessary?
|
|
//
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
Irp->IoStatus.Status = STATUS_CANCELLED;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|