735 lines
19 KiB
C
735 lines
19 KiB
C
/*++
|
||
|
||
Copyright (c) 1990-2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
power.c
|
||
|
||
Abstract:
|
||
|
||
This file contains the support for power management
|
||
|
||
Environment:
|
||
|
||
Kernel Mode Driver.
|
||
|
||
Notes:
|
||
|
||
Nothing in here or in routines referenced from here should be pageable.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "busp.h"
|
||
#include "pnpisa.h"
|
||
#include <initguid.h>
|
||
#include <wdmguid.h>
|
||
#include "halpnpp.h"
|
||
|
||
NTSTATUS
|
||
PiDispatchPower(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
PiDispatchPowerFdo(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
PiDispatchPowerPdo(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
PipPassPowerIrpFdo(
|
||
PDEVICE_OBJECT DeviceObject,
|
||
PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
PipPowerIrpNotSupportedPdo(
|
||
PDEVICE_OBJECT DeviceObject,
|
||
PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
PipQueryPowerStatePdo (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
PipSetPowerStatePdo (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
PipSetQueryPowerStateFdo (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
PipRequestPowerUpCompletionRoutinePdo (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN UCHAR MinorFunction,
|
||
IN POWER_STATE PowerState,
|
||
IN PVOID Context,
|
||
IN PIO_STATUS_BLOCK IoStatus
|
||
);
|
||
|
||
NTSTATUS
|
||
FdoContingentPowerCompletionRoutine (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN UCHAR MinorFunction,
|
||
IN POWER_STATE PowerState,
|
||
IN PVOID Context,
|
||
IN PIO_STATUS_BLOCK IoStatus
|
||
);
|
||
|
||
const PUCHAR SystemPowerStateStrings[] = {
|
||
"Unspecified",
|
||
"Working",
|
||
"Sleeping1",
|
||
"Sleeping2",
|
||
"Sleeping3",
|
||
"Hibernate",
|
||
"Shutdown"
|
||
};
|
||
|
||
const PUCHAR DevicePowerStateStrings[] = {
|
||
"Unspecified",
|
||
"D0",
|
||
"D1",
|
||
"D2",
|
||
"D3"
|
||
};
|
||
|
||
const PPI_DISPATCH PiPowerDispatchTableFdo[] =
|
||
{
|
||
PipPassPowerIrpFdo,
|
||
PipPassPowerIrpFdo,
|
||
PipSetQueryPowerStateFdo,
|
||
PipSetQueryPowerStateFdo,
|
||
};
|
||
|
||
#if ISOLATE_CARDS
|
||
const PPI_DISPATCH PiPowerDispatchTablePdo[] =
|
||
{
|
||
PipPowerIrpNotSupportedPdo,
|
||
PipPowerIrpNotSupportedPdo,
|
||
PipSetPowerStatePdo,
|
||
PipQueryPowerStatePdo,
|
||
};
|
||
#endif
|
||
|
||
|
||
VOID
|
||
PipDumpPowerIrpLocation(
|
||
PIO_STACK_LOCATION IrpSp
|
||
)
|
||
{
|
||
DebugPrintContinue((
|
||
DEBUG_POWER,
|
||
"%s %d\n",
|
||
(IrpSp->Parameters.Power.Type == DevicePowerState) ?
|
||
DevicePowerStateStrings[IrpSp->Parameters.Power.State.DeviceState] : SystemPowerStateStrings[IrpSp->Parameters.Power.State.SystemState],
|
||
IrpSp->Parameters.Power.ShutdownType));
|
||
}
|
||
|
||
NTSTATUS
|
||
PiDispatchPower(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles all the IRP_MJ_POWER IRPs.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to the device object for which this IRP applies.
|
||
|
||
Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch.
|
||
|
||
Return Value:
|
||
|
||
NT status.
|
||
|
||
--*/
|
||
{
|
||
PIO_STACK_LOCATION irpSp;
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PPI_BUS_EXTENSION busExtension;
|
||
|
||
//
|
||
// Make sure this is a valid device object.
|
||
//
|
||
|
||
busExtension = DeviceObject->DeviceExtension;
|
||
|
||
#if !ISOLATE_CARDS
|
||
return PiDispatchPowerFdo(DeviceObject, Irp);
|
||
#else
|
||
if (busExtension->Flags & DF_BUS) {
|
||
return PiDispatchPowerFdo(DeviceObject, Irp);
|
||
} else {
|
||
return PiDispatchPowerPdo(DeviceObject, Irp);
|
||
}
|
||
#endif
|
||
}
|
||
|
||
#if ISOLATE_CARDS
|
||
|
||
NTSTATUS
|
||
PipPowerIrpNotSupportedPdo(
|
||
PDEVICE_OBJECT DeviceObject,
|
||
PIRP Irp
|
||
)
|
||
{
|
||
PIO_STACK_LOCATION irpSp;
|
||
|
||
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
||
PoStartNextPowerIrp(Irp);
|
||
|
||
DebugPrint((DEBUG_POWER,
|
||
"Completing unsupported power irp %x for PDO %x\n",
|
||
irpSp->MinorFunction,
|
||
DeviceObject
|
||
));
|
||
|
||
PipCompleteRequest(Irp, STATUS_NOT_SUPPORTED, NULL);
|
||
return STATUS_NOT_SUPPORTED;
|
||
}
|
||
|
||
NTSTATUS
|
||
PiDispatchPowerPdo(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles all the IRP_MJ_POWER IRPs.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to the device object for which this IRP applies.
|
||
|
||
Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch.
|
||
|
||
Return Value:
|
||
|
||
NT status.
|
||
|
||
--*/
|
||
{
|
||
PIO_STACK_LOCATION irpSp;
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PDEVICE_INFORMATION deviceExtension;
|
||
|
||
//
|
||
// Make sure this is a valid device object.
|
||
//
|
||
|
||
deviceExtension = DeviceObject->DeviceExtension;
|
||
if (deviceExtension->Flags & DF_DELETED) {
|
||
status = STATUS_NO_SUCH_DEVICE;
|
||
PoStartNextPowerIrp(Irp);
|
||
PipCompleteRequest(Irp, status, NULL);
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// Get a pointer to our stack location and take appropriate action based
|
||
// on the minor function.
|
||
//
|
||
|
||
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
||
if (irpSp->MinorFunction > IRP_MN_PO_MAXIMUM_FUNCTION) {
|
||
status = PipPowerIrpNotSupportedPdo(DeviceObject, Irp);
|
||
} else {
|
||
status = PiPowerDispatchTablePdo[irpSp->MinorFunction](DeviceObject, Irp);
|
||
}
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PipQueryPowerStatePdo (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles the Query_Power irp for the PDO .
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to the device object for which this IRP applies.
|
||
|
||
Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch.
|
||
|
||
Return Value:
|
||
|
||
NT status.
|
||
|
||
--*/
|
||
{
|
||
|
||
DEVICE_POWER_STATE targetState;
|
||
NTSTATUS status;
|
||
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
|
||
|
||
DebugPrint((DEBUG_POWER, "QueryPower on PDO %x: ", DeviceObject));
|
||
PipDumpPowerIrpLocation(irpSp);
|
||
|
||
if (irpSp->Parameters.Power.Type == DevicePowerState) {
|
||
targetState=irpSp->Parameters.Power.State.DeviceState;
|
||
ASSERT ((targetState == PowerDeviceD0) ||
|
||
(targetState == PowerDeviceD3));
|
||
|
||
if ((targetState == PowerDeviceD0) ||
|
||
(targetState == PowerDeviceD3) ) {
|
||
|
||
status=Irp->IoStatus.Status = STATUS_SUCCESS;
|
||
} else {
|
||
status=Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
||
}
|
||
} else {
|
||
//
|
||
// Just succeed S irps
|
||
//
|
||
status=Irp->IoStatus.Status = STATUS_SUCCESS;
|
||
}
|
||
|
||
PoStartNextPowerIrp (Irp);
|
||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||
|
||
DebugPrint((DEBUG_POWER, "QueryPower on PDO %x: returned %x\n", DeviceObject, status));
|
||
return status;
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
PipSetPowerStatePdo (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles SET_POWER_IRP for the IsaPnp device (i.e. PDO)
|
||
It sets the devices power state to the power state type as indicated. In
|
||
the case of a device state change which is transitioning a device out of
|
||
the PowerDevice0 state, we need call PoSetPowerState prior to leaving the
|
||
PowerDeviceD0. In the case if a device state change which is transitioning
|
||
a device into the PowerDeviceD0 state, we call PoSetPowerState after the
|
||
device is successfully put into the PowerDeviceD0 state.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to the device object for which this IRP applies.
|
||
|
||
Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch.
|
||
|
||
Return Value:
|
||
|
||
NT status.
|
||
|
||
--*/
|
||
{
|
||
PDEVICE_INFORMATION pdoExtension;
|
||
NTSTATUS status;
|
||
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
|
||
DEVICE_POWER_STATE targetState=irpSp->Parameters.Power.State.DeviceState;
|
||
POWER_STATE newState;
|
||
|
||
DebugPrint((DEBUG_POWER, "SetPower on PDO %x: ", DeviceObject));
|
||
PipDumpPowerIrpLocation(irpSp);
|
||
|
||
pdoExtension = PipReferenceDeviceInformation(DeviceObject, FALSE);
|
||
if (pdoExtension == NULL) {
|
||
status = STATUS_NO_SUCH_DEVICE;
|
||
} else if (pdoExtension->Flags & DF_NOT_FUNCTIONING) {
|
||
status = STATUS_NO_SUCH_DEVICE;
|
||
PipDereferenceDeviceInformation(pdoExtension, FALSE);
|
||
} else {
|
||
if (irpSp->Parameters.Power.Type == DevicePowerState) {
|
||
|
||
// * On transition from D0 to D0, we do nothing.
|
||
//
|
||
// * On transition to D3, we'll deactivate the card.
|
||
//
|
||
// * On transition from D3->D0 we'll refresh the resources
|
||
// and activate the card.
|
||
//
|
||
if ((targetState == PowerDeviceD0) &&
|
||
(pdoExtension->DevicePowerState == PowerDeviceD0)) {
|
||
// Do not try to power device back up if this is a D0->D0
|
||
// transition. The device is already powered.
|
||
DebugPrint((DEBUG_POWER,
|
||
"PDO %x D0 -> D0 Transition ignored\n", DeviceObject));
|
||
} else if ((pdoExtension->DevicePowerState == PowerDeviceD0) &&
|
||
pdoExtension->CrashDump) {
|
||
DebugPrint((DEBUG_POWER,
|
||
"PDO %x D0 -> ?? Transition ignored, crash file\n",
|
||
DeviceObject));
|
||
} else if (targetState > PowerDeviceD0) {
|
||
targetState = PowerDeviceD3;
|
||
DebugPrint((DEBUG_POWER,
|
||
"Powering down PDO %x CSN %d/LDN %d\n",
|
||
DeviceObject,
|
||
pdoExtension->CardInformation->CardSelectNumber,
|
||
pdoExtension->LogicalDeviceNumber
|
||
));
|
||
if ((pdoExtension->Flags & (DF_ACTIVATED | DF_READ_DATA_PORT)) == DF_ACTIVATED) {
|
||
if (!(PipRDPNode->Flags & (DF_STOPPED|DF_REMOVED|DF_SURPRISE_REMOVED))) {
|
||
PipWakeAndSelectDevice(
|
||
(UCHAR) pdoExtension->CardInformation->CardSelectNumber,
|
||
(UCHAR) pdoExtension->LogicalDeviceNumber);
|
||
PipDeactivateDevice();
|
||
PipWaitForKey();
|
||
} else {
|
||
targetState = PowerDeviceD0;
|
||
}
|
||
}
|
||
} else {
|
||
if ((pdoExtension->Flags & (DF_ACTIVATED | DF_READ_DATA_PORT)) == DF_ACTIVATED) {
|
||
DebugPrint((DEBUG_POWER,
|
||
"Powering up PDO %x CSN %d/LDN %d\n",
|
||
DeviceObject,
|
||
pdoExtension->CardInformation->CardSelectNumber,
|
||
pdoExtension->LogicalDeviceNumber
|
||
));
|
||
if (!(PipRDPNode->Flags & (DF_STOPPED|DF_REMOVED|DF_SURPRISE_REMOVED))) {
|
||
PipWakeAndSelectDevice(
|
||
(UCHAR) pdoExtension->CardInformation->CardSelectNumber,
|
||
(UCHAR) pdoExtension->LogicalDeviceNumber);
|
||
status = PipSetDeviceResources(
|
||
pdoExtension,
|
||
pdoExtension->AllocatedResources);
|
||
if (NT_SUCCESS(status)) {
|
||
PipActivateDevice();
|
||
}
|
||
PipWaitForKey();
|
||
} else {
|
||
targetState = PowerDeviceD3;
|
||
}
|
||
|
||
}
|
||
}
|
||
newState.DeviceState = targetState;
|
||
PoSetPowerState(DeviceObject, DevicePowerState, newState);
|
||
pdoExtension->DevicePowerState = targetState;
|
||
}
|
||
status = STATUS_SUCCESS;
|
||
PipDereferenceDeviceInformation(pdoExtension, FALSE);
|
||
}
|
||
|
||
Irp->IoStatus.Status = status;
|
||
|
||
PoStartNextPowerIrp (Irp);
|
||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||
|
||
DebugPrint((DEBUG_POWER, "SetPower on PDO %x: returned %x\n", DeviceObject, status));
|
||
return status;
|
||
}
|
||
#endif
|
||
|
||
NTSTATUS
|
||
PipPassPowerIrpFdo(
|
||
PDEVICE_OBJECT DeviceObject,
|
||
PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Description:
|
||
|
||
This function pass the power Irp to lower level driver.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - the Fdo
|
||
Irp - the request
|
||
|
||
Return:
|
||
|
||
STATUS_PENDING
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status;
|
||
PPI_BUS_EXTENSION busExtension;
|
||
PIO_STACK_LOCATION irpSp;
|
||
|
||
PoStartNextPowerIrp(Irp);
|
||
|
||
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
||
busExtension = (PPI_BUS_EXTENSION) DeviceObject->DeviceExtension;
|
||
|
||
DebugPrint((DEBUG_POWER,
|
||
"Passing down power irp %x for FDO %x to %x\n",
|
||
irpSp->MinorFunction,
|
||
DeviceObject,
|
||
busExtension->AttachedDevice
|
||
));
|
||
|
||
IoSkipCurrentIrpStackLocation(Irp);
|
||
status = PoCallDriver(busExtension->AttachedDevice, Irp);
|
||
DebugPrint((DEBUG_POWER,
|
||
"Passed down power irp for FDO: returned %x\n",
|
||
status));
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PiDispatchPowerFdo(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles all the IRP_MJ_POWER IRPs.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to the device object for which this IRP applies.
|
||
|
||
Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch.
|
||
|
||
Return Value:
|
||
|
||
NT status.
|
||
|
||
--*/
|
||
{
|
||
PIO_STACK_LOCATION irpSp;
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PPI_BUS_EXTENSION busExtension;
|
||
|
||
//
|
||
// Make sure this is a valid device object.
|
||
//
|
||
|
||
busExtension = DeviceObject->DeviceExtension;
|
||
if (busExtension->AttachedDevice == NULL) {
|
||
status = STATUS_NO_SUCH_DEVICE;
|
||
PoStartNextPowerIrp(Irp);
|
||
PipCompleteRequest(Irp, status, NULL);
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// Get a pointer to our stack location and take appropriate action based
|
||
// on the minor function.
|
||
//
|
||
|
||
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
||
if (irpSp->MinorFunction > IRP_MN_PO_MAXIMUM_FUNCTION) {
|
||
return PipPassPowerIrpFdo(DeviceObject, Irp);
|
||
} else {
|
||
status = PiPowerDispatchTableFdo[irpSp->MinorFunction](DeviceObject, Irp);
|
||
}
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PipSetQueryPowerStateFdo (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles QUERY_POWER or SET_POWER IRPs for the IsaPnp bus device
|
||
(i.e. FDO). It sets the devices power state for the power state type as indicated.
|
||
In the case of a device state change which is transitioning a device out of
|
||
the PowerDevice0 state, we need call PoSetPowerState prior to leaving the
|
||
PowerDeviceD0. In the case if a device state change which is transitioning
|
||
a device into the PowerDeviceD0 state, we call PoSetPowerState after the
|
||
device is successfully put into the PowerDeviceD0 state.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to the device object for which this IRP applies.
|
||
|
||
Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch.
|
||
|
||
Return Value:
|
||
|
||
NT status.
|
||
|
||
--*/
|
||
{
|
||
PPI_BUS_EXTENSION fdoExtension;
|
||
PIO_STACK_LOCATION irpSp;
|
||
NTSTATUS status;
|
||
|
||
fdoExtension = DeviceObject->DeviceExtension;
|
||
|
||
irpSp = IoGetCurrentIrpStackLocation (Irp);
|
||
|
||
DebugPrint((DEBUG_POWER, "%s on FDO %x: ",
|
||
(irpSp->MinorFunction == IRP_MN_SET_POWER) ? "SetPower" :
|
||
"QueryPower", DeviceObject));
|
||
PipDumpPowerIrpLocation(irpSp);
|
||
|
||
if (irpSp->Parameters.Power.Type == SystemPowerState) {
|
||
POWER_STATE powerState;
|
||
|
||
switch (irpSp->Parameters.Power.State.SystemState) {
|
||
case PowerSystemWorking:
|
||
|
||
//
|
||
// Make sure the bus is on for these system states
|
||
//
|
||
|
||
powerState.DeviceState = PowerDeviceD0;
|
||
break;
|
||
|
||
case PowerSystemSleeping1:
|
||
case PowerSystemHibernate:
|
||
case PowerSystemShutdown:
|
||
case PowerSystemSleeping2:
|
||
case PowerSystemSleeping3:
|
||
|
||
//
|
||
// Going to sleep ... Power down
|
||
//
|
||
|
||
powerState.DeviceState = PowerDeviceD3;
|
||
break;
|
||
|
||
default:
|
||
|
||
//
|
||
// Unknown request - be safe power up
|
||
//
|
||
|
||
ASSERT (TRUE == FALSE);
|
||
powerState.DeviceState = PowerDeviceD0;
|
||
break;
|
||
}
|
||
|
||
DebugPrint((DEBUG_POWER, "request power irp to busdev %x, pending\n",
|
||
fdoExtension->FunctionalBusDevice));
|
||
IoMarkIrpPending(Irp);
|
||
PoRequestPowerIrp (
|
||
fdoExtension->FunctionalBusDevice,
|
||
irpSp->MinorFunction,
|
||
powerState,
|
||
FdoContingentPowerCompletionRoutine,
|
||
Irp,
|
||
NULL
|
||
);
|
||
|
||
return STATUS_PENDING;
|
||
|
||
}
|
||
|
||
status = PipPassPowerIrpFdo(DeviceObject, Irp);
|
||
DebugPrint((DEBUG_POWER, "SetPower(device) on FDO %x: returned %x\n", DeviceObject, status));
|
||
return status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
FdoContingentPowerCompletionRoutine (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN UCHAR MinorFunction,
|
||
IN POWER_STATE PowerState,
|
||
IN PVOID Context,
|
||
IN PIO_STATUS_BLOCK IoStatus
|
||
)
|
||
{
|
||
PIRP irp = Context;
|
||
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp);
|
||
|
||
DebugPrint((DEBUG_POWER, "requested power irp completed to %x\n", DeviceObject));
|
||
|
||
//
|
||
// Propagate the status of the transient power IRP
|
||
//
|
||
irp->IoStatus.Status = IoStatus->Status;
|
||
|
||
if (NT_SUCCESS(IoStatus->Status)) {
|
||
|
||
PPI_BUS_EXTENSION fdoExtension;
|
||
|
||
fdoExtension = DeviceObject->DeviceExtension;
|
||
|
||
PoStartNextPowerIrp (irp);
|
||
//
|
||
// changing device power state call PoSetPowerState now.
|
||
//
|
||
|
||
if (MinorFunction == IRP_MN_SET_POWER) {
|
||
SYSTEM_POWER_STATE OldSystemPowerState = fdoExtension->SystemPowerState;
|
||
|
||
fdoExtension->SystemPowerState = irpSp->Parameters.Power.State.SystemState;
|
||
fdoExtension->DevicePowerState = PowerState.DeviceState;
|
||
PoSetPowerState (
|
||
DeviceObject,
|
||
DevicePowerState,
|
||
PowerState
|
||
);
|
||
DebugPrint((DEBUG_POWER, "New FDO %x powerstate system %s/%s\n",
|
||
DeviceObject,
|
||
SystemPowerStateStrings[fdoExtension->SystemPowerState],
|
||
DevicePowerStateStrings[fdoExtension->DevicePowerState]));
|
||
#if ISOLATE_CARDS
|
||
|
||
if ((OldSystemPowerState == PowerSystemHibernate) ||
|
||
(OldSystemPowerState == PowerSystemSleeping3) ) {
|
||
BOOLEAN needsRescan;
|
||
|
||
PipReportStateChange(PiSWaitForKey);
|
||
if ((fdoExtension->BusNumber == 0) && PipRDPNode &&
|
||
(PipRDPNode->Flags & (DF_ACTIVATED|DF_PROCESSING_RDP|DF_QUERY_STOPPED)) == DF_ACTIVATED) {
|
||
needsRescan = PipMinimalCheckBus(fdoExtension);
|
||
if (needsRescan) {
|
||
PipRDPNode->Flags |= DF_NEEDS_RESCAN;
|
||
IoInvalidateDeviceRelations(
|
||
fdoExtension->PhysicalBusDevice,
|
||
BusRelations);
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|
||
IoSkipCurrentIrpStackLocation (irp);
|
||
PoCallDriver (fdoExtension->AttachedDevice, irp);
|
||
|
||
} else {
|
||
|
||
PoStartNextPowerIrp (irp);
|
||
IoCompleteRequest(irp, IO_NO_INCREMENT);
|
||
}
|
||
|
||
return STATUS_SUCCESS;
|
||
} // FdoContingentPowerCompletionRoutine
|
||
|