Leaked source code of windows server 2003
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.
 
 
 
 
 
 

694 lines
19 KiB

/*--------------------------------------------------------------------------
*
* Copyright (C) Cyclades Corporation, 2000-2001.
* All rights reserved.
*
* Cyclades-Z Enumerator Driver
*
* This file: power.c
*
* Description: This module contains contains the power calls
* for the cyclades-Z bus driver.
*
* Notes: This code supports Windows 2000 and Windows XP,
* x86 and ia64 processors.
*
* Complies with Cyclades SW Coding Standard rev 1.3.
*
*--------------------------------------------------------------------------
*/
/*-------------------------------------------------------------------------
*
* Change History
*
*--------------------------------------------------------------------------
* Initial implementation based on Microsoft sample code.
*
*--------------------------------------------------------------------------
*/
#include "pch.h"
#ifdef ALLOC_PRAGMA
//#pragma alloc_text (PAGE, Cycladz_Power)
//#pragma alloc_text (PAGE, Cycladz_FDO_Power)
//#pragma alloc_text (PAGE, Cycladz_PDO_Power)
#endif
typedef struct _POWER_COMPLETION_CONTEXT {
PDEVICE_OBJECT DeviceObject;
PIRP SIrp;
} POWER_COMPLETION_CONTEXT, *PPOWER_COMPLETION_CONTEXT;
VOID
OnPowerRequestComplete(
PDEVICE_OBJECT DeviceObject,
UCHAR MinorFunction,
POWER_STATE state,
POWER_COMPLETION_CONTEXT* PowerContext,
PIO_STATUS_BLOCK IoStatus
)
/*++
Routine Description:
Completion routine for D-IRP.
Arguments:
Return Value:
NT status code
--*/
{
PFDO_DEVICE_DATA fdoData = (PFDO_DEVICE_DATA) PowerContext->DeviceObject->DeviceExtension;
PIRP sIrp = PowerContext->SIrp;
UNREFERENCED_PARAMETER (DeviceObject);
UNREFERENCED_PARAMETER (MinorFunction);
UNREFERENCED_PARAMETER (state);
Cycladz_KdPrint(fdoData,SER_DBG_POWER_TRACE, (">OnPowerRequestComplete\n"));
//
// Here we copy the D-IRP status into the S-IRP
//
sIrp->IoStatus.Status = IoStatus->Status;
//
// Release the IRP
//
PoStartNextPowerIrp(sIrp);
IoCompleteRequest(sIrp, IO_NO_INCREMENT);
//
// Cleanup
//
ExFreePool(PowerContext);
Cycladz_DecIoCount(fdoData);
Cycladz_KdPrint(fdoData,SER_DBG_POWER_TRACE, ("<OnPowerRequestComplete\n"));
}
NTSTATUS
Cycladz_FDOSystemPowerComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
--*/
{
POWER_COMPLETION_CONTEXT* powerContext;
POWER_STATE powerState;
POWER_STATE_TYPE powerType;
PIO_STACK_LOCATION stack;
PFDO_DEVICE_DATA data;
NTSTATUS status = Irp->IoStatus.Status;
UNREFERENCED_PARAMETER (Context);
data = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
Cycladz_KdPrint(data,SER_DBG_POWER_TRACE, (">SystemPowerComplete\n"));
if (!NT_SUCCESS(status)) {
PoStartNextPowerIrp(Irp);
Cycladz_DecIoCount (data);
Cycladz_KdPrint(data,SER_DBG_POWER_TRACE, ("<SystemPowerComplete1\n"));
return STATUS_SUCCESS;
}
stack = IoGetCurrentIrpStackLocation (Irp);
powerState = stack->Parameters.Power.State;
switch (stack->Parameters.Power.State.SystemState) {
case PowerSystemUnspecified:
powerState.DeviceState = PowerDeviceUnspecified;
break;
case PowerSystemWorking:
powerState.DeviceState = PowerDeviceD0;
break;
case PowerSystemSleeping1:
case PowerSystemSleeping2:
case PowerSystemSleeping3:
case PowerSystemHibernate:
case PowerSystemShutdown:
case PowerSystemMaximum:
powerState.DeviceState = PowerDeviceD3;
break;
default:
powerState.DeviceState = PowerDeviceD3;
}
//
// Send IRP to change device state
//
powerContext = (POWER_COMPLETION_CONTEXT*)
ExAllocatePool(NonPagedPool, sizeof(POWER_COMPLETION_CONTEXT));
if (!powerContext) {
status = STATUS_INSUFFICIENT_RESOURCES;
} else {
powerContext->DeviceObject = DeviceObject;
powerContext->SIrp = Irp;
status = PoRequestPowerIrp(data->Self, IRP_MN_SET_POWER, powerState, OnPowerRequestComplete,
powerContext, NULL);
}
if (!NT_SUCCESS(status)) {
Cycladz_KdPrint(data,SER_DBG_POWER_TRACE, ("PoRequestPowerIrp %x\n",status));
if (powerContext) {
ExFreePool(powerContext);
}
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = status;
//IoCompleteRequest(Irp, IO_NO_INCREMENT); Toaster has this line.
Cycladz_DecIoCount(data);
Cycladz_KdPrint(data,SER_DBG_POWER_TRACE, ("<2SystemPowerComplete\n"));
return status;
}
Cycladz_KdPrint(data,SER_DBG_POWER_TRACE, ("<3SystemPowerComplete\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
VOID
Cycladz_PowerOnWorkItem(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
)
/*++
Routine Description:
This routine starts the Z hardware.
Arguments:
Return Value:
NT status code
--*/
{
PIRP Irp;
PFDO_DEVICE_DATA fdoData;
PWORKER_THREAD_CONTEXT context = (PWORKER_THREAD_CONTEXT)Context;
fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
Cycladz_KdPrint(fdoData,SER_DBG_CYCLADES, (">Cycladz_PowerOnWorkItem Irp %x\n",context->Irp));
Irp = context->Irp;
Cycladz_DoesBoardExist(fdoData);
PoSetPowerState (DeviceObject, context->PowerType, context->PowerState);
PoStartNextPowerIrp (Irp);
IoCompleteRequest (context->Irp, IO_NO_INCREMENT);
//
// Cleanup before exiting from the worker thread.
//
IoFreeWorkItem(context->WorkItem);
ExFreePool((PVOID)context);
Cycladz_KdPrint(fdoData,SER_DBG_CYCLADES, ("<Cycladz_PowerOnWorkItem\n"));
Cycladz_DecIoCount (fdoData);
}
NTSTATUS
Cycladz_FDOPowerComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
--*/
{
PIO_WORKITEM item;
PWORKER_THREAD_CONTEXT context;
POWER_STATE powerState;
POWER_STATE_TYPE powerType;
PIO_STACK_LOCATION stack;
PFDO_DEVICE_DATA data;
//NTSTATUS status = STATUS_SUCCESS; //Removed in build 2072
UNREFERENCED_PARAMETER (Context);
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
data = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
stack = IoGetCurrentIrpStackLocation (Irp);
powerType = stack->Parameters.Power.Type;
powerState = stack->Parameters.Power.State;
Cycladz_KdPrint(data,SER_DBG_CYCLADES, ("In Cycladz_FDOPowerComplete Irp %x\n",Irp));
switch (stack->MinorFunction) {
case IRP_MN_SET_POWER:
switch (powerType) {
case DevicePowerState:
Cycladz_KdPrint(data,SER_DBG_CYCLADES, ("IRP_MN_SET_POWER Device\n"));
//
// Powering Up
//
ASSERT (powerState.DeviceState < data->DeviceState);
context = ExAllocatePool (NonPagedPool,
sizeof(WORKER_THREAD_CONTEXT));
if(context){
item = IoAllocateWorkItem(DeviceObject);
context->Irp = Irp;
context->DeviceObject= DeviceObject;
context->WorkItem = item;
context->PowerType = powerType;
context->PowerState = powerState;
if (item) {
IoMarkIrpPending(Irp);
IoQueueWorkItem (item,
Cycladz_PowerOnWorkItem,
DelayedWorkQueue,
context);
return STATUS_MORE_PROCESSING_REQUIRED;
} else {
//status = STATUS_INSUFFICIENT_RESOURCES;
// What should we do? DDK says we cannot fail SET_POWER.
}
} else {
//status = STATUS_INSUFFICIENT_RESOURCES;
// What should we do? DDK says we cannot fail SET_POWER.
}
data->DeviceState = powerState.DeviceState;
//PoSetPowerState (data->Self, powerType, powerState);
break;
default:
Cycladz_KdPrint(data,SER_DBG_CYCLADES, ("IRP_MN_SET_POWER not Device\n"));
break;
}
break;
case IRP_MN_QUERY_POWER:
Cycladz_KdPrint(data,SER_DBG_CYCLADES, ("IRP_MN_QUERY_POWER not Device\n"));
ASSERT (IRP_MN_QUERY_POWER != stack->MinorFunction);
break;
default:
ASSERT (0xBADBAD == IRP_MN_QUERY_POWER);
break;
}
PoStartNextPowerIrp (Irp);
Cycladz_DecIoCount (data);
//return status; Changed to below line in build 2072
Cycladz_KdPrint(data,SER_DBG_CYCLADES, ("Leaving Cycladz_FDOPowerComplete\n"));
return STATUS_SUCCESS; // Continue completion...
}
NTSTATUS
Cycladz_FDO_Power (
PFDO_DEVICE_DATA Data,
PIRP Irp
)
/*++
--*/
{
NTSTATUS status;
BOOLEAN hookit = FALSE;
POWER_STATE powerState;
POWER_STATE_TYPE powerType;
PIO_STACK_LOCATION stack;
// ADDED FANNY
ULONG indexPDO;
stack = IoGetCurrentIrpStackLocation (Irp);
powerType = stack->Parameters.Power.Type;
powerState = stack->Parameters.Power.State;
Cycladz_KdPrint(Data,SER_DBG_CYCLADES, ("In Cycladz_FDO_Power Irp %x\n",Irp));
status = Cycladz_IncIoCount (Data);
if (!NT_SUCCESS (status)) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = status;
PoStartNextPowerIrp (Irp);
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
switch (stack->MinorFunction) {
case IRP_MN_SET_POWER:
//
// If it hasn't started, we just pass it through
//
//if (Data->Started != TRUE) { // Added in DDK final version
// status = Irp->IoStatus.Status = STATUS_SUCCESS;
// break;
//}
if (Data->DevicePnPState != Started) { // Toaster Bus compares to == NotStarted
status = Irp->IoStatus.Status = STATUS_SUCCESS;
break;
}
Cycladz_KdPrint(Data,
SER_DBG_PNP_TRACE,
("Cycladz-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:
IoMarkIrpPending(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);
status = Cycladz_IncIoCount (Data);
ASSERT (STATUS_SUCCESS == status);
IoSetCompletionRoutine (Irp,
Cycladz_FDOSystemPowerComplete,
NULL,
TRUE,
TRUE,
TRUE);
status = PoCallDriver (Data->TopOfStack, Irp);
Cycladz_KdPrint(Data,SER_DBG_CYCLADES, ("Leaving Cycladz_FDO_Power\n"));
Cycladz_DecIoCount (Data);
return STATUS_PENDING;
}
break;
case IRP_MN_QUERY_POWER:
Cycladz_KdPrint(Data,SER_DBG_CYCLADES,("IRP_MN_QUERY_POWER\n"));
status = Irp->IoStatus.Status = STATUS_SUCCESS;
break;
default:
//
// status should be STATUS_SUCCESS
//
break;
}
if (hookit) {
IoMarkIrpPending(Irp);
IoCopyCurrentIrpStackLocationToNext (Irp);
status = Cycladz_IncIoCount (Data);
ASSERT (STATUS_SUCCESS == status);
IoSetCompletionRoutine (Irp,
Cycladz_FDOPowerComplete,
NULL,
TRUE,
TRUE,
TRUE);
status = PoCallDriver (Data->TopOfStack, Irp);
Cycladz_KdPrint(Data,SER_DBG_CYCLADES, ("Leaving Cycladz_FDO_Power\n"));
Cycladz_DecIoCount (Data);
return STATUS_PENDING;
}
PoStartNextPowerIrp (Irp);
IoSkipCurrentIrpStackLocation(Irp);
status = PoCallDriver (Data->TopOfStack, Irp);
Cycladz_KdPrint(Data,SER_DBG_CYCLADES, ("Leaving Cycladz_FDO_Power\n"));
Cycladz_DecIoCount (Data);
return status;
}
NTSTATUS
Cycladz_PDO_Power (
PPDO_DEVICE_DATA PdoData,
PIRP Irp
)
/*++
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION stack;
POWER_STATE powerState;
POWER_STATE_TYPE powerType;
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:
Cycladz_KdPrint(PdoData,SER_DBG_CYCLADES,("IRP_MN_SET_POWER Device Pdo %x\n",
PdoData->Self));
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:
Cycladz_KdPrint(PdoData,SER_DBG_CYCLADES,("IRP_MN_SET_POWER System Pdo %x\n",
PdoData->Self));
//
// Default to STATUS_SUCCESS
//
break;
default:
status = STATUS_NOT_IMPLEMENTED;
break;
}
break;
case IRP_MN_QUERY_POWER:
Cycladz_KdPrint(PdoData,SER_DBG_CYCLADES,("IRP_MN_QUERY_POWER Pdo %x\n",PdoData->Self));
//
// Default to STATUS_SUCCESS
//
break;
case IRP_MN_WAIT_WAKE:
case IRP_MN_POWER_SEQUENCE:
Cycladz_KdPrint(PdoData,SER_DBG_CYCLADES,("IRP_MN_ NOT IMPLEMENTED\n"));
status = STATUS_NOT_IMPLEMENTED;
break;
default:
status = Irp->IoStatus.Status;
}
Irp->IoStatus.Status = status;
PoStartNextPowerIrp (Irp);
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
Cycladz_Power (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
--*/
{
PIO_STACK_LOCATION irpStack;
NTSTATUS status;
PCOMMON_DEVICE_DATA commonData;
status = STATUS_SUCCESS;
irpStack = IoGetCurrentIrpStackLocation (Irp);
ASSERT (IRP_MJ_POWER == irpStack->MajorFunction);
commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
if (commonData->IsFDO) {
status =
Cycladz_FDO_Power ((PFDO_DEVICE_DATA) DeviceObject->DeviceExtension,
Irp);
} else {
status =
Cycladz_PDO_Power ((PPDO_DEVICE_DATA) DeviceObject->DeviceExtension,
Irp);
}
return status;
}
NTSTATUS
Cycladz_GotoPowerState(IN PDEVICE_OBJECT PDevObj,
IN PFDO_DEVICE_DATA PDevExt,
IN DEVICE_POWER_STATE DevPowerState)
/*++
Routine Description:
This routine causes the driver to request the stack go to a particular
power state.
Arguments:
PDevObj - Pointer to the device object for this device
PDevExt - Pointer to the device extension we are working from
DevPowerState - the power state we wish to go to
Return Value:
The function value is the final status of the call
--*/
{
KEVENT gotoPowEvent;
NTSTATUS status;
POWER_STATE powerState;
UNREFERENCED_PARAMETER (PDevExt);
PAGED_CODE();
Cycladz_KdPrint(PDevExt,SER_DBG_CYCLADES, ("In Cycladz_GotoPowerState\n"));
powerState.DeviceState = DevPowerState;
KeInitializeEvent(&gotoPowEvent, SynchronizationEvent, FALSE);
status = PoRequestPowerIrp(PDevObj, IRP_MN_SET_POWER, powerState,
Cycladz_SystemPowerCompletion, &gotoPowEvent,
NULL);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&gotoPowEvent, Executive, KernelMode, FALSE, NULL);
status = STATUS_SUCCESS;
}
#if DBG
if (!NT_SUCCESS(status)) {
Cycladz_KdPrint(PDevExt,SER_DBG_CYCLADES, ("Cycladz_GotoPowerState FAILED\n"));
}
#endif
Cycladz_KdPrint(PDevExt,SER_DBG_CYCLADES, ("Leaving Cycladz_GotoPowerState\n"));
return status;
}
NTSTATUS
Cycladz_SystemPowerCompletion(IN PDEVICE_OBJECT PDevObj, UCHAR MinorFunction,
IN POWER_STATE PowerState, IN PVOID Context,
PIO_STATUS_BLOCK IoStatus)
/*++
Routine Description:
This routine is the completion routine for PoRequestPowerIrp calls
in this module.
Arguments:
PDevObj - Pointer to the device object the irp is completing for
MinorFunction - IRP_MN_XXXX value requested
PowerState - Power state request was made of
Context - Event to set or NULL if no setting required
IoStatus - Status block from request
Return Value:
VOID
--*/
{
UNREFERENCED_PARAMETER (PDevObj);
UNREFERENCED_PARAMETER (MinorFunction);
UNREFERENCED_PARAMETER (PowerState);
UNREFERENCED_PARAMETER (IoStatus);
if (Context != NULL) {
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, 0);
}
return STATUS_SUCCESS;
}