#include "precomp.h" // Precompiled header /**************************************************************************************** * * * Module: SPX_POWER.C * * * * Creation: 15th October 1998 * * * * Author: Paul Smith * * * * Version: 1.0.0 * * * * Description: Handle all Power IRPS. * * * ****************************************************************************************/ /* History... 1.0.0 27/09/98 PBS Creation. */ #define FILE_ID SPX_POWR_C // File ID for Event Logging see SPX_DEFS.H for values. BOOLEAN BREAK_ON_POWER_UP = FALSE; // Prototypes NTSTATUS Spx_Card_FDO_DispatchPower(IN PDEVICE_OBJECT pFDO, IN PIRP pIrp); NTSTATUS Spx_CardSetSystemPowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp); NTSTATUS Spx_CardSetDevicePowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp); NTSTATUS Spx_CardSetPowerStateD0(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp); NTSTATUS Spx_CardSetPowerStateD3(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp); NTSTATUS Spx_Port_PDO_DispatchPower(IN PDEVICE_OBJECT pPDO, IN PIRP pIrp); NTSTATUS Spx_PortQuerySystemPowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp); NTSTATUS Spx_PortSetSystemPowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp); NTSTATUS Spx_PortSetDevicePowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp); NTSTATUS Spx_PortSetPowerStateD0(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp); NTSTATUS Spx_PortSetPowerStateD3(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp); NTSTATUS Spx_PowerWaitForDriverBelow(IN PDEVICE_OBJECT pLowerDevObj, IN PIRP pIrp); // End of prototypes // Paging.. #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, Spx_DispatchPower) #pragma alloc_text(PAGE, Spx_Card_FDO_DispatchPower) #pragma alloc_text(PAGE, Spx_CardSetSystemPowerState) #pragma alloc_text(PAGE, Spx_CardSetDevicePowerState) #pragma alloc_text(PAGE, Spx_CardSetPowerStateD0) #pragma alloc_text(PAGE, Spx_CardSetPowerStateD3) #pragma alloc_text(PAGE, Spx_Port_PDO_DispatchPower) #pragma alloc_text(PAGE, Spx_PortQuerySystemPowerState) #pragma alloc_text(PAGE, Spx_PortSetSystemPowerState) #pragma alloc_text(PAGE, Spx_PortSetDevicePowerState) #pragma alloc_text(PAGE, Spx_PortSetPowerStateD0) #pragma alloc_text(PAGE, Spx_PortSetPowerStateD3) #endif // ALLOC_PRAGMA ////////////////////////////////////////////////////////////////////////////////////////// // // Routine Description: // The power dispatch routine determine if the IRP is for a card or a port and // then call the correct dispatch routine. // // Arguments: // pDevObject - pointer to a device object. // pIrp - pointer to an I/O request packet. // // Return value: // NT status code. // ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS Spx_DispatchPower(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp) { PCOMMON_OBJECT_DATA CommonData = (PCOMMON_OBJECT_DATA) pDevObject->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL if(CommonData->IsFDO) status = Spx_Card_FDO_DispatchPower(pDevObject, pIrp); else status = Spx_Port_PDO_DispatchPower(pDevObject, pIrp); return status; } // Spx_DispatchPower ////////////////////////////////////////////////////////////////////////////////////////// // // Routine Description: // The power dispatch routine to handle power IRPs for card devices. // // Arguments: // pFDO - pointer to a device object. // pIrp - pointer to an I/O request packet. // // Return value: // NT status code. // ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS Spx_Card_FDO_DispatchPower(IN PDEVICE_OBJECT pFDO, IN PIRP pIrp) { PCARD_DEVICE_EXTENSION pCard = pFDO->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL switch (pIrpStack->MinorFunction) { case IRP_MN_SET_POWER: // Driver MUST never fail this IRP. { switch(pIrpStack->Parameters.Power.Type) { case SystemPowerState: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_SET_POWER Irp - Type SystemPowerState for Card %d.\n", PRODUCT_NAME, pCard->CardNumber)); return Spx_CardSetSystemPowerState(pFDO, pIrp); case DevicePowerState: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_SET_POWER Irp - Type DevicePowerState for Card %d.\n", PRODUCT_NAME, pCard->CardNumber)); return Spx_CardSetDevicePowerState(pFDO, pIrp); default: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_SET_POWER - Type 0x%02X Irp for Card %d.\n", PRODUCT_NAME, pIrpStack->Parameters.Power.Type, pCard->CardNumber)); status = STATUS_SUCCESS; pIrp->IoStatus.Status = status; break; } break; } case IRP_MN_QUERY_POWER: { switch(pIrpStack->Parameters.Power.Type) { case SystemPowerState: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_QUERY_POWER Irp - Type SystemPowerState for Card %d.\n", PRODUCT_NAME, pCard->CardNumber)); status = STATUS_SUCCESS; pIrp->IoStatus.Status = status; break; case DevicePowerState: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_QUERY_POWER Irp - Type DevicePowerState for Card %d.\n", PRODUCT_NAME, pCard->CardNumber)); status = STATUS_SUCCESS; pIrp->IoStatus.Status = status; break; default: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_QUERY_POWER - Type 0x%02X Irp for Card %d.\n", PRODUCT_NAME, pIrpStack->Parameters.Power.Type, pCard->CardNumber)); status = STATUS_SUCCESS; pIrp->IoStatus.Status = status; break; } break; } case IRP_MN_WAIT_WAKE: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_WAIT_WAKE Irp for Card %d.\n", PRODUCT_NAME, pCard->CardNumber)); status = STATUS_NOT_SUPPORTED; pIrp->IoStatus.Status = status; break; case IRP_MN_POWER_SEQUENCE: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_POWER_SEQUENCE Irp for Card %d.\n", PRODUCT_NAME, pCard->CardNumber)); status = STATUS_NOT_IMPLEMENTED; pIrp->IoStatus.Status = status; break; default: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got an UNKNOWN POWER Irp for Card %d.\n", PRODUCT_NAME, pCard->CardNumber)); status = STATUS_NOT_SUPPORTED; break; } PoStartNextPowerIrp(pIrp); IoSkipCurrentIrpStackLocation(pIrp); PoCallDriver(pCard->LowerDeviceObject, pIrp); return status; } // Spx_Card_FDO_DispatchPower ////////////////////////////////////////////////////////////////////////////////////////// // Spx_CardSetSystemPowerState ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS Spx_CardSetSystemPowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp) { PCARD_DEVICE_EXTENSION pCard = pDevObject->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); POWER_STATE PowerState; PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_CardSetSystemPowerState for Card %d.\n", PRODUCT_NAME, pCard->CardNumber)); switch (pIrpStack->Parameters.Power.State.SystemState) { case PowerSystemUnspecified: PowerState.DeviceState = PowerDeviceUnspecified; PoRequestPowerIrp(pCard->PDO, IRP_MN_SET_POWER, PowerState, NULL, NULL, NULL); break; case PowerSystemWorking: PowerState.DeviceState = PowerDeviceD0; PoRequestPowerIrp(pCard->PDO, IRP_MN_SET_POWER, PowerState, NULL, NULL, NULL); break; case PowerSystemSleeping1: case PowerSystemSleeping2: case PowerSystemSleeping3: case PowerSystemHibernate: case PowerSystemShutdown: case PowerSystemMaximum: PowerState.DeviceState = PowerDeviceD3; PoRequestPowerIrp(pCard->PDO, IRP_MN_SET_POWER, PowerState, NULL, NULL, NULL); break; default: break; } pIrp->IoStatus.Status = STATUS_SUCCESS; PoStartNextPowerIrp(pIrp); IoSkipCurrentIrpStackLocation(pIrp); PoCallDriver(pCard->LowerDeviceObject, pIrp); return status; } // Spx_CardSetSystemPowerState ////////////////////////////////////////////////////////////////////////////////////////// // Spx_CardSetDevicePowerState ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS Spx_CardSetDevicePowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp) { PCARD_DEVICE_EXTENSION pCard = pDevObject->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_CardSetDevicePowerState for Card %d.\n", PRODUCT_NAME, pCard->CardNumber)); switch(pIrpStack->Parameters.Power.State.DeviceState) { case PowerDeviceD0: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Card %d goes into power state D0.\n", PRODUCT_NAME, pCard->CardNumber)); if(pCard->DeviceState == pIrpStack->Parameters.Power.State.DeviceState) SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Card %d is already in power state D0.\n", PRODUCT_NAME, pCard->CardNumber)); else return Spx_CardSetPowerStateD0(pDevObject, pIrp); // Switch ON break; case PowerDeviceD1: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Card %d goes into power state D1.\n", PRODUCT_NAME, pCard->CardNumber)); if(pCard->DeviceState >= pIrpStack->Parameters.Power.State.DeviceState) SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Card %d is already in power state D1 or lower.\n", PRODUCT_NAME, pCard->CardNumber)); else return Spx_CardSetPowerStateD3(pDevObject, pIrp); // Switch OFF break; case PowerDeviceD2: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Card %d goes into power state D2.\n", PRODUCT_NAME, pCard->CardNumber)); if(pCard->DeviceState >= pIrpStack->Parameters.Power.State.DeviceState) SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Card %d is already in power state D2 or lower.\n", PRODUCT_NAME, pCard->CardNumber)); else return Spx_CardSetPowerStateD3(pDevObject, pIrp); // Switch OFF break; case PowerDeviceD3: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Card %d goes into power state D3.\n", PRODUCT_NAME, pCard->CardNumber)); if(pCard->DeviceState == pIrpStack->Parameters.Power.State.DeviceState) SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Card %d is already in power state D3.\n", PRODUCT_NAME, pCard->CardNumber)); else return Spx_CardSetPowerStateD3(pDevObject, pIrp); // Switch OFF break; default: break; } pIrp->IoStatus.Status = STATUS_SUCCESS; PoStartNextPowerIrp(pIrp); IoSkipCurrentIrpStackLocation(pIrp); PoCallDriver(pCard->LowerDeviceObject, pIrp); return status; } // Spx_CardSetDevicePowerState ////////////////////////////////////////////////////////////////////////////////////////// // Spx_SetPowerStateD0 - Sets power state D0 for Card - ON ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS Spx_CardSetPowerStateD0(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp) { PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); PCARD_DEVICE_EXTENSION pCard = pDevObject->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_CardSetPowerStateD0 for Card %d.\n", PRODUCT_NAME, pCard->CardNumber)); status = Spx_PowerWaitForDriverBelow(pCard->LowerDeviceObject, pIrp); #if DBG if(BREAK_ON_POWER_UP) { BREAK_ON_POWER_UP = FALSE; KdPrint(("%s: Breaking debugger whilst powering up Card %d to debug after a hibernate\n", PRODUCT_NAME, pCard->CardNumber)); DbgBreakPoint(); } #endif SetPnpPowerFlags(pCard, PPF_POWERED); if(SPX_SUCCESS(pIrp->IoStatus.Status = XXX_CardPowerUp(pCard))) // RESTORE HARDWARE STATE HERE & START CARD { // Inform Power Manager the of the new power state. PoSetPowerState(pDevObject, pIrpStack->Parameters.Power.Type, pIrpStack->Parameters.Power.State); pCard->DeviceState = PowerDeviceD0; // Store new power state. } PoStartNextPowerIrp(pIrp); // Ready for next power IRP. IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP. return status; } // Spx_SetPowerStateD0 ////////////////////////////////////////////////////////////////////////////////////////// // Spx_SetPowerStateD3 - Sets power state D3 for Card - OFF ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS Spx_CardSetPowerStateD3(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp) { PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); PCARD_DEVICE_EXTENSION pCard = pDevObject->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_CardSetPowerStateD3 for Card %d.\n", PRODUCT_NAME, pCard->CardNumber)); ClearPnpPowerFlags(pCard, PPF_POWERED); if(SPX_SUCCESS(pIrp->IoStatus.Status = XXX_CardPowerDown(pCard))) // SAVE HARDWARE STATE HERE & STOP CARD { // Inform Power Manager the of the new power state. PoSetPowerState(pDevObject, pIrpStack->Parameters.Power.Type, pIrpStack->Parameters.Power.State); pCard->DeviceState = PowerDeviceD3; // Store new power state. } PoStartNextPowerIrp(pIrp); // Ready for next power IRP. IoSkipCurrentIrpStackLocation(pIrp); PoCallDriver(pCard->LowerDeviceObject, pIrp); // Pass IRP on down. return status; } // Spx_SetPowerStateD3 ////////////////////////////////////////////////////////////////////////////////////////// // // Routine Description: // The power dispatch routine to handle power IRPs for port devices. // // Arguments: // pPDO - pointer to a device object. // pIrp - pointer to an I/O request packet. // // Return value: // NT status code. // ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS Spx_Port_PDO_DispatchPower(IN PDEVICE_OBJECT pPDO, IN PIRP pIrp) { PPORT_DEVICE_EXTENSION pPort = pPDO->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); POWER_STATE PowerState; PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL switch (pIrpStack->MinorFunction) { case IRP_MN_SET_POWER: { switch(pIrpStack->Parameters.Power.Type) { case SystemPowerState: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_SET_POWER Irp - Type SystemPowerState for Port %d.\n", PRODUCT_NAME, pPort->PortNumber)); return Spx_PortSetSystemPowerState(pPDO, pIrp); case DevicePowerState: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_SET_POWER Irp - Type DevicePowerState for Port %d.\n", PRODUCT_NAME, pPort->PortNumber)); return Spx_PortSetDevicePowerState(pPDO, pIrp); default: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_SET_POWER - Type 0x%02X Irp for Port %d.\n", PRODUCT_NAME, pIrpStack->Parameters.Power.Type, pPort->PortNumber)); status = STATUS_SUCCESS; pIrp->IoStatus.Status = status; break; } break; } case IRP_MN_QUERY_POWER: { switch(pIrpStack->Parameters.Power.Type) { case SystemPowerState: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_QUERY_POWER Irp - Type SystemPowerState for Port %d.\n", PRODUCT_NAME, pPort->PortNumber)); return Spx_PortQuerySystemPowerState(pPDO, pIrp); case DevicePowerState: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_QUERY_POWER Irp - Type DevicePowerState for Port %d.\n", PRODUCT_NAME, pPort->PortNumber)); switch(pIrpStack->Parameters.Power.State.DeviceState) { case PowerDeviceD0: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System is asking if Port %d can go to power state D0.\n", PRODUCT_NAME, pPort->PortNumber)); status = STATUS_SUCCESS; break; case PowerDeviceD1: case PowerDeviceD2: case PowerDeviceD3: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System is asking if Port %d can go to low power state D1, D2 or D3.\n", PRODUCT_NAME, pPort->PortNumber)); status = XXX_PortQueryPowerDown(pPort); break; default: status = STATUS_SUCCESS; break; } break; default: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_QUERY_POWER - Type 0x%02X Irp for Port %d.\n", PRODUCT_NAME, pIrpStack->Parameters.Power.Type, pPort->PortNumber)); break; } pIrp->IoStatus.Status = status; break; } case IRP_MN_WAIT_WAKE: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_WAIT_WAKE Irp for Port %d.\n", PRODUCT_NAME, pPort->PortNumber)); status = STATUS_NOT_SUPPORTED; pIrp->IoStatus.Status = status; break; case IRP_MN_POWER_SEQUENCE: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got IRP_MN_POWER_SEQUENCE Irp for Port %d.\n", PRODUCT_NAME, pPort->PortNumber)); status = STATUS_NOT_IMPLEMENTED; pIrp->IoStatus.Status = status; break; default: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Got an UNKNOWN POWER Irp for Port %d.\n", PRODUCT_NAME, pPort->PortNumber)); status = STATUS_NOT_SUPPORTED; break; } PoStartNextPowerIrp(pIrp); IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP. return status; } // Spx_Port_PDO_DispatchPower ////////////////////////////////////////////////////////////////////////////////////////// // Spx_PortSetSystemPowerState ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS Spx_PortSetSystemPowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp) { PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); POWER_STATE PowerState; PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_PortSetSystemPowerState for Port %d.\n", PRODUCT_NAME, pPort->PortNumber)); switch (pIrpStack->Parameters.Power.State.SystemState) { case PowerSystemUnspecified: PowerState.DeviceState = PowerDeviceUnspecified; PoRequestPowerIrp(pDevObject, IRP_MN_SET_POWER, PowerState, NULL, NULL, NULL); break; case PowerSystemWorking: PowerState.DeviceState = PowerDeviceD0; PoRequestPowerIrp(pDevObject, IRP_MN_SET_POWER, PowerState, NULL, NULL, NULL); break; case PowerSystemSleeping1: case PowerSystemSleeping2: case PowerSystemSleeping3: case PowerSystemHibernate: case PowerSystemShutdown: case PowerSystemMaximum: PowerState.DeviceState = PowerDeviceD3; PoRequestPowerIrp(pDevObject, IRP_MN_SET_POWER, PowerState, NULL, NULL, NULL); break; default: break; } pIrp->IoStatus.Status = STATUS_SUCCESS; PoStartNextPowerIrp(pIrp); IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP. return status; } // Spx_PortSetSystemPowerState ////////////////////////////////////////////////////////////////////////////////////////// // Spx_PortQuerySystemPowerState ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS Spx_PortQuerySystemPowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp) { PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); POWER_STATE PowerState; PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_PortQuerySystemPowerState for Port %d.\n", PRODUCT_NAME, pPort->PortNumber)); switch (pIrpStack->Parameters.Power.State.SystemState) { case PowerSystemUnspecified: PowerState.DeviceState = PowerDeviceUnspecified; PoRequestPowerIrp(pDevObject, IRP_MN_QUERY_POWER, PowerState, NULL, NULL, NULL); break; case PowerSystemWorking: PowerState.DeviceState = PowerDeviceD0; PoRequestPowerIrp(pDevObject, IRP_MN_QUERY_POWER, PowerState, NULL, NULL, NULL); break; case PowerSystemSleeping1: case PowerSystemSleeping2: case PowerSystemSleeping3: case PowerSystemHibernate: case PowerSystemShutdown: case PowerSystemMaximum: PowerState.DeviceState = PowerDeviceD3; PoRequestPowerIrp(pDevObject, IRP_MN_QUERY_POWER, PowerState, NULL, NULL, NULL); break; default: break; } pIrp->IoStatus.Status = STATUS_SUCCESS; PoStartNextPowerIrp(pIrp); IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP. return status; } // Spx_PortQuerySystemPowerState ////////////////////////////////////////////////////////////////////////////////////////// // Spx_PortSetDevicePowerState ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS Spx_PortSetDevicePowerState(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp) { PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_PortSetDevicePowerState for Port %d.\n", PRODUCT_NAME, pPort->PortNumber)); switch(pIrpStack->Parameters.Power.State.DeviceState) { case PowerDeviceD0: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Port %d goes into power state D0.\n", PRODUCT_NAME, pPort->PortNumber)); if(pPort->DeviceState == pIrpStack->Parameters.Power.State.DeviceState) SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Port %d is already in power state D0.\n", PRODUCT_NAME, pPort->PortNumber)); else return Spx_PortSetPowerStateD0(pDevObject, pIrp); // Switch ON break; case PowerDeviceD1: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Port %d goes into power state D1.\n", PRODUCT_NAME, pPort->PortNumber)); if(pPort->DeviceState >= pIrpStack->Parameters.Power.State.DeviceState) SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Port %d is already in power state D1 or lower.\n", PRODUCT_NAME, pPort->PortNumber)); else return Spx_PortSetPowerStateD3(pDevObject, pIrp); // Switch OFF break; case PowerDeviceD2: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Port %d goes into power state D2.\n", PRODUCT_NAME, pPort->PortNumber)); if(pPort->DeviceState >= pIrpStack->Parameters.Power.State.DeviceState) SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Port %d is already in power state D2 or lower.\n", PRODUCT_NAME, pPort->PortNumber)); else return Spx_PortSetPowerStateD3(pDevObject, pIrp); // Switch OFF break; case PowerDeviceD3: SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: System requests Port %d goes into power state D3.\n", PRODUCT_NAME, pPort->PortNumber)); if(pPort->DeviceState == pIrpStack->Parameters.Power.State.DeviceState) SpxDbgMsg(SPX_TRACE_POWER_IRPS, ("%s: Port %d is already in power state D3.\n", PRODUCT_NAME, pPort->PortNumber)); else return Spx_PortSetPowerStateD3(pDevObject, pIrp); // Switch OFF break; default: break; } pIrp->IoStatus.Status = STATUS_SUCCESS; PoStartNextPowerIrp(pIrp); IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP. return status; } // Spx_PortSetDevicePowerState ////////////////////////////////////////////////////////////////////////////////////////// // Spx_PortSetPowerStateD0 - Sets power state D0 for Port - ON ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS Spx_PortSetPowerStateD0(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp) { PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_PortSetPowerStateD0 for Port %d.\n", PRODUCT_NAME, pPort->PortNumber)); SetPnpPowerFlags(pPort, PPF_POWERED); if(SPX_SUCCESS(pIrp->IoStatus.Status = XXX_PortPowerUp(pPort))) // RESTORE HARDWARE STATE HERE & START PORT { // Inform Power Manager the of the new power state. PoSetPowerState(pDevObject, pIrpStack->Parameters.Power.Type, pIrpStack->Parameters.Power.State); pPort->DeviceState = PowerDeviceD0; // Store new power state. Spx_UnstallIrps(pPort); // Restart any queued IRPs (from a previous start) } PoStartNextPowerIrp(pIrp); // Ready for next power IRP. IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP. return status; } // Spx_PortSetPowerStateD0 ////////////////////////////////////////////////////////////////////////////////////////// // Spx_PortSetPowerStateD3 - Sets power state D3 for Port - OFF ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS Spx_PortSetPowerStateD3(IN PDEVICE_OBJECT pDevObject, IN PIRP pIrp) { PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering Spx_PortSetPowerStateD3 for Port %d.\n", PRODUCT_NAME, pPort->PortNumber)); ClearPnpPowerFlags(pPort, PPF_POWERED); if(SPX_SUCCESS(pIrp->IoStatus.Status = XXX_PortPowerDown(pPort))) // SAVE HARDWARE STATE HERE & STOP PORT { // Inform Power Manager the of the new power state. PoSetPowerState(pDevObject, pIrpStack->Parameters.Power.Type, pIrpStack->Parameters.Power.State); pPort->DeviceState = PowerDeviceD3; // Store new power state. } PoStartNextPowerIrp(pIrp); // Ready for next power IRP. IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Complete current IRP. return status; } // Spx_PortSetPowerStateD3 ////////////////////////////////////////////////////////////////////////////////////////// // Spx_PowerWaitForDriverBelow - Waits for lower driver. ////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS Spx_PowerWaitForDriverBelow(IN PDEVICE_OBJECT pLowerDevObj, IN PIRP pIrp) { KEVENT EventWaitLowerDrivers; NTSTATUS status; pIrp->IoStatus.Status = STATUS_SUCCESS; IoCopyCurrentIrpStackLocationToNext(pIrp); // Copy parameters to the stack below KeInitializeEvent(&EventWaitLowerDrivers, SynchronizationEvent, FALSE); // Initialise event if need to wait IoSetCompletionRoutine(pIrp, Spx_DispatchPnpPowerComplete, &EventWaitLowerDrivers, TRUE, TRUE, TRUE); if((status = PoCallDriver(pLowerDevObj, pIrp)) == STATUS_PENDING) { KeWaitForSingleObject(&EventWaitLowerDrivers, Executive, KernelMode, FALSE, NULL); status = pIrp->IoStatus.Status; } return(status); } // Spx_PowerWaitForDriverBelow