/* * PCM pseudo code 5.1 .. 6.1 */ static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy) { struct fddi_mib_p *mib ; mib = phy->mib ; DB_PCMN(1,"SIG rec %x %x:\n", bit,phy->r_val[bit] ) ; bit++ ; switch(bit) { case 0: case 1: case 2: break ; case 3 : if (phy->r_val[1] == 0 && phy->r_val[2] == 0) mib->fddiPORTNeighborType = TA ; else if (phy->r_val[1] == 0 && phy->r_val[2] == 1) mib->fddiPORTNeighborType = TB ; else if (phy->r_val[1] == 1 && phy->r_val[2] == 0) mib->fddiPORTNeighborType = TS ; else if (phy->r_val[1] == 1 && phy->r_val[2] == 1) mib->fddiPORTNeighborType = TM ; break ; case 4: if (mib->fddiPORTMy_Type == TM && mib->fddiPORTNeighborType == TM) { DB_PCMN(1,"PCM %c : E100 withhold M-M\n", phy->phy_name,0) ; mib->fddiPORTPC_Withhold = PC_WH_M_M ; RS_SET(smc,RS_EVENT) ; } else if (phy->t_val[3] || phy->r_val[3]) { mib->fddiPORTPC_Withhold = PC_WH_NONE ; if (mib->fddiPORTMy_Type == TM || mib->fddiPORTNeighborType == TM) phy->pc_mode = PM_TREE ; else phy->pc_mode = PM_PEER ; /* reevaluate the selection criteria (wc_flag) */ all_selection_criteria (smc); if (phy->wc_flag) { mib->fddiPORTPC_Withhold = PC_WH_PATH ; } } else { mib->fddiPORTPC_Withhold = PC_WH_OTHER ; RS_SET(smc,RS_EVENT) ; DB_PCMN(1,"PCM %c : E101 withhold other\n", phy->phy_name,0) ; } phy->twisted = ((mib->fddiPORTMy_Type != TS) && (mib->fddiPORTMy_Type != TM) && (mib->fddiPORTNeighborType == mib->fddiPORTMy_Type)) ; if (phy->twisted) { DB_PCMN(1,"PCM %c : E102 !!! TWISTED !!!\n", phy->phy_name,0) ; } break ; case 5 : break ; case 6: if (phy->t_val[4] || phy->r_val[4]) { if ((phy->t_val[4] && phy->t_val[5]) || (phy->r_val[4] && phy->r_val[5]) ) phy->lc_test = LC_EXTENDED ; else phy->lc_test = LC_LONG ; } else if (phy->t_val[5] || phy->r_val[5]) phy->lc_test = LC_MEDIUM ; else phy->lc_test = LC_SHORT ; switch (phy->lc_test) { case LC_SHORT : /* 50ms */ outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LENGTH ) ; phy->t_next[7] = smc->s.pcm_lc_short ; break ; case LC_MEDIUM : /* 500ms */ outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LONGLN ) ; phy->t_next[7] = smc->s.pcm_lc_medium ; break ; case LC_LONG : SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ; phy->t_next[7] = smc->s.pcm_lc_long ; break ; case LC_EXTENDED : SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ; phy->t_next[7] = smc->s.pcm_lc_extended ; break ; } if (phy->t_next[7] > smc->s.pcm_lc_medium) { start_pcm_timer0(smc,phy->t_next[7],PC_TIMEOUT_LCT,phy); } DB_PCMN(1,"LCT timer = %ld us\n", phy->t_next[7], 0) ; phy->t_next[9] = smc->s.pcm_t_next_9 ; break ; case 7: if (phy->t_val[6]) { phy->cf_loop = TRUE ; } phy->td_flag = TRUE ; break ; case 8: if (phy->t_val[7] || phy->r_val[7]) { DB_PCMN(1,"PCM %c : E103 LCT fail %s\n", phy->phy_name,phy->t_val[7]? "local":"remote") ; queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ; } break ; case 9: if (phy->t_val[8] || phy->r_val[8]) { if (phy->t_val[8]) phy->cf_loop = TRUE ; phy->td_flag = TRUE ; } break ; case 10: if (phy->r_val[9]) { /* neighbor intends to have MAC on output */ ; mib->fddiPORTMacIndicated.R_val = TRUE ; } else { /* neighbor does not intend to have MAC on output */ ; mib->fddiPORTMacIndicated.R_val = FALSE ; } break ; } }
/* CFM state machine called by dispatcher do display state change process event until SM is stable */ void cfm(struct s_smc *smc, int event) { int state ; /* remember last state */ int cond ; int oldstate ; /* We will do the following: */ /* - compute the variable WC_Flag for every port (This is where */ /* we can extend the requested path checking !!) */ /* - do the old (SMT 6.2 like) state machine */ /* - do the resulting station states */ all_selection_criteria (smc); /* We will check now whether a state transition is allowed or not */ /* - change the portstates */ cem_priv_state (smc, event); oldstate = smc->mib.fddiSMTCF_State ; do { DB_CFM("CFM : state %s%s", (smc->mib.fddiSMTCF_State & AFLAG) ? "ACTIONS " : "", cfm_states[smc->mib.fddiSMTCF_State & ~AFLAG]) ; DB_CFM(" event %s\n",cfm_events[event],0) ; state = smc->mib.fddiSMTCF_State ; cfm_fsm(smc,event) ; event = 0 ; } while (state != smc->mib.fddiSMTCF_State) ; #ifndef SLIM_SMT /* * check peer wrap condition */ cond = FALSE ; if ( (smc->mib.fddiSMTCF_State == SC9_C_WRAP_A && smc->y[PA].pc_mode == PM_PEER) || (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B && smc->y[PB].pc_mode == PM_PEER) || (smc->mib.fddiSMTCF_State == SC11_C_WRAP_S && smc->y[PS].pc_mode == PM_PEER && smc->y[PS].mib->fddiPORTNeighborType != TS ) ) { cond = TRUE ; } if (cond != smc->mib.fddiSMTPeerWrapFlag) smt_srf_event(smc,SMT_COND_SMT_PEER_WRAP,0,cond) ; #if 0 /* * Don't send ever MAC_PATH_CHANGE events. Our MAC is hard-wired * to the primary path. */ /* * path change */ if (smc->mib.fddiSMTCF_State != oldstate) { smt_srf_event(smc,SMT_EVENT_MAC_PATH_CHANGE,INDEX_MAC,0) ; } #endif #endif /* no SLIM_SMT */ /* * set MAC port type */ smc->mib.m[MAC0].fddiMACDownstreamPORTType = cf_to_ptype[smc->mib.fddiSMTCF_State] ; cfm_state_change(smc,(int)smc->mib.fddiSMTCF_State) ; }