You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
480 lines
12 KiB
480 lines
12 KiB
/*++
|
|
Module Name:
|
|
|
|
POWER.C
|
|
|
|
Abstract:
|
|
|
|
This module contains contains the plugplay power calls
|
|
for a serial port bus enumerator PNP / WDM driver.
|
|
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include <ntddk.h>
|
|
#include <ntddser.h>
|
|
#include "mxenum.h"
|
|
#include "mxlog.h"
|
|
|
|
static const PHYSICAL_ADDRESS SerialPhysicalZero = {0};
|
|
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text (PAGE, MxenumPowerDispatch)
|
|
#pragma alloc_text (PAGE, MxenumFdoPowerDispatch)
|
|
#pragma alloc_text (PAGE, MxenumPdoPowerDispatch)
|
|
#endif
|
|
|
|
NTSTATUS
|
|
MxenumPowerDispatch (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION irpStack;
|
|
NTSTATUS status;
|
|
PCOMMON_DEVICE_DATA commonData;
|
|
|
|
PAGED_CODE ();
|
|
|
|
status = STATUS_SUCCESS;
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
// ASSERT (IRP_MJ_POWER == irpStack->MajorFunction);
|
|
|
|
commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
|
|
|
|
if (commonData->IsFDO) {
|
|
status =
|
|
MxenumFdoPowerDispatch ((PFDO_DEVICE_DATA) DeviceObject->DeviceExtension,
|
|
Irp);
|
|
} else {
|
|
|
|
status =
|
|
MxenumPdoPowerDispatch ((PPDO_DEVICE_DATA) DeviceObject->DeviceExtension,
|
|
Irp);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
MxenumFdoPowerComplete (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
MxenumFdoPowerDispatch(
|
|
PFDO_DEVICE_DATA Data,
|
|
PIRP Irp
|
|
)
|
|
/*++
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
BOOLEAN hookit = FALSE;
|
|
POWER_STATE powerState;
|
|
POWER_STATE_TYPE powerType;
|
|
PIO_STACK_LOCATION stack;
|
|
UCHAR minorFunction;
|
|
|
|
stack = IoGetCurrentIrpStackLocation (Irp);
|
|
minorFunction = stack->MinorFunction;
|
|
powerType = stack->Parameters.Power.Type;
|
|
powerState = stack->Parameters.Power.State;
|
|
|
|
PAGED_CODE ();
|
|
|
|
status = MxenumIncIoCount (Data);
|
|
if (!NT_SUCCESS (status)) {
|
|
PoStartNextPowerIrp (Irp);
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
return status;
|
|
}
|
|
status = Irp->IoStatus.Status;
|
|
|
|
switch (minorFunction) {
|
|
case IRP_MN_SET_POWER:
|
|
MxenumKdPrint( MXENUM_DBG_TRACE,
|
|
("Serenum-PnP Setting %s state to %d\n",
|
|
((powerType == SystemPowerState) ? "System" : "Device"),
|
|
powerState.SystemState));
|
|
|
|
switch (powerType) {
|
|
case DevicePowerState:
|
|
status = Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
|
|
if (Data->DeviceState < powerState.DeviceState) {
|
|
//
|
|
// Powering down
|
|
|
|
PoSetPowerState (Data->Self, powerType, powerState);
|
|
Data->DeviceState = powerState.DeviceState;
|
|
} else if (Data->DeviceState > powerState.DeviceState) {
|
|
//
|
|
// Powering Up
|
|
//
|
|
hookit = TRUE;
|
|
}
|
|
|
|
break;
|
|
|
|
case SystemPowerState:
|
|
|
|
MxenumKdPrint (MXENUM_DBG_TRACE,
|
|
("In SystemPowerState\n"
|
|
" Current System state = %d\n"
|
|
" Device started = %d\n"
|
|
" System state to be set = %d\n"
|
|
" Irql = %x\n",
|
|
Data->SystemState,
|
|
Data->Started,
|
|
powerState.SystemState,
|
|
KeGetCurrentIrql()));
|
|
/* 3-22-01 by William
|
|
if ((Data->SystemState == PowerSystemHibernate)&&
|
|
*/
|
|
if ((Data->SystemState != PowerSystemWorking)&&
|
|
// (Data->Started == TRUE)&&
|
|
(powerState.SystemState == PowerSystemWorking)){
|
|
|
|
ULONG i;
|
|
MxenumKdPrint (MXENUM_DBG_TRACE,("Hook it\n"));
|
|
// hookit = TRUE;
|
|
|
|
|
|
MxenumKdPrint (MXENUM_DBG_TRACE,
|
|
("Start Device: Start to download\n"));
|
|
|
|
i = 0;
|
|
while (BoardDesc[Data->BoardType-1][i])
|
|
i++;
|
|
i <<= 1;
|
|
|
|
status = MxenumDownloadFirmware(Data,TRUE);
|
|
MxenumKdPrint (MXENUM_DBG_TRACE,
|
|
("BoardDesc(%d)->%ws\n",i,BoardDesc[Data->BoardType-1]));
|
|
|
|
if (status != 0) {
|
|
ULONG j;
|
|
|
|
j = 0;
|
|
while (DownloadErrMsg[status-1][j])
|
|
j++;
|
|
j <<= 1;
|
|
|
|
MxenumKdPrint (MXENUM_DBG_TRACE,
|
|
("Start Device: Device started failure\n"));
|
|
#if 0
|
|
MxenumLogError(
|
|
DeviceObject->DriverObject,
|
|
NULL,
|
|
SerialPhysicalZero,
|
|
SerialPhysicalZero,
|
|
0,
|
|
0,
|
|
0,
|
|
19,
|
|
STATUS_SUCCESS,
|
|
MXENUM_DOWNLOAD_FAIL,
|
|
i + sizeof (WCHAR),
|
|
BoardDesc[Data->BoardType -1],
|
|
j + sizeof (WCHAR),
|
|
DownloadErrMsg[status -1]
|
|
);
|
|
#endif
|
|
|
|
Data->Started = FALSE;
|
|
|
|
}
|
|
else {
|
|
MxenumKdPrint (MXENUM_DBG_TRACE,
|
|
("Start Device: Device started successfully\n"));
|
|
Data->Started = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
status = STATUS_SUCCESS; // return SUCCESS anyway
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
//
|
|
// Power IRPS come synchronously; drivers must call
|
|
// PoStartNextPowerIrp, when they are ready for the next power
|
|
// irp. This can be called here, or in the completetion
|
|
// routine, but never the less must be called.
|
|
//
|
|
Irp->IoStatus.Status = status;
|
|
Data->SystemState = powerState.SystemState;
|
|
IoCopyCurrentIrpStackLocationToNext (Irp);
|
|
PoStartNextPowerIrp (Irp);
|
|
PoCallDriver (Data->TopOfStack, Irp);
|
|
|
|
MxenumDecIoCount (Data);
|
|
return status;
|
|
|
|
|
|
|
|
case IRP_MN_QUERY_POWER:
|
|
//
|
|
Data->PowerQueryLock = TRUE;
|
|
status = Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
IoCopyCurrentIrpStackLocationToNext (Irp);
|
|
|
|
if (hookit) {
|
|
status = MxenumIncIoCount (Data);
|
|
// ASSERT (STATUS_SUCCESS == status);
|
|
IoSetCompletionRoutine (Irp,
|
|
MxenumFdoPowerComplete,
|
|
NULL,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
PoCallDriver (Data->TopOfStack, Irp);
|
|
|
|
} else {
|
|
//
|
|
// Power IRPS come synchronously; drivers must call
|
|
// PoStartNextPowerIrp, when they are ready for the next power
|
|
// irp. This can be called here, or in the completetion
|
|
// routine, but never the less must be called.
|
|
//
|
|
PoStartNextPowerIrp (Irp);
|
|
|
|
PoCallDriver (Data->TopOfStack, Irp);
|
|
}
|
|
|
|
#if 0
|
|
if ((minorFunction == IRP_MN_SET_POWER)&&
|
|
(powerType == SystemPowerState)) {
|
|
Data->SystemState = powerState.SystemState;
|
|
}
|
|
#endif
|
|
|
|
MxenumDecIoCount (Data);
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
MxenumFdoPowerComplete (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
--*/
|
|
{
|
|
POWER_STATE powerState;
|
|
POWER_STATE_TYPE powerType;
|
|
PIO_STACK_LOCATION stack;
|
|
PFDO_DEVICE_DATA data;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
UNREFERENCED_PARAMETER (Context);
|
|
|
|
data = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
|
|
stack = IoGetCurrentIrpStackLocation (Irp);
|
|
powerType = stack->Parameters.Power.Type;
|
|
powerState = stack->Parameters.Power.State;
|
|
MxenumKdPrint (MXENUM_DBG_TRACE,
|
|
("MxenumFdoPowerComplete,irql=%x\n",KeGetCurrentIrql()));
|
|
|
|
|
|
switch (stack->MinorFunction) {
|
|
case IRP_MN_SET_POWER:
|
|
switch (powerType) {
|
|
case DevicePowerState:
|
|
//
|
|
// Powering Up
|
|
//
|
|
// ASSERT (powerState.DeviceState < data->DeviceState);
|
|
data->DeviceState = powerState.DeviceState;
|
|
|
|
PoSetPowerState (data->Self, powerType, powerState);
|
|
|
|
break;
|
|
|
|
case SystemPowerState:
|
|
{
|
|
ULONG i;
|
|
|
|
MxenumKdPrint (MXENUM_DBG_TRACE,
|
|
("Start Device: Start to download\n"));
|
|
|
|
i = 0;
|
|
while (BoardDesc[data->BoardType-1][i])
|
|
i++;
|
|
i <<= 1;
|
|
|
|
status = MxenumDownloadFirmware(data,TRUE);
|
|
MxenumKdPrint (MXENUM_DBG_TRACE,
|
|
("BoardDesc(%d)->%ws\n",i,BoardDesc[data->BoardType-1]));
|
|
|
|
if (status != 0) {
|
|
ULONG j;
|
|
|
|
j = 0;
|
|
while (DownloadErrMsg[status-1][j])
|
|
j++;
|
|
j <<= 1;
|
|
|
|
MxenumKdPrint (MXENUM_DBG_TRACE,
|
|
("Start Device: Device started failure\n"));
|
|
MxenumLogError(
|
|
DeviceObject->DriverObject,
|
|
NULL,
|
|
SerialPhysicalZero,
|
|
SerialPhysicalZero,
|
|
0,
|
|
0,
|
|
0,
|
|
19,
|
|
STATUS_SUCCESS,
|
|
MXENUM_DOWNLOAD_FAIL,
|
|
i + sizeof (WCHAR),
|
|
BoardDesc[data->BoardType -1],
|
|
j + sizeof (WCHAR),
|
|
DownloadErrMsg[status -1]
|
|
);
|
|
|
|
data->Started = FALSE;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
else {
|
|
MxenumKdPrint (MXENUM_DBG_TRACE,
|
|
("Start Device: Device started successfully\n"));
|
|
data->Started = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_QUERY_POWER:
|
|
|
|
// ASSERT (IRP_MN_QUERY_POWER != stack->MinorFunction);
|
|
break;
|
|
|
|
default:
|
|
// ASSERT (0xBADBAD == IRP_MN_QUERY_POWER);
|
|
break;
|
|
}
|
|
|
|
PoStartNextPowerIrp (Irp);
|
|
MxenumDecIoCount (data);
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
VOID
|
|
MxenumPdoPowerComplete (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN UCHAR MinorFunction,
|
|
IN POWER_STATE PowerState,
|
|
IN PVOID Irp,
|
|
IN PIO_STATUS_BLOCK IoStatus
|
|
);
|
|
|
|
NTSTATUS
|
|
MxenumPdoPowerDispatch (
|
|
PPDO_DEVICE_DATA PdoData,
|
|
PIRP Irp
|
|
)
|
|
/*++
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PIO_STACK_LOCATION stack;
|
|
POWER_STATE powerState;
|
|
POWER_STATE_TYPE powerType;
|
|
|
|
PAGED_CODE();
|
|
|
|
status = Irp->IoStatus.Status;
|
|
|
|
stack = IoGetCurrentIrpStackLocation (Irp);
|
|
powerType = stack->Parameters.Power.Type;
|
|
powerState = stack->Parameters.Power.State;
|
|
|
|
switch (stack->MinorFunction) {
|
|
case IRP_MN_SET_POWER:
|
|
switch (powerType) {
|
|
case DevicePowerState:
|
|
if (PdoData->DeviceState > powerState.DeviceState) {
|
|
PoSetPowerState (PdoData->Self, powerType, powerState);
|
|
PdoData->DeviceState = powerState.DeviceState;
|
|
} else if (PdoData->DeviceState < powerState.DeviceState) {
|
|
//
|
|
// Powering down.
|
|
//
|
|
PoSetPowerState (PdoData->Self, powerType, powerState);
|
|
PdoData->DeviceState = powerState.DeviceState;
|
|
}
|
|
break;
|
|
|
|
case SystemPowerState:
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
// status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_QUERY_POWER:
|
|
PdoData->PowerQueryLock = TRUE;
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IRP_MN_WAIT_WAKE:
|
|
case IRP_MN_POWER_SEQUENCE:
|
|
default:
|
|
// status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
PoStartNextPowerIrp (Irp);
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
return status;
|
|
}
|