18a978a17SVictor Perevertkin // 28a978a17SVictor Perevertkin // Copyright (C) Microsoft. All rights reserved. 38a978a17SVictor Perevertkin // 48a978a17SVictor Perevertkin #ifndef _FXPOWERSTATEMACHINE_H_ 58a978a17SVictor Perevertkin #define _FXPOWERSTATEMACHINE_H_ 68a978a17SVictor Perevertkin 78a978a17SVictor Perevertkin // @@SMVERIFY_SPLIT_BEGIN 88a978a17SVictor Perevertkin // 98a978a17SVictor Perevertkin // Treat these values as a bit field when comparing for known dropped events in 108a978a17SVictor Perevertkin // the current state and treat them as values when they known transition events 118a978a17SVictor Perevertkin // from state to the next. 128a978a17SVictor Perevertkin // 138a978a17SVictor Perevertkin enum FxPowerEvent { 148a978a17SVictor Perevertkin PowerEventInvalid = 0x0000, 158a978a17SVictor Perevertkin PowerD0 = 0x0001, 168a978a17SVictor Perevertkin PowerDx = 0x0002, 178a978a17SVictor Perevertkin PowerWakeArrival = 0x0004, 188a978a17SVictor Perevertkin PowerWakeSucceeded = 0x0008, 198a978a17SVictor Perevertkin PowerWakeFailed = 0x0010, 208a978a17SVictor Perevertkin PowerWakeCanceled = 0x0020, 218a978a17SVictor Perevertkin PowerImplicitD0 = 0x0040, 228a978a17SVictor Perevertkin PowerImplicitD3 = 0x0080, 238a978a17SVictor Perevertkin PowerParentToD0 = 0x0100, 248a978a17SVictor Perevertkin PowerMarkPageable = 0x0200, 258a978a17SVictor Perevertkin PowerMarkNonpageable = 0x0400, 268a978a17SVictor Perevertkin PowerCompleteD0 = 0x0800, 278a978a17SVictor Perevertkin PowerCompleteDx = 0x1000, 288a978a17SVictor Perevertkin PowerWakeInterruptCompleteTransition 298a978a17SVictor Perevertkin = 0x2000, 308a978a17SVictor Perevertkin 318a978a17SVictor Perevertkin // 328a978a17SVictor Perevertkin // Not a real event, just a value that indicates all of the events which 338a978a17SVictor Perevertkin // goto the head of the queue and are always processed, even if the state is 348a978a17SVictor Perevertkin // locked. 358a978a17SVictor Perevertkin // 368a978a17SVictor Perevertkin PowerPriorityEventsMask = PowerParentToD0 | 378a978a17SVictor Perevertkin PowerCompleteD0 | 388a978a17SVictor Perevertkin PowerCompleteDx | 398a978a17SVictor Perevertkin PowerWakeInterruptCompleteTransition, 408a978a17SVictor Perevertkin 418a978a17SVictor Perevertkin // 428a978a17SVictor Perevertkin // Not a real event, just a value that indicate all of the events which 438a978a17SVictor Perevertkin // should not be in the queue, if a similar event is already enqueued. 448a978a17SVictor Perevertkin // 458a978a17SVictor Perevertkin PowerSingularEventMask = PowerParentToD0, 468a978a17SVictor Perevertkin 47*1f377076SVictor Perevertkin PowerEventMaximum = 0xFFFF, 488a978a17SVictor Perevertkin }; 498a978a17SVictor Perevertkin 508a978a17SVictor Perevertkin union FxPowerStateInfo { 518a978a17SVictor Perevertkin struct { 528a978a17SVictor Perevertkin // 538a978a17SVictor Perevertkin // Is this a state where we rest and wait for events to bring us out 548a978a17SVictor Perevertkin // of that state. 558a978a17SVictor Perevertkin // 568a978a17SVictor Perevertkin // NOTE: this value is purely notational, we don't use it anywhere in 578a978a17SVictor Perevertkin // the state machine. If need be, reuse this slot for something 588a978a17SVictor Perevertkin // else without worry. 598a978a17SVictor Perevertkin // 608a978a17SVictor Perevertkin ULONG QueueOpen : 1; 618a978a17SVictor Perevertkin 628a978a17SVictor Perevertkin // 638a978a17SVictor Perevertkin // Bit of events we know we can drop in this state 648a978a17SVictor Perevertkin // 658a978a17SVictor Perevertkin ULONG KnownDroppedEvents : 31; 668a978a17SVictor Perevertkin } Bits; 678a978a17SVictor Perevertkin 688a978a17SVictor Perevertkin struct { 698a978a17SVictor Perevertkin // 708a978a17SVictor Perevertkin // Maps to the same bit location as QueueOpen. Since we start 718a978a17SVictor Perevertkin // KnownDroppedEvents at the next bit, start our bits by at the next 728a978a17SVictor Perevertkin // bit as well. 738a978a17SVictor Perevertkin // 748a978a17SVictor Perevertkin ULONG Reserved : 1; 758a978a17SVictor Perevertkin 768a978a17SVictor Perevertkin // 778a978a17SVictor Perevertkin // These are defined so that we can easily tell in the debugger what 788a978a17SVictor Perevertkin // each set bit in KnownDroppedEvents maps to in the FxPowerEvent enum 798a978a17SVictor Perevertkin // 808a978a17SVictor Perevertkin ULONG PowerD0Known : 1; 818a978a17SVictor Perevertkin ULONG PowerDxKnown : 1; 828a978a17SVictor Perevertkin ULONG PowerWakeArrivalKnown : 1; 838a978a17SVictor Perevertkin ULONG PowerWakeSucceededKnown : 1; 848a978a17SVictor Perevertkin ULONG PowerWakeFailedKnown : 1; 858a978a17SVictor Perevertkin ULONG PowerWakeCanceledKnown : 1; 868a978a17SVictor Perevertkin ULONG PowerImplicitD0Known : 1; 878a978a17SVictor Perevertkin ULONG PowerImplicitD3Known : 1; 888a978a17SVictor Perevertkin ULONG PowerParentToD0Known : 1; 898a978a17SVictor Perevertkin ULONG PowerMarkPageableKnown : 1; 908a978a17SVictor Perevertkin ULONG PowerMarkNonpageableKnown : 1; 918a978a17SVictor Perevertkin ULONG PowerCompleteD0Known : 1; 928a978a17SVictor Perevertkin ULONG PowerCompleteDxKnown : 1; 938a978a17SVictor Perevertkin } BitsByName; 948a978a17SVictor Perevertkin }; 958a978a17SVictor Perevertkin 968a978a17SVictor Perevertkin 978a978a17SVictor Perevertkin struct POWER_EVENT_TARGET_STATE { 988a978a17SVictor Perevertkin FxPowerEvent PowerEvent; 998a978a17SVictor Perevertkin 1008a978a17SVictor Perevertkin WDF_DEVICE_POWER_STATE TargetState; 1018a978a17SVictor Perevertkin 1028a978a17SVictor Perevertkin EVENT_TRAP_FIELD 1038a978a17SVictor Perevertkin }; 1048a978a17SVictor Perevertkin 1058a978a17SVictor Perevertkin typedef const POWER_EVENT_TARGET_STATE* CPPPOWER_EVENT_TARGET_STATE; 1068a978a17SVictor Perevertkin 1078a978a17SVictor Perevertkin typedef 1088a978a17SVictor Perevertkin WDF_DEVICE_POWER_STATE 1098a978a17SVictor Perevertkin (*PFN_POWER_STATE_ENTRY_FUNCTION)( 1108a978a17SVictor Perevertkin FxPkgPnp* 1118a978a17SVictor Perevertkin ); 1128a978a17SVictor Perevertkin 1138a978a17SVictor Perevertkin typedef struct POWER_STATE_TABLE { 1148a978a17SVictor Perevertkin // 1158a978a17SVictor Perevertkin // Function called when the state is entered 1168a978a17SVictor Perevertkin // 1178a978a17SVictor Perevertkin PFN_POWER_STATE_ENTRY_FUNCTION StateFunc; 1188a978a17SVictor Perevertkin 1198a978a17SVictor Perevertkin // 1208a978a17SVictor Perevertkin // First state transition out of this state 1218a978a17SVictor Perevertkin // 1228a978a17SVictor Perevertkin POWER_EVENT_TARGET_STATE FirstTargetState; 1238a978a17SVictor Perevertkin 1248a978a17SVictor Perevertkin // 1258a978a17SVictor Perevertkin // Other state transitions out of this state if FirstTargetState is not 1268a978a17SVictor Perevertkin // matched. This is an array where we expect the final element to be 1278a978a17SVictor Perevertkin // { PowerEventMaximum, WdfDevStatePowerNull } 1288a978a17SVictor Perevertkin // 1298a978a17SVictor Perevertkin CPPPOWER_EVENT_TARGET_STATE OtherTargetStates; 1308a978a17SVictor Perevertkin 1318a978a17SVictor Perevertkin FxPowerStateInfo StateInfo; 1328a978a17SVictor Perevertkin 1338a978a17SVictor Perevertkin } *PPOWER_STATE_TABLE; 1348a978a17SVictor Perevertkin 1358a978a17SVictor Perevertkin typedef const POWER_STATE_TABLE* CPPOWER_STATE_TABLE; 1368a978a17SVictor Perevertkin 1378a978a17SVictor Perevertkin #if FX_STATE_MACHINE_VERIFY 1388a978a17SVictor Perevertkin #define MAX_POWER_STATE_ENTRY_FN_RETURN_STATES (5) 1398a978a17SVictor Perevertkin 1408a978a17SVictor Perevertkin struct POWER_STATE_ENTRY_FUNCTION_TARGET_STATE { 1418a978a17SVictor Perevertkin // 1428a978a17SVictor Perevertkin // Return value from state entry function 1438a978a17SVictor Perevertkin // 1448a978a17SVictor Perevertkin WDF_DEVICE_POWER_STATE State; 1458a978a17SVictor Perevertkin 1468a978a17SVictor Perevertkin // 1478a978a17SVictor Perevertkin // type of device the returning state applies to 1488a978a17SVictor Perevertkin // 1498a978a17SVictor Perevertkin FxStateMachineDeviceType DeviceType; 1508a978a17SVictor Perevertkin 1518a978a17SVictor Perevertkin // 1528a978a17SVictor Perevertkin // Info about the state transition 1538a978a17SVictor Perevertkin // 1548a978a17SVictor Perevertkin PSTR Comment; 1558a978a17SVictor Perevertkin }; 1568a978a17SVictor Perevertkin 1578a978a17SVictor Perevertkin struct POWER_STATE_ENTRY_FN_RETURN_STATE_TABLE { 1588a978a17SVictor Perevertkin // 1598a978a17SVictor Perevertkin // array of state transitions caused by state entry function 1608a978a17SVictor Perevertkin // 1618a978a17SVictor Perevertkin POWER_STATE_ENTRY_FUNCTION_TARGET_STATE TargetStates[MAX_POWER_STATE_ENTRY_FN_RETURN_STATES]; 1628a978a17SVictor Perevertkin }; 1638a978a17SVictor Perevertkin 1648a978a17SVictor Perevertkin typedef const POWER_STATE_ENTRY_FN_RETURN_STATE_TABLE* CPPOWER_STATE_ENTRY_FN_RETURN_STATE_TABLE; 1658a978a17SVictor Perevertkin #endif // FX_STATE_MACHINE_VERIFY 1668a978a17SVictor Perevertkin 1678a978a17SVictor Perevertkin // @@SMVERIFY_SPLIT_END 1688a978a17SVictor Perevertkin 1698a978a17SVictor Perevertkin // 1708a978a17SVictor Perevertkin // This type of union is done so that we can 1718a978a17SVictor Perevertkin // 1) shrink the array element to the smallest size possible 1728a978a17SVictor Perevertkin // 2) keep types within the structure so we can dump it in the debugger 1738a978a17SVictor Perevertkin // 1748a978a17SVictor Perevertkin union FxPowerMachineEventQueue { 1758a978a17SVictor Perevertkin struct { 1768a978a17SVictor Perevertkin FxPowerEvent Event1 : 16; 1778a978a17SVictor Perevertkin FxPowerEvent Event2 : 16; 1788a978a17SVictor Perevertkin FxPowerEvent Event3 : 16; 1798a978a17SVictor Perevertkin FxPowerEvent Event4 : 16; 1808a978a17SVictor Perevertkin FxPowerEvent Event5 : 16; 1818a978a17SVictor Perevertkin FxPowerEvent Event6 : 16; 1828a978a17SVictor Perevertkin FxPowerEvent Event7 : 16; 1838a978a17SVictor Perevertkin FxPowerEvent Event8 : 16; 1848a978a17SVictor Perevertkin } E; 1858a978a17SVictor Perevertkin 1868a978a17SVictor Perevertkin USHORT Events[PowerEventQueueDepth]; 1878a978a17SVictor Perevertkin }; 1888a978a17SVictor Perevertkin 1898a978a17SVictor Perevertkin // 1908a978a17SVictor Perevertkin // Same as FxPowerMachineEventQueue 1918a978a17SVictor Perevertkin // 1928a978a17SVictor Perevertkin union FxPowerMachineStateHistory { 1938a978a17SVictor Perevertkin struct { 1948a978a17SVictor Perevertkin WDF_DEVICE_POWER_STATE State1 : 16; 1958a978a17SVictor Perevertkin WDF_DEVICE_POWER_STATE State2 : 16; 1968a978a17SVictor Perevertkin WDF_DEVICE_POWER_STATE State3 : 16; 1978a978a17SVictor Perevertkin WDF_DEVICE_POWER_STATE State4 : 16; 1988a978a17SVictor Perevertkin WDF_DEVICE_POWER_STATE State5 : 16; 1998a978a17SVictor Perevertkin WDF_DEVICE_POWER_STATE State6 : 16; 2008a978a17SVictor Perevertkin WDF_DEVICE_POWER_STATE State7 : 16; 2018a978a17SVictor Perevertkin WDF_DEVICE_POWER_STATE State8 : 16; 2028a978a17SVictor Perevertkin } S; 2038a978a17SVictor Perevertkin 2048a978a17SVictor Perevertkin USHORT History[PowerEventQueueDepth]; 2058a978a17SVictor Perevertkin }; 2068a978a17SVictor Perevertkin 2078a978a17SVictor Perevertkin struct FxPowerMachine : public FxThreadedEventQueue { FxPowerMachineFxPowerMachine2088a978a17SVictor Perevertkin FxPowerMachine( 2098a978a17SVictor Perevertkin VOID 2108a978a17SVictor Perevertkin ) : FxThreadedEventQueue(PowerEventQueueDepth) 2118a978a17SVictor Perevertkin { 2128a978a17SVictor Perevertkin // 2138a978a17SVictor Perevertkin // m_WaitWakeLock can not be initialized here since Initiliaze can 2148a978a17SVictor Perevertkin // return failure for UM. It's now being initialized in Init() function. 2158a978a17SVictor Perevertkin // 2168a978a17SVictor Perevertkin 2178a978a17SVictor Perevertkin InitializeListHead(&m_WaitWakeIrpToBeProcessedList); 2188a978a17SVictor Perevertkin 2198a978a17SVictor Perevertkin RtlZeroMemory(&m_Queue, sizeof(m_Queue)); 2208a978a17SVictor Perevertkin RtlZeroMemory(&m_States, sizeof(m_States)); 2218a978a17SVictor Perevertkin 2228a978a17SVictor Perevertkin m_States.History[IncrementHistoryIndex()] = WdfDevStatePowerObjectCreated; 2238a978a17SVictor Perevertkin m_IoCallbackFailure = FALSE; 2248a978a17SVictor Perevertkin m_PowerDownFailure = FALSE; 2258a978a17SVictor Perevertkin m_SingularEventsPresent = 0x0; 2268a978a17SVictor Perevertkin } 2278a978a17SVictor Perevertkin 2288a978a17SVictor Perevertkin _Must_inspect_result_ 2298a978a17SVictor Perevertkin NTSTATUS 2308a978a17SVictor Perevertkin Init( 2318a978a17SVictor Perevertkin __inout FxPkgPnp* Pnp, 2328a978a17SVictor Perevertkin __in PFN_PNP_EVENT_WORKER WorkerRoutine 2338a978a17SVictor Perevertkin ); 2348a978a17SVictor Perevertkin 2358a978a17SVictor Perevertkin FxPowerMachineEventQueue m_Queue; 2368a978a17SVictor Perevertkin 2378a978a17SVictor Perevertkin FxPowerMachineStateHistory m_States; 2388a978a17SVictor Perevertkin 2398a978a17SVictor Perevertkin // 2408a978a17SVictor Perevertkin // Lock to guard wait wake irp 2418a978a17SVictor Perevertkin // 2428a978a17SVictor Perevertkin MxLock m_WaitWakeLock; 2438a978a17SVictor Perevertkin 2448a978a17SVictor Perevertkin // 2458a978a17SVictor Perevertkin // List of wait wake requests which have either been completed or cancelled 2468a978a17SVictor Perevertkin // and we are waiting for the state machine to process and complete the irp. 2478a978a17SVictor Perevertkin // 2488a978a17SVictor Perevertkin // We require a list of irps (instead of just storage for one irp) because 2498a978a17SVictor Perevertkin // the power policy owner might be misbehaving and sending wake requests 2508a978a17SVictor Perevertkin // successively down the stack and we want the state machine to be able 2518a978a17SVictor Perevertkin // to keep track of all the requests. 2528a978a17SVictor Perevertkin // 2538a978a17SVictor Perevertkin LIST_ENTRY m_WaitWakeIrpToBeProcessedList; 2548a978a17SVictor Perevertkin 2558a978a17SVictor Perevertkin union { 2568a978a17SVictor Perevertkin USHORT m_SingularEventsPresent; 2578a978a17SVictor Perevertkin 2588a978a17SVictor Perevertkin union { 2598a978a17SVictor Perevertkin // 2608a978a17SVictor Perevertkin // These are defined so that we can easily tell in the debugger what 2618a978a17SVictor Perevertkin // each set bit in m_SingularEventsPresent maps to in the 2628a978a17SVictor Perevertkin // FxPowerEvent enum. 2638a978a17SVictor Perevertkin // 2648a978a17SVictor Perevertkin USHORT PowerD0Known : 1; 2658a978a17SVictor Perevertkin USHORT PowerDxKnown : 1; 2668a978a17SVictor Perevertkin USHORT PowerWakeArrivalKnown : 1; 2678a978a17SVictor Perevertkin USHORT PowerWakeSucceededKnown : 1; 2688a978a17SVictor Perevertkin USHORT PowerWakeFailedKnown : 1; 2698a978a17SVictor Perevertkin USHORT PowerWakeCanceledKnown : 1; 2708a978a17SVictor Perevertkin USHORT PowerImplicitD0Known : 1; 2718a978a17SVictor Perevertkin USHORT PowerImplicitD3Known : 1; 2728a978a17SVictor Perevertkin USHORT PowerParentToD0Known : 1; 2738a978a17SVictor Perevertkin USHORT PowerMarkPageableKnown : 1; 2748a978a17SVictor Perevertkin USHORT PowerMarkNonpageableKnown : 1; 2758a978a17SVictor Perevertkin USHORT PowerCompleteD0Known : 1; 2768a978a17SVictor Perevertkin USHORT PowerCompleteDxKnown : 1; 2778a978a17SVictor Perevertkin } m_SingularEventsPresentByName; 2788a978a17SVictor Perevertkin }; 2798a978a17SVictor Perevertkin 2808a978a17SVictor Perevertkin BOOLEAN m_IoCallbackFailure; 2818a978a17SVictor Perevertkin 2828a978a17SVictor Perevertkin BOOLEAN m_PowerDownFailure; 2838a978a17SVictor Perevertkin }; 2848a978a17SVictor Perevertkin 2858a978a17SVictor Perevertkin #endif // _FXPOWERSTATEMACHINE_H_ 286