// // Copyright (C) Microsoft. All rights reserved. // #ifndef _FXPNPSTATEMACHINE_H_ #define _FXPNPSTATEMACHINE_H_ // @@SMVERIFY_SPLIT_BEGIN typedef WDF_DEVICE_PNP_STATE (*PFN_PNP_STATE_ENTRY_FUNCTION)( FxPkgPnp* This ); // // Treat these values as a bit field when comparing for known dropped events in // the current state and treat them as values when they known transition events // from state to the next. // enum FxPnpEvent { PnpEventInvalid = 0x000000, PnpEventAddDevice = 0x000001, PnpEventStartDevice = 0x000002, PnpEventStartDeviceComplete = 0x000004, PnpEventStartDeviceFailed = 0x000008, PnpEventQueryRemove = 0x000010, PnpEventQueryStop = 0x000020, PnpEventCancelRemove = 0x000040, PnpEventCancelStop = 0x000080, PnpEventStop = 0x000100, PnpEventRemove = 0x000200, PnpEventSurpriseRemove = 0x000400, PnpEventEject = 0x000800, PnpEventPwrPolStopped = 0x001000, PnpEventPwrPolStopFailed = 0x002000, PnpEventPowerUpFailed = 0x004000, PnpEventPowerDownFailed = 0x008000, PnpEventParentRemoved = 0x010000, PnpEventChildrenRemovalComplete = 0x020000, PnpEventPwrPolStarted = 0x040000, PnpEventPwrPolStartFailed = 0x080000, PnpEventDeviceInD0 = 0x100000, PnpEventPwrPolRemoved = 0x200000, // // Not a real event, just a value that shows all of the events which have // queued the pnp irp. If we drop one of these events, we *must* complete // the pended pnp irp. See PnpProcessEventInner. // PnpEventPending = PnpEventStartDeviceComplete | PnpEventQueryRemove | PnpEventQueryStop | PnpEventCancelRemove | PnpEventCancelStop | PnpEventStop | PnpEventSurpriseRemove | PnpEventEject, // // Not a real event, just a value that indicates all of the events which // goto the head of the queue and are always processed, even if the state is // locked. // PnpPriorityEventsMask = PnpEventPwrPolStarted | PnpEventPwrPolStartFailed | PnpEventPwrPolStopped | PnpEventPwrPolStopFailed | PnpEventDeviceInD0 | PnpEventPwrPolRemoved, PnpEventNull = 0xFFFFFFFF, }; // // Bit packed ULONG. // union FxPnpStateInfo { struct { // // Indicates whether the state is open to all events // ULONG QueueOpen : 1; // // Bit of events we know we can drop in this state // ULONG KnownDroppedEvents : 31; } Bits; struct { // // Maps to the same bit location as QueueOpen. Since we start // KnownDroppedEvents at the next bit, start our bits by at the next // bit as well. // ULONG Reserved : 1; // // These are defined so that we can easily tell in the debugger what // each set bit in KnownDroppedEvents maps to in the FxPnpEvent enum // ULONG PnpEventAddDeviceKnown : 1; ULONG PnpEventStartDeviceKnown : 1; ULONG PnpEventStartDeviceCompleteKnown : 1; ULONG PnpEventStartDeviceFailedKnown : 1; ULONG PnpEventQueryRemoveKnown : 1; ULONG PnpEventQueryStopKnown : 1; ULONG PnpEventCancelRemoveKnown : 1; ULONG PnpEventCancelStopKnown : 1; ULONG PnpEventStopKnown : 1; ULONG PnpEventRemoveKnown : 1; ULONG PnpEventSurpriseRemoveKnown : 1; ULONG PnpEventEjectKnown : 1; ULONG PnpEventPwrPolStopped : 1; ULONG PnpEventPwrPolStopFailed : 1; ULONG PnpEventPowerUpFailedKnown : 1; ULONG PnpEventPowerDownFailedKnown : 1; ULONG PnpEventParentRemovedKnown : 1; ULONG PnpEventChildrenRemovalCompleteKnown : 1; ULONG PnpEventPwrPolStarted : 1; ULONG PnpEventPwrPolStartFailed : 1; } BitsByName; }; struct PNP_EVENT_TARGET_STATE { FxPnpEvent PnpEvent; WDF_DEVICE_PNP_STATE TargetState; EVENT_TRAP_FIELD }; typedef const PNP_EVENT_TARGET_STATE* CPPNP_EVENT_TARGET_STATE; struct PNP_STATE_TABLE { // // Framework internal function // PFN_PNP_STATE_ENTRY_FUNCTION StateFunc; PNP_EVENT_TARGET_STATE FirstTargetState; CPPNP_EVENT_TARGET_STATE OtherTargetStates; FxPnpStateInfo StateInfo; }; typedef const PNP_STATE_TABLE* CPPNP_STATE_TABLE; #if FX_STATE_MACHINE_VERIFY #define MAX_PNP_STATE_ENTRY_FN_RETURN_STATES (5) struct PNP_STATE_ENTRY_FUNCTION_TARGET_STATE { // // Return value from state entry function // WDF_DEVICE_PNP_STATE State; // // type of device the returning state applies to // FxStateMachineDeviceType DeviceType; // // Info about the state transition // PSTR Comment; }; typedef const PNP_STATE_ENTRY_FUNCTION_TARGET_STATE* CPPNP_STATE_ENTRY_FUNCTION_TARGET_STATE; struct PNP_STATE_ENTRY_FN_RETURN_STATE_TABLE { // // array of state transitions caused by state entry function // PNP_STATE_ENTRY_FUNCTION_TARGET_STATE TargetStates[MAX_PNP_STATE_ENTRY_FN_RETURN_STATES]; }; typedef const PNP_STATE_ENTRY_FN_RETURN_STATE_TABLE* CPPNP_STATE_ENTRY_FN_RETURN_STATE_TABLE; #endif //FX_STATE_MACHINE_VERIFY // @@SMVERIFY_SPLIT_END // // This type of union is done so that we can // 1) shrink the array element to the smallest size possible // 2) keep types within the structure so we can dump it in the debugger // union FxPnpMachineStateHistory { struct { WDF_DEVICE_PNP_STATE State1 : 16; WDF_DEVICE_PNP_STATE State2 : 16; WDF_DEVICE_PNP_STATE State3 : 16; WDF_DEVICE_PNP_STATE State4 : 16; WDF_DEVICE_PNP_STATE State5 : 16; WDF_DEVICE_PNP_STATE State6 : 16; WDF_DEVICE_PNP_STATE State7 : 16; WDF_DEVICE_PNP_STATE State8 : 16; } S; USHORT History[PnpEventQueueDepth]; }; struct FxPnpMachine : public FxWorkItemEventQueue { FxPnpMachine( VOID ) : FxWorkItemEventQueue(PnpEventQueueDepth) { RtlZeroMemory(&m_Queue[0], sizeof(m_Queue)); RtlZeroMemory(&m_States, sizeof(m_States)); m_States.History[IncrementHistoryIndex()] = WdfDevStatePnpObjectCreated; m_FireAndForget = FALSE; } FxPnpEvent m_Queue[PnpEventQueueDepth]; FxPnpMachineStateHistory m_States; BOOLEAN m_FireAndForget; }; #endif // _FXPNPSTATEMACHINE_H_