⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcmplc.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifdef	CONCENTRATOR	if (!plc_is_installed(smc,phy))		return(PC_QLS) ;#endif	state = inpw(PLC(phy,PL_STATUS_A)) & PL_LINE_ST ;	switch(state) {	case PL_L_QLS:		state = PC_QLS ;		break ;	case PL_L_MLS:		state = PC_MLS ;		break ;	case PL_L_HLS:		state = PC_HLS ;		break ;	case PL_L_ILS4:	case PL_L_ILS16:		state = PC_ILS ;		break ;	case PL_L_ALS:		state = PC_LS_PDR ;		break ;	default :		state = PC_LS_NONE ;	}	return(state) ;}static int plc_send_bits(struct s_smc *smc, struct s_phy *phy, int len){	int np = phy->np ;		/* PHY index */	int	n ;	int	i ;	SK_UNUSED(smc) ;	/* create bit vector */	for (i = len-1,n = 0 ; i >= 0 ; i--) {		n = (n<<1) | phy->t_val[phy->bitn+i] ;	}	if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) {#if	0		printf("PL_PCM_SIGNAL is set\n") ;#endif		return(1) ;	}	/* write bit[n] & length = 1 to regs */	outpw(PLC(np,PL_VECTOR_LEN),len-1) ;	/* len=nr-1 */	outpw(PLC(np,PL_XMIT_VECTOR),n) ;#ifdef	DEBUG#if 1#ifdef	DEBUG_BRD	if (smc->debug.d_plc & 0x80)#else	if (debug.d_plc & 0x80)#endif		printf("SIGNALING bit %d .. %d\n",phy->bitn,phy->bitn+len-1) ;#endif#endif	return(0) ;}/* * config plc muxes */void plc_config_mux(struct s_smc *smc, int mux){	if (smc->s.sas != SMT_DAS)		return ;	if (mux == MUX_WRAPB) {		SETMASK(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ;		SETMASK(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP,PL_SC_REM_LOOP) ;	}	else {		CLEAR(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL) ;		CLEAR(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP) ;	}	CLEAR(PLC(PB,PL_CNTRL_B),PL_CONFIG_CNTRL) ;	CLEAR(PLC(PB,PL_CNTRL_A),PL_SC_REM_LOOP) ;}/*	PCM state machine	called by dispatcher  & fddi_init() (driver)	do		display state change		process event	until SM is stable*/void pcm(struct s_smc *smc, const int np, int event){	int	state ;	int	oldstate ;	struct s_phy	*phy ;	struct fddi_mib_p	*mib ;#ifndef	CONCENTRATOR	/*	 * ignore 2nd PHY if SAS	 */	if ((np != PS) && (smc->s.sas == SMT_SAS))		return ;#endif	phy = &smc->y[np] ;	mib = phy->mib ;	oldstate = mib->fddiPORTPCMState ;	do {		DB_PCM("PCM %c: state %s",			phy->phy_name,			(mib->fddiPORTPCMState & AFLAG) ? "ACTIONS " : "") ;		DB_PCM("%s, event %s\n",			pcm_states[mib->fddiPORTPCMState & ~AFLAG],			pcm_events[event]) ;		state = mib->fddiPORTPCMState ;		pcm_fsm(smc,phy,event) ;		event = 0 ;	} while (state != mib->fddiPORTPCMState) ;	/*	 * because the PLC does the bit signaling for us,	 * we're always in SIGNAL state	 * the MIB want's to see CONNECT	 * we therefore fake an entry in the MIB	 */	if (state == PC5_SIGNAL)		mib->fddiPORTPCMStateX = PC3_CONNECT ;	else		mib->fddiPORTPCMStateX = state ;#ifndef	SLIM_SMT	/*	 * path change	 */	if (	mib->fddiPORTPCMState != oldstate &&		((oldstate == PC8_ACTIVE) || (mib->fddiPORTPCMState == PC8_ACTIVE))) {		smt_srf_event(smc,SMT_EVENT_PORT_PATH_CHANGE,			(int) (INDEX_PORT+ phy->np),0) ;	}#endif#ifdef FDDI_MIB	/* check whether a snmp-trap has to be sent */	if ( mib->fddiPORTPCMState != oldstate ) {		/* a real state change took place */		DB_SNMP ("PCM from %d to %d\n", oldstate, mib->fddiPORTPCMState);		if ( mib->fddiPORTPCMState == PC0_OFF ) {			/* send first trap */			snmp_fddi_trap (smc, 1, (int) mib->fddiPORTIndex );		} else if ( oldstate == PC0_OFF ) {			/* send second trap */			snmp_fddi_trap (smc, 2, (int) mib->fddiPORTIndex );		} else if ( mib->fddiPORTPCMState != PC2_TRACE &&			oldstate == PC8_ACTIVE ) {			/* send third trap */			snmp_fddi_trap (smc, 3, (int) mib->fddiPORTIndex );		} else if ( mib->fddiPORTPCMState == PC8_ACTIVE ) {			/* send fourth trap */			snmp_fddi_trap (smc, 4, (int) mib->fddiPORTIndex );		}	}#endif	pcm_state_change(smc,np,state) ;}/* * PCM state machine */static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd){	int	i ;	int	np = phy->np ;		/* PHY index */	struct s_plc	*plc ;	struct fddi_mib_p	*mib ;#ifndef	MOT_ELM	u_short	plc_rev ;		/* Revision of the plc */#endif	/* nMOT_ELM */	plc = &phy->plc ;	mib = phy->mib ;	/*	 * general transitions independent of state	 */	switch (cmd) {	case PC_STOP :		/*PC00-PC80*/		if (mib->fddiPORTPCMState != PC9_MAINT) {			GO_STATE(PC0_OFF) ;			AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)				FDDI_PORT_EVENT, (u_long) FDDI_PORT_STOP,				smt_get_port_event_word(smc));		}		return ;	case PC_START :		/*PC01-PC81*/		if (mib->fddiPORTPCMState != PC9_MAINT)			GO_STATE(PC1_BREAK) ;		return ;	case PC_DISABLE :		/* PC09-PC99 */		GO_STATE(PC9_MAINT) ;		AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)			FDDI_PORT_EVENT, (u_long) FDDI_PORT_DISABLED,			smt_get_port_event_word(smc));		return ;	case PC_TIMEOUT_LCT :		/* if long or extended LCT */		stop_pcm_timer0(smc,phy) ;		CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;		/* end of LCT is indicate by PCM_CODE (initiate PCM event) */		return ;	}	switch(mib->fddiPORTPCMState) {	case ACTIONS(PC0_OFF) :		stop_pcm_timer0(smc,phy) ;		outpw(PLC(np,PL_CNTRL_A),0) ;		CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;		CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;		sm_ph_lem_stop(smc,np) ;		/* disable LEM */		phy->cf_loop = FALSE ;		phy->cf_join = FALSE ;		queue_event(smc,EVENT_CFM,CF_JOIN+np) ;		plc_go_state(smc,np,PL_PCM_STOP) ;		mib->fddiPORTConnectState = PCM_DISABLED ;		ACTIONS_DONE() ;		break ;	case PC0_OFF:		/*PC09*/		if (cmd == PC_MAINT) {			GO_STATE(PC9_MAINT) ;			break ;		}		break ;	case ACTIONS(PC1_BREAK) :		/* Stop the LCT timer if we came from Signal state */		stop_pcm_timer0(smc,phy) ;		ACTIONS_DONE() ;		plc_go_state(smc,np,0) ;		CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;		CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;		sm_ph_lem_stop(smc,np) ;		/* disable LEM */		/*		 * if vector is already loaded, go to OFF to clear PCM_SIGNAL		 */#if	0		if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) {			plc_go_state(smc,np,PL_PCM_STOP) ;			/* TB_MIN ? */		}#endif		/*		 * Go to OFF state in any case.		 */		plc_go_state(smc,np,PL_PCM_STOP) ;		if (mib->fddiPORTPC_Withhold == PC_WH_NONE)			mib->fddiPORTConnectState = PCM_CONNECTING ;		phy->cf_loop = FALSE ;		phy->cf_join = FALSE ;		queue_event(smc,EVENT_CFM,CF_JOIN+np) ;		phy->ls_flag = FALSE ;		phy->pc_mode = PM_NONE ;	/* needed by CFM */		phy->bitn = 0 ;			/* bit signaling start bit */		for (i = 0 ; i < 3 ; i++)			pc_tcode_actions(smc,i,phy) ;		/* Set the non-active interrupt mask register */		outpw(PLC(np,PL_INTR_MASK),plc_imsk_na) ;		/*		 * If the LCT was stopped. There might be a		 * PCM_CODE interrupt event present.		 * This must be cleared.		 */		(void)inpw(PLC(np,PL_INTR_EVENT)) ;#ifndef	MOT_ELM		/* Get the plc revision for revision dependent code */		plc_rev = inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK ;		if (plc_rev != PLC_REV_SN3)#endif	/* MOT_ELM */		{			/*			 * No supernet III PLC, so set Xmit verctor and			 * length BEFORE starting the state machine.			 */			if (plc_send_bits(smc,phy,3)) {				return ;			}		}		/*		 * Now give the Start command.		 * - The start command shall be done before setting the bits		 *   to be signaled. (In PLC-S description and PLCS in SN3.		 * - The start command shall be issued AFTER setting the		 *   XMIT vector and the XMIT length register.		 *		 * We do it exactly according this specs for the old PLC and		 * the new PLCS inside the SN3.		 * For the usual PLCS we try it the way it is done for the		 * old PLC and set the XMIT registers again, if the PLC is		 * not in SIGNAL state. This is done according to an PLCS		 * errata workaround.		 */		plc_go_state(smc,np,PL_PCM_START) ;		/*		 * workaround for PLC-S eng. sample errata		 */#ifdef	MOT_ELM		if (!(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL))#else	/* nMOT_ELM */		if (((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) !=			PLC_REVISION_A) &&			!(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL))#endif	/* nMOT_ELM */		{			/*			 * Set register again (PLCS errata) or the first time			 * (new SN3 PLCS).			 */			(void) plc_send_bits(smc,phy,3) ;		}		/*		 * end of workaround		 */		GO_STATE(PC5_SIGNAL) ;		plc->p_state = PS_BIT3 ;		plc->p_bits = 3 ;		plc->p_start = 0 ;		break ;	case PC1_BREAK :		break ;	case ACTIONS(PC2_TRACE) :		plc_go_state(smc,np,PL_PCM_TRACE) ;		ACTIONS_DONE() ;		break ;	case PC2_TRACE :		break ;	case PC3_CONNECT :	/* these states are done by hardware */	case PC4_NEXT :		break ;	case ACTIONS(PC5_SIGNAL) :		ACTIONS_DONE() ;	case PC5_SIGNAL :		if ((cmd != PC_SIGNAL) && (cmd != PC_TIMEOUT_LCT))			break ;		switch (plc->p_state) {		case PS_BIT3 :			for (i = 0 ; i <= 2 ; i++)				pc_rcode_actions(smc,i,phy) ;			pc_tcode_actions(smc,3,phy) ;			plc->p_state = PS_BIT4 ;			plc->p_bits = 1 ;			plc->p_start = 3 ;			phy->bitn = 3 ;			if (plc_send_bits(smc,phy,1)) {				return ;			}			break ;		case PS_BIT4 :			pc_rcode_actions(smc,3,phy) ;			for (i = 4 ; i <= 6 ; i++)				pc_tcode_actions(smc,i,phy) ;			plc->p_state = PS_BIT7 ;			plc->p_bits = 3 ;			plc->p_start = 4 ;			phy->bitn = 4 ;			if (plc_send_bits(smc,phy,3)) {				return ;			}			break ;		case PS_BIT7 :			for (i = 3 ; i <= 6 ; i++)				pc_rcode_actions(smc,i,phy) ;			plc->p_state = PS_LCT ;			plc->p_bits = 0 ;			plc->p_start = 7 ;			phy->bitn = 7 ;		sm_ph_lem_start(smc,np,(int)smc->s.lct_short) ; /* enable LEM */			/* start LCT */			i = inpw(PLC(np,PL_CNTRL_B)) & ~PL_PC_LOOP ;			outpw(PLC(np,PL_CNTRL_B),i) ;	/* must be cleared */			outpw(PLC(np,PL_CNTRL_B),i | PL_RLBP) ;			break ;		case PS_LCT :			/* check for local LCT failure */			pc_tcode_actions(smc,7,phy) ;			/*			 * set tval[7]			 */			plc->p_state = PS_BIT8 ;			plc->p_bits = 1 ;			plc->p_start = 7 ;			phy->bitn = 7 ;			if (plc_send_bits(smc,phy,1)) {				return ;			}			break ;		case PS_BIT8 :			/* check for remote LCT failure */			pc_rcode_actions(smc,7,phy) ;			if (phy->t_val[7] || phy->r_val[7]) {				plc_go_state(smc,np,PL_PCM_STOP) ;				GO_STATE(PC1_BREAK) ;				break ;			}			for (i = 8 ; i <= 9 ; i++)				pc_tcode_actions(smc,i,phy) ;			plc->p_state = PS_JOIN ;			plc->p_bits = 2 ;			plc->p_start = 8 ;			phy->bitn = 8 ;			if (plc_send_bits(smc,phy,2)) {				return ;			}			break ;		case PS_JOIN :			for (i = 8 ; i <= 9 ; i++)				pc_rcode_actions(smc,i,phy) ;			plc->p_state = PS_ACTIVE ;			GO_STATE(PC6_JOIN) ;			break ;		}		break ;	case ACTIONS(PC6_JOIN) :		/*		 * prevent mux error when going from WRAP_A to WRAP_B		 */		if (smc->s.sas == SMT_DAS && np == PB &&			(smc->y[PA].pc_mode == PM_TREE ||			 smc->y[PB].pc_mode == PM_TREE)) {			SETMASK(PLC(np,PL_CNTRL_A),				PL_SC_REM_LOOP,PL_SC_REM_LOOP) ;			SETMASK(PLC(np,PL_CNTRL_B),				PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ;		}		SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ;		SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ;		ACTIONS_DONE() ;		cmd = 0 ;		/* fall thru */	case PC6_JOIN :		switch (plc->p_state) {		case PS_ACTIVE:			/*PC88b*/			if (!phy->cf_join) {				phy->cf_join = TRUE ;				queue_event(smc,EVENT_CFM,CF_JOIN+np) ; ;			}			if (cmd == PC_JOIN)				GO_STATE(PC8_ACTIVE) ;			/*PC82*/			if (cmd == PC_TRACE) {				GO_STATE(PC2_TRACE) ;				break ;			}			break ;		}		break ;	case PC7_VERIFY :		break ;	case ACTIONS(PC8_ACTIVE) :		/*		 * start LEM for SMT		 */		sm_ph_lem_start(smc,(int)phy->np,LCT_LEM_MAX) ;		phy->tr_flag = FALSE ;		mib->fddiPORTConnectState = PCM_ACTIVE ;		/* Set the active interrupt mask register */		outpw(PLC(np,PL_INTR_MASK),plc_imsk_act) ;		ACTIONS_DONE() ;		break ;	case PC8_ACTIVE :		/*PC81 is done by PL_TNE_EXPIRED irq */		/*PC82*/		if (cmd == PC_TRACE) {			GO_STATE(PC2_TRACE) ;			break ;		}		/*PC88c: is done by TRACE_PROP irq */		break ;	case ACTIONS(PC9_MAINT) :		stop_pcm_timer0(smc,phy) ;		CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;		CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;		CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ;	/* disable LEM int. */		sm_ph_lem_stop(smc,np) ;		/* disable LEM */		phy->cf_loop = FALSE ;		phy->cf_join = FALSE ;		queue_event(smc,EVENT_CFM,CF_JOIN+np) ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -