Beispiel #1
0
void ASIC11096SPI::Init()
{
	// THESE NEED TO BE CHANGED TO MATCH YOUR OWN HARDWARE
	// set up direction register
	CLRMASK(sysRegs->iop->IOPMOD, BIT(kDRDY) | BIT(kMISO));
	SETMASK(sysRegs->iop->IOPMOD, BIT(kSSNOT) | BIT(kRESET) | BIT(kSCLK)
			| BIT(kMOSI));
	
	// make sure the output pins are in the correct state
	SETMASK(sysRegs->iop->IOPDATA, BIT(kSSNOT));
	CLRMASK(sysRegs->iop->IOPDATA, BIT(kRESET) | BIT(kSCLK));
}
Beispiel #2
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) ;
}
Beispiel #3
0
void ASIC11096SPI::SetMOSI(bool high)
{
	// THESE NEED TO BE CHANGED TO MATCH YOUR OWN HARDWARE
	if(high)
	{
		SETMASK(sysRegs->iop->IOPDATA, BIT(kMOSI));
	}
	else
	{
		CLRMASK(sysRegs->iop->IOPDATA, BIT(kMOSI));
	}
}
Beispiel #4
0
/*
 * LEM functions
 */
static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold)
{
	struct lem_counter *lem = &smc->y[np].lem ;

	lem->lem_on = 1 ;
	lem->lem_errors = 0L ;

	/* Do NOT reset mib->fddiPORTLer_Estimate here. It is called too
	 * often.
	 */

	outpw(PLC(np,PL_LE_THRESHOLD),threshold) ;
	(void)inpw(PLC(np,PL_LINK_ERR_CTR)) ;	/* clear error counter */

	/* enable LE INT */
	SETMASK(PLC(np,PL_INTR_MASK),PL_LE_CTR,PL_LE_CTR) ;
}
Beispiel #5
0
/*
 * 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) ;
		plc_go_state(smc,np,PL_PCM_STOP) ;
		mib->fddiPORTConnectState = PCM_DISABLED ;
		SETMASK(PLC(np,PL_CNTRL_B),PL_MAINT,PL_MAINT) ;
		sm_ph_linestate(smc,np,(int) MIB2LS(mib->fddiPORTMaint_LS)) ;
		outpw(PLC(np,PL_CNTRL_A),PL_SC_BYPASS) ;
		ACTIONS_DONE() ;
		break ;
	case PC9_MAINT :
		DB_PCMN(1,"PCM %c : MAINT\n",phy->phy_name,0) ;
		/*PC90*/
		if (cmd == PC_ENABLE) {
			GO_STATE(PC0_OFF) ;
			break ;
		}
		break ;

	default:
		SMT_PANIC(smc,SMT_E0118, SMT_E0118_MSG) ;
		break ;
	}
}
Beispiel #6
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 ;
	}
}
Beispiel #7
0
void ASIC11096SPI::End()
{
	// THESE NEED TO BE CHANGED TO MATCH YOUR OWN HARDWARE
	SETMASK(sysRegs->iop->IOPDATA, BIT(kSSNOT));
}
Beispiel #8
0
void ASIC11096SPI::Reset()
{
	// THESE NEED TO BE CHANGED TO MATCH YOUR OWN HARDWARE
	SETMASK(sysRegs->iop->IOPDATA, BIT(kRESET));
	CLRMASK(sysRegs->iop->IOPDATA, BIT(kRESET));
}