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;
|
||
}
|