2010-03-01 00:44:33 +00:00
|
|
|
#include <ntddk.h>
|
|
|
|
|
|
|
|
#include <acpi.h>
|
|
|
|
#include <acpisys.h>
|
|
|
|
|
|
|
|
#include <acpi_bus.h>
|
|
|
|
#include <acpi_drivers.h>
|
|
|
|
|
2010-03-17 05:30:22 +00:00
|
|
|
#define NDEBUG
|
2010-03-01 00:44:33 +00:00
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
Bus_Power (
|
|
|
|
PDEVICE_OBJECT DeviceObject,
|
|
|
|
PIRP Irp
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PIO_STACK_LOCATION irpStack;
|
|
|
|
NTSTATUS status;
|
|
|
|
PCOMMON_DEVICE_DATA commonData;
|
|
|
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
ASSERT (IRP_MJ_POWER == irpStack->MajorFunction);
|
|
|
|
|
|
|
|
commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
|
|
|
|
|
|
|
|
if (commonData->IsFDO) {
|
|
|
|
|
|
|
|
DPRINT("FDO %s IRP:0x%p %s %s\n",
|
|
|
|
PowerMinorFunctionString(irpStack->MinorFunction), Irp,
|
|
|
|
DbgSystemPowerString(commonData->SystemPowerState),
|
|
|
|
DbgDevicePowerString(commonData->DevicePowerState));
|
|
|
|
|
|
|
|
|
|
|
|
status = Bus_FDO_Power ((PFDO_DEVICE_DATA)DeviceObject->DeviceExtension,
|
|
|
|
Irp);
|
|
|
|
} else {
|
|
|
|
|
|
|
|
DPRINT("PDO %s IRP:0x%p %s %s\n",
|
|
|
|
PowerMinorFunctionString(irpStack->MinorFunction), Irp,
|
|
|
|
DbgSystemPowerString(commonData->SystemPowerState),
|
|
|
|
DbgDevicePowerString(commonData->DevicePowerState));
|
|
|
|
|
|
|
|
status = Bus_PDO_Power ((PPDO_DEVICE_DATA)DeviceObject->DeviceExtension,
|
|
|
|
Irp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
Bus_FDO_Power (
|
|
|
|
PFDO_DEVICE_DATA Data,
|
|
|
|
PIRP Irp
|
|
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
POWER_STATE powerState;
|
|
|
|
POWER_STATE_TYPE powerType;
|
|
|
|
PIO_STACK_LOCATION stack;
|
|
|
|
ULONG AcpiState;
|
|
|
|
ACPI_STATUS AcpiStatus;
|
2010-03-06 18:15:56 +00:00
|
|
|
SYSTEM_POWER_STATE oldPowerState;
|
2010-03-01 00:44:33 +00:00
|
|
|
|
|
|
|
stack = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
powerType = stack->Parameters.Power.Type;
|
|
|
|
powerState = stack->Parameters.Power.State;
|
|
|
|
|
|
|
|
|
|
|
|
if (stack->MinorFunction == IRP_MN_SET_POWER) {
|
|
|
|
DPRINT("\tRequest to set %s state to %s\n",
|
|
|
|
((powerType == SystemPowerState) ? "System" : "Device"),
|
|
|
|
((powerType == SystemPowerState) ? \
|
|
|
|
DbgSystemPowerString(powerState.SystemState) :\
|
|
|
|
DbgDevicePowerString(powerState.DeviceState)));
|
|
|
|
}
|
|
|
|
|
2010-03-06 18:15:56 +00:00
|
|
|
if (powerType == SystemPowerState)
|
|
|
|
{
|
2010-03-01 00:44:33 +00:00
|
|
|
switch (powerState.SystemState) {
|
|
|
|
case PowerSystemSleeping1:
|
|
|
|
AcpiState = ACPI_STATE_S1;
|
|
|
|
break;
|
|
|
|
case PowerSystemSleeping2:
|
|
|
|
AcpiState = ACPI_STATE_S2;
|
|
|
|
break;
|
|
|
|
case PowerSystemSleeping3:
|
|
|
|
AcpiState = ACPI_STATE_S3;
|
|
|
|
break;
|
|
|
|
case PowerSystemHibernate:
|
|
|
|
AcpiState = ACPI_STATE_S4;
|
|
|
|
break;
|
|
|
|
case PowerSystemShutdown:
|
|
|
|
AcpiState = ACPI_STATE_S5;
|
|
|
|
break;
|
|
|
|
default:
|
2010-03-06 18:15:56 +00:00
|
|
|
AcpiState = ACPI_STATE_UNKNOWN;
|
|
|
|
ASSERT(FALSE);
|
|
|
|
break;
|
2010-03-01 00:44:33 +00:00
|
|
|
}
|
2010-03-06 18:15:56 +00:00
|
|
|
oldPowerState = Data->Common.SystemPowerState;
|
|
|
|
Data->Common.SystemPowerState = powerState.SystemState;
|
2010-03-06 22:22:28 +00:00
|
|
|
AcpiStatus = acpi_suspend(AcpiState);
|
2010-03-01 00:44:33 +00:00
|
|
|
if (!ACPI_SUCCESS(AcpiStatus)) {
|
|
|
|
DPRINT1("Failed to enter sleep state %d (Status 0x%X)\n",
|
|
|
|
AcpiState, AcpiStatus);
|
2010-03-06 18:15:56 +00:00
|
|
|
Data->Common.SystemPowerState = oldPowerState;
|
2010-03-01 00:44:33 +00:00
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PoStartNextPowerIrp (Irp);
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
status = PoCallDriver (Data->NextLowerDriver, Irp);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
Bus_PDO_Power (
|
|
|
|
PPDO_DEVICE_DATA PdoData,
|
|
|
|
PIRP Irp
|
|
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
PIO_STACK_LOCATION stack;
|
|
|
|
POWER_STATE powerState;
|
|
|
|
POWER_STATE_TYPE powerType;
|
2010-03-06 06:03:04 +00:00
|
|
|
ULONG error;
|
2010-03-01 00:44:33 +00:00
|
|
|
|
|
|
|
stack = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
powerType = stack->Parameters.Power.Type;
|
|
|
|
powerState = stack->Parameters.Power.State;
|
|
|
|
|
|
|
|
switch (stack->MinorFunction) {
|
|
|
|
case IRP_MN_SET_POWER:
|
|
|
|
|
|
|
|
DPRINT("\tSetting %s power state to %s\n",
|
|
|
|
((powerType == SystemPowerState) ? "System" : "Device"),
|
|
|
|
((powerType == SystemPowerState) ? \
|
|
|
|
DbgSystemPowerString(powerState.SystemState) : \
|
|
|
|
DbgDevicePowerString(powerState.DeviceState)));
|
|
|
|
|
|
|
|
switch (powerType) {
|
|
|
|
case DevicePowerState:
|
2010-03-06 18:15:56 +00:00
|
|
|
if (!PdoData->AcpiHandle || !acpi_bus_power_manageable(PdoData->AcpiHandle))
|
2010-03-06 06:03:04 +00:00
|
|
|
{
|
2010-03-06 18:15:56 +00:00
|
|
|
PoSetPowerState(PdoData->Common.Self, DevicePowerState, powerState);
|
2010-03-06 06:03:04 +00:00
|
|
|
PdoData->Common.DevicePowerState = powerState.DeviceState;
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (powerState.DeviceState)
|
|
|
|
{
|
|
|
|
case PowerDeviceD0:
|
2010-03-06 18:15:56 +00:00
|
|
|
error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D0);
|
2010-03-06 06:03:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PowerDeviceD1:
|
2010-03-06 18:15:56 +00:00
|
|
|
error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D1);
|
2010-03-06 06:03:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PowerDeviceD2:
|
2010-03-06 18:15:56 +00:00
|
|
|
error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D2);
|
2010-03-06 06:03:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PowerDeviceD3:
|
2010-03-06 18:15:56 +00:00
|
|
|
error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D3);
|
2010-03-06 06:03:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
error = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ACPI_SUCCESS(error))
|
|
|
|
{
|
2010-03-06 18:15:56 +00:00
|
|
|
PoSetPowerState(PdoData->Common.Self, DevicePowerState, powerState);
|
2010-03-06 06:03:04 +00:00
|
|
|
PdoData->Common.DevicePowerState = powerState.DeviceState;
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
2010-03-01 00:44:33 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SystemPowerState:
|
|
|
|
PdoData->Common.SystemPowerState = powerState.SystemState;
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
status = STATUS_NOT_SUPPORTED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_QUERY_POWER:
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_WAIT_WAKE:
|
|
|
|
//
|
|
|
|
// We cannot support wait-wake because we are root-enumerated
|
|
|
|
// driver, and our parent, the PnP manager, doesn't support wait-wake.
|
|
|
|
//
|
|
|
|
case IRP_MN_POWER_SEQUENCE:
|
|
|
|
default:
|
|
|
|
status = STATUS_NOT_SUPPORTED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status != STATUS_NOT_SUPPORTED) {
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = status;
|
|
|
|
}
|
|
|
|
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
status = Irp->IoStatus.Status;
|
|
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
|
|
|
PCHAR
|
|
|
|
PowerMinorFunctionString (
|
|
|
|
UCHAR MinorFunction
|
|
|
|
)
|
|
|
|
{
|
|
|
|
switch (MinorFunction)
|
|
|
|
{
|
|
|
|
case IRP_MN_SET_POWER:
|
|
|
|
return "IRP_MN_SET_POWER";
|
|
|
|
case IRP_MN_QUERY_POWER:
|
|
|
|
return "IRP_MN_QUERY_POWER";
|
|
|
|
case IRP_MN_POWER_SEQUENCE:
|
|
|
|
return "IRP_MN_POWER_SEQUENCE";
|
|
|
|
case IRP_MN_WAIT_WAKE:
|
|
|
|
return "IRP_MN_WAIT_WAKE";
|
|
|
|
|
|
|
|
default:
|
|
|
|
return "unknown_power_irp";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PCHAR
|
|
|
|
DbgSystemPowerString(
|
|
|
|
SYSTEM_POWER_STATE Type
|
|
|
|
)
|
|
|
|
{
|
|
|
|
switch (Type)
|
|
|
|
{
|
|
|
|
case PowerSystemUnspecified:
|
|
|
|
return "PowerSystemUnspecified";
|
|
|
|
case PowerSystemWorking:
|
|
|
|
return "PowerSystemWorking";
|
|
|
|
case PowerSystemSleeping1:
|
|
|
|
return "PowerSystemSleeping1";
|
|
|
|
case PowerSystemSleeping2:
|
|
|
|
return "PowerSystemSleeping2";
|
|
|
|
case PowerSystemSleeping3:
|
|
|
|
return "PowerSystemSleeping3";
|
|
|
|
case PowerSystemHibernate:
|
|
|
|
return "PowerSystemHibernate";
|
|
|
|
case PowerSystemShutdown:
|
|
|
|
return "PowerSystemShutdown";
|
|
|
|
case PowerSystemMaximum:
|
|
|
|
return "PowerSystemMaximum";
|
|
|
|
default:
|
|
|
|
return "UnKnown System Power State";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PCHAR
|
|
|
|
DbgDevicePowerString(
|
|
|
|
DEVICE_POWER_STATE Type
|
|
|
|
)
|
|
|
|
{
|
|
|
|
switch (Type)
|
|
|
|
{
|
|
|
|
case PowerDeviceUnspecified:
|
|
|
|
return "PowerDeviceUnspecified";
|
|
|
|
case PowerDeviceD0:
|
|
|
|
return "PowerDeviceD0";
|
|
|
|
case PowerDeviceD1:
|
|
|
|
return "PowerDeviceD1";
|
|
|
|
case PowerDeviceD2:
|
|
|
|
return "PowerDeviceD2";
|
|
|
|
case PowerDeviceD3:
|
|
|
|
return "PowerDeviceD3";
|
|
|
|
case PowerDeviceMaximum:
|
|
|
|
return "PowerDeviceMaximum";
|
|
|
|
default:
|
|
|
|
return "UnKnown Device Power State";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|