📄 power.c
字号:
/*******************************************************************************
* Copyright (c) 2006 PLX Technology, Inc.
*
* PLX Technology Inc. licenses this software under specific terms and
* conditions. Use of any of the software or derviatives thereof in any
* product without a PLX Technology chip is strictly prohibited.
*
* PLX Technology, Inc. provides this software AS IS, WITHOUT ANY WARRANTY,
* EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. PLX makes no guarantee
* or representations regarding the use of, or the results of the use of,
* the software and documentation in terms of correctness, accuracy,
* reliability, currentness, or otherwise; and you rely on the software,
* documentation and results solely at your own risk.
*
* IN NO EVENT SHALL PLX BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS,
* LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES
* OF ANY KIND. IN NO EVENT SHALL PLX'S TOTAL LIABILITY EXCEED THE SUM
* PAID TO PLX FOR THE PRODUCT LICENSED HEREUNDER.
*
******************************************************************************/
/******************************************************************************
*
* File Name:
*
* Power.c
*
* Description:
*
* Power Management functions
*
* Revision History:
*
* 02-01-06 : PCI SDK v4.40
*
******************************************************************************/
#include "ApiFunctions.h"
#include "PciSupport.h"
#include "PlugPlay.h"
#include "Power.h"
#include "SupportFunc.h"
/******************************************************************************
*
* Function : Dispatch_Power
*
* Description: Handles power requests
*
******************************************************************************/
NTSTATUS
Dispatch_Power(
PDEVICE_OBJECT fdo,
PIRP pIrp
)
{
NTSTATUS status;
PIO_STACK_LOCATION stack;
PlxLockDevice(
fdo->DeviceExtension
);
DebugPrintf(("Received POWER Message (IRP=0x%p) ==> ", pIrp));
stack =
IoGetCurrentIrpStackLocation(
pIrp
);
switch (stack->MinorFunction)
{
case IRP_MN_WAIT_WAKE:
DebugPrintf_NoInfo(("IRP_MN_WAIT_WAKE\n"));
status =
DefaultPowerHandler(
fdo,
pIrp
);
break;
case IRP_MN_POWER_SEQUENCE:
DebugPrintf_NoInfo(("IRP_MN_POWER_SEQUENCE\n"));
status =
DefaultPowerHandler(
fdo,
pIrp
);
break;
case IRP_MN_SET_POWER:
DebugPrintf_NoInfo(("IRP_MN_SET_POWER\n"));
if (stack->Parameters.Power.Type == SystemPowerState)
{
DebugPrintf((
"SystemContext = 0x%08x SystemPowerState = 0x%08x\n",
stack->Parameters.Power.SystemContext,
stack->Parameters.Power.State.SystemState
));
}
else
{
DebugPrintf((
"SystemContext = 0x%08x DevicePowerState = 0x%08x\n",
stack->Parameters.Power.SystemContext,
stack->Parameters.Power.State.DeviceState
));
}
status =
HandleSetPower(
fdo,
pIrp
);
break;
case IRP_MN_QUERY_POWER:
DebugPrintf_NoInfo(("IRP_MN_QUERY_POWER\n"));
DebugPrintf((
"SystemContext = 0x%08x\n",
stack->Parameters.Power.SystemContext
));
status =
HandleQueryPower(
fdo,
pIrp
);
break;
default:
DebugPrintf_NoInfo((
"Unsupported IRP_MN_Xxx (0x%08x)\n",
stack->MinorFunction
));
status =
DefaultPowerHandler(
fdo,
pIrp
);
break;
}
PlxUnlockDevice(
fdo->DeviceExtension
);
return status;
}
/******************************************************************************
*
* Function : DefaultPowerHandler
*
* Description: Handle defaults power requests
*
******************************************************************************/
NTSTATUS
DefaultPowerHandler(
PDEVICE_OBJECT fdo,
PIRP pIrp
)
{
DebugPrintf(("Forwarded IRP to next lower driver\n"));
// Must be done while we own the IRP
PoStartNextPowerIrp(
pIrp
);
IoSkipCurrentIrpStackLocation(
pIrp
);
return PoCallDriver(
((DEVICE_EXTENSION *)fdo->DeviceExtension)->pLowerDeviceObject,
pIrp
);
}
/******************************************************************************
*
* Function : HandleSetPower
*
* Description: Handles IRP_MN_SET_POWER IRP
*
******************************************************************************/
NTSTATUS
HandleSetPower(
PDEVICE_OBJECT fdo,
PIRP pIrp
)
{
U32 context;
NTSTATUS status;
POWER_STATE state;
POWER_STATE_TYPE type;
DEVICE_EXTENSION *pdx;
PIO_STACK_LOCATION stack;
DEVICE_POWER_STATE devstate;
pdx = fdo->DeviceExtension;
stack = IoGetCurrentIrpStackLocation(pIrp);
context = stack->Parameters.Power.SystemContext;
type = stack->Parameters.Power.Type;
state = stack->Parameters.Power.State;
/* If this IRP pertains to a system state, we want to put ourselves into
* a corresponding device state. The rule here is very simple: if the
* system is below SystemWorking, me must go to D3. If the system is
* in SystemWorking, we're allowed to pick our own state (so we pick
* D0). We can't just change our power state now, though: we must send
* ourselves a separate POWER IRP with the selected device state.
*/
if (type == SystemPowerState)
{
if (state.SystemState <= PowerSystemWorking)
devstate = PowerDeviceD0;
else
devstate = PowerDeviceD3;
}
else
devstate = state.DeviceState;
// If we're adding power, first pass the IRP down. Queue the
// requisite device IRP in the completion routine after the
// lower layers have restored power.
if (devstate < pdx->PowerState)
{
// Adding more power
IoCopyCurrentIrpStackLocationToNext(
pIrp
);
IoSetCompletionRoutine(
pIrp,
(PIO_COMPLETION_ROUTINE) OnFinishPowerUp,
NULL,
TRUE,
TRUE,
TRUE
);
return PoCallDriver(
pdx->pLowerDeviceObject,
pIrp
);
}
else if (devstate > pdx->PowerState)
{
/* If we're removing power, first do the device specific part.
* Then send the request down the stack. In the case of a system
* power request, send ourselves a device power IRP to power down first.
* In the case of a device power request, use PoSetPowerState to tell
* the Power Manager what we're about to do and then actually depower
* the hardware.
*/
// Removing power
if (type == SystemPowerState)
{
// Change in system state
status =
SendDeviceSetPower(
fdo,
devstate,
context
);
if (!NT_SUCCESS(status))
{
// Couldn't set device power state
PoStartNextPowerIrp(
pIrp
);
return PlxCompleteIrpWithInformation(
pIrp,
status,
0
);
}
}
else
{
// Change in device state
PoSetPowerState(
fdo,
type,
state
); // before we power down
SetPowerState(
fdo,
devstate
);
}
// Pass request down
return DefaultPowerHandler(
fdo,
pIrp
);
}
// Pass request down
return DefaultPowerHandler(
fdo,
pIrp
);
}
/******************************************************************************
*
* Function : HandleQueryPower
*
* Description: Handle the IRP_MN_QUERY_POWER power IRP
*
******************************************************************************/
NTSTATUS
HandleQueryPower(
PDEVICE_OBJECT fdo,
PIRP pIrp
)
{
PIO_STACK_LOCATION stack;
DEVICE_POWER_STATE devstate;
stack =
IoGetCurrentIrpStackLocation(
pIrp
);
switch (stack->Parameters.Power.Type)
{
case SystemPowerState:
DebugPrintf(("Query System Power State\n"));
if (stack->Parameters.Power.State.SystemState <= PowerSystemWorking)
devstate = PowerDeviceD0;
else
devstate = PowerDeviceD3;
break;
case DevicePowerState:
DebugPrintf(("Query Device Power State\n"));
devstate = stack->Parameters.Power.State.DeviceState;
if (PlxIsPowerLevelSupported(
fdo->DeviceExtension,
devstate - PowerDeviceD0 + D0
) == FALSE)
{
// Unsupported power level, we must fail the IRP
DebugPrintf((
"WARNING - HandleQueryPower() unsupported power level\n"
));
return PlxCompleteIrpWithInformation(
pIrp,
STATUS_POWER_STATE_INVALID,
0
);
}
break;
default:
DebugPrintf(("Unknown query power state type\n"));
break;
}
// Pass request down
return DefaultPowerHandler(
fdo,
pIrp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -