Example #1
0
/*
	process ECM event
*/
static void ecm_fsm(struct s_smc *smc, int cmd)
{
	int ls_a ;			/* current line state PHY A */
	int ls_b ;			/* current line state PHY B */
	int	p ;			/* ports */


	smc->mib.fddiSMTBypassPresent = sm_pm_bypass_present(smc) ;
	if (cmd == EC_CONNECT)
		smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ;

	/* For AIX event notification: */
	/* Is a disconnect  command remotely issued ? */
	if (cmd == EC_DISCONNECT &&
		smc->mib.fddiSMTRemoteDisconnectFlag == TRUE)
		AIX_EVENT (smc, (u_long) CIO_HARD_FAIL, (u_long)
			FDDI_REMOTE_DISCONNECT, smt_get_event_word(smc),
			smt_get_error_word(smc) );

	/*jd 05-Aug-1999 Bug #10419 "Port Disconnect fails at Dup MAc Cond."*/
	if (cmd == EC_CONNECT) {
		smc->e.DisconnectFlag = FALSE ;
	}
	else if (cmd == EC_DISCONNECT) {
		smc->e.DisconnectFlag = TRUE ;
	}
	
	switch(smc->mib.fddiSMTECMState) {
	case ACTIONS(EC0_OUT) :
		/*
		 * We do not perform a path test
		 */
		smc->e.path_test = PT_PASSED ;
		smc->e.ecm_line_state = FALSE ;
		stop_ecm_timer(smc) ;
		ACTIONS_DONE() ;
		break ;
	case EC0_OUT:
		/*EC01*/
		if (cmd == EC_CONNECT && !smc->mib.fddiSMTBypassPresent
			&& smc->e.path_test==PT_PASSED) {
			GO_STATE(EC1_IN) ;
			break ;
		}
		/*EC05*/
		else if (cmd == EC_CONNECT && (smc->e.path_test==PT_PASSED) &&
			smc->mib.fddiSMTBypassPresent &&
			(smc->s.sas == SMT_DAS)) {
			GO_STATE(EC5_INSERT) ;
			break ;
		}
		break;
	case ACTIONS(EC1_IN) :
		stop_ecm_timer(smc) ;
		smc->e.trace_prop = 0 ;
		sm_ma_control(smc,MA_TREQ) ;
		for (p = 0 ; p < NUMPHYS ; p++)
			if (smc->mib.p[p].fddiPORTHardwarePresent)
				queue_event(smc,EVENT_PCMA+p,PC_START) ;
		ACTIONS_DONE() ;
		break ;
	case EC1_IN:
		/*EC12*/
		if (cmd == EC_TRACE_PROP) {
			prop_actions(smc) ;
			GO_STATE(EC2_TRACE) ;
			break ;
		}
		/*EC13*/
		else if (cmd == EC_DISCONNECT) {
			GO_STATE(EC3_LEAVE) ;
			break ;
		}
		break;
	case ACTIONS(EC2_TRACE) :
		start_ecm_timer(smc,MIB2US(smc->mib.fddiSMTTrace_MaxExpiration),
			EC_TIMEOUT_TMAX) ;
		ACTIONS_DONE() ;
		break ;
	case EC2_TRACE :
		/*EC22*/
		if (cmd == EC_TRACE_PROP) {
			prop_actions(smc) ;
			GO_STATE(EC2_TRACE) ;
			break ;
		}
		/*EC23a*/
		else if (cmd == EC_DISCONNECT) {
			smc->e.path_test = PT_EXITING ;
			GO_STATE(EC3_LEAVE) ;
			break ;
		}
		/*EC23b*/
		else if (smc->e.path_test == PT_PENDING) {
			GO_STATE(EC3_LEAVE) ;
			break ;
		}
		/*EC23c*/
		else if (cmd == EC_TIMEOUT_TMAX) {
			/* Trace_Max is expired */
			/* -> send AIX_EVENT */
			AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
				(u_long) FDDI_SMT_ERROR, (u_long)
				FDDI_TRACE_MAX, smt_get_error_word(smc));
			smc->e.path_test = PT_PENDING ;
			GO_STATE(EC3_LEAVE) ;
			break ;
		}
		break ;
	case ACTIONS(EC3_LEAVE) :
		start_ecm_timer(smc,smc->s.ecm_td_min,EC_TIMEOUT_TD) ;
		for (p = 0 ; p < NUMPHYS ; p++)
			queue_event(smc,EVENT_PCMA+p,PC_STOP) ;
		ACTIONS_DONE() ;
		break ;
	case EC3_LEAVE:
		/*EC30*/
		if (cmd == EC_TIMEOUT_TD && !smc->mib.fddiSMTBypassPresent &&
			(smc->e.path_test != PT_PENDING)) {
			GO_STATE(EC0_OUT) ;
			break ;
		}
		/*EC34*/
		else if (cmd == EC_TIMEOUT_TD &&
			(smc->e.path_test == PT_PENDING)) {
			GO_STATE(EC4_PATH_TEST) ;
			break ;
		}
		/*EC31*/
		else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
			GO_STATE(EC1_IN) ;
			break ;
		}
		/*EC33*/
		else if (cmd == EC_DISCONNECT &&
			smc->e.path_test == PT_PENDING) {
			smc->e.path_test = PT_EXITING ;
			/*
			 * stay in state - state will be left via timeout
			 */
		}
		/*EC37*/
		else if (cmd == EC_TIMEOUT_TD &&
			smc->mib.fddiSMTBypassPresent &&
			smc->e.path_test != PT_PENDING) {
			GO_STATE(EC7_DEINSERT) ;
			break ;
		}
		break ;
	case ACTIONS(EC4_PATH_TEST) :
		stop_ecm_timer(smc) ;
		smc->e.path_test = PT_TESTING ;
		start_ecm_timer(smc,smc->s.ecm_test_done,EC_TEST_DONE) ;
		/* now perform path test ... just a simulation */
		ACTIONS_DONE() ;
		break ;
	case EC4_PATH_TEST :
		/* path test done delay */
		if (cmd == EC_TEST_DONE)
			smc->e.path_test = PT_PASSED ;

		if (smc->e.path_test == PT_FAILED)
			RS_SET(smc,RS_PATHTEST) ;

		/*EC40a*/
		if (smc->e.path_test == PT_FAILED &&
			!smc->mib.fddiSMTBypassPresent) {
			GO_STATE(EC0_OUT) ;
			break ;
		}
		/*EC40b*/
		else if (cmd == EC_DISCONNECT &&
			!smc->mib.fddiSMTBypassPresent) {
			GO_STATE(EC0_OUT) ;
			break ;
		}
		/*EC41*/
		else if (smc->e.path_test == PT_PASSED) {
			GO_STATE(EC1_IN) ;
			break ;
		}
		/*EC47a*/
		else if (smc->e.path_test == PT_FAILED &&
			smc->mib.fddiSMTBypassPresent) {
			GO_STATE(EC7_DEINSERT) ;
			break ;
		}
		/*EC47b*/
		else if (cmd == EC_DISCONNECT &&
			smc->mib.fddiSMTBypassPresent) {
			GO_STATE(EC7_DEINSERT) ;
			break ;
		}
		break ;
	case ACTIONS(EC5_INSERT) :
		sm_pm_bypass_req(smc,BP_INSERT);
		start_ecm_timer(smc,smc->s.ecm_in_max,EC_TIMEOUT_INMAX) ;
static void ecm_fsm(struct s_smc *smc, int cmd)
{
	int ls_a ;			
	int ls_b ;			
	int	p ;			


	smc->mib.fddiSMTBypassPresent = sm_pm_bypass_present(smc) ;
	if (cmd == EC_CONNECT)
		smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ;

	
	
	if (cmd == EC_DISCONNECT &&
		smc->mib.fddiSMTRemoteDisconnectFlag == TRUE)
		AIX_EVENT (smc, (u_long) CIO_HARD_FAIL, (u_long)
			FDDI_REMOTE_DISCONNECT, smt_get_event_word(smc),
			smt_get_error_word(smc) );

	
	if (cmd == EC_CONNECT) {
		smc->e.DisconnectFlag = FALSE ;
	}
	else if (cmd == EC_DISCONNECT) {
		smc->e.DisconnectFlag = TRUE ;
	}
	
	switch(smc->mib.fddiSMTECMState) {
	case ACTIONS(EC0_OUT) :
		smc->e.path_test = PT_PASSED ;
		smc->e.ecm_line_state = FALSE ;
		stop_ecm_timer(smc) ;
		ACTIONS_DONE() ;
		break ;
	case EC0_OUT:
		
		if (cmd == EC_CONNECT && !smc->mib.fddiSMTBypassPresent
			&& smc->e.path_test==PT_PASSED) {
			GO_STATE(EC1_IN) ;
			break ;
		}
		
		else if (cmd == EC_CONNECT && (smc->e.path_test==PT_PASSED) &&
			smc->mib.fddiSMTBypassPresent &&
			(smc->s.sas == SMT_DAS)) {
			GO_STATE(EC5_INSERT) ;
			break ;
		}
		break;
	case ACTIONS(EC1_IN) :
		stop_ecm_timer(smc) ;
		smc->e.trace_prop = 0 ;
		sm_ma_control(smc,MA_TREQ) ;
		for (p = 0 ; p < NUMPHYS ; p++)
			if (smc->mib.p[p].fddiPORTHardwarePresent)
				queue_event(smc,EVENT_PCMA+p,PC_START) ;
		ACTIONS_DONE() ;
		break ;
	case EC1_IN:
		
		if (cmd == EC_TRACE_PROP) {
			prop_actions(smc) ;
			GO_STATE(EC2_TRACE) ;
			break ;
		}
		
		else if (cmd == EC_DISCONNECT) {
			GO_STATE(EC3_LEAVE) ;
			break ;
		}
		break;
	case ACTIONS(EC2_TRACE) :
		start_ecm_timer(smc,MIB2US(smc->mib.fddiSMTTrace_MaxExpiration),
			EC_TIMEOUT_TMAX) ;
		ACTIONS_DONE() ;
		break ;
	case EC2_TRACE :
		
		if (cmd == EC_TRACE_PROP) {
			prop_actions(smc) ;
			GO_STATE(EC2_TRACE) ;
			break ;
		}
		
		else if (cmd == EC_DISCONNECT) {
			smc->e.path_test = PT_EXITING ;
			GO_STATE(EC3_LEAVE) ;
			break ;
		}
		
		else if (smc->e.path_test == PT_PENDING) {
			GO_STATE(EC3_LEAVE) ;
			break ;
		}
		
		else if (cmd == EC_TIMEOUT_TMAX) {
			
			
			AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
				(u_long) FDDI_SMT_ERROR, (u_long)
				FDDI_TRACE_MAX, smt_get_error_word(smc));
			smc->e.path_test = PT_PENDING ;
			GO_STATE(EC3_LEAVE) ;
			break ;
		}
		break ;
	case ACTIONS(EC3_LEAVE) :
		start_ecm_timer(smc,smc->s.ecm_td_min,EC_TIMEOUT_TD) ;
		for (p = 0 ; p < NUMPHYS ; p++)
			queue_event(smc,EVENT_PCMA+p,PC_STOP) ;
		ACTIONS_DONE() ;
		break ;
	case EC3_LEAVE:
		
		if (cmd == EC_TIMEOUT_TD && !smc->mib.fddiSMTBypassPresent &&
			(smc->e.path_test != PT_PENDING)) {
			GO_STATE(EC0_OUT) ;
			break ;
		}
		
		else if (cmd == EC_TIMEOUT_TD &&
			(smc->e.path_test == PT_PENDING)) {
			GO_STATE(EC4_PATH_TEST) ;
			break ;
		}
		
		else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
			GO_STATE(EC1_IN) ;
			break ;
		}
		
		else if (cmd == EC_DISCONNECT &&
			smc->e.path_test == PT_PENDING) {
			smc->e.path_test = PT_EXITING ;
		}
		
		else if (cmd == EC_TIMEOUT_TD &&
			smc->mib.fddiSMTBypassPresent &&
			smc->e.path_test != PT_PENDING) {
			GO_STATE(EC7_DEINSERT) ;
			break ;
		}
		break ;
	case ACTIONS(EC4_PATH_TEST) :
		stop_ecm_timer(smc) ;
		smc->e.path_test = PT_TESTING ;
		start_ecm_timer(smc,smc->s.ecm_test_done,EC_TEST_DONE) ;
		
		ACTIONS_DONE() ;
		break ;
	case EC4_PATH_TEST :
		
		if (cmd == EC_TEST_DONE)
			smc->e.path_test = PT_PASSED ;

		if (smc->e.path_test == PT_FAILED)
			RS_SET(smc,RS_PATHTEST) ;

		
		if (smc->e.path_test == PT_FAILED &&
			!smc->mib.fddiSMTBypassPresent) {
			GO_STATE(EC0_OUT) ;
			break ;
		}
		
		else if (cmd == EC_DISCONNECT &&
			!smc->mib.fddiSMTBypassPresent) {
			GO_STATE(EC0_OUT) ;
			break ;
		}
		
		else if (smc->e.path_test == PT_PASSED) {
			GO_STATE(EC1_IN) ;
			break ;
		}
		
		else if (smc->e.path_test == PT_FAILED &&
			smc->mib.fddiSMTBypassPresent) {
			GO_STATE(EC7_DEINSERT) ;
			break ;
		}
		
		else if (cmd == EC_DISCONNECT &&
			smc->mib.fddiSMTBypassPresent) {
			GO_STATE(EC7_DEINSERT) ;
			break ;
		}
		break ;
	case ACTIONS(EC5_INSERT) :
		sm_pm_bypass_req(smc,BP_INSERT);
		start_ecm_timer(smc,smc->s.ecm_in_max,EC_TIMEOUT_INMAX) ;
		ACTIONS_DONE() ;
		break ;
	case EC5_INSERT :
		
		if (cmd == EC_TIMEOUT_INMAX) {
			GO_STATE(EC6_CHECK) ;
			break ;
		}
		
		else if (cmd == EC_DISCONNECT) {
			GO_STATE(EC7_DEINSERT) ;
			break ;
		}
		break ;
	case ACTIONS(EC6_CHECK) :
		start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
		smc->e.ecm_line_state = TRUE ;	
		(void) sm_pm_ls_latch(smc,PA,1) ; 
		(void) sm_pm_ls_latch(smc,PB,1) ; 
		ACTIONS_DONE() ;
		break ;
	case EC6_CHECK :
		ls_a = sm_pm_get_ls(smc,PA) ;
		ls_b = sm_pm_get_ls(smc,PB) ;

		
		if (((ls_a == PC_QLS) || (ls_a == PC_HLS)) &&
		    ((ls_b == PC_QLS) || (ls_b == PC_HLS)) ) {
			smc->e.sb_flag = FALSE ;
			smc->e.ecm_line_state = FALSE ;
			GO_STATE(EC1_IN) ;
			break ;
		}
		
		else if (!smc->e.sb_flag &&
			 (((ls_a == PC_ILS) && (ls_b == PC_QLS)) ||
			  ((ls_a == PC_QLS) && (ls_b == PC_ILS)))){
			smc->e.sb_flag = TRUE ;
			DB_ECMN(1,"ECM : EC6_CHECK - stuck bypass\n",0,0) ;
			AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
				FDDI_SMT_ERROR, (u_long) FDDI_BYPASS_STUCK,
				smt_get_error_word(smc));
		}
		
		else if (cmd == EC_DISCONNECT) {
			smc->e.ecm_line_state = FALSE ;
			GO_STATE(EC7_DEINSERT) ;
			break ;
		}
		else {
			start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
		}
		break ;
	case ACTIONS(EC7_DEINSERT) :
		sm_pm_bypass_req(smc,BP_DEINSERT);
		start_ecm_timer(smc,smc->s.ecm_i_max,EC_TIMEOUT_IMAX) ;
		ACTIONS_DONE() ;
		break ;
	case EC7_DEINSERT:
		
		if (cmd == EC_TIMEOUT_IMAX) {
			GO_STATE(EC0_OUT) ;
			break ;
		}
		
		else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
			GO_STATE(EC5_INSERT) ;
			break ;
		}
		break;
	default:
		SMT_PANIC(smc,SMT_E0107, SMT_E0107_MSG) ;
		break;
	}
}
Example #3
0
File: ecm.c Project: 274914765/C
/*
    process ECM event
*/
static void ecm_fsm(struct s_smc *smc, int cmd)
{
    int ls_a ;            /* current line state PHY A */
    int ls_b ;            /* current line state PHY B */
    int    p ;            /* ports */


    smc->mib.fddiSMTBypassPresent = sm_pm_bypass_present(smc) ;
    if (cmd == EC_CONNECT)
        smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ;

    /* For AIX event notification: */
    /* Is a disconnect  command remotely issued ? */
    if (cmd == EC_DISCONNECT &&
        smc->mib.fddiSMTRemoteDisconnectFlag == TRUE)
        AIX_EVENT (smc, (u_long) CIO_HARD_FAIL, (u_long)
            FDDI_REMOTE_DISCONNECT, smt_get_event_word(smc),
            smt_get_error_word(smc) );

    /*jd 05-Aug-1999 Bug #10419 "Port Disconnect fails at Dup MAc Cond."*/
    if (cmd == EC_CONNECT) {
        smc->e.DisconnectFlag = FALSE ;
    }
    else if (cmd == EC_DISCONNECT) {
        smc->e.DisconnectFlag = TRUE ;
    }
    
    switch(smc->mib.fddiSMTECMState) {
    case ACTIONS(EC0_OUT) :
        /*
         * We do not perform a path test
         */
        smc->e.path_test = PT_PASSED ;
        smc->e.ecm_line_state = FALSE ;
        stop_ecm_timer(smc) ;
        ACTIONS_DONE() ;
        break ;
    case EC0_OUT:
        /*EC01*/
        if (cmd == EC_CONNECT && !smc->mib.fddiSMTBypassPresent
            && smc->e.path_test==PT_PASSED) {
            GO_STATE(EC1_IN) ;
            break ;
        }
        /*EC05*/
        else if (cmd == EC_CONNECT && (smc->e.path_test==PT_PASSED) &&
            smc->mib.fddiSMTBypassPresent &&
            (smc->s.sas == SMT_DAS)) {
            GO_STATE(EC5_INSERT) ;
            break ;
        }
        break;
    case ACTIONS(EC1_IN) :
        stop_ecm_timer(smc) ;
        smc->e.trace_prop = 0 ;
        sm_ma_control(smc,MA_TREQ) ;
        for (p = 0 ; p < NUMPHYS ; p++)
            if (smc->mib.p[p].fddiPORTHardwarePresent)
                queue_event(smc,EVENT_PCMA+p,PC_START) ;
        ACTIONS_DONE() ;
        break ;
    case EC1_IN:
        /*EC12*/
        if (cmd == EC_TRACE_PROP) {
            prop_actions(smc) ;
            GO_STATE(EC2_TRACE) ;
            break ;
        }
        /*EC13*/
        else if (cmd == EC_DISCONNECT) {
            GO_STATE(EC3_LEAVE) ;
            break ;
        }
        break;
    case ACTIONS(EC2_TRACE) :
        start_ecm_timer(smc,MIB2US(smc->mib.fddiSMTTrace_MaxExpiration),
            EC_TIMEOUT_TMAX) ;
        ACTIONS_DONE() ;
        break ;
    case EC2_TRACE :
        /*EC22*/
        if (cmd == EC_TRACE_PROP) {
            prop_actions(smc) ;
            GO_STATE(EC2_TRACE) ;
            break ;
        }
        /*EC23a*/
        else if (cmd == EC_DISCONNECT) {
            smc->e.path_test = PT_EXITING ;
            GO_STATE(EC3_LEAVE) ;
            break ;
        }
        /*EC23b*/
        else if (smc->e.path_test == PT_PENDING) {
            GO_STATE(EC3_LEAVE) ;
            break ;
        }
        /*EC23c*/
        else if (cmd == EC_TIMEOUT_TMAX) {
            /* Trace_Max is expired */
            /* -> send AIX_EVENT */
            AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
                (u_long) FDDI_SMT_ERROR, (u_long)
                FDDI_TRACE_MAX, smt_get_error_word(smc));
            smc->e.path_test = PT_PENDING ;
            GO_STATE(EC3_LEAVE) ;
            break ;
        }
        break ;
    case ACTIONS(EC3_LEAVE) :
        start_ecm_timer(smc,smc->s.ecm_td_min,EC_TIMEOUT_TD) ;
        for (p = 0 ; p < NUMPHYS ; p++)
            queue_event(smc,EVENT_PCMA+p,PC_STOP) ;
        ACTIONS_DONE() ;
        break ;
    case EC3_LEAVE:
        /*EC30*/
        if (cmd == EC_TIMEOUT_TD && !smc->mib.fddiSMTBypassPresent &&
            (smc->e.path_test != PT_PENDING)) {
            GO_STATE(EC0_OUT) ;
            break ;
        }
        /*EC34*/
        else if (cmd == EC_TIMEOUT_TD &&
            (smc->e.path_test == PT_PENDING)) {
            GO_STATE(EC4_PATH_TEST) ;
            break ;
        }
        /*EC31*/
        else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
            GO_STATE(EC1_IN) ;
            break ;
        }
        /*EC33*/
        else if (cmd == EC_DISCONNECT &&
            smc->e.path_test == PT_PENDING) {
            smc->e.path_test = PT_EXITING ;
            /*
             * stay in state - state will be left via timeout
             */
        }
        /*EC37*/
        else if (cmd == EC_TIMEOUT_TD &&
            smc->mib.fddiSMTBypassPresent &&
            smc->e.path_test != PT_PENDING) {
            GO_STATE(EC7_DEINSERT) ;
            break ;
        }
        break ;
    case ACTIONS(EC4_PATH_TEST) :
        stop_ecm_timer(smc) ;
        smc->e.path_test = PT_TESTING ;
        start_ecm_timer(smc,smc->s.ecm_test_done,EC_TEST_DONE) ;
        /* now perform path test ... just a simulation */
        ACTIONS_DONE() ;
        break ;
    case EC4_PATH_TEST :
        /* path test done delay */
        if (cmd == EC_TEST_DONE)
            smc->e.path_test = PT_PASSED ;

        if (smc->e.path_test == PT_FAILED)
            RS_SET(smc,RS_PATHTEST) ;

        /*EC40a*/
        if (smc->e.path_test == PT_FAILED &&
            !smc->mib.fddiSMTBypassPresent) {
            GO_STATE(EC0_OUT) ;
            break ;
        }
        /*EC40b*/
        else if (cmd == EC_DISCONNECT &&
            !smc->mib.fddiSMTBypassPresent) {
            GO_STATE(EC0_OUT) ;
            break ;
        }
        /*EC41*/
        else if (smc->e.path_test == PT_PASSED) {
            GO_STATE(EC1_IN) ;
            break ;
        }
        /*EC47a*/
        else if (smc->e.path_test == PT_FAILED &&
            smc->mib.fddiSMTBypassPresent) {
            GO_STATE(EC7_DEINSERT) ;
            break ;
        }
        /*EC47b*/
        else if (cmd == EC_DISCONNECT &&
            smc->mib.fddiSMTBypassPresent) {
            GO_STATE(EC7_DEINSERT) ;
            break ;
        }
        break ;
    case ACTIONS(EC5_INSERT) :
        sm_pm_bypass_req(smc,BP_INSERT);
        start_ecm_timer(smc,smc->s.ecm_in_max,EC_TIMEOUT_INMAX) ;
        ACTIONS_DONE() ;
        break ;
    case EC5_INSERT :
        /*EC56*/
        if (cmd == EC_TIMEOUT_INMAX) {
            GO_STATE(EC6_CHECK) ;
            break ;
        }
        /*EC57*/
        else if (cmd == EC_DISCONNECT) {
            GO_STATE(EC7_DEINSERT) ;
            break ;
        }
        break ;
    case ACTIONS(EC6_CHECK) :
        /*
         * in EC6_CHECK, we *POLL* the line state !
         * check whether both bypass switches have switched.
         */
        start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
        smc->e.ecm_line_state = TRUE ;    /* flag to pcm: report Q/HLS */
        (void) sm_pm_ls_latch(smc,PA,1) ; /* enable line state latch */
        (void) sm_pm_ls_latch(smc,PB,1) ; /* enable line state latch */
        ACTIONS_DONE() ;
        break ;
    case EC6_CHECK :
        ls_a = sm_pm_get_ls(smc,PA) ;
        ls_b = sm_pm_get_ls(smc,PB) ;

        /*EC61*/
        if (((ls_a == PC_QLS) || (ls_a == PC_HLS)) &&
            ((ls_b == PC_QLS) || (ls_b == PC_HLS)) ) {
            smc->e.sb_flag = FALSE ;
            smc->e.ecm_line_state = FALSE ;
            GO_STATE(EC1_IN) ;
            break ;
        }
        /*EC66*/
        else if (!smc->e.sb_flag &&
             (((ls_a == PC_ILS) && (ls_b == PC_QLS)) ||
              ((ls_a == PC_QLS) && (ls_b == PC_ILS)))){
            smc->e.sb_flag = TRUE ;
            DB_ECMN(1,"ECM : EC6_CHECK - stuck bypass\n",0,0) ;
            AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
                FDDI_SMT_ERROR, (u_long) FDDI_BYPASS_STUCK,
                smt_get_error_word(smc));
        }
        /*EC67*/
        else if (cmd == EC_DISCONNECT) {
            smc->e.ecm_line_state = FALSE ;
            GO_STATE(EC7_DEINSERT) ;
            break ;
        }
        else {
            /*
             * restart poll
             */
            start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
        }
        break ;
    case ACTIONS(EC7_DEINSERT) :
        sm_pm_bypass_req(smc,BP_DEINSERT);
        start_ecm_timer(smc,smc->s.ecm_i_max,EC_TIMEOUT_IMAX) ;
        ACTIONS_DONE() ;
        break ;
    case EC7_DEINSERT:
        /*EC70*/
        if (cmd == EC_TIMEOUT_IMAX) {
            GO_STATE(EC0_OUT) ;
            break ;
        }
        /*EC75*/
        else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
            GO_STATE(EC5_INSERT) ;
            break ;
        }
        break;
    default:
        SMT_PANIC(smc,SMT_E0107, SMT_E0107_MSG) ;
        break;
    }
}
Example #4
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 ;
	}
}
/*
	process RMT event
*/
static void rmt_fsm(struct s_smc *smc, int cmd)
{
	/*
	 * RM00-RM70 : from all states
	 */
	if (!smc->r.rm_join && !smc->r.rm_loop &&
		smc->mib.m[MAC0].fddiMACRMTState != ACTIONS(RM0_ISOLATED) &&
		smc->mib.m[MAC0].fddiMACRMTState != RM0_ISOLATED) {
		RS_SET(smc,RS_NORINGOP) ;
		rmt_indication(smc,0) ;
		GO_STATE(RM0_ISOLATED) ;
		return ;
	}

	switch(smc->mib.m[MAC0].fddiMACRMTState) {
	case ACTIONS(RM0_ISOLATED) :
		stop_rmt_timer0(smc) ;
		stop_rmt_timer1(smc) ;
		stop_rmt_timer2(smc) ;

		/*
		 * Disable MAC.
		 */
		sm_ma_control(smc,MA_OFFLINE) ;
		smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
		smc->r.loop_avail = FALSE ;
		smc->r.sm_ma_avail = FALSE ;
		smc->r.no_flag = TRUE ;
		DB_RMTN(1,"RMT : ISOLATED\n",0,0) ;
		ACTIONS_DONE() ;
		break ;
	case RM0_ISOLATED :
		/*RM01*/
		if (smc->r.rm_join || smc->r.rm_loop) {
			/*
			 * According to the standard the MAC must be reset
			 * here. The FORMAC will be initialized and Claim
			 * and Beacon Frames will be uploaded to the MAC.
			 * So any change of Treq will take effect NOW.
			 */
			sm_ma_control(smc,MA_RESET) ;
			GO_STATE(RM1_NON_OP) ;
			break ;
		}
		break ;
	case ACTIONS(RM1_NON_OP) :
		start_rmt_timer0(smc,smc->s.rmt_t_non_op,RM_TIMEOUT_NON_OP) ;
		stop_rmt_timer1(smc) ;
		stop_rmt_timer2(smc) ;
		sm_ma_control(smc,MA_BEACON) ;
		DB_RMTN(1,"RMT : RING DOWN\n",0,0) ;
		RS_SET(smc,RS_NORINGOP) ;
		smc->r.sm_ma_avail = FALSE ;
		rmt_indication(smc,0) ;
		ACTIONS_DONE() ;
		break ;
	case RM1_NON_OP :
		/*RM12*/
		if (cmd == RM_RING_OP) {
			RS_SET(smc,RS_RINGOPCHANGE) ;
			GO_STATE(RM2_RING_OP) ;
			break ;
		}
		/*RM13*/
		else if (cmd == RM_TIMEOUT_NON_OP) {
			smc->r.bn_flag = FALSE ;
			smc->r.no_flag = TRUE ;
			GO_STATE(RM3_DETECT) ;
			break ;
		}
		break ;
	case ACTIONS(RM2_RING_OP) :
		stop_rmt_timer0(smc) ;
		stop_rmt_timer1(smc) ;
		stop_rmt_timer2(smc) ;
		smc->r.no_flag = FALSE ;
		if (smc->r.rm_loop)
			smc->r.loop_avail = TRUE ;
		if (smc->r.rm_join) {
			smc->r.sm_ma_avail = TRUE ;
			if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
			smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
				else
			smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
		}
		DB_RMTN(1,"RMT : RING UP\n",0,0) ;
		RS_CLEAR(smc,RS_NORINGOP) ;
		RS_SET(smc,RS_RINGOPCHANGE) ;
		rmt_indication(smc,1) ;
		smt_stat_counter(smc,0) ;
		ACTIONS_DONE() ;
		break ;
	case RM2_RING_OP :
		/*RM21*/
		if (cmd == RM_RING_NON_OP) {
			smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
			smc->r.loop_avail = FALSE ;
			RS_SET(smc,RS_RINGOPCHANGE) ;
			GO_STATE(RM1_NON_OP) ;
			break ;
		}
		/*RM22a*/
		else if (cmd == RM_ENABLE_FLAG) {
			if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
			smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
				else
			smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
		}
		/*RM25*/
		else if (smc->r.dup_addr_test == DA_FAILED) {
			smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
			smc->r.loop_avail = FALSE ;
			smc->r.da_flag = TRUE ;
			GO_STATE(RM5_RING_OP_DUP) ;
			break ;
		}
		break ;
	case ACTIONS(RM3_DETECT) :
		start_rmt_timer0(smc,smc->s.mac_d_max*2,RM_TIMEOUT_D_MAX) ;
		start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
		start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
		sm_mac_check_beacon_claim(smc) ;
		DB_RMTN(1,"RMT : RM3_DETECT\n",0,0) ;
		ACTIONS_DONE() ;
		break ;
	case RM3_DETECT :
		if (cmd == RM_TIMEOUT_POLL) {
			start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
			sm_mac_check_beacon_claim(smc) ;
			break ;
		}
		if (cmd == RM_TIMEOUT_D_MAX) {
			smc->r.timer0_exp = TRUE ;
		}
		/*
		 *jd(22-Feb-1999)
		 * We need a time ">= 2*mac_d_max" since we had finished
		 * Claim or Beacon state. So we will restart timer0 at
		 * every state change.
		 */
		if (cmd == RM_TX_STATE_CHANGE) {
			start_rmt_timer0(smc,
					 smc->s.mac_d_max*2,
					 RM_TIMEOUT_D_MAX) ;
		}
		/*RM32*/
		if (cmd == RM_RING_OP) {
			GO_STATE(RM2_RING_OP) ;
			break ;
		}
		/*RM33a*/
		else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON)
			&& smc->r.bn_flag) {
			smc->r.bn_flag = FALSE ;
		}
		/*RM33b*/
		else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
			int	tx ;
			/*
			 * set bn_flag only if in state T4 or T5:
			 * only if we're the beaconer should we start the
			 * trace !
			 */
			if ((tx =  sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
			DB_RMTN(2,"RMT : DETECT && TRT_EXPIRED && T4/T5\n",0,0);
				smc->r.bn_flag = TRUE ;
				/*
				 * If one of the upstream stations beaconed
				 * and the link to the upstream neighbor is
				 * lost we need to restart the stuck timer to
				 * check the "stuck beacon" condition.
				 */
				start_rmt_timer1(smc,smc->s.rmt_t_stuck,
					RM_TIMEOUT_T_STUCK) ;
			}
			/*
			 * We do NOT need to clear smc->r.bn_flag in case of
			 * not being in state T4 or T5, because the flag
			 * must be cleared in order to get in this condition.
			 */

			DB_RMTN(2,
			"RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)\n",
			tx,smc->r.bn_flag) ;
		}
		/*RM34a*/
		else if (cmd == RM_MY_CLAIM && smc->r.timer0_exp) {
			rmt_new_dup_actions(smc) ;
			GO_STATE(RM4_NON_OP_DUP) ;
			break ;
		}
		/*RM34b*/
		else if (cmd == RM_MY_BEACON && smc->r.timer0_exp) {
			rmt_new_dup_actions(smc) ;
			GO_STATE(RM4_NON_OP_DUP) ;
			break ;
		}
		/*RM34c*/
		else if (cmd == RM_VALID_CLAIM) {
			rmt_new_dup_actions(smc) ;
			GO_STATE(RM4_NON_OP_DUP) ;
			break ;
		}
		/*RM36*/
		else if (cmd == RM_TIMEOUT_T_STUCK &&
			smc->r.rm_join && smc->r.bn_flag) {
			GO_STATE(RM6_DIRECTED) ;
			break ;
		}
		break ;
	case ACTIONS(RM4_NON_OP_DUP) :
		start_rmt_timer0(smc,smc->s.rmt_t_announce,RM_TIMEOUT_ANNOUNCE);
		start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
		start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
		sm_mac_check_beacon_claim(smc) ;
		DB_RMTN(1,"RMT : RM4_NON_OP_DUP\n",0,0) ;
		ACTIONS_DONE() ;
		break ;
	case RM4_NON_OP_DUP :
		if (cmd == RM_TIMEOUT_POLL) {
			start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
			sm_mac_check_beacon_claim(smc) ;
			break ;
		}
		/*RM41*/
		if (!smc->r.da_flag) {
			GO_STATE(RM1_NON_OP) ;
			break ;
		}
		/*RM44a*/
		else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
			smc->r.bn_flag) {
			smc->r.bn_flag = FALSE ;
		}
		/*RM44b*/
		else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
			int	tx ;
			/*
			 * set bn_flag only if in state T4 or T5:
			 * only if we're the beaconer should we start the
			 * trace !
			 */
			if ((tx =  sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
			DB_RMTN(2,"RMT : NOPDUP && TRT_EXPIRED && T4/T5\n",0,0);
				smc->r.bn_flag = TRUE ;
				/*
				 * If one of the upstream stations beaconed
				 * and the link to the upstream neighbor is
				 * lost we need to restart the stuck timer to
				 * check the "stuck beacon" condition.
				 */
				start_rmt_timer1(smc,smc->s.rmt_t_stuck,
					RM_TIMEOUT_T_STUCK) ;
			}
			/*
			 * We do NOT need to clear smc->r.bn_flag in case of
			 * not being in state T4 or T5, because the flag
			 * must be cleared in order to get in this condition.
			 */

			DB_RMTN(2,
			"RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)\n",
			tx,smc->r.bn_flag) ;
		}
		/*RM44c*/
		else if (cmd == RM_TIMEOUT_ANNOUNCE && !smc->r.bn_flag) {
			rmt_dup_actions(smc) ;
		}
		/*RM45*/
		else if (cmd == RM_RING_OP) {
			smc->r.no_flag = FALSE ;
			GO_STATE(RM5_RING_OP_DUP) ;
			break ;
		}
		/*RM46*/
		else if (cmd == RM_TIMEOUT_T_STUCK &&
			smc->r.rm_join && smc->r.bn_flag) {
			GO_STATE(RM6_DIRECTED) ;
			break ;
		}
		break ;
	case ACTIONS(RM5_RING_OP_DUP) :
		stop_rmt_timer0(smc) ;
		stop_rmt_timer1(smc) ;
		stop_rmt_timer2(smc) ;
		DB_RMTN(1,"RMT : RM5_RING_OP_DUP\n",0,0) ;
		ACTIONS_DONE() ;
		break;
	case RM5_RING_OP_DUP :
		/*RM52*/
		if (smc->r.dup_addr_test == DA_PASSED) {
			smc->r.da_flag = FALSE ;
			GO_STATE(RM2_RING_OP) ;
			break ;
		}
		/*RM54*/
		else if (cmd == RM_RING_NON_OP) {
			smc->r.jm_flag = FALSE ;
			smc->r.bn_flag = FALSE ;
			GO_STATE(RM4_NON_OP_DUP) ;
			break ;
		}
		break ;
	case ACTIONS(RM6_DIRECTED) :
		start_rmt_timer0(smc,smc->s.rmt_t_direct,RM_TIMEOUT_T_DIRECT) ;
		stop_rmt_timer1(smc) ;
		start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
		sm_ma_control(smc,MA_DIRECTED) ;
		RS_SET(smc,RS_BEACON) ;
		DB_RMTN(1,"RMT : RM6_DIRECTED\n",0,0) ;
		ACTIONS_DONE() ;
		break ;
	case RM6_DIRECTED :
		/*RM63*/
		if (cmd == RM_TIMEOUT_POLL) {
			start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
			sm_mac_check_beacon_claim(smc) ;
#ifndef SUPERNET_3
			/* Because of problems with the Supernet II chip set
			 * sending of Directed Beacon will stop after 165ms
			 * therefore restart_trt_for_dbcn(smc) will be called
			 * to prevent this.
			 */
			restart_trt_for_dbcn(smc) ;
#endif /*SUPERNET_3*/
			break ;
		}
		if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
			!smc->r.da_flag) {
			smc->r.bn_flag = FALSE ;
			GO_STATE(RM3_DETECT) ;
			break ;
		}
		/*RM64*/
		else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
			smc->r.da_flag) {
			smc->r.bn_flag = FALSE ;
			GO_STATE(RM4_NON_OP_DUP) ;
			break ;
		}
		/*RM67*/
		else if (cmd == RM_TIMEOUT_T_DIRECT) {
			GO_STATE(RM7_TRACE) ;
			break ;
		}
		break ;
	case ACTIONS(RM7_TRACE) :
		stop_rmt_timer0(smc) ;
		stop_rmt_timer1(smc) ;
		stop_rmt_timer2(smc) ;
		smc->e.trace_prop |= ENTITY_BIT(ENTITY_MAC) ;
		queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ;
		DB_RMTN(1,"RMT : RM7_TRACE\n",0,0) ;
		ACTIONS_DONE() ;
		break ;
	case RM7_TRACE :
		break ;
	default:
		SMT_PANIC(smc,SMT_E0122, SMT_E0122_MSG) ;
		break;
	}
}
Example #6
0
/*ARGSUSED1*/
static void cfm_fsm(struct s_smc *smc, int cmd)
{
	switch(smc->mib.fddiSMTCF_State) {
	case ACTIONS(SC0_ISOLATED) :
		smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
		smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
		smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
		smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
		smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_SEPA ;
		config_mux(smc,MUX_ISOLATE) ;	/* configure PHY Mux */
		smc->r.rm_loop = FALSE ;
		smc->r.rm_join = FALSE ;
		queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
		/* Don't do the WC-Flag changing here */
		ACTIONS_DONE() ;
		DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
		break;
	case SC0_ISOLATED :
		/*SC07*/
		/*SAS port can be PA or PB ! */
		if (smc->s.sas && (smc->y[PA].cf_join || smc->y[PA].cf_loop ||
				smc->y[PB].cf_join || smc->y[PB].cf_loop)) {
			GO_STATE(SC11_C_WRAP_S) ;
			break ;
		}
		/*SC01*/
		if ((smc->y[PA].cem_pst == CEM_PST_UP && smc->y[PA].cf_join &&
		     !smc->y[PA].wc_flag) || smc->y[PA].cf_loop) {
			GO_STATE(SC9_C_WRAP_A) ;
			break ;
		}
		/*SC02*/
		if ((smc->y[PB].cem_pst == CEM_PST_UP && smc->y[PB].cf_join &&
		     !smc->y[PB].wc_flag) || smc->y[PB].cf_loop) {
			GO_STATE(SC10_C_WRAP_B) ;
			break ;
		}
		break ;
	case ACTIONS(SC9_C_WRAP_A) :
		smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
		smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
		smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
		smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
		smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
		config_mux(smc,MUX_WRAPA) ;		/* configure PHY mux */
		if (smc->y[PA].cf_loop) {
			smc->r.rm_join = FALSE ;
			smc->r.rm_loop = TRUE ;
			queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
		}
		if (smc->y[PA].cf_join) {
			smc->r.rm_loop = FALSE ;
			smc->r.rm_join = TRUE ;
			queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
		}
		ACTIONS_DONE() ;
		DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
		break ;
	case SC9_C_WRAP_A :
		/*SC10*/
		if ( (smc->y[PA].wc_flag || !smc->y[PA].cf_join) &&
		      !smc->y[PA].cf_loop ) {
			GO_STATE(SC0_ISOLATED) ;
			break ;
		}
		/*SC12*/
		else if ( (smc->y[PB].cf_loop && smc->y[PA].cf_join &&
			   smc->y[PA].cem_pst == CEM_PST_UP) ||
			  ((smc->y[PB].cf_loop ||
			   (smc->y[PB].cf_join &&
			    smc->y[PB].cem_pst == CEM_PST_UP)) &&
			    (smc->y[PA].pc_mode == PM_TREE ||
			     smc->y[PB].pc_mode == PM_TREE))) {
			smc->y[PA].scrub = TRUE ;
			GO_STATE(SC10_C_WRAP_B) ;
			break ;
		}
		/*SC14*/
		else if (!smc->s.attach_s &&
			  smc->y[PA].cf_join &&
			  smc->y[PA].cem_pst == CEM_PST_UP &&
			  smc->y[PA].pc_mode == PM_PEER && smc->y[PB].cf_join &&
			  smc->y[PB].cem_pst == CEM_PST_UP &&
			  smc->y[PB].pc_mode == PM_PEER) {
			smc->y[PA].scrub = TRUE ;
			smc->y[PB].scrub = TRUE ;
			GO_STATE(SC4_THRU_A) ;
			break ;
		}
		/*SC15*/
		else if ( smc->s.attach_s &&
			  smc->y[PA].cf_join &&
			  smc->y[PA].cem_pst == CEM_PST_UP &&
			  smc->y[PA].pc_mode == PM_PEER &&
			  smc->y[PB].cf_join &&
			  smc->y[PB].cem_pst == CEM_PST_UP &&
			  smc->y[PB].pc_mode == PM_PEER) {
			smc->y[PA].scrub = TRUE ;
			smc->y[PB].scrub = TRUE ;
			GO_STATE(SC5_THRU_B) ;
			break ;
		}
		break ;
	case ACTIONS(SC10_C_WRAP_B) :
		smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
		smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
		smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
		smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
		smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
		config_mux(smc,MUX_WRAPB) ;		/* configure PHY mux */
		if (smc->y[PB].cf_loop) {
			smc->r.rm_join = FALSE ;
			smc->r.rm_loop = TRUE ;
			queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
		}
		if (smc->y[PB].cf_join) {
			smc->r.rm_loop = FALSE ;
			smc->r.rm_join = TRUE ;
			queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
		}
		ACTIONS_DONE() ;
		DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
		break ;
	case SC10_C_WRAP_B :
		/*SC20*/
		if ( !smc->y[PB].cf_join && !smc->y[PB].cf_loop ) {
			GO_STATE(SC0_ISOLATED) ;
			break ;
		}
		/*SC21*/
		else if ( smc->y[PA].cf_loop && smc->y[PA].pc_mode == PM_PEER &&
			  smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
			smc->y[PB].scrub = TRUE ;
			GO_STATE(SC9_C_WRAP_A) ;
			break ;
		}
		/*SC24*/
		else if (!smc->s.attach_s &&
			 smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
			 smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
			smc->y[PA].scrub = TRUE ;
			smc->y[PB].scrub = TRUE ;
			GO_STATE(SC4_THRU_A) ;
			break ;
		}
		/*SC25*/
		else if ( smc->s.attach_s &&
			 smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
			 smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
			smc->y[PA].scrub = TRUE ;
			smc->y[PB].scrub = TRUE ;
			GO_STATE(SC5_THRU_B) ;
			break ;
		}
		break ;
	case ACTIONS(SC4_THRU_A) :
		smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
		smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
		smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
		smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
		smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
		config_mux(smc,MUX_THRUA) ;		/* configure PHY mux */
		smc->r.rm_loop = FALSE ;
		smc->r.rm_join = TRUE ;
		queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
		ACTIONS_DONE() ;
		DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
		break ;
	case SC4_THRU_A :
		/*SC41*/
		if (smc->y[PB].wc_flag || !smc->y[PB].cf_join) {
			smc->y[PA].scrub = TRUE ;
			GO_STATE(SC9_C_WRAP_A) ;
			break ;
		}
		/*SC42*/
		else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
			smc->y[PB].scrub = TRUE ;
			GO_STATE(SC10_C_WRAP_B) ;
			break ;
		}
		/*SC45*/
		else if (smc->s.attach_s) {
			smc->y[PB].scrub = TRUE ;
			GO_STATE(SC5_THRU_B) ;
			break ;
		}
		break ;
	case ACTIONS(SC5_THRU_B) :
		smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
		smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
		smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
		smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
		smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
		config_mux(smc,MUX_THRUB) ;		/* configure PHY mux */
		smc->r.rm_loop = FALSE ;
		smc->r.rm_join = TRUE ;
		queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
		ACTIONS_DONE() ;
		DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
		break ;
	case SC5_THRU_B :
		/*SC51*/
		if (!smc->y[PB].cf_join || smc->y[PB].wc_flag) {
			smc->y[PA].scrub = TRUE ;
			GO_STATE(SC9_C_WRAP_A) ;
			break ;
		}
		/*SC52*/
		else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
			smc->y[PB].scrub = TRUE ;
			GO_STATE(SC10_C_WRAP_B) ;
			break ;
		}
		/*SC54*/
		else if (!smc->s.attach_s) {
			smc->y[PA].scrub = TRUE ;
			GO_STATE(SC4_THRU_A) ;
			break ;
		}
		break ;
	case ACTIONS(SC11_C_WRAP_S) :
		smc->mib.p[PS].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
		smc->mib.p[PS].fddiPORTMACPlacement = INDEX_MAC ;
		smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
		config_mux(smc,MUX_WRAPS) ;		/* configure PHY mux */
		if (smc->y[PA].cf_loop || smc->y[PB].cf_loop) {
			smc->r.rm_join = FALSE ;
			smc->r.rm_loop = TRUE ;
			queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
		}
		if (smc->y[PA].cf_join || smc->y[PB].cf_join) {
			smc->r.rm_loop = FALSE ;
			smc->r.rm_join = TRUE ;
			queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
		}
		ACTIONS_DONE() ;
		DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
		break ;
	case SC11_C_WRAP_S :
		/*SC70*/
		if ( !smc->y[PA].cf_join && !smc->y[PA].cf_loop &&
		     !smc->y[PB].cf_join && !smc->y[PB].cf_loop) {
			GO_STATE(SC0_ISOLATED) ;
			break ;
		}
		break ;
	default:
		SMT_PANIC(smc,SMT_E0106, SMT_E0106_MSG) ;
		break;
	}
}