static int __gfsm_fsm_exec(TfwGState *st, int fsm_id, struct sk_buff *skb, unsigned int off) { int r, slot, dummy; st->curr = slot = __gfsm_fsm_lookup(st, fsm_id, &dummy); BUG_ON(st->curr < 0); FSM_STATE(st) |= TFW_GFSM_ONSTACK; TFW_DBG("GFSM exec fsm %d, state %#x\n", fsm_id, st->states[slot]); r = fsm_htbl[fsm_id](st->obj, skb, off); /* If current FSM finishes, remove its state. */ if ((st->states[slot] & TFW_GFSM_STATE_MASK) == TFW_GFSM_STATE_LAST) { FSM_STATE(st) = BAD_STATE; st->curr = -1; } else { st->states[slot] &= ~TFW_GFSM_ONSTACK; } return r; }
/** * Move the FSM to new state @state and call all registered hooks for it. * * Iterates over all priorities for current state of top (current) FSM and * switch to the registered FSMs. * * Currently there is TFW_GFSM_WC_BMAP_SZ priorities (and each priority * has 32-bit states bitmap), so we use this fact to speedup the iteration. */ int tfw_gfsm_move(TfwGState *st, unsigned short state, struct sk_buff *skb, unsigned int off) { int r = TFW_PASS, p, fsm; unsigned int *hooks = fsm_hooks_bm[FSM(st)]; unsigned long mask = 1 << state; TFW_DBG("GFSM move from %#x to %#x\n", FSM_STATE(st), state); /* Remember current FSM context. */ SET_STATE(st, state); /* Start from higest priority. */ for (p = TFW_GFSM_HOOK_PRIORITY_HIGH; p < TFW_GFSM_HOOK_PRIORITY_NUM; ++p) { /* * TODO Handle different priorities by ordering the hooks, * rather than fixed priority levels to avoid spinning in vain. */ if (!(hooks[p] & mask)) return TFW_PASS; /* Switch context to other FSM. */ fsm = tfw_gfsm_switch(st, state, p); /* * Don't execute FSM handler who executed us, * the FSM will just continue it's processing when all other * executed FSMs exit. */ if (FSM_STATE(st) & TFW_GFSM_ONSTACK) continue; switch (__gfsm_fsm_exec(st, fsm, skb, off)) { case TFW_BLOCK: return TFW_BLOCK; case TFW_POSTPONE: /* * Postpone processing if at least one FSM * needs more data. */ r = TFW_POSTPONE; } } return r; }
/** * The function must be called by first FSM processing @obj or * independent code, such that alls FSMs can use it for dispatching. */ void tfw_gfsm_state_init(TfwGState *st, void *obj, int st0) { st->obj = obj; memset(st->states, __BAD_STATE_BYTE, sizeof(st->states)); FSM_STATE(st) = st0; }
/** * Context switch from current FSM at state @state to next FSM. */ static int tfw_gfsm_switch(TfwGState *st, int state, int prio) { int shift = prio * TFW_GFSM_PRIO_N + (state & TFW_GFSM_STATE_MASK); int fsm_next = fsm_hooks[FSM(st)][shift].fsm_id; int fsm_curr = state >> TFW_GFSM_FSM_SHIFT; int free_slot; TFW_DBG("GFSM switch from fsm %d at state %d to fsm %d at state %#x\n", fsm_curr, state, fsm_next, fsm_hooks[fsm_curr][shift].st0); st->curr = __gfsm_fsm_lookup(st, fsm_next, &free_slot); if (st->curr < 0) { /* Create new clear state for the next FSM. */ BUG_ON(free_slot < 0); st->curr = free_slot; FSM_STATE(st) = fsm_hooks[fsm_curr][shift].st0; } return fsm_next; }
#include <string.h> /* for memcpy */ #include "TCPIP Stack/ZGLinkMgrII.h" #if !defined (ZG_CONFIG_NO_ADHOCMGRII) #include "TCPIP Stack/ZGConsole.h" #include "TCPIP Stack/ZGAdhocMgrII.h" #include "TCPIP Stack/ZGCommon.h" ROM tFSMState g_adhocFSM[ZG_MAX_STATES] = { /* kNULL */ FSM_STATE( kNULL, kNULL, kNULL, kNULL, kNULL, kNULL ), /* kSTIdle */ FSM_STATE( kNULL, kNULL, kNULL, genericIdleNextState, kNULL, kNULL ), /* kSTGetChipVersion */ FSM_STATE( kNULL, kNULL, kNULL, kNULL, kNULL, kNULL ), /* kSTEnThrottleTable */ FSM_STATE( ZGLibSetThrottleTable, genericThrottleTableRequest, genericComplete, genericThrottleTableNext, kSTSetMacAddr, kSTIdle ), /* kSTSetConnLostCondition */ FSM_STATE( kNULL, kNULL, kNULL, kNULL, kNULL, kNULL ), /* kSTSetMacAddr */ FSM_STATE( ZGLibSetMacAddr, genericSetMacAddrRequest, genericSetMacAddrComplete, kNULL, kSTSetRegDom, kSTIdle ),
#if defined(ZG_CS_TRIS) #include <string.h> /* for memcpy */ #include "TCPIP Stack/ZGLinkMgrII.h" #if defined (ZG_CONFIG_LINKMGRII) #include "TCPIP Stack/ZGWifiMgrII.h" #include "TCPIP Stack/ZGAdhocMgrII.h" /* These FSM tables are intended for ROM */ ROM tFSMState g_emptyFSM[2] = { /* kNULL */ FSM_STATE( kNULL, kNULL, kNULL, kNULL, kNULL, kNULL ), /* kSTIdle */ FSM_STATE( kNULL, kNULL, kNULL, genericIdleNextState, kNULL, kNULL ) }; /* System Globals */ tZGLinkMgrCtx g_linkMgrCtx; tZGVoidReturn ZGLinkMgrSetMode( tZGLMNetworkMode mode ) { APPCXT.FSM.currentMode = mode;