162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * (C)Copyright 1998,1999 SysKonnect, 562306a36Sopenharmony_ci * a business unit of Schneider & Koch & Co. Datensysteme GmbH. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * See the file "skfddi.c" for further information. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * The information in this file is provided "AS IS" without warranty. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci ******************************************************************************/ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* 1462306a36Sopenharmony_ci SMT ECM 1562306a36Sopenharmony_ci Entity Coordination Management 1662306a36Sopenharmony_ci Hardware independent state machine 1762306a36Sopenharmony_ci*/ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* 2062306a36Sopenharmony_ci * Hardware independent state machine implemantation 2162306a36Sopenharmony_ci * The following external SMT functions are referenced : 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * queue_event() 2462306a36Sopenharmony_ci * smt_timer_start() 2562306a36Sopenharmony_ci * smt_timer_stop() 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * The following external HW dependent functions are referenced : 2862306a36Sopenharmony_ci * sm_pm_bypass_req() 2962306a36Sopenharmony_ci * sm_pm_get_ls() 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * The following HW dependent events are required : 3262306a36Sopenharmony_ci * NONE 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include "h/types.h" 3762306a36Sopenharmony_ci#include "h/fddi.h" 3862306a36Sopenharmony_ci#include "h/smc.h" 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define KERNEL 4162306a36Sopenharmony_ci#include "h/smtstate.h" 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* 4462306a36Sopenharmony_ci * FSM Macros 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_ci#define AFLAG 0x10 4762306a36Sopenharmony_ci#define GO_STATE(x) (smc->mib.fddiSMTECMState = (x)|AFLAG) 4862306a36Sopenharmony_ci#define ACTIONS_DONE() (smc->mib.fddiSMTECMState &= ~AFLAG) 4962306a36Sopenharmony_ci#define ACTIONS(x) (x|AFLAG) 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define EC0_OUT 0 /* not inserted */ 5262306a36Sopenharmony_ci#define EC1_IN 1 /* inserted */ 5362306a36Sopenharmony_ci#define EC2_TRACE 2 /* tracing */ 5462306a36Sopenharmony_ci#define EC3_LEAVE 3 /* leaving the ring */ 5562306a36Sopenharmony_ci#define EC4_PATH_TEST 4 /* performing path test */ 5662306a36Sopenharmony_ci#define EC5_INSERT 5 /* bypass being turned on */ 5762306a36Sopenharmony_ci#define EC6_CHECK 6 /* checking bypass */ 5862306a36Sopenharmony_ci#define EC7_DEINSERT 7 /* bypass being turnde off */ 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* 6162306a36Sopenharmony_ci * symbolic state names 6262306a36Sopenharmony_ci */ 6362306a36Sopenharmony_cistatic const char * const ecm_states[] = { 6462306a36Sopenharmony_ci "EC0_OUT","EC1_IN","EC2_TRACE","EC3_LEAVE","EC4_PATH_TEST", 6562306a36Sopenharmony_ci "EC5_INSERT","EC6_CHECK","EC7_DEINSERT" 6662306a36Sopenharmony_ci} ; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* 6962306a36Sopenharmony_ci * symbolic event names 7062306a36Sopenharmony_ci */ 7162306a36Sopenharmony_cistatic const char * const ecm_events[] = { 7262306a36Sopenharmony_ci "NONE","EC_CONNECT","EC_DISCONNECT","EC_TRACE_PROP","EC_PATH_TEST", 7362306a36Sopenharmony_ci "EC_TIMEOUT_TD","EC_TIMEOUT_TMAX", 7462306a36Sopenharmony_ci "EC_TIMEOUT_IMAX","EC_TIMEOUT_INMAX","EC_TEST_DONE" 7562306a36Sopenharmony_ci} ; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/* 7862306a36Sopenharmony_ci * all Globals are defined in smc.h 7962306a36Sopenharmony_ci * struct s_ecm 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci/* 8362306a36Sopenharmony_ci * function declarations 8462306a36Sopenharmony_ci */ 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic void ecm_fsm(struct s_smc *smc, int cmd); 8762306a36Sopenharmony_cistatic void start_ecm_timer(struct s_smc *smc, u_long value, int event); 8862306a36Sopenharmony_cistatic void stop_ecm_timer(struct s_smc *smc); 8962306a36Sopenharmony_cistatic void prop_actions(struct s_smc *smc); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/* 9262306a36Sopenharmony_ci init ECM state machine 9362306a36Sopenharmony_ci clear all ECM vars and flags 9462306a36Sopenharmony_ci*/ 9562306a36Sopenharmony_civoid ecm_init(struct s_smc *smc) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci smc->e.path_test = PT_PASSED ; 9862306a36Sopenharmony_ci smc->e.trace_prop = 0 ; 9962306a36Sopenharmony_ci smc->e.sb_flag = 0 ; 10062306a36Sopenharmony_ci smc->mib.fddiSMTECMState = ACTIONS(EC0_OUT) ; 10162306a36Sopenharmony_ci smc->e.ecm_line_state = FALSE ; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci/* 10562306a36Sopenharmony_ci ECM state machine 10662306a36Sopenharmony_ci called by dispatcher 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci do 10962306a36Sopenharmony_ci display state change 11062306a36Sopenharmony_ci process event 11162306a36Sopenharmony_ci until SM is stable 11262306a36Sopenharmony_ci*/ 11362306a36Sopenharmony_civoid ecm(struct s_smc *smc, int event) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci int state ; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci do { 11862306a36Sopenharmony_ci DB_ECM("ECM : state %s%s event %s", 11962306a36Sopenharmony_ci smc->mib.fddiSMTECMState & AFLAG ? "ACTIONS " : "", 12062306a36Sopenharmony_ci ecm_states[smc->mib.fddiSMTECMState & ~AFLAG], 12162306a36Sopenharmony_ci ecm_events[event]); 12262306a36Sopenharmony_ci state = smc->mib.fddiSMTECMState ; 12362306a36Sopenharmony_ci ecm_fsm(smc,event) ; 12462306a36Sopenharmony_ci event = 0 ; 12562306a36Sopenharmony_ci } while (state != smc->mib.fddiSMTECMState) ; 12662306a36Sopenharmony_ci ecm_state_change(smc,(int)smc->mib.fddiSMTECMState) ; 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/* 13062306a36Sopenharmony_ci process ECM event 13162306a36Sopenharmony_ci*/ 13262306a36Sopenharmony_cistatic void ecm_fsm(struct s_smc *smc, int cmd) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci int ls_a ; /* current line state PHY A */ 13562306a36Sopenharmony_ci int ls_b ; /* current line state PHY B */ 13662306a36Sopenharmony_ci int p ; /* ports */ 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci smc->mib.fddiSMTBypassPresent = sm_pm_bypass_present(smc) ; 14062306a36Sopenharmony_ci if (cmd == EC_CONNECT) 14162306a36Sopenharmony_ci smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci /* For AIX event notification: */ 14462306a36Sopenharmony_ci /* Is a disconnect command remotely issued ? */ 14562306a36Sopenharmony_ci if (cmd == EC_DISCONNECT && 14662306a36Sopenharmony_ci smc->mib.fddiSMTRemoteDisconnectFlag == TRUE) { 14762306a36Sopenharmony_ci AIX_EVENT (smc, (u_long) CIO_HARD_FAIL, (u_long) 14862306a36Sopenharmony_ci FDDI_REMOTE_DISCONNECT, smt_get_event_word(smc), 14962306a36Sopenharmony_ci smt_get_error_word(smc) ); 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci /*jd 05-Aug-1999 Bug #10419 "Port Disconnect fails at Dup MAc Cond."*/ 15362306a36Sopenharmony_ci if (cmd == EC_CONNECT) { 15462306a36Sopenharmony_ci smc->e.DisconnectFlag = FALSE ; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci else if (cmd == EC_DISCONNECT) { 15762306a36Sopenharmony_ci smc->e.DisconnectFlag = TRUE ; 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci switch(smc->mib.fddiSMTECMState) { 16162306a36Sopenharmony_ci case ACTIONS(EC0_OUT) : 16262306a36Sopenharmony_ci /* 16362306a36Sopenharmony_ci * We do not perform a path test 16462306a36Sopenharmony_ci */ 16562306a36Sopenharmony_ci smc->e.path_test = PT_PASSED ; 16662306a36Sopenharmony_ci smc->e.ecm_line_state = FALSE ; 16762306a36Sopenharmony_ci stop_ecm_timer(smc) ; 16862306a36Sopenharmony_ci ACTIONS_DONE() ; 16962306a36Sopenharmony_ci break ; 17062306a36Sopenharmony_ci case EC0_OUT: 17162306a36Sopenharmony_ci /*EC01*/ 17262306a36Sopenharmony_ci if (cmd == EC_CONNECT && !smc->mib.fddiSMTBypassPresent 17362306a36Sopenharmony_ci && smc->e.path_test==PT_PASSED) { 17462306a36Sopenharmony_ci GO_STATE(EC1_IN) ; 17562306a36Sopenharmony_ci break ; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci /*EC05*/ 17862306a36Sopenharmony_ci else if (cmd == EC_CONNECT && (smc->e.path_test==PT_PASSED) && 17962306a36Sopenharmony_ci smc->mib.fddiSMTBypassPresent && 18062306a36Sopenharmony_ci (smc->s.sas == SMT_DAS)) { 18162306a36Sopenharmony_ci GO_STATE(EC5_INSERT) ; 18262306a36Sopenharmony_ci break ; 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci break; 18562306a36Sopenharmony_ci case ACTIONS(EC1_IN) : 18662306a36Sopenharmony_ci stop_ecm_timer(smc) ; 18762306a36Sopenharmony_ci smc->e.trace_prop = 0 ; 18862306a36Sopenharmony_ci sm_ma_control(smc,MA_TREQ) ; 18962306a36Sopenharmony_ci for (p = 0 ; p < NUMPHYS ; p++) 19062306a36Sopenharmony_ci if (smc->mib.p[p].fddiPORTHardwarePresent) 19162306a36Sopenharmony_ci queue_event(smc,EVENT_PCMA+p,PC_START) ; 19262306a36Sopenharmony_ci ACTIONS_DONE() ; 19362306a36Sopenharmony_ci break ; 19462306a36Sopenharmony_ci case EC1_IN: 19562306a36Sopenharmony_ci /*EC12*/ 19662306a36Sopenharmony_ci if (cmd == EC_TRACE_PROP) { 19762306a36Sopenharmony_ci prop_actions(smc) ; 19862306a36Sopenharmony_ci GO_STATE(EC2_TRACE) ; 19962306a36Sopenharmony_ci break ; 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci /*EC13*/ 20262306a36Sopenharmony_ci else if (cmd == EC_DISCONNECT) { 20362306a36Sopenharmony_ci GO_STATE(EC3_LEAVE) ; 20462306a36Sopenharmony_ci break ; 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci break; 20762306a36Sopenharmony_ci case ACTIONS(EC2_TRACE) : 20862306a36Sopenharmony_ci start_ecm_timer(smc,MIB2US(smc->mib.fddiSMTTrace_MaxExpiration), 20962306a36Sopenharmony_ci EC_TIMEOUT_TMAX) ; 21062306a36Sopenharmony_ci ACTIONS_DONE() ; 21162306a36Sopenharmony_ci break ; 21262306a36Sopenharmony_ci case EC2_TRACE : 21362306a36Sopenharmony_ci /*EC22*/ 21462306a36Sopenharmony_ci if (cmd == EC_TRACE_PROP) { 21562306a36Sopenharmony_ci prop_actions(smc) ; 21662306a36Sopenharmony_ci GO_STATE(EC2_TRACE) ; 21762306a36Sopenharmony_ci break ; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci /*EC23a*/ 22062306a36Sopenharmony_ci else if (cmd == EC_DISCONNECT) { 22162306a36Sopenharmony_ci smc->e.path_test = PT_EXITING ; 22262306a36Sopenharmony_ci GO_STATE(EC3_LEAVE) ; 22362306a36Sopenharmony_ci break ; 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci /*EC23b*/ 22662306a36Sopenharmony_ci else if (smc->e.path_test == PT_PENDING) { 22762306a36Sopenharmony_ci GO_STATE(EC3_LEAVE) ; 22862306a36Sopenharmony_ci break ; 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci /*EC23c*/ 23162306a36Sopenharmony_ci else if (cmd == EC_TIMEOUT_TMAX) { 23262306a36Sopenharmony_ci /* Trace_Max is expired */ 23362306a36Sopenharmony_ci /* -> send AIX_EVENT */ 23462306a36Sopenharmony_ci AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, 23562306a36Sopenharmony_ci (u_long) FDDI_SMT_ERROR, (u_long) 23662306a36Sopenharmony_ci FDDI_TRACE_MAX, smt_get_error_word(smc)); 23762306a36Sopenharmony_ci smc->e.path_test = PT_PENDING ; 23862306a36Sopenharmony_ci GO_STATE(EC3_LEAVE) ; 23962306a36Sopenharmony_ci break ; 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci break ; 24262306a36Sopenharmony_ci case ACTIONS(EC3_LEAVE) : 24362306a36Sopenharmony_ci start_ecm_timer(smc,smc->s.ecm_td_min,EC_TIMEOUT_TD) ; 24462306a36Sopenharmony_ci for (p = 0 ; p < NUMPHYS ; p++) 24562306a36Sopenharmony_ci queue_event(smc,EVENT_PCMA+p,PC_STOP) ; 24662306a36Sopenharmony_ci ACTIONS_DONE() ; 24762306a36Sopenharmony_ci break ; 24862306a36Sopenharmony_ci case EC3_LEAVE: 24962306a36Sopenharmony_ci /*EC30*/ 25062306a36Sopenharmony_ci if (cmd == EC_TIMEOUT_TD && !smc->mib.fddiSMTBypassPresent && 25162306a36Sopenharmony_ci (smc->e.path_test != PT_PENDING)) { 25262306a36Sopenharmony_ci GO_STATE(EC0_OUT) ; 25362306a36Sopenharmony_ci break ; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci /*EC34*/ 25662306a36Sopenharmony_ci else if (cmd == EC_TIMEOUT_TD && 25762306a36Sopenharmony_ci (smc->e.path_test == PT_PENDING)) { 25862306a36Sopenharmony_ci GO_STATE(EC4_PATH_TEST) ; 25962306a36Sopenharmony_ci break ; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci /*EC31*/ 26262306a36Sopenharmony_ci else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) { 26362306a36Sopenharmony_ci GO_STATE(EC1_IN) ; 26462306a36Sopenharmony_ci break ; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci /*EC33*/ 26762306a36Sopenharmony_ci else if (cmd == EC_DISCONNECT && 26862306a36Sopenharmony_ci smc->e.path_test == PT_PENDING) { 26962306a36Sopenharmony_ci smc->e.path_test = PT_EXITING ; 27062306a36Sopenharmony_ci /* 27162306a36Sopenharmony_ci * stay in state - state will be left via timeout 27262306a36Sopenharmony_ci */ 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci /*EC37*/ 27562306a36Sopenharmony_ci else if (cmd == EC_TIMEOUT_TD && 27662306a36Sopenharmony_ci smc->mib.fddiSMTBypassPresent && 27762306a36Sopenharmony_ci smc->e.path_test != PT_PENDING) { 27862306a36Sopenharmony_ci GO_STATE(EC7_DEINSERT) ; 27962306a36Sopenharmony_ci break ; 28062306a36Sopenharmony_ci } 28162306a36Sopenharmony_ci break ; 28262306a36Sopenharmony_ci case ACTIONS(EC4_PATH_TEST) : 28362306a36Sopenharmony_ci stop_ecm_timer(smc) ; 28462306a36Sopenharmony_ci smc->e.path_test = PT_TESTING ; 28562306a36Sopenharmony_ci start_ecm_timer(smc,smc->s.ecm_test_done,EC_TEST_DONE) ; 28662306a36Sopenharmony_ci /* now perform path test ... just a simulation */ 28762306a36Sopenharmony_ci ACTIONS_DONE() ; 28862306a36Sopenharmony_ci break ; 28962306a36Sopenharmony_ci case EC4_PATH_TEST : 29062306a36Sopenharmony_ci /* path test done delay */ 29162306a36Sopenharmony_ci if (cmd == EC_TEST_DONE) 29262306a36Sopenharmony_ci smc->e.path_test = PT_PASSED ; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci if (smc->e.path_test == PT_FAILED) 29562306a36Sopenharmony_ci RS_SET(smc,RS_PATHTEST) ; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci /*EC40a*/ 29862306a36Sopenharmony_ci if (smc->e.path_test == PT_FAILED && 29962306a36Sopenharmony_ci !smc->mib.fddiSMTBypassPresent) { 30062306a36Sopenharmony_ci GO_STATE(EC0_OUT) ; 30162306a36Sopenharmony_ci break ; 30262306a36Sopenharmony_ci } 30362306a36Sopenharmony_ci /*EC40b*/ 30462306a36Sopenharmony_ci else if (cmd == EC_DISCONNECT && 30562306a36Sopenharmony_ci !smc->mib.fddiSMTBypassPresent) { 30662306a36Sopenharmony_ci GO_STATE(EC0_OUT) ; 30762306a36Sopenharmony_ci break ; 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci /*EC41*/ 31062306a36Sopenharmony_ci else if (smc->e.path_test == PT_PASSED) { 31162306a36Sopenharmony_ci GO_STATE(EC1_IN) ; 31262306a36Sopenharmony_ci break ; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci /*EC47a*/ 31562306a36Sopenharmony_ci else if (smc->e.path_test == PT_FAILED && 31662306a36Sopenharmony_ci smc->mib.fddiSMTBypassPresent) { 31762306a36Sopenharmony_ci GO_STATE(EC7_DEINSERT) ; 31862306a36Sopenharmony_ci break ; 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci /*EC47b*/ 32162306a36Sopenharmony_ci else if (cmd == EC_DISCONNECT && 32262306a36Sopenharmony_ci smc->mib.fddiSMTBypassPresent) { 32362306a36Sopenharmony_ci GO_STATE(EC7_DEINSERT) ; 32462306a36Sopenharmony_ci break ; 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci break ; 32762306a36Sopenharmony_ci case ACTIONS(EC5_INSERT) : 32862306a36Sopenharmony_ci sm_pm_bypass_req(smc,BP_INSERT); 32962306a36Sopenharmony_ci start_ecm_timer(smc,smc->s.ecm_in_max,EC_TIMEOUT_INMAX) ; 33062306a36Sopenharmony_ci ACTIONS_DONE() ; 33162306a36Sopenharmony_ci break ; 33262306a36Sopenharmony_ci case EC5_INSERT : 33362306a36Sopenharmony_ci /*EC56*/ 33462306a36Sopenharmony_ci if (cmd == EC_TIMEOUT_INMAX) { 33562306a36Sopenharmony_ci GO_STATE(EC6_CHECK) ; 33662306a36Sopenharmony_ci break ; 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci /*EC57*/ 33962306a36Sopenharmony_ci else if (cmd == EC_DISCONNECT) { 34062306a36Sopenharmony_ci GO_STATE(EC7_DEINSERT) ; 34162306a36Sopenharmony_ci break ; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci break ; 34462306a36Sopenharmony_ci case ACTIONS(EC6_CHECK) : 34562306a36Sopenharmony_ci /* 34662306a36Sopenharmony_ci * in EC6_CHECK, we *POLL* the line state ! 34762306a36Sopenharmony_ci * check whether both bypass switches have switched. 34862306a36Sopenharmony_ci */ 34962306a36Sopenharmony_ci start_ecm_timer(smc,smc->s.ecm_check_poll,0) ; 35062306a36Sopenharmony_ci smc->e.ecm_line_state = TRUE ; /* flag to pcm: report Q/HLS */ 35162306a36Sopenharmony_ci ACTIONS_DONE() ; 35262306a36Sopenharmony_ci break ; 35362306a36Sopenharmony_ci case EC6_CHECK : 35462306a36Sopenharmony_ci ls_a = sm_pm_get_ls(smc,PA) ; 35562306a36Sopenharmony_ci ls_b = sm_pm_get_ls(smc,PB) ; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci /*EC61*/ 35862306a36Sopenharmony_ci if (((ls_a == PC_QLS) || (ls_a == PC_HLS)) && 35962306a36Sopenharmony_ci ((ls_b == PC_QLS) || (ls_b == PC_HLS)) ) { 36062306a36Sopenharmony_ci smc->e.sb_flag = FALSE ; 36162306a36Sopenharmony_ci smc->e.ecm_line_state = FALSE ; 36262306a36Sopenharmony_ci GO_STATE(EC1_IN) ; 36362306a36Sopenharmony_ci break ; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci /*EC66*/ 36662306a36Sopenharmony_ci else if (!smc->e.sb_flag && 36762306a36Sopenharmony_ci (((ls_a == PC_ILS) && (ls_b == PC_QLS)) || 36862306a36Sopenharmony_ci ((ls_a == PC_QLS) && (ls_b == PC_ILS)))){ 36962306a36Sopenharmony_ci smc->e.sb_flag = TRUE ; 37062306a36Sopenharmony_ci DB_ECMN(1, "ECM : EC6_CHECK - stuck bypass"); 37162306a36Sopenharmony_ci AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long) 37262306a36Sopenharmony_ci FDDI_SMT_ERROR, (u_long) FDDI_BYPASS_STUCK, 37362306a36Sopenharmony_ci smt_get_error_word(smc)); 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci /*EC67*/ 37662306a36Sopenharmony_ci else if (cmd == EC_DISCONNECT) { 37762306a36Sopenharmony_ci smc->e.ecm_line_state = FALSE ; 37862306a36Sopenharmony_ci GO_STATE(EC7_DEINSERT) ; 37962306a36Sopenharmony_ci break ; 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci else { 38262306a36Sopenharmony_ci /* 38362306a36Sopenharmony_ci * restart poll 38462306a36Sopenharmony_ci */ 38562306a36Sopenharmony_ci start_ecm_timer(smc,smc->s.ecm_check_poll,0) ; 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci break ; 38862306a36Sopenharmony_ci case ACTIONS(EC7_DEINSERT) : 38962306a36Sopenharmony_ci sm_pm_bypass_req(smc,BP_DEINSERT); 39062306a36Sopenharmony_ci start_ecm_timer(smc,smc->s.ecm_i_max,EC_TIMEOUT_IMAX) ; 39162306a36Sopenharmony_ci ACTIONS_DONE() ; 39262306a36Sopenharmony_ci break ; 39362306a36Sopenharmony_ci case EC7_DEINSERT: 39462306a36Sopenharmony_ci /*EC70*/ 39562306a36Sopenharmony_ci if (cmd == EC_TIMEOUT_IMAX) { 39662306a36Sopenharmony_ci GO_STATE(EC0_OUT) ; 39762306a36Sopenharmony_ci break ; 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci /*EC75*/ 40062306a36Sopenharmony_ci else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) { 40162306a36Sopenharmony_ci GO_STATE(EC5_INSERT) ; 40262306a36Sopenharmony_ci break ; 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci break; 40562306a36Sopenharmony_ci default: 40662306a36Sopenharmony_ci SMT_PANIC(smc,SMT_E0107, SMT_E0107_MSG) ; 40762306a36Sopenharmony_ci break; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci#ifndef CONCENTRATOR 41262306a36Sopenharmony_ci/* 41362306a36Sopenharmony_ci * trace propagation actions for SAS & DAS 41462306a36Sopenharmony_ci */ 41562306a36Sopenharmony_cistatic void prop_actions(struct s_smc *smc) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci int port_in = 0 ; 41862306a36Sopenharmony_ci int port_out = 0 ; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci RS_SET(smc,RS_EVENT) ; 42162306a36Sopenharmony_ci switch (smc->s.sas) { 42262306a36Sopenharmony_ci case SMT_SAS : 42362306a36Sopenharmony_ci port_in = port_out = pcm_get_s_port(smc) ; 42462306a36Sopenharmony_ci break ; 42562306a36Sopenharmony_ci case SMT_DAS : 42662306a36Sopenharmony_ci port_in = cfm_get_mac_input(smc) ; /* PA or PB */ 42762306a36Sopenharmony_ci port_out = cfm_get_mac_output(smc) ; /* PA or PB */ 42862306a36Sopenharmony_ci break ; 42962306a36Sopenharmony_ci case SMT_NAC : 43062306a36Sopenharmony_ci SMT_PANIC(smc,SMT_E0108, SMT_E0108_MSG) ; 43162306a36Sopenharmony_ci return ; 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci DB_ECM("ECM : prop_actions - trace_prop %lu", smc->e.trace_prop); 43562306a36Sopenharmony_ci DB_ECM("ECM : prop_actions - in %d out %d", port_in, port_out); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if (smc->e.trace_prop & ENTITY_BIT(ENTITY_MAC)) { 43862306a36Sopenharmony_ci /* trace initiatior */ 43962306a36Sopenharmony_ci DB_ECM("ECM : initiate TRACE on PHY %c", 'A' + port_in - PA); 44062306a36Sopenharmony_ci queue_event(smc,EVENT_PCM+port_in,PC_TRACE) ; 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci else if ((smc->e.trace_prop & ENTITY_BIT(ENTITY_PHY(PA))) && 44362306a36Sopenharmony_ci port_out != PA) { 44462306a36Sopenharmony_ci /* trace propagate upstream */ 44562306a36Sopenharmony_ci DB_ECM("ECM : propagate TRACE on PHY B"); 44662306a36Sopenharmony_ci queue_event(smc,EVENT_PCMB,PC_TRACE) ; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci else if ((smc->e.trace_prop & ENTITY_BIT(ENTITY_PHY(PB))) && 44962306a36Sopenharmony_ci port_out != PB) { 45062306a36Sopenharmony_ci /* trace propagate upstream */ 45162306a36Sopenharmony_ci DB_ECM("ECM : propagate TRACE on PHY A"); 45262306a36Sopenharmony_ci queue_event(smc,EVENT_PCMA,PC_TRACE) ; 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci else { 45562306a36Sopenharmony_ci /* signal trace termination */ 45662306a36Sopenharmony_ci DB_ECM("ECM : TRACE terminated"); 45762306a36Sopenharmony_ci smc->e.path_test = PT_PENDING ; 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci smc->e.trace_prop = 0 ; 46062306a36Sopenharmony_ci} 46162306a36Sopenharmony_ci#else 46262306a36Sopenharmony_ci/* 46362306a36Sopenharmony_ci * trace propagation actions for Concentrator 46462306a36Sopenharmony_ci */ 46562306a36Sopenharmony_cistatic void prop_actions(struct s_smc *smc) 46662306a36Sopenharmony_ci{ 46762306a36Sopenharmony_ci int initiator ; 46862306a36Sopenharmony_ci int upstream ; 46962306a36Sopenharmony_ci int p ; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci RS_SET(smc,RS_EVENT) ; 47262306a36Sopenharmony_ci while (smc->e.trace_prop) { 47362306a36Sopenharmony_ci DB_ECM("ECM : prop_actions - trace_prop %d", 47462306a36Sopenharmony_ci smc->e.trace_prop); 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci if (smc->e.trace_prop & ENTITY_BIT(ENTITY_MAC)) { 47762306a36Sopenharmony_ci initiator = ENTITY_MAC ; 47862306a36Sopenharmony_ci smc->e.trace_prop &= ~ENTITY_BIT(ENTITY_MAC) ; 47962306a36Sopenharmony_ci DB_ECM("ECM: MAC initiates trace"); 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci else { 48262306a36Sopenharmony_ci for (p = NUMPHYS-1 ; p >= 0 ; p--) { 48362306a36Sopenharmony_ci if (smc->e.trace_prop & 48462306a36Sopenharmony_ci ENTITY_BIT(ENTITY_PHY(p))) 48562306a36Sopenharmony_ci break ; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci initiator = ENTITY_PHY(p) ; 48862306a36Sopenharmony_ci smc->e.trace_prop &= ~ENTITY_BIT(ENTITY_PHY(p)) ; 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci upstream = cem_get_upstream(smc,initiator) ; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci if (upstream == ENTITY_MAC) { 49362306a36Sopenharmony_ci /* signal trace termination */ 49462306a36Sopenharmony_ci DB_ECM("ECM : TRACE terminated"); 49562306a36Sopenharmony_ci smc->e.path_test = PT_PENDING ; 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci else { 49862306a36Sopenharmony_ci /* trace propagate upstream */ 49962306a36Sopenharmony_ci DB_ECM("ECM : propagate TRACE on PHY %d", upstream); 50062306a36Sopenharmony_ci queue_event(smc,EVENT_PCM+upstream,PC_TRACE) ; 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci} 50462306a36Sopenharmony_ci#endif 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci/* 50862306a36Sopenharmony_ci * SMT timer interface 50962306a36Sopenharmony_ci * start ECM timer 51062306a36Sopenharmony_ci */ 51162306a36Sopenharmony_cistatic void start_ecm_timer(struct s_smc *smc, u_long value, int event) 51262306a36Sopenharmony_ci{ 51362306a36Sopenharmony_ci smt_timer_start(smc,&smc->e.ecm_timer,value,EV_TOKEN(EVENT_ECM,event)); 51462306a36Sopenharmony_ci} 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci/* 51762306a36Sopenharmony_ci * SMT timer interface 51862306a36Sopenharmony_ci * stop ECM timer 51962306a36Sopenharmony_ci */ 52062306a36Sopenharmony_cistatic void stop_ecm_timer(struct s_smc *smc) 52162306a36Sopenharmony_ci{ 52262306a36Sopenharmony_ci if (smc->e.ecm_timer.tm_active) 52362306a36Sopenharmony_ci smt_timer_stop(smc,&smc->e.ecm_timer) ; 52462306a36Sopenharmony_ci} 525