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