12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
233f810b2SJeff Kirsher /******************************************************************************
333f810b2SJeff Kirsher *
433f810b2SJeff Kirsher * (C)Copyright 1998,1999 SysKonnect,
533f810b2SJeff Kirsher * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
633f810b2SJeff Kirsher *
733f810b2SJeff Kirsher * See the file "skfddi.c" for further information.
833f810b2SJeff Kirsher *
933f810b2SJeff Kirsher * The information in this file is provided "AS IS" without warranty.
1033f810b2SJeff Kirsher *
1133f810b2SJeff Kirsher ******************************************************************************/
1233f810b2SJeff Kirsher
1333f810b2SJeff Kirsher /*
1433f810b2SJeff Kirsher SMT ECM
1533f810b2SJeff Kirsher Entity Coordination Management
1633f810b2SJeff Kirsher Hardware independent state machine
1733f810b2SJeff Kirsher */
1833f810b2SJeff Kirsher
1933f810b2SJeff Kirsher /*
2033f810b2SJeff Kirsher * Hardware independent state machine implemantation
2133f810b2SJeff Kirsher * The following external SMT functions are referenced :
2233f810b2SJeff Kirsher *
2333f810b2SJeff Kirsher * queue_event()
2433f810b2SJeff Kirsher * smt_timer_start()
2533f810b2SJeff Kirsher * smt_timer_stop()
2633f810b2SJeff Kirsher *
2733f810b2SJeff Kirsher * The following external HW dependent functions are referenced :
2833f810b2SJeff Kirsher * sm_pm_bypass_req()
2933f810b2SJeff Kirsher * sm_pm_get_ls()
3033f810b2SJeff Kirsher *
3133f810b2SJeff Kirsher * The following HW dependent events are required :
3233f810b2SJeff Kirsher * NONE
3333f810b2SJeff Kirsher *
3433f810b2SJeff Kirsher */
3533f810b2SJeff Kirsher
3633f810b2SJeff Kirsher #include "h/types.h"
3733f810b2SJeff Kirsher #include "h/fddi.h"
3833f810b2SJeff Kirsher #include "h/smc.h"
3933f810b2SJeff Kirsher
4033f810b2SJeff Kirsher #define KERNEL
4133f810b2SJeff Kirsher #include "h/smtstate.h"
4233f810b2SJeff Kirsher
4333f810b2SJeff Kirsher /*
4433f810b2SJeff Kirsher * FSM Macros
4533f810b2SJeff Kirsher */
4633f810b2SJeff Kirsher #define AFLAG 0x10
4733f810b2SJeff Kirsher #define GO_STATE(x) (smc->mib.fddiSMTECMState = (x)|AFLAG)
4833f810b2SJeff Kirsher #define ACTIONS_DONE() (smc->mib.fddiSMTECMState &= ~AFLAG)
4933f810b2SJeff Kirsher #define ACTIONS(x) (x|AFLAG)
5033f810b2SJeff Kirsher
5133f810b2SJeff Kirsher #define EC0_OUT 0 /* not inserted */
5233f810b2SJeff Kirsher #define EC1_IN 1 /* inserted */
5333f810b2SJeff Kirsher #define EC2_TRACE 2 /* tracing */
5433f810b2SJeff Kirsher #define EC3_LEAVE 3 /* leaving the ring */
5533f810b2SJeff Kirsher #define EC4_PATH_TEST 4 /* performing path test */
5633f810b2SJeff Kirsher #define EC5_INSERT 5 /* bypass being turned on */
5733f810b2SJeff Kirsher #define EC6_CHECK 6 /* checking bypass */
5833f810b2SJeff Kirsher #define EC7_DEINSERT 7 /* bypass being turnde off */
5933f810b2SJeff Kirsher
6033f810b2SJeff Kirsher /*
6133f810b2SJeff Kirsher * symbolic state names
6233f810b2SJeff Kirsher */
6333f810b2SJeff Kirsher static const char * const ecm_states[] = {
6433f810b2SJeff Kirsher "EC0_OUT","EC1_IN","EC2_TRACE","EC3_LEAVE","EC4_PATH_TEST",
6533f810b2SJeff Kirsher "EC5_INSERT","EC6_CHECK","EC7_DEINSERT"
6633f810b2SJeff Kirsher } ;
6733f810b2SJeff Kirsher
6833f810b2SJeff Kirsher /*
6933f810b2SJeff Kirsher * symbolic event names
7033f810b2SJeff Kirsher */
7133f810b2SJeff Kirsher static const char * const ecm_events[] = {
7233f810b2SJeff Kirsher "NONE","EC_CONNECT","EC_DISCONNECT","EC_TRACE_PROP","EC_PATH_TEST",
7333f810b2SJeff Kirsher "EC_TIMEOUT_TD","EC_TIMEOUT_TMAX",
7433f810b2SJeff Kirsher "EC_TIMEOUT_IMAX","EC_TIMEOUT_INMAX","EC_TEST_DONE"
7533f810b2SJeff Kirsher } ;
7633f810b2SJeff Kirsher
7733f810b2SJeff Kirsher /*
7833f810b2SJeff Kirsher * all Globals are defined in smc.h
7933f810b2SJeff Kirsher * struct s_ecm
8033f810b2SJeff Kirsher */
8133f810b2SJeff Kirsher
8233f810b2SJeff Kirsher /*
8333f810b2SJeff Kirsher * function declarations
8433f810b2SJeff Kirsher */
8533f810b2SJeff Kirsher
8633f810b2SJeff Kirsher static void ecm_fsm(struct s_smc *smc, int cmd);
8733f810b2SJeff Kirsher static void start_ecm_timer(struct s_smc *smc, u_long value, int event);
8833f810b2SJeff Kirsher static void stop_ecm_timer(struct s_smc *smc);
8933f810b2SJeff Kirsher static void prop_actions(struct s_smc *smc);
9033f810b2SJeff Kirsher
9133f810b2SJeff Kirsher /*
9233f810b2SJeff Kirsher init ECM state machine
9333f810b2SJeff Kirsher clear all ECM vars and flags
9433f810b2SJeff Kirsher */
ecm_init(struct s_smc * smc)9533f810b2SJeff Kirsher void ecm_init(struct s_smc *smc)
9633f810b2SJeff Kirsher {
9733f810b2SJeff Kirsher smc->e.path_test = PT_PASSED ;
9833f810b2SJeff Kirsher smc->e.trace_prop = 0 ;
9933f810b2SJeff Kirsher smc->e.sb_flag = 0 ;
10033f810b2SJeff Kirsher smc->mib.fddiSMTECMState = ACTIONS(EC0_OUT) ;
10133f810b2SJeff Kirsher smc->e.ecm_line_state = FALSE ;
10233f810b2SJeff Kirsher }
10333f810b2SJeff Kirsher
10433f810b2SJeff Kirsher /*
10533f810b2SJeff Kirsher ECM state machine
10633f810b2SJeff Kirsher called by dispatcher
10733f810b2SJeff Kirsher
10833f810b2SJeff Kirsher do
10933f810b2SJeff Kirsher display state change
11033f810b2SJeff Kirsher process event
11133f810b2SJeff Kirsher until SM is stable
11233f810b2SJeff Kirsher */
ecm(struct s_smc * smc,int event)11333f810b2SJeff Kirsher void ecm(struct s_smc *smc, int event)
11433f810b2SJeff Kirsher {
11533f810b2SJeff Kirsher int state ;
11633f810b2SJeff Kirsher
11733f810b2SJeff Kirsher do {
1185671e8c1SJoe Perches DB_ECM("ECM : state %s%s event %s",
1195671e8c1SJoe Perches smc->mib.fddiSMTECMState & AFLAG ? "ACTIONS " : "",
1205671e8c1SJoe Perches ecm_states[smc->mib.fddiSMTECMState & ~AFLAG],
1215671e8c1SJoe Perches ecm_events[event]);
12233f810b2SJeff Kirsher state = smc->mib.fddiSMTECMState ;
12333f810b2SJeff Kirsher ecm_fsm(smc,event) ;
12433f810b2SJeff Kirsher event = 0 ;
12533f810b2SJeff Kirsher } while (state != smc->mib.fddiSMTECMState) ;
12633f810b2SJeff Kirsher ecm_state_change(smc,(int)smc->mib.fddiSMTECMState) ;
12733f810b2SJeff Kirsher }
12833f810b2SJeff Kirsher
12933f810b2SJeff Kirsher /*
13033f810b2SJeff Kirsher process ECM event
13133f810b2SJeff Kirsher */
ecm_fsm(struct s_smc * smc,int cmd)13233f810b2SJeff Kirsher static void ecm_fsm(struct s_smc *smc, int cmd)
13333f810b2SJeff Kirsher {
13433f810b2SJeff Kirsher int ls_a ; /* current line state PHY A */
13533f810b2SJeff Kirsher int ls_b ; /* current line state PHY B */
13633f810b2SJeff Kirsher int p ; /* ports */
13733f810b2SJeff Kirsher
13833f810b2SJeff Kirsher
13933f810b2SJeff Kirsher smc->mib.fddiSMTBypassPresent = sm_pm_bypass_present(smc) ;
14033f810b2SJeff Kirsher if (cmd == EC_CONNECT)
14133f810b2SJeff Kirsher smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ;
14233f810b2SJeff Kirsher
14333f810b2SJeff Kirsher /* For AIX event notification: */
14433f810b2SJeff Kirsher /* Is a disconnect command remotely issued ? */
14533f810b2SJeff Kirsher if (cmd == EC_DISCONNECT &&
146*918895bfSLee Jones smc->mib.fddiSMTRemoteDisconnectFlag == TRUE) {
14733f810b2SJeff Kirsher AIX_EVENT (smc, (u_long) CIO_HARD_FAIL, (u_long)
14833f810b2SJeff Kirsher FDDI_REMOTE_DISCONNECT, smt_get_event_word(smc),
14933f810b2SJeff Kirsher smt_get_error_word(smc) );
150*918895bfSLee Jones }
15133f810b2SJeff Kirsher
15233f810b2SJeff Kirsher /*jd 05-Aug-1999 Bug #10419 "Port Disconnect fails at Dup MAc Cond."*/
15333f810b2SJeff Kirsher if (cmd == EC_CONNECT) {
15433f810b2SJeff Kirsher smc->e.DisconnectFlag = FALSE ;
15533f810b2SJeff Kirsher }
15633f810b2SJeff Kirsher else if (cmd == EC_DISCONNECT) {
15733f810b2SJeff Kirsher smc->e.DisconnectFlag = TRUE ;
15833f810b2SJeff Kirsher }
15933f810b2SJeff Kirsher
16033f810b2SJeff Kirsher switch(smc->mib.fddiSMTECMState) {
16133f810b2SJeff Kirsher case ACTIONS(EC0_OUT) :
16233f810b2SJeff Kirsher /*
16333f810b2SJeff Kirsher * We do not perform a path test
16433f810b2SJeff Kirsher */
16533f810b2SJeff Kirsher smc->e.path_test = PT_PASSED ;
16633f810b2SJeff Kirsher smc->e.ecm_line_state = FALSE ;
16733f810b2SJeff Kirsher stop_ecm_timer(smc) ;
16833f810b2SJeff Kirsher ACTIONS_DONE() ;
16933f810b2SJeff Kirsher break ;
17033f810b2SJeff Kirsher case EC0_OUT:
17133f810b2SJeff Kirsher /*EC01*/
17233f810b2SJeff Kirsher if (cmd == EC_CONNECT && !smc->mib.fddiSMTBypassPresent
17333f810b2SJeff Kirsher && smc->e.path_test==PT_PASSED) {
17433f810b2SJeff Kirsher GO_STATE(EC1_IN) ;
17533f810b2SJeff Kirsher break ;
17633f810b2SJeff Kirsher }
17733f810b2SJeff Kirsher /*EC05*/
17833f810b2SJeff Kirsher else if (cmd == EC_CONNECT && (smc->e.path_test==PT_PASSED) &&
17933f810b2SJeff Kirsher smc->mib.fddiSMTBypassPresent &&
18033f810b2SJeff Kirsher (smc->s.sas == SMT_DAS)) {
18133f810b2SJeff Kirsher GO_STATE(EC5_INSERT) ;
18233f810b2SJeff Kirsher break ;
18333f810b2SJeff Kirsher }
18433f810b2SJeff Kirsher break;
18533f810b2SJeff Kirsher case ACTIONS(EC1_IN) :
18633f810b2SJeff Kirsher stop_ecm_timer(smc) ;
18733f810b2SJeff Kirsher smc->e.trace_prop = 0 ;
18833f810b2SJeff Kirsher sm_ma_control(smc,MA_TREQ) ;
18933f810b2SJeff Kirsher for (p = 0 ; p < NUMPHYS ; p++)
19033f810b2SJeff Kirsher if (smc->mib.p[p].fddiPORTHardwarePresent)
19133f810b2SJeff Kirsher queue_event(smc,EVENT_PCMA+p,PC_START) ;
19233f810b2SJeff Kirsher ACTIONS_DONE() ;
19333f810b2SJeff Kirsher break ;
19433f810b2SJeff Kirsher case EC1_IN:
19533f810b2SJeff Kirsher /*EC12*/
19633f810b2SJeff Kirsher if (cmd == EC_TRACE_PROP) {
19733f810b2SJeff Kirsher prop_actions(smc) ;
19833f810b2SJeff Kirsher GO_STATE(EC2_TRACE) ;
19933f810b2SJeff Kirsher break ;
20033f810b2SJeff Kirsher }
20133f810b2SJeff Kirsher /*EC13*/
20233f810b2SJeff Kirsher else if (cmd == EC_DISCONNECT) {
20333f810b2SJeff Kirsher GO_STATE(EC3_LEAVE) ;
20433f810b2SJeff Kirsher break ;
20533f810b2SJeff Kirsher }
20633f810b2SJeff Kirsher break;
20733f810b2SJeff Kirsher case ACTIONS(EC2_TRACE) :
20833f810b2SJeff Kirsher start_ecm_timer(smc,MIB2US(smc->mib.fddiSMTTrace_MaxExpiration),
20933f810b2SJeff Kirsher EC_TIMEOUT_TMAX) ;
21033f810b2SJeff Kirsher ACTIONS_DONE() ;
21133f810b2SJeff Kirsher break ;
21233f810b2SJeff Kirsher case EC2_TRACE :
21333f810b2SJeff Kirsher /*EC22*/
21433f810b2SJeff Kirsher if (cmd == EC_TRACE_PROP) {
21533f810b2SJeff Kirsher prop_actions(smc) ;
21633f810b2SJeff Kirsher GO_STATE(EC2_TRACE) ;
21733f810b2SJeff Kirsher break ;
21833f810b2SJeff Kirsher }
21933f810b2SJeff Kirsher /*EC23a*/
22033f810b2SJeff Kirsher else if (cmd == EC_DISCONNECT) {
22133f810b2SJeff Kirsher smc->e.path_test = PT_EXITING ;
22233f810b2SJeff Kirsher GO_STATE(EC3_LEAVE) ;
22333f810b2SJeff Kirsher break ;
22433f810b2SJeff Kirsher }
22533f810b2SJeff Kirsher /*EC23b*/
22633f810b2SJeff Kirsher else if (smc->e.path_test == PT_PENDING) {
22733f810b2SJeff Kirsher GO_STATE(EC3_LEAVE) ;
22833f810b2SJeff Kirsher break ;
22933f810b2SJeff Kirsher }
23033f810b2SJeff Kirsher /*EC23c*/
23133f810b2SJeff Kirsher else if (cmd == EC_TIMEOUT_TMAX) {
23233f810b2SJeff Kirsher /* Trace_Max is expired */
23333f810b2SJeff Kirsher /* -> send AIX_EVENT */
23433f810b2SJeff Kirsher AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
23533f810b2SJeff Kirsher (u_long) FDDI_SMT_ERROR, (u_long)
23633f810b2SJeff Kirsher FDDI_TRACE_MAX, smt_get_error_word(smc));
23733f810b2SJeff Kirsher smc->e.path_test = PT_PENDING ;
23833f810b2SJeff Kirsher GO_STATE(EC3_LEAVE) ;
23933f810b2SJeff Kirsher break ;
24033f810b2SJeff Kirsher }
24133f810b2SJeff Kirsher break ;
24233f810b2SJeff Kirsher case ACTIONS(EC3_LEAVE) :
24333f810b2SJeff Kirsher start_ecm_timer(smc,smc->s.ecm_td_min,EC_TIMEOUT_TD) ;
24433f810b2SJeff Kirsher for (p = 0 ; p < NUMPHYS ; p++)
24533f810b2SJeff Kirsher queue_event(smc,EVENT_PCMA+p,PC_STOP) ;
24633f810b2SJeff Kirsher ACTIONS_DONE() ;
24733f810b2SJeff Kirsher break ;
24833f810b2SJeff Kirsher case EC3_LEAVE:
24933f810b2SJeff Kirsher /*EC30*/
25033f810b2SJeff Kirsher if (cmd == EC_TIMEOUT_TD && !smc->mib.fddiSMTBypassPresent &&
25133f810b2SJeff Kirsher (smc->e.path_test != PT_PENDING)) {
25233f810b2SJeff Kirsher GO_STATE(EC0_OUT) ;
25333f810b2SJeff Kirsher break ;
25433f810b2SJeff Kirsher }
25533f810b2SJeff Kirsher /*EC34*/
25633f810b2SJeff Kirsher else if (cmd == EC_TIMEOUT_TD &&
25733f810b2SJeff Kirsher (smc->e.path_test == PT_PENDING)) {
25833f810b2SJeff Kirsher GO_STATE(EC4_PATH_TEST) ;
25933f810b2SJeff Kirsher break ;
26033f810b2SJeff Kirsher }
26133f810b2SJeff Kirsher /*EC31*/
26233f810b2SJeff Kirsher else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
26333f810b2SJeff Kirsher GO_STATE(EC1_IN) ;
26433f810b2SJeff Kirsher break ;
26533f810b2SJeff Kirsher }
26633f810b2SJeff Kirsher /*EC33*/
26733f810b2SJeff Kirsher else if (cmd == EC_DISCONNECT &&
26833f810b2SJeff Kirsher smc->e.path_test == PT_PENDING) {
26933f810b2SJeff Kirsher smc->e.path_test = PT_EXITING ;
27033f810b2SJeff Kirsher /*
27133f810b2SJeff Kirsher * stay in state - state will be left via timeout
27233f810b2SJeff Kirsher */
27333f810b2SJeff Kirsher }
27433f810b2SJeff Kirsher /*EC37*/
27533f810b2SJeff Kirsher else if (cmd == EC_TIMEOUT_TD &&
27633f810b2SJeff Kirsher smc->mib.fddiSMTBypassPresent &&
27733f810b2SJeff Kirsher smc->e.path_test != PT_PENDING) {
27833f810b2SJeff Kirsher GO_STATE(EC7_DEINSERT) ;
27933f810b2SJeff Kirsher break ;
28033f810b2SJeff Kirsher }
28133f810b2SJeff Kirsher break ;
28233f810b2SJeff Kirsher case ACTIONS(EC4_PATH_TEST) :
28333f810b2SJeff Kirsher stop_ecm_timer(smc) ;
28433f810b2SJeff Kirsher smc->e.path_test = PT_TESTING ;
28533f810b2SJeff Kirsher start_ecm_timer(smc,smc->s.ecm_test_done,EC_TEST_DONE) ;
28633f810b2SJeff Kirsher /* now perform path test ... just a simulation */
28733f810b2SJeff Kirsher ACTIONS_DONE() ;
28833f810b2SJeff Kirsher break ;
28933f810b2SJeff Kirsher case EC4_PATH_TEST :
29033f810b2SJeff Kirsher /* path test done delay */
29133f810b2SJeff Kirsher if (cmd == EC_TEST_DONE)
29233f810b2SJeff Kirsher smc->e.path_test = PT_PASSED ;
29333f810b2SJeff Kirsher
29433f810b2SJeff Kirsher if (smc->e.path_test == PT_FAILED)
29533f810b2SJeff Kirsher RS_SET(smc,RS_PATHTEST) ;
29633f810b2SJeff Kirsher
29733f810b2SJeff Kirsher /*EC40a*/
29833f810b2SJeff Kirsher if (smc->e.path_test == PT_FAILED &&
29933f810b2SJeff Kirsher !smc->mib.fddiSMTBypassPresent) {
30033f810b2SJeff Kirsher GO_STATE(EC0_OUT) ;
30133f810b2SJeff Kirsher break ;
30233f810b2SJeff Kirsher }
30333f810b2SJeff Kirsher /*EC40b*/
30433f810b2SJeff Kirsher else if (cmd == EC_DISCONNECT &&
30533f810b2SJeff Kirsher !smc->mib.fddiSMTBypassPresent) {
30633f810b2SJeff Kirsher GO_STATE(EC0_OUT) ;
30733f810b2SJeff Kirsher break ;
30833f810b2SJeff Kirsher }
30933f810b2SJeff Kirsher /*EC41*/
31033f810b2SJeff Kirsher else if (smc->e.path_test == PT_PASSED) {
31133f810b2SJeff Kirsher GO_STATE(EC1_IN) ;
31233f810b2SJeff Kirsher break ;
31333f810b2SJeff Kirsher }
31433f810b2SJeff Kirsher /*EC47a*/
31533f810b2SJeff Kirsher else if (smc->e.path_test == PT_FAILED &&
31633f810b2SJeff Kirsher smc->mib.fddiSMTBypassPresent) {
31733f810b2SJeff Kirsher GO_STATE(EC7_DEINSERT) ;
31833f810b2SJeff Kirsher break ;
31933f810b2SJeff Kirsher }
32033f810b2SJeff Kirsher /*EC47b*/
32133f810b2SJeff Kirsher else if (cmd == EC_DISCONNECT &&
32233f810b2SJeff Kirsher smc->mib.fddiSMTBypassPresent) {
32333f810b2SJeff Kirsher GO_STATE(EC7_DEINSERT) ;
32433f810b2SJeff Kirsher break ;
32533f810b2SJeff Kirsher }
32633f810b2SJeff Kirsher break ;
32733f810b2SJeff Kirsher case ACTIONS(EC5_INSERT) :
32833f810b2SJeff Kirsher sm_pm_bypass_req(smc,BP_INSERT);
32933f810b2SJeff Kirsher start_ecm_timer(smc,smc->s.ecm_in_max,EC_TIMEOUT_INMAX) ;
33033f810b2SJeff Kirsher ACTIONS_DONE() ;
33133f810b2SJeff Kirsher break ;
33233f810b2SJeff Kirsher case EC5_INSERT :
33333f810b2SJeff Kirsher /*EC56*/
33433f810b2SJeff Kirsher if (cmd == EC_TIMEOUT_INMAX) {
33533f810b2SJeff Kirsher GO_STATE(EC6_CHECK) ;
33633f810b2SJeff Kirsher break ;
33733f810b2SJeff Kirsher }
33833f810b2SJeff Kirsher /*EC57*/
33933f810b2SJeff Kirsher else if (cmd == EC_DISCONNECT) {
34033f810b2SJeff Kirsher GO_STATE(EC7_DEINSERT) ;
34133f810b2SJeff Kirsher break ;
34233f810b2SJeff Kirsher }
34333f810b2SJeff Kirsher break ;
34433f810b2SJeff Kirsher case ACTIONS(EC6_CHECK) :
34533f810b2SJeff Kirsher /*
34633f810b2SJeff Kirsher * in EC6_CHECK, we *POLL* the line state !
34733f810b2SJeff Kirsher * check whether both bypass switches have switched.
34833f810b2SJeff Kirsher */
34933f810b2SJeff Kirsher start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
35033f810b2SJeff Kirsher smc->e.ecm_line_state = TRUE ; /* flag to pcm: report Q/HLS */
35133f810b2SJeff Kirsher ACTIONS_DONE() ;
35233f810b2SJeff Kirsher break ;
35333f810b2SJeff Kirsher case EC6_CHECK :
35433f810b2SJeff Kirsher ls_a = sm_pm_get_ls(smc,PA) ;
35533f810b2SJeff Kirsher ls_b = sm_pm_get_ls(smc,PB) ;
35633f810b2SJeff Kirsher
35733f810b2SJeff Kirsher /*EC61*/
35833f810b2SJeff Kirsher if (((ls_a == PC_QLS) || (ls_a == PC_HLS)) &&
35933f810b2SJeff Kirsher ((ls_b == PC_QLS) || (ls_b == PC_HLS)) ) {
36033f810b2SJeff Kirsher smc->e.sb_flag = FALSE ;
36133f810b2SJeff Kirsher smc->e.ecm_line_state = FALSE ;
36233f810b2SJeff Kirsher GO_STATE(EC1_IN) ;
36333f810b2SJeff Kirsher break ;
36433f810b2SJeff Kirsher }
36533f810b2SJeff Kirsher /*EC66*/
36633f810b2SJeff Kirsher else if (!smc->e.sb_flag &&
36733f810b2SJeff Kirsher (((ls_a == PC_ILS) && (ls_b == PC_QLS)) ||
36833f810b2SJeff Kirsher ((ls_a == PC_QLS) && (ls_b == PC_ILS)))){
36933f810b2SJeff Kirsher smc->e.sb_flag = TRUE ;
3705671e8c1SJoe Perches DB_ECMN(1, "ECM : EC6_CHECK - stuck bypass");
37133f810b2SJeff Kirsher AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
37233f810b2SJeff Kirsher FDDI_SMT_ERROR, (u_long) FDDI_BYPASS_STUCK,
37333f810b2SJeff Kirsher smt_get_error_word(smc));
37433f810b2SJeff Kirsher }
37533f810b2SJeff Kirsher /*EC67*/
37633f810b2SJeff Kirsher else if (cmd == EC_DISCONNECT) {
37733f810b2SJeff Kirsher smc->e.ecm_line_state = FALSE ;
37833f810b2SJeff Kirsher GO_STATE(EC7_DEINSERT) ;
37933f810b2SJeff Kirsher break ;
38033f810b2SJeff Kirsher }
38133f810b2SJeff Kirsher else {
38233f810b2SJeff Kirsher /*
38333f810b2SJeff Kirsher * restart poll
38433f810b2SJeff Kirsher */
38533f810b2SJeff Kirsher start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
38633f810b2SJeff Kirsher }
38733f810b2SJeff Kirsher break ;
38833f810b2SJeff Kirsher case ACTIONS(EC7_DEINSERT) :
38933f810b2SJeff Kirsher sm_pm_bypass_req(smc,BP_DEINSERT);
39033f810b2SJeff Kirsher start_ecm_timer(smc,smc->s.ecm_i_max,EC_TIMEOUT_IMAX) ;
39133f810b2SJeff Kirsher ACTIONS_DONE() ;
39233f810b2SJeff Kirsher break ;
39333f810b2SJeff Kirsher case EC7_DEINSERT:
39433f810b2SJeff Kirsher /*EC70*/
39533f810b2SJeff Kirsher if (cmd == EC_TIMEOUT_IMAX) {
39633f810b2SJeff Kirsher GO_STATE(EC0_OUT) ;
39733f810b2SJeff Kirsher break ;
39833f810b2SJeff Kirsher }
39933f810b2SJeff Kirsher /*EC75*/
40033f810b2SJeff Kirsher else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
40133f810b2SJeff Kirsher GO_STATE(EC5_INSERT) ;
40233f810b2SJeff Kirsher break ;
40333f810b2SJeff Kirsher }
40433f810b2SJeff Kirsher break;
40533f810b2SJeff Kirsher default:
40633f810b2SJeff Kirsher SMT_PANIC(smc,SMT_E0107, SMT_E0107_MSG) ;
40733f810b2SJeff Kirsher break;
40833f810b2SJeff Kirsher }
40933f810b2SJeff Kirsher }
41033f810b2SJeff Kirsher
41133f810b2SJeff Kirsher #ifndef CONCENTRATOR
41233f810b2SJeff Kirsher /*
41333f810b2SJeff Kirsher * trace propagation actions for SAS & DAS
41433f810b2SJeff Kirsher */
prop_actions(struct s_smc * smc)41533f810b2SJeff Kirsher static void prop_actions(struct s_smc *smc)
41633f810b2SJeff Kirsher {
41733f810b2SJeff Kirsher int port_in = 0 ;
41833f810b2SJeff Kirsher int port_out = 0 ;
41933f810b2SJeff Kirsher
42033f810b2SJeff Kirsher RS_SET(smc,RS_EVENT) ;
42133f810b2SJeff Kirsher switch (smc->s.sas) {
42233f810b2SJeff Kirsher case SMT_SAS :
42333f810b2SJeff Kirsher port_in = port_out = pcm_get_s_port(smc) ;
42433f810b2SJeff Kirsher break ;
42533f810b2SJeff Kirsher case SMT_DAS :
42633f810b2SJeff Kirsher port_in = cfm_get_mac_input(smc) ; /* PA or PB */
42733f810b2SJeff Kirsher port_out = cfm_get_mac_output(smc) ; /* PA or PB */
42833f810b2SJeff Kirsher break ;
42933f810b2SJeff Kirsher case SMT_NAC :
43033f810b2SJeff Kirsher SMT_PANIC(smc,SMT_E0108, SMT_E0108_MSG) ;
43133f810b2SJeff Kirsher return ;
43233f810b2SJeff Kirsher }
43333f810b2SJeff Kirsher
4345671e8c1SJoe Perches DB_ECM("ECM : prop_actions - trace_prop %lu", smc->e.trace_prop);
4355671e8c1SJoe Perches DB_ECM("ECM : prop_actions - in %d out %d", port_in, port_out);
43633f810b2SJeff Kirsher
43733f810b2SJeff Kirsher if (smc->e.trace_prop & ENTITY_BIT(ENTITY_MAC)) {
43833f810b2SJeff Kirsher /* trace initiatior */
4395671e8c1SJoe Perches DB_ECM("ECM : initiate TRACE on PHY %c", 'A' + port_in - PA);
44033f810b2SJeff Kirsher queue_event(smc,EVENT_PCM+port_in,PC_TRACE) ;
44133f810b2SJeff Kirsher }
44233f810b2SJeff Kirsher else if ((smc->e.trace_prop & ENTITY_BIT(ENTITY_PHY(PA))) &&
44333f810b2SJeff Kirsher port_out != PA) {
44433f810b2SJeff Kirsher /* trace propagate upstream */
4455671e8c1SJoe Perches DB_ECM("ECM : propagate TRACE on PHY B");
44633f810b2SJeff Kirsher queue_event(smc,EVENT_PCMB,PC_TRACE) ;
44733f810b2SJeff Kirsher }
44833f810b2SJeff Kirsher else if ((smc->e.trace_prop & ENTITY_BIT(ENTITY_PHY(PB))) &&
44933f810b2SJeff Kirsher port_out != PB) {
45033f810b2SJeff Kirsher /* trace propagate upstream */
4515671e8c1SJoe Perches DB_ECM("ECM : propagate TRACE on PHY A");
45233f810b2SJeff Kirsher queue_event(smc,EVENT_PCMA,PC_TRACE) ;
45333f810b2SJeff Kirsher }
45433f810b2SJeff Kirsher else {
45533f810b2SJeff Kirsher /* signal trace termination */
4565671e8c1SJoe Perches DB_ECM("ECM : TRACE terminated");
45733f810b2SJeff Kirsher smc->e.path_test = PT_PENDING ;
45833f810b2SJeff Kirsher }
45933f810b2SJeff Kirsher smc->e.trace_prop = 0 ;
46033f810b2SJeff Kirsher }
46133f810b2SJeff Kirsher #else
46233f810b2SJeff Kirsher /*
46333f810b2SJeff Kirsher * trace propagation actions for Concentrator
46433f810b2SJeff Kirsher */
prop_actions(struct s_smc * smc)46533f810b2SJeff Kirsher static void prop_actions(struct s_smc *smc)
46633f810b2SJeff Kirsher {
46733f810b2SJeff Kirsher int initiator ;
46833f810b2SJeff Kirsher int upstream ;
46933f810b2SJeff Kirsher int p ;
47033f810b2SJeff Kirsher
47133f810b2SJeff Kirsher RS_SET(smc,RS_EVENT) ;
47233f810b2SJeff Kirsher while (smc->e.trace_prop) {
4735671e8c1SJoe Perches DB_ECM("ECM : prop_actions - trace_prop %d",
4745671e8c1SJoe Perches smc->e.trace_prop);
47533f810b2SJeff Kirsher
47633f810b2SJeff Kirsher if (smc->e.trace_prop & ENTITY_BIT(ENTITY_MAC)) {
47733f810b2SJeff Kirsher initiator = ENTITY_MAC ;
47833f810b2SJeff Kirsher smc->e.trace_prop &= ~ENTITY_BIT(ENTITY_MAC) ;
4795671e8c1SJoe Perches DB_ECM("ECM: MAC initiates trace");
48033f810b2SJeff Kirsher }
48133f810b2SJeff Kirsher else {
48233f810b2SJeff Kirsher for (p = NUMPHYS-1 ; p >= 0 ; p--) {
48333f810b2SJeff Kirsher if (smc->e.trace_prop &
48433f810b2SJeff Kirsher ENTITY_BIT(ENTITY_PHY(p)))
48533f810b2SJeff Kirsher break ;
48633f810b2SJeff Kirsher }
48733f810b2SJeff Kirsher initiator = ENTITY_PHY(p) ;
48833f810b2SJeff Kirsher smc->e.trace_prop &= ~ENTITY_BIT(ENTITY_PHY(p)) ;
48933f810b2SJeff Kirsher }
49033f810b2SJeff Kirsher upstream = cem_get_upstream(smc,initiator) ;
49133f810b2SJeff Kirsher
49233f810b2SJeff Kirsher if (upstream == ENTITY_MAC) {
49333f810b2SJeff Kirsher /* signal trace termination */
4945671e8c1SJoe Perches DB_ECM("ECM : TRACE terminated");
49533f810b2SJeff Kirsher smc->e.path_test = PT_PENDING ;
49633f810b2SJeff Kirsher }
49733f810b2SJeff Kirsher else {
49833f810b2SJeff Kirsher /* trace propagate upstream */
4995671e8c1SJoe Perches DB_ECM("ECM : propagate TRACE on PHY %d", upstream);
50033f810b2SJeff Kirsher queue_event(smc,EVENT_PCM+upstream,PC_TRACE) ;
50133f810b2SJeff Kirsher }
50233f810b2SJeff Kirsher }
50333f810b2SJeff Kirsher }
50433f810b2SJeff Kirsher #endif
50533f810b2SJeff Kirsher
50633f810b2SJeff Kirsher
50733f810b2SJeff Kirsher /*
50833f810b2SJeff Kirsher * SMT timer interface
50933f810b2SJeff Kirsher * start ECM timer
51033f810b2SJeff Kirsher */
start_ecm_timer(struct s_smc * smc,u_long value,int event)51133f810b2SJeff Kirsher static void start_ecm_timer(struct s_smc *smc, u_long value, int event)
51233f810b2SJeff Kirsher {
51333f810b2SJeff Kirsher smt_timer_start(smc,&smc->e.ecm_timer,value,EV_TOKEN(EVENT_ECM,event));
51433f810b2SJeff Kirsher }
51533f810b2SJeff Kirsher
51633f810b2SJeff Kirsher /*
51733f810b2SJeff Kirsher * SMT timer interface
51833f810b2SJeff Kirsher * stop ECM timer
51933f810b2SJeff Kirsher */
stop_ecm_timer(struct s_smc * smc)52033f810b2SJeff Kirsher static void stop_ecm_timer(struct s_smc *smc)
52133f810b2SJeff Kirsher {
52233f810b2SJeff Kirsher if (smc->e.ecm_timer.tm_active)
52333f810b2SJeff Kirsher smt_timer_stop(smc,&smc->e.ecm_timer) ;
52433f810b2SJeff Kirsher }
525