1 // 2 // Copyright (C) Microsoft. All rights reserved. 3 // 4 #ifndef _FXPOWERSTATEMACHINE_H_ 5 #define _FXPOWERSTATEMACHINE_H_ 6 7 // @@SMVERIFY_SPLIT_BEGIN 8 // 9 // Treat these values as a bit field when comparing for known dropped events in 10 // the current state and treat them as values when they known transition events 11 // from state to the next. 12 // 13 enum FxPowerEvent { 14 PowerEventInvalid = 0x0000, 15 PowerD0 = 0x0001, 16 PowerDx = 0x0002, 17 PowerWakeArrival = 0x0004, 18 PowerWakeSucceeded = 0x0008, 19 PowerWakeFailed = 0x0010, 20 PowerWakeCanceled = 0x0020, 21 PowerImplicitD0 = 0x0040, 22 PowerImplicitD3 = 0x0080, 23 PowerParentToD0 = 0x0100, 24 PowerMarkPageable = 0x0200, 25 PowerMarkNonpageable = 0x0400, 26 PowerCompleteD0 = 0x0800, 27 PowerCompleteDx = 0x1000, 28 PowerWakeInterruptCompleteTransition 29 = 0x2000, 30 31 // 32 // Not a real event, just a value that indicates all of the events which 33 // goto the head of the queue and are always processed, even if the state is 34 // locked. 35 // 36 PowerPriorityEventsMask = PowerParentToD0 | 37 PowerCompleteD0 | 38 PowerCompleteDx | 39 PowerWakeInterruptCompleteTransition, 40 41 // 42 // Not a real event, just a value that indicate all of the events which 43 // should not be in the queue, if a similar event is already enqueued. 44 // 45 PowerSingularEventMask = PowerParentToD0, 46 47 PowerEventMaximum = 0xFFFF, 48 }; 49 50 union FxPowerStateInfo { 51 struct { 52 // 53 // Is this a state where we rest and wait for events to bring us out 54 // of that state. 55 // 56 // NOTE: this value is purely notational, we don't use it anywhere in 57 // the state machine. If need be, reuse this slot for something 58 // else without worry. 59 // 60 ULONG QueueOpen : 1; 61 62 // 63 // Bit of events we know we can drop in this state 64 // 65 ULONG KnownDroppedEvents : 31; 66 } Bits; 67 68 struct { 69 // 70 // Maps to the same bit location as QueueOpen. Since we start 71 // KnownDroppedEvents at the next bit, start our bits by at the next 72 // bit as well. 73 // 74 ULONG Reserved : 1; 75 76 // 77 // These are defined so that we can easily tell in the debugger what 78 // each set bit in KnownDroppedEvents maps to in the FxPowerEvent enum 79 // 80 ULONG PowerD0Known : 1; 81 ULONG PowerDxKnown : 1; 82 ULONG PowerWakeArrivalKnown : 1; 83 ULONG PowerWakeSucceededKnown : 1; 84 ULONG PowerWakeFailedKnown : 1; 85 ULONG PowerWakeCanceledKnown : 1; 86 ULONG PowerImplicitD0Known : 1; 87 ULONG PowerImplicitD3Known : 1; 88 ULONG PowerParentToD0Known : 1; 89 ULONG PowerMarkPageableKnown : 1; 90 ULONG PowerMarkNonpageableKnown : 1; 91 ULONG PowerCompleteD0Known : 1; 92 ULONG PowerCompleteDxKnown : 1; 93 } BitsByName; 94 }; 95 96 97 struct POWER_EVENT_TARGET_STATE { 98 FxPowerEvent PowerEvent; 99 100 WDF_DEVICE_POWER_STATE TargetState; 101 102 EVENT_TRAP_FIELD 103 }; 104 105 typedef const POWER_EVENT_TARGET_STATE* CPPPOWER_EVENT_TARGET_STATE; 106 107 typedef 108 WDF_DEVICE_POWER_STATE 109 (*PFN_POWER_STATE_ENTRY_FUNCTION)( 110 FxPkgPnp* 111 ); 112 113 typedef struct POWER_STATE_TABLE { 114 // 115 // Function called when the state is entered 116 // 117 PFN_POWER_STATE_ENTRY_FUNCTION StateFunc; 118 119 // 120 // First state transition out of this state 121 // 122 POWER_EVENT_TARGET_STATE FirstTargetState; 123 124 // 125 // Other state transitions out of this state if FirstTargetState is not 126 // matched. This is an array where we expect the final element to be 127 // { PowerEventMaximum, WdfDevStatePowerNull } 128 // 129 CPPPOWER_EVENT_TARGET_STATE OtherTargetStates; 130 131 FxPowerStateInfo StateInfo; 132 133 } *PPOWER_STATE_TABLE; 134 135 typedef const POWER_STATE_TABLE* CPPOWER_STATE_TABLE; 136 137 #if FX_STATE_MACHINE_VERIFY 138 #define MAX_POWER_STATE_ENTRY_FN_RETURN_STATES (5) 139 140 struct POWER_STATE_ENTRY_FUNCTION_TARGET_STATE { 141 // 142 // Return value from state entry function 143 // 144 WDF_DEVICE_POWER_STATE State; 145 146 // 147 // type of device the returning state applies to 148 // 149 FxStateMachineDeviceType DeviceType; 150 151 // 152 // Info about the state transition 153 // 154 PSTR Comment; 155 }; 156 157 struct POWER_STATE_ENTRY_FN_RETURN_STATE_TABLE { 158 // 159 // array of state transitions caused by state entry function 160 // 161 POWER_STATE_ENTRY_FUNCTION_TARGET_STATE TargetStates[MAX_POWER_STATE_ENTRY_FN_RETURN_STATES]; 162 }; 163 164 typedef const POWER_STATE_ENTRY_FN_RETURN_STATE_TABLE* CPPOWER_STATE_ENTRY_FN_RETURN_STATE_TABLE; 165 #endif // FX_STATE_MACHINE_VERIFY 166 167 // @@SMVERIFY_SPLIT_END 168 169 // 170 // This type of union is done so that we can 171 // 1) shrink the array element to the smallest size possible 172 // 2) keep types within the structure so we can dump it in the debugger 173 // 174 union FxPowerMachineEventQueue { 175 struct { 176 FxPowerEvent Event1 : 16; 177 FxPowerEvent Event2 : 16; 178 FxPowerEvent Event3 : 16; 179 FxPowerEvent Event4 : 16; 180 FxPowerEvent Event5 : 16; 181 FxPowerEvent Event6 : 16; 182 FxPowerEvent Event7 : 16; 183 FxPowerEvent Event8 : 16; 184 } E; 185 186 USHORT Events[PowerEventQueueDepth]; 187 }; 188 189 // 190 // Same as FxPowerMachineEventQueue 191 // 192 union FxPowerMachineStateHistory { 193 struct { 194 WDF_DEVICE_POWER_STATE State1 : 16; 195 WDF_DEVICE_POWER_STATE State2 : 16; 196 WDF_DEVICE_POWER_STATE State3 : 16; 197 WDF_DEVICE_POWER_STATE State4 : 16; 198 WDF_DEVICE_POWER_STATE State5 : 16; 199 WDF_DEVICE_POWER_STATE State6 : 16; 200 WDF_DEVICE_POWER_STATE State7 : 16; 201 WDF_DEVICE_POWER_STATE State8 : 16; 202 } S; 203 204 USHORT History[PowerEventQueueDepth]; 205 }; 206 207 struct FxPowerMachine : public FxThreadedEventQueue { 208 FxPowerMachine( 209 VOID 210 ) : FxThreadedEventQueue(PowerEventQueueDepth) 211 { 212 // 213 // m_WaitWakeLock can not be initialized here since Initiliaze can 214 // return failure for UM. It's now being initialized in Init() function. 215 // 216 217 InitializeListHead(&m_WaitWakeIrpToBeProcessedList); 218 219 RtlZeroMemory(&m_Queue, sizeof(m_Queue)); 220 RtlZeroMemory(&m_States, sizeof(m_States)); 221 222 m_States.History[IncrementHistoryIndex()] = WdfDevStatePowerObjectCreated; 223 m_IoCallbackFailure = FALSE; 224 m_PowerDownFailure = FALSE; 225 m_SingularEventsPresent = 0x0; 226 } 227 228 _Must_inspect_result_ 229 NTSTATUS 230 Init( 231 __inout FxPkgPnp* Pnp, 232 __in PFN_PNP_EVENT_WORKER WorkerRoutine 233 ); 234 235 FxPowerMachineEventQueue m_Queue; 236 237 FxPowerMachineStateHistory m_States; 238 239 // 240 // Lock to guard wait wake irp 241 // 242 MxLock m_WaitWakeLock; 243 244 // 245 // List of wait wake requests which have either been completed or cancelled 246 // and we are waiting for the state machine to process and complete the irp. 247 // 248 // We require a list of irps (instead of just storage for one irp) because 249 // the power policy owner might be misbehaving and sending wake requests 250 // successively down the stack and we want the state machine to be able 251 // to keep track of all the requests. 252 // 253 LIST_ENTRY m_WaitWakeIrpToBeProcessedList; 254 255 union { 256 USHORT m_SingularEventsPresent; 257 258 union { 259 // 260 // These are defined so that we can easily tell in the debugger what 261 // each set bit in m_SingularEventsPresent maps to in the 262 // FxPowerEvent enum. 263 // 264 USHORT PowerD0Known : 1; 265 USHORT PowerDxKnown : 1; 266 USHORT PowerWakeArrivalKnown : 1; 267 USHORT PowerWakeSucceededKnown : 1; 268 USHORT PowerWakeFailedKnown : 1; 269 USHORT PowerWakeCanceledKnown : 1; 270 USHORT PowerImplicitD0Known : 1; 271 USHORT PowerImplicitD3Known : 1; 272 USHORT PowerParentToD0Known : 1; 273 USHORT PowerMarkPageableKnown : 1; 274 USHORT PowerMarkNonpageableKnown : 1; 275 USHORT PowerCompleteD0Known : 1; 276 USHORT PowerCompleteDxKnown : 1; 277 } m_SingularEventsPresentByName; 278 }; 279 280 BOOLEAN m_IoCallbackFailure; 281 282 BOOLEAN m_PowerDownFailure; 283 }; 284 285 #endif // _FXPOWERSTATEMACHINE_H_ 286