Example #1
0
/*
 * 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 ;
	}
}
Example #2
0
/*
	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) ;
}