452 lines
10 KiB
C
452 lines
10 KiB
C
|
//
|
|||
|
// This file contains functions that handle Power Management IRPs
|
|||
|
//
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Copyright (C) Microsoft Corporation, 1998 - 1998
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
power.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This file contains routines that handle ParClass Power Management IRPs.
|
|||
|
|
|||
|
Revision History :
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "pch.h"
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ParPower (
|
|||
|
IN PDEVICE_OBJECT pDeviceObject,
|
|||
|
IN PIRP pIrp
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the ParClass dispatch routine for all Power Management IRPs.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pDeviceObject - represents a parallel device
|
|||
|
|
|||
|
pIrp - Power IRP
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS - if successful.
|
|||
|
!STATUS_SUCCESS - otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDEVICE_EXTENSION Extension = pDeviceObject->DeviceExtension;
|
|||
|
|
|||
|
//
|
|||
|
// determine the type of DeviceObject and forward the call as appropriate
|
|||
|
//
|
|||
|
if( Extension->IsPdo ) {
|
|||
|
return ParPdoPower (Extension, pIrp); // this is a PDO (PODOs never get Power IRPs)
|
|||
|
} else {
|
|||
|
return ParFdoPower (Extension, pIrp); // this is the ParClass FDO
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ParPdoPower (
|
|||
|
IN PDEVICE_EXTENSION Extension,
|
|||
|
IN PIRP pIrp
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine handles all Power IRPs for PDOs.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pDeviceObject - represents a parallel device
|
|||
|
|
|||
|
pIrp - PNP Irp
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS - if successful.
|
|||
|
STATUS_UNSUCCESSFUL - otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
POWER_STATE_TYPE powerType;
|
|||
|
POWER_STATE powerState;
|
|||
|
PIO_STACK_LOCATION pIrpStack;
|
|||
|
NTSTATUS status = STATUS_SUCCESS;
|
|||
|
|
|||
|
ParDump2(PARPOWER, ("ParPdoPower(...)\n") );
|
|||
|
|
|||
|
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
|
|||
|
|
|||
|
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:
|
|||
|
|
|||
|
ParDump2(PARPOWER, ("PARCLASS-PnP Setting %s state to %d\n",
|
|||
|
((powerType == SystemPowerState) ? "System" : "Device"),
|
|||
|
powerState.SystemState) );
|
|||
|
|
|||
|
switch (powerType) {
|
|||
|
|
|||
|
case DevicePowerState:
|
|||
|
|
|||
|
if (Extension->DeviceState < powerState.DeviceState) {
|
|||
|
|
|||
|
//
|
|||
|
// Powering down
|
|||
|
//
|
|||
|
|
|||
|
if (PowerDeviceD0 == Extension->DeviceState) {
|
|||
|
|
|||
|
//
|
|||
|
// Do the power on stuff here.
|
|||
|
//
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else if (powerState.DeviceState < Extension->DeviceState) {
|
|||
|
|
|||
|
//
|
|||
|
// Powering Up
|
|||
|
//
|
|||
|
}
|
|||
|
|
|||
|
PoSetPowerState (Extension->DeviceObject, powerType, powerState);
|
|||
|
Extension->DeviceState = powerState.DeviceState;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case SystemPowerState:
|
|||
|
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
status = STATUS_NOT_SUPPORTED;
|
|||
|
}
|
|||
|
|
|||
|
pIrp->IoStatus.Status = status;
|
|||
|
PoStartNextPowerIrp (pIrp);
|
|||
|
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
|
|||
|
return (status);
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ParPowerComplete (
|
|||
|
IN PDEVICE_OBJECT pDeviceObject,
|
|||
|
IN PIRP pIrp,
|
|||
|
IN PDEVICE_EXTENSION Extension
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine handles all IRP_MJ_POWER IRPs.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pDeviceObject - represents the port device
|
|||
|
|
|||
|
pIrp - PNP irp
|
|||
|
|
|||
|
Extension - Device Extension
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Status
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
POWER_STATE_TYPE powerType;
|
|||
|
POWER_STATE powerState;
|
|||
|
PIO_STACK_LOCATION pIrpStack;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER( pDeviceObject );
|
|||
|
|
|||
|
ParDump2(PARPOWER, ("Enter ParPowerComplete(...)\n") );
|
|||
|
|
|||
|
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:
|
|||
|
|
|||
|
ParDump2(PARPOWER, ("PARCLASS-PnP Setting %s state to %d\n",
|
|||
|
((powerType == SystemPowerState) ? "System" : "Device"),
|
|||
|
powerState.SystemState) );
|
|||
|
|
|||
|
switch (powerType) {
|
|||
|
|
|||
|
case DevicePowerState:
|
|||
|
|
|||
|
if (Extension->DeviceState < powerState.DeviceState) {
|
|||
|
|
|||
|
//
|
|||
|
// Powering down
|
|||
|
//
|
|||
|
|
|||
|
ASSERTMSG ("Invalid power completion Device Down\n", FALSE);
|
|||
|
|
|||
|
} else if (powerState.DeviceState < Extension->DeviceState) {
|
|||
|
|
|||
|
//
|
|||
|
// Powering Up
|
|||
|
//
|
|||
|
if( Extension->IsPdo ) {
|
|||
|
// only call for PDOs
|
|||
|
PoSetPowerState (Extension->DeviceObject, powerType, powerState);
|
|||
|
}
|
|||
|
|
|||
|
if (PowerDeviceD0 == Extension->DeviceState) {
|
|||
|
|
|||
|
//
|
|||
|
// Do the power on stuff here.
|
|||
|
//
|
|||
|
|
|||
|
}
|
|||
|
Extension->DeviceState = powerState.DeviceState;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case SystemPowerState:
|
|||
|
|
|||
|
if (Extension->SystemState < powerState.SystemState) {
|
|||
|
|
|||
|
//
|
|||
|
// Powering down
|
|||
|
//
|
|||
|
|
|||
|
ASSERTMSG ("Invalid power completion System Down\n", FALSE);
|
|||
|
|
|||
|
} else if (powerState.SystemState < Extension->SystemState) {
|
|||
|
|
|||
|
//
|
|||
|
// Powering Up
|
|||
|
//
|
|||
|
if (PowerSystemWorking == powerState.SystemState) {
|
|||
|
|
|||
|
//
|
|||
|
// Do the system start up stuff here.
|
|||
|
//
|
|||
|
|
|||
|
powerState.DeviceState = PowerDeviceD0;
|
|||
|
PoRequestPowerIrp (Extension->DeviceObject,
|
|||
|
IRP_MN_SET_POWER,
|
|||
|
powerState,
|
|||
|
NULL, // no completion function
|
|||
|
NULL, // and no context
|
|||
|
NULL);
|
|||
|
}
|
|||
|
|
|||
|
Extension->SystemState = powerState.SystemState;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
ASSERTMSG ("Power Complete: Bad Power State", FALSE);
|
|||
|
}
|
|||
|
|
|||
|
PoStartNextPowerIrp (pIrp);
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ParFdoPower (
|
|||
|
IN PDEVICE_EXTENSION Extension,
|
|||
|
IN PIRP pIrp
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine handles all Power IRPs Fdos.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pDeviceObject - represents a parallel device
|
|||
|
|
|||
|
pIrp - PNP Irp
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS - if successful.
|
|||
|
STATUS_UNSUCCESSFUL - otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
POWER_STATE_TYPE powerType;
|
|||
|
POWER_STATE powerState;
|
|||
|
PIO_STACK_LOCATION pIrpStack;
|
|||
|
NTSTATUS status = STATUS_SUCCESS;
|
|||
|
BOOLEAN hookit = FALSE;
|
|||
|
|
|||
|
ParDump2(PARPOWER, ("ParFdoPower(...)\n") );
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS status = ParAcquireRemoveLock(&Extension->RemoveLock, pIrp);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
pIrp->IoStatus.Status = status;
|
|||
|
pIrp->IoStatus.Information = 0;
|
|||
|
PoStartNextPowerIrp( pIrp );
|
|||
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|||
|
return status;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
|
|||
|
|
|||
|
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:
|
|||
|
|
|||
|
ParDump2(PARPOWER, ("PARCLASS-PnP Setting %s state to %d\n",
|
|||
|
((powerType == SystemPowerState) ? "System" : "Device"),
|
|||
|
powerState.SystemState) );
|
|||
|
|
|||
|
switch (powerType) {
|
|||
|
|
|||
|
case DevicePowerState:
|
|||
|
|
|||
|
if (Extension->DeviceState < powerState.DeviceState) {
|
|||
|
//
|
|||
|
// Powering down
|
|||
|
//
|
|||
|
|
|||
|
// Don't call - this is an FDO
|
|||
|
// PoSetPowerState (Extension->DeviceObject, powerType, powerState);
|
|||
|
|
|||
|
if (PowerDeviceD0 == Extension->DeviceState) {
|
|||
|
|
|||
|
//
|
|||
|
// Do the power on stuff here.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// WORKWORK
|
|||
|
//
|
|||
|
// We must check to see that our children are in a
|
|||
|
// consistent power state.
|
|||
|
//
|
|||
|
|
|||
|
}
|
|||
|
Extension->DeviceState = powerState.DeviceState;
|
|||
|
|
|||
|
} else if (powerState.DeviceState < Extension->DeviceState) {
|
|||
|
|
|||
|
//
|
|||
|
// Powering Up
|
|||
|
//
|
|||
|
hookit = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case SystemPowerState:
|
|||
|
|
|||
|
if (Extension->SystemState < powerState.SystemState) {
|
|||
|
|
|||
|
//
|
|||
|
// Powering down
|
|||
|
//
|
|||
|
if (PowerSystemWorking == Extension->SystemState) {
|
|||
|
|
|||
|
//
|
|||
|
// Do the system shut down stuff here.
|
|||
|
//
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
powerState.DeviceState = PowerDeviceD3;
|
|||
|
PoRequestPowerIrp (Extension->DeviceObject,
|
|||
|
IRP_MN_SET_POWER,
|
|||
|
powerState,
|
|||
|
NULL, // no completion function
|
|||
|
NULL, // and no context
|
|||
|
NULL);
|
|||
|
Extension->SystemState = powerState.SystemState;
|
|||
|
|
|||
|
} else if (powerState.SystemState < Extension->SystemState) {
|
|||
|
|
|||
|
//
|
|||
|
// Powering Up
|
|||
|
//
|
|||
|
hookit = TRUE;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
status = STATUS_NOT_SUPPORTED;
|
|||
|
}
|
|||
|
|
|||
|
IoCopyCurrentIrpStackLocationToNext (pIrp);
|
|||
|
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
|
|||
|
pIrp->IoStatus.Status = status;
|
|||
|
PoStartNextPowerIrp (pIrp);
|
|||
|
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
|
|||
|
|
|||
|
} else if (hookit) {
|
|||
|
|
|||
|
IoSetCompletionRoutine(pIrp, ParPowerComplete, Extension, TRUE, TRUE, TRUE);
|
|||
|
status = PoCallDriver(Extension->ParentDeviceObject, pIrp);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
PoStartNextPowerIrp (pIrp);
|
|||
|
status = PoCallDriver (Extension->ParentDeviceObject, pIrp);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ParReleaseRemoveLock(&Extension->RemoveLock, pIrp);
|
|||
|
return status;
|
|||
|
}
|