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;    
}