321 lines
8.4 KiB
C
321 lines
8.4 KiB
C
//+-------------------------------------------------------------------------
|
||
//
|
||
// Microsoft Windows
|
||
//
|
||
// Copyright (C) Microsoft Corporation, 1998 - 1999
|
||
//
|
||
// File: power.c
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
|
||
#include "pch.h"
|
||
|
||
VOID
|
||
PowerStateCallback(
|
||
IN PVOID CallbackContext,
|
||
IN PVOID Argument1,
|
||
IN PVOID Argument2
|
||
)
|
||
{
|
||
ULONG_PTR action = (ULONG_PTR)Argument1;
|
||
ULONG_PTR state = (ULONG_PTR)Argument2;
|
||
|
||
UNREFERENCED_PARAMETER(CallbackContext);
|
||
|
||
if( PO_CB_AC_STATUS == action ) {
|
||
|
||
//
|
||
// AC <-> DC Transition has occurred
|
||
// state == TRUE if on AC, else FALSE.
|
||
//
|
||
PowerStateIsAC = (BOOLEAN)state;
|
||
// DbgPrint("PowerState is now %s\n",PowerStateIsAC?"AC":"Battery");
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
PptPowerComplete (
|
||
IN PDEVICE_OBJECT pDeviceObject,
|
||
IN PIRP pIrp,
|
||
IN PFDO_EXTENSION Fdx
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles all IRP_MJ_POWER IRPs.
|
||
|
||
Arguments:
|
||
|
||
pDeviceObject - represents the port device
|
||
|
||
pIrp - PNP irp
|
||
|
||
Fdx - Device Extension
|
||
|
||
Return Value:
|
||
|
||
Status
|
||
|
||
--*/
|
||
{
|
||
POWER_STATE_TYPE powerType;
|
||
POWER_STATE powerState;
|
||
PIO_STACK_LOCATION pIrpStack;
|
||
|
||
UNREFERENCED_PARAMETER( pDeviceObject );
|
||
|
||
if( pIrp->PendingReturned ) {
|
||
IoMarkIrpPending( pIrp );
|
||
}
|
||
|
||
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
|
||
|
||
powerType = pIrpStack->Parameters.Power.Type;
|
||
powerState = pIrpStack->Parameters.Power.State;
|
||
|
||
switch (pIrpStack->MinorFunction) {
|
||
|
||
case IRP_MN_QUERY_POWER:
|
||
|
||
ASSERTMSG ("Invalid power completion minor code: Query Power\n", FALSE);
|
||
break;
|
||
|
||
case IRP_MN_SET_POWER:
|
||
|
||
DD((PCE)Fdx,DDT,"Power - Setting %s state to %d\n",
|
||
( (powerType == SystemPowerState) ? "System" : "Device" ), powerState.SystemState);
|
||
|
||
switch (powerType) {
|
||
case DevicePowerState:
|
||
if (Fdx->DeviceState < powerState.DeviceState) {
|
||
//
|
||
// Powering down
|
||
//
|
||
|
||
ASSERTMSG ("Invalid power completion Device Down\n", FALSE);
|
||
|
||
} else if (powerState.DeviceState < Fdx->DeviceState) {
|
||
//
|
||
// Powering Up
|
||
//
|
||
PoSetPowerState (Fdx->DeviceObject, powerType, powerState);
|
||
|
||
if (PowerDeviceD0 == Fdx->DeviceState) {
|
||
|
||
//
|
||
// Do the power on stuff here.
|
||
//
|
||
|
||
}
|
||
Fdx->DeviceState = powerState.DeviceState;
|
||
}
|
||
break;
|
||
|
||
case SystemPowerState:
|
||
|
||
if (Fdx->SystemState < powerState.SystemState) {
|
||
//
|
||
// Powering down
|
||
//
|
||
|
||
ASSERTMSG ("Invalid power completion System Down\n", FALSE);
|
||
|
||
} else if (powerState.SystemState < Fdx->SystemState) {
|
||
//
|
||
// Powering Up
|
||
//
|
||
if (PowerSystemWorking == powerState.SystemState) {
|
||
|
||
//
|
||
// Do the system start up stuff here.
|
||
//
|
||
|
||
powerState.DeviceState = PowerDeviceD0;
|
||
PoRequestPowerIrp (Fdx->DeviceObject,
|
||
IRP_MN_SET_POWER,
|
||
powerState,
|
||
NULL, // no completion function
|
||
NULL, // and no context
|
||
NULL);
|
||
}
|
||
|
||
Fdx->SystemState = powerState.SystemState;
|
||
}
|
||
break;
|
||
}
|
||
|
||
|
||
break;
|
||
|
||
default:
|
||
ASSERTMSG ("Power Complete: Bad Power State", FALSE);
|
||
}
|
||
|
||
PoStartNextPowerIrp (pIrp);
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
PptFdoPower (
|
||
IN PDEVICE_OBJECT pDeviceObject,
|
||
IN PIRP pIrp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles all IRP_MJ_POWER IRPs.
|
||
|
||
Arguments:
|
||
|
||
pDeviceObject - represents the port device
|
||
|
||
pIrp - PNP irp
|
||
|
||
Return Value:
|
||
|
||
Status
|
||
|
||
--*/
|
||
{
|
||
POWER_STATE_TYPE powerType;
|
||
POWER_STATE powerState;
|
||
PIO_STACK_LOCATION pIrpStack;
|
||
NTSTATUS status;
|
||
PFDO_EXTENSION fdx;
|
||
BOOLEAN hookit = FALSE;
|
||
BOOLEAN bogusIrp = FALSE;
|
||
|
||
//
|
||
// WORKWORK. THIS CODE DOESN'T DO MUCH...NEED TO CHECK OUT FULL POWER FUNCTIONALITY.
|
||
//
|
||
|
||
fdx = pDeviceObject->DeviceExtension;
|
||
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
|
||
|
||
status = PptAcquireRemoveLock(&fdx->RemoveLock, pIrp);
|
||
if( !NT_SUCCESS(status) ) {
|
||
PoStartNextPowerIrp(pIrp);
|
||
return P4CompleteRequest( pIrp, status, pIrp->IoStatus.Information );
|
||
}
|
||
|
||
powerType = pIrpStack->Parameters.Power.Type;
|
||
powerState = pIrpStack->Parameters.Power.State;
|
||
|
||
switch (pIrpStack->MinorFunction) {
|
||
|
||
case IRP_MN_QUERY_POWER:
|
||
|
||
status = STATUS_SUCCESS;
|
||
break;
|
||
|
||
case IRP_MN_SET_POWER:
|
||
|
||
DD((PCE)fdx,DDT,"Power - Setting %s state to %d\n",
|
||
( (powerType == SystemPowerState) ? "System" : "Device" ), powerState.SystemState);
|
||
|
||
status = STATUS_SUCCESS;
|
||
|
||
switch (powerType) {
|
||
case DevicePowerState:
|
||
if (fdx->DeviceState < powerState.DeviceState) {
|
||
//
|
||
// Powering down
|
||
//
|
||
|
||
PoSetPowerState (fdx->DeviceObject, powerType, powerState);
|
||
|
||
if (PowerDeviceD0 == fdx->DeviceState) {
|
||
|
||
//
|
||
// Do the power on stuff here.
|
||
//
|
||
|
||
}
|
||
fdx->DeviceState = powerState.DeviceState;
|
||
|
||
} else if (powerState.DeviceState < fdx->DeviceState) {
|
||
//
|
||
// Powering Up
|
||
//
|
||
hookit = TRUE;
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
case SystemPowerState:
|
||
|
||
if (fdx->SystemState < powerState.SystemState) {
|
||
//
|
||
// Powering down
|
||
//
|
||
if (PowerSystemWorking == fdx->SystemState) {
|
||
|
||
//
|
||
// Do the system shut down stuff here.
|
||
//
|
||
|
||
}
|
||
|
||
powerState.DeviceState = PowerDeviceD3;
|
||
PoRequestPowerIrp (fdx->DeviceObject,
|
||
IRP_MN_SET_POWER,
|
||
powerState,
|
||
NULL, // no completion function
|
||
NULL, // and no context
|
||
NULL);
|
||
fdx->SystemState = powerState.SystemState;
|
||
|
||
} else if (powerState.SystemState < fdx->SystemState) {
|
||
//
|
||
// Powering Up
|
||
//
|
||
hookit = TRUE;
|
||
}
|
||
break;
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
bogusIrp = TRUE;
|
||
status = STATUS_NOT_SUPPORTED;
|
||
}
|
||
|
||
IoCopyCurrentIrpStackLocationToNext (pIrp);
|
||
|
||
if (!NT_SUCCESS (status)) {
|
||
|
||
PoStartNextPowerIrp (pIrp);
|
||
|
||
if( bogusIrp ) {
|
||
status = PoCallDriver( fdx->ParentDeviceObject, pIrp );
|
||
} else {
|
||
P4CompleteRequest( pIrp, status, pIrp->IoStatus.Information );
|
||
}
|
||
|
||
} else if (hookit) {
|
||
|
||
IoSetCompletionRoutine( pIrp, PptPowerComplete, fdx, TRUE, TRUE, TRUE );
|
||
status = PoCallDriver (fdx->ParentDeviceObject, pIrp);
|
||
|
||
} else {
|
||
|
||
PoStartNextPowerIrp (pIrp);
|
||
status = PoCallDriver (fdx->ParentDeviceObject, pIrp);
|
||
|
||
}
|
||
|
||
PptReleaseRemoveLock(&fdx->RemoveLock, pIrp);
|
||
|
||
return status;
|
||
}
|