/*++ Copyright (c) 1997 Microsoft Corporation Module Name: POWER.C Abstract: This module contains contains the power calls for the serenum bus driver. @@BEGIN_DDKSPLIT Author: Jay Senior @@END_DDKSPLIT Environment: kernel mode only Notes: @@BEGIN_DDKSPLIT Revision History: Louis J. Giliberto, Jr. 07-Jan-2000 @@END_DDKSPLIT --*/ #include "pch.h" #ifdef ALLOC_PRAGMA //#pragma alloc_text (PAGE, Serenum_Power) //#pragma alloc_text (PAGE, Serenum_FDO_Power) //#pragma alloc_text (PAGE, Serenum_PDO_Power) #endif NTSTATUS Serenum_FDOPowerComplete (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; 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; 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; default: break; } break; case IRP_MN_QUERY_POWER: ASSERT(IRP_MN_QUERY_POWER != stack->MinorFunction); break; default: // // Basically, this is ASSERT(0) // ASSERT(0xBADBAD == IRP_MN_QUERY_POWER); break; } PoStartNextPowerIrp(Irp); Serenum_DecIoCount(data); return STATUS_SUCCESS; // Continue completion... } NTSTATUS Serenum_FDO_Power(PFDO_DEVICE_DATA Data, PIRP Irp) /*++ --*/ { NTSTATUS status; BOOLEAN hookit = FALSE; POWER_STATE powerState; POWER_STATE_TYPE powerType; PIO_STACK_LOCATION stack; stack = IoGetCurrentIrpStackLocation(Irp); powerType = stack->Parameters.Power.Type; powerState = stack->Parameters.Power.State; status = Serenum_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) { status = Irp->IoStatus.Status = STATUS_SUCCESS; break; } Serenum_KdPrint(Data, SER_DBG_PNP_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) { PoSetPowerState (Data->Self, powerType, powerState); Data->DeviceState = powerState.DeviceState; } else if (Data->DeviceState > powerState.DeviceState) { // // Powering Up // hookit = TRUE; } break; case SystemPowerState: // // status should be STATUS_SUCCESS // break; } break; case IRP_MN_QUERY_POWER: status = Irp->IoStatus.Status = STATUS_SUCCESS; break; default: // // status should be STATUS_SUCCESS // break; } IoCopyCurrentIrpStackLocationToNext (Irp); if (hookit) { status = Serenum_IncIoCount (Data); ASSERT (STATUS_SUCCESS == status); IoSetCompletionRoutine(Irp, Serenum_FDOPowerComplete, NULL, TRUE, TRUE, TRUE); status = PoCallDriver (Data->TopOfStack, Irp); } else { PoStartNextPowerIrp (Irp); status = PoCallDriver (Data->TopOfStack, Irp); } Serenum_DecIoCount (Data); return status; } NTSTATUS Serenum_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: 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: // // Default to STATUS_SUCCESS // break; default: status = STATUS_NOT_IMPLEMENTED; break; } break; case IRP_MN_QUERY_POWER: // // Default to STATUS_SUCCESS // break; case IRP_MN_WAIT_WAKE: case IRP_MN_POWER_SEQUENCE: status = STATUS_NOT_IMPLEMENTED; break; default: status = Irp->IoStatus.Status; } Irp->IoStatus.Status = status; PoStartNextPowerIrp (Irp); IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } NTSTATUS Serenum_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 = Serenum_FDO_Power ((PFDO_DEVICE_DATA) DeviceObject->DeviceExtension, Irp); } else { status = Serenum_PDO_Power ((PPDO_DEVICE_DATA) DeviceObject->DeviceExtension, Irp); } return status; }