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