VOID FxPowerIdleMachine::ProcessEventLocked( __in FxPowerIdleEvents Event ) /*++ Routine Description: Processes an event and runs it through the state machine Arguments: Return Value: --*/ { const FxIdleStateTable* entry; FxPowerIdleStates newState; FxPkgPnp* pPkgPnp; pPkgPnp = GetPnpPkg(this); m_EventHistory[m_EventHistoryIndex] = Event; m_EventHistoryIndex = (m_EventHistoryIndex + 1) % (sizeof(m_EventHistory)/sizeof(m_EventHistory[0])); entry = &m_StateTable[m_CurrentIdleState-FxIdleStopped]; newState = FxIdleMax; for (ULONG i = 0; i < entry->TargetStatesCount; i++) { if (entry->TargetStates[i].PowerIdleEvent == Event) { DO_EVENT_TRAP(&entry->TargetStates[i]); newState = entry->TargetStates[i].PowerIdleState; break; } } if (newState == FxIdleMax) { switch (Event) { case PowerIdleEventIoIncrement: case PowerIdleEventIoDecrement: // // We always can handle io increment, io decrement, and query return // to idle from any state... // break; case PowerIdleEventEnabled: if (m_Flags & FxPowerIdleTimerEnabled) { // // Getting an enable event while enabled is OK // break; } // || || Fall || || // \/ \/ through \/ \/ default: // // ...but we should not be dropping any other events from this state. // // DoTraceLevelMessage( pPkgPnp->GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP, "WDFDEVICE 0x%p !devobj 0x%p power idle state %!FxPowerIdleStates!" " dropping event %!FxPowerIdleEvents!", pPkgPnp->GetDevice()->GetHandle(), pPkgPnp->GetDevice()->GetDeviceObject(), m_CurrentIdleState, Event); COVERAGE_TRAP(); } } while (newState != FxIdleMax) { DoTraceLevelMessage( pPkgPnp->GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNPPOWERSTATES, "WDFDEVICE 0x%p !devobj 0x%p entering power idle state " "%!FxPowerIdleStates! from %!FxPowerIdleStates!", pPkgPnp->GetDevice()->GetHandle(), pPkgPnp->GetDevice()->GetDeviceObject(), newState, m_CurrentIdleState); m_StateHistory[m_StateHistoryIndex] = newState; m_StateHistoryIndex = (m_StateHistoryIndex + 1) % (sizeof(m_StateHistory)/sizeof(m_StateHistory[0])); m_CurrentIdleState = newState; entry = &m_StateTable[m_CurrentIdleState-FxIdleStopped]; if (entry->StateFunc != NULL) { newState = entry->StateFunc(this); } else { newState = FxIdleMax; } } }
VOID FxWakeInterruptMachine::ProcessEventInner( __inout FxPostProcessInfo* Info ) { KIRQL irql; FxWakeInterruptEvents event; const FxWakeInterruptStateTable* entry; FxWakeInterruptStates newState; // // Process as many events as we can // for ( ; ; ) { // // Acquire state machine *queue* lock // Lock(&irql); if (IsEmpty()) { // // The queue is empty. // GetFinishedState(Info); Unlock(irql); return; } // // Get the event from the queue // event = m_Queue[GetHead()]; IncrementHead(); // // Drop the state machine *queue* lock // Unlock(irql); // // Get the state table entry for the current state // // NOTE: Prefast complains about buffer overflow if (m_CurrentState == // WakeInterruptMax), but that should never happen because WakeInterruptMax is not a real // state. We just use it to represent the maximum value in the enum that // defines the states. // __analysis_assume(m_CurrentState < WakeInterruptMax); entry = &m_StateTable[m_CurrentState - WakeInterruptFailed]; // // Based on the event received, figure out the next state // newState = WakeInterruptMax; for (ULONG i = 0; i < entry->TargetStatesCount; i++) { if (entry->TargetStates[i].WakeInterruptEvent == event) { DO_EVENT_TRAP(&entry->TargetStates[i]); newState = entry->TargetStates[i].WakeInterruptState; break; } } if (newState == WakeInterruptMax) { // // Unexpected event for this state // DoTraceLevelMessage( m_PkgPnp->GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP, "WDFDEVICE 0x%p !devobj 0x%p wake interrupt state " "%!FxWakeInterruptStates! dropping event " "%!FxWakeInterruptEvents!", m_PkgPnp->GetDevice()->GetHandle(), m_PkgPnp->GetDevice()->GetDeviceObject(), m_CurrentState, event ); COVERAGE_TRAP(); } while (newState != WakeInterruptMax) { DoTraceLevelMessage( m_PkgPnp->GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNPPOWERSTATES, "WDFDEVICE 0x%p !devobj 0x%p entering wake interrupt " "state %!FxWakeInterruptStates! from " "%!FxWakeInterruptStates!", m_PkgPnp->GetDevice()->GetHandle(), m_PkgPnp->GetDevice()->GetDeviceObject(), newState, m_CurrentState ); // // Update the state history array // m_States.History[IncrementHistoryIndex()] = (UCHAR) newState; // // Move to the new state // m_CurrentState = (BYTE) newState; entry = &m_StateTable[m_CurrentState-WakeInterruptFailed]; // // Invoke the state entry function (if present) for the new state // if (entry->StateFunc != NULL) { newState = entry->StateFunc(this); } else { newState = WakeInterruptMax; } } } return; }