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 PCM 1562306a36Sopenharmony_ci Physical Connection Management 1662306a36Sopenharmony_ci*/ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* 1962306a36Sopenharmony_ci * Hardware independent state machine implemantation 2062306a36Sopenharmony_ci * The following external SMT functions are referenced : 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * queue_event() 2362306a36Sopenharmony_ci * smt_timer_start() 2462306a36Sopenharmony_ci * smt_timer_stop() 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * The following external HW dependent functions are referenced : 2762306a36Sopenharmony_ci * sm_pm_control() 2862306a36Sopenharmony_ci * sm_ph_linestate() 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * The following HW dependent events are required : 3162306a36Sopenharmony_ci * PC_QLS 3262306a36Sopenharmony_ci * PC_ILS 3362306a36Sopenharmony_ci * PC_HLS 3462306a36Sopenharmony_ci * PC_MLS 3562306a36Sopenharmony_ci * PC_NSE 3662306a36Sopenharmony_ci * PC_LEM 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#include "h/types.h" 4262306a36Sopenharmony_ci#include "h/fddi.h" 4362306a36Sopenharmony_ci#include "h/smc.h" 4462306a36Sopenharmony_ci#include "h/supern_2.h" 4562306a36Sopenharmony_ci#define KERNEL 4662306a36Sopenharmony_ci#include "h/smtstate.h" 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#ifdef FDDI_MIB 4962306a36Sopenharmony_ciextern int snmp_fddi_trap( 5062306a36Sopenharmony_ci#ifdef ANSIC 5162306a36Sopenharmony_cistruct s_smc * smc, int type, int index 5262306a36Sopenharmony_ci#endif 5362306a36Sopenharmony_ci); 5462306a36Sopenharmony_ci#endif 5562306a36Sopenharmony_ci#ifdef CONCENTRATOR 5662306a36Sopenharmony_ciextern int plc_is_installed( 5762306a36Sopenharmony_ci#ifdef ANSIC 5862306a36Sopenharmony_cistruct s_smc *smc , 5962306a36Sopenharmony_ciint p 6062306a36Sopenharmony_ci#endif 6162306a36Sopenharmony_ci) ; 6262306a36Sopenharmony_ci#endif 6362306a36Sopenharmony_ci/* 6462306a36Sopenharmony_ci * FSM Macros 6562306a36Sopenharmony_ci */ 6662306a36Sopenharmony_ci#define AFLAG (0x20) 6762306a36Sopenharmony_ci#define GO_STATE(x) (mib->fddiPORTPCMState = (x)|AFLAG) 6862306a36Sopenharmony_ci#define ACTIONS_DONE() (mib->fddiPORTPCMState &= ~AFLAG) 6962306a36Sopenharmony_ci#define ACTIONS(x) (x|AFLAG) 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* 7262306a36Sopenharmony_ci * PCM states 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_ci#define PC0_OFF 0 7562306a36Sopenharmony_ci#define PC1_BREAK 1 7662306a36Sopenharmony_ci#define PC2_TRACE 2 7762306a36Sopenharmony_ci#define PC3_CONNECT 3 7862306a36Sopenharmony_ci#define PC4_NEXT 4 7962306a36Sopenharmony_ci#define PC5_SIGNAL 5 8062306a36Sopenharmony_ci#define PC6_JOIN 6 8162306a36Sopenharmony_ci#define PC7_VERIFY 7 8262306a36Sopenharmony_ci#define PC8_ACTIVE 8 8362306a36Sopenharmony_ci#define PC9_MAINT 9 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci/* 8662306a36Sopenharmony_ci * symbolic state names 8762306a36Sopenharmony_ci */ 8862306a36Sopenharmony_cistatic const char * const pcm_states[] = { 8962306a36Sopenharmony_ci "PC0_OFF","PC1_BREAK","PC2_TRACE","PC3_CONNECT","PC4_NEXT", 9062306a36Sopenharmony_ci "PC5_SIGNAL","PC6_JOIN","PC7_VERIFY","PC8_ACTIVE","PC9_MAINT" 9162306a36Sopenharmony_ci} ; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* 9462306a36Sopenharmony_ci * symbolic event names 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_cistatic const char * const pcm_events[] = { 9762306a36Sopenharmony_ci "NONE","PC_START","PC_STOP","PC_LOOP","PC_JOIN","PC_SIGNAL", 9862306a36Sopenharmony_ci "PC_REJECT","PC_MAINT","PC_TRACE","PC_PDR", 9962306a36Sopenharmony_ci "PC_ENABLE","PC_DISABLE", 10062306a36Sopenharmony_ci "PC_QLS","PC_ILS","PC_MLS","PC_HLS","PC_LS_PDR","PC_LS_NONE", 10162306a36Sopenharmony_ci "PC_TIMEOUT_TB_MAX","PC_TIMEOUT_TB_MIN", 10262306a36Sopenharmony_ci "PC_TIMEOUT_C_MIN","PC_TIMEOUT_T_OUT", 10362306a36Sopenharmony_ci "PC_TIMEOUT_TL_MIN","PC_TIMEOUT_T_NEXT","PC_TIMEOUT_LCT", 10462306a36Sopenharmony_ci "PC_NSE","PC_LEM" 10562306a36Sopenharmony_ci} ; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci#ifdef MOT_ELM 10862306a36Sopenharmony_ci/* 10962306a36Sopenharmony_ci * PCL-S control register 11062306a36Sopenharmony_ci * this register in the PLC-S controls the scrambling parameters 11162306a36Sopenharmony_ci */ 11262306a36Sopenharmony_ci#define PLCS_CONTROL_C_U 0 11362306a36Sopenharmony_ci#define PLCS_CONTROL_C_S (PL_C_SDOFF_ENABLE | PL_C_SDON_ENABLE | \ 11462306a36Sopenharmony_ci PL_C_CIPHER_ENABLE) 11562306a36Sopenharmony_ci#define PLCS_FASSERT_U 0 11662306a36Sopenharmony_ci#define PLCS_FASSERT_S 0xFd76 /* 52.0 us */ 11762306a36Sopenharmony_ci#define PLCS_FDEASSERT_U 0 11862306a36Sopenharmony_ci#define PLCS_FDEASSERT_S 0 11962306a36Sopenharmony_ci#else /* nMOT_ELM */ 12062306a36Sopenharmony_ci/* 12162306a36Sopenharmony_ci * PCL-S control register 12262306a36Sopenharmony_ci * this register in the PLC-S controls the scrambling parameters 12362306a36Sopenharmony_ci * can be patched for ANSI compliance if standard changes 12462306a36Sopenharmony_ci */ 12562306a36Sopenharmony_cistatic const u_char plcs_control_c_u[17] = "PLC_CNTRL_C_U=\0\0" ; 12662306a36Sopenharmony_cistatic const u_char plcs_control_c_s[17] = "PLC_CNTRL_C_S=\01\02" ; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci#define PLCS_CONTROL_C_U (plcs_control_c_u[14] | (plcs_control_c_u[15]<<8)) 12962306a36Sopenharmony_ci#define PLCS_CONTROL_C_S (plcs_control_c_s[14] | (plcs_control_c_s[15]<<8)) 13062306a36Sopenharmony_ci#endif /* nMOT_ELM */ 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci/* 13362306a36Sopenharmony_ci * external vars 13462306a36Sopenharmony_ci */ 13562306a36Sopenharmony_ci/* struct definition see 'cmtdef.h' (also used by CFM) */ 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci#define PS_OFF 0 13862306a36Sopenharmony_ci#define PS_BIT3 1 13962306a36Sopenharmony_ci#define PS_BIT4 2 14062306a36Sopenharmony_ci#define PS_BIT7 3 14162306a36Sopenharmony_ci#define PS_LCT 4 14262306a36Sopenharmony_ci#define PS_BIT8 5 14362306a36Sopenharmony_ci#define PS_JOIN 6 14462306a36Sopenharmony_ci#define PS_ACTIVE 7 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci#define LCT_LEM_MAX 255 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/* 14962306a36Sopenharmony_ci * PLC timing parameter 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci#define PLC_MS(m) ((int)((0x10000L-(m*100000L/2048)))) 15362306a36Sopenharmony_ci#define SLOW_TL_MIN PLC_MS(6) 15462306a36Sopenharmony_ci#define SLOW_C_MIN PLC_MS(10) 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic const struct plt { 15762306a36Sopenharmony_ci int timer ; /* relative plc timer address */ 15862306a36Sopenharmony_ci int para ; /* default timing parameters */ 15962306a36Sopenharmony_ci} pltm[] = { 16062306a36Sopenharmony_ci { PL_C_MIN, SLOW_C_MIN }, /* min t. to remain Connect State */ 16162306a36Sopenharmony_ci { PL_TL_MIN, SLOW_TL_MIN }, /* min t. to transmit a Line State */ 16262306a36Sopenharmony_ci { PL_TB_MIN, TP_TB_MIN }, /* min break time */ 16362306a36Sopenharmony_ci { PL_T_OUT, TP_T_OUT }, /* Signaling timeout */ 16462306a36Sopenharmony_ci { PL_LC_LENGTH, TP_LC_LENGTH }, /* Link Confidence Test Time */ 16562306a36Sopenharmony_ci { PL_T_SCRUB, TP_T_SCRUB }, /* Scrub Time == MAC TVX time ! */ 16662306a36Sopenharmony_ci { PL_NS_MAX, TP_NS_MAX }, /* max t. that noise is tolerated */ 16762306a36Sopenharmony_ci { 0,0 } 16862306a36Sopenharmony_ci} ; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci/* 17162306a36Sopenharmony_ci * interrupt mask 17262306a36Sopenharmony_ci */ 17362306a36Sopenharmony_ci#ifdef SUPERNET_3 17462306a36Sopenharmony_ci/* 17562306a36Sopenharmony_ci * Do we need the EBUF error during signaling, too, to detect SUPERNET_3 17662306a36Sopenharmony_ci * PLL bug? 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_cistatic const int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK | 17962306a36Sopenharmony_ci PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR; 18062306a36Sopenharmony_ci#else /* SUPERNET_3 */ 18162306a36Sopenharmony_ci/* 18262306a36Sopenharmony_ci * We do NOT need the elasticity buffer error during signaling. 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_cistatic int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK | 18562306a36Sopenharmony_ci PL_PCM_ENABLED | PL_SELF_TEST ; 18662306a36Sopenharmony_ci#endif /* SUPERNET_3 */ 18762306a36Sopenharmony_cistatic const int plc_imsk_act = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK | 18862306a36Sopenharmony_ci PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci/* internal functions */ 19162306a36Sopenharmony_cistatic void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd); 19262306a36Sopenharmony_cistatic void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy); 19362306a36Sopenharmony_cistatic void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy); 19462306a36Sopenharmony_cistatic void reset_lem_struct(struct s_phy *phy); 19562306a36Sopenharmony_cistatic void plc_init(struct s_smc *smc, int p); 19662306a36Sopenharmony_cistatic void sm_ph_lem_start(struct s_smc *smc, int np, int threshold); 19762306a36Sopenharmony_cistatic void sm_ph_lem_stop(struct s_smc *smc, int np); 19862306a36Sopenharmony_cistatic void sm_ph_linestate(struct s_smc *smc, int phy, int ls); 19962306a36Sopenharmony_cistatic void real_init_plc(struct s_smc *smc); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci/* 20262306a36Sopenharmony_ci * SMT timer interface 20362306a36Sopenharmony_ci * start PCM timer 0 20462306a36Sopenharmony_ci */ 20562306a36Sopenharmony_cistatic void start_pcm_timer0(struct s_smc *smc, u_long value, int event, 20662306a36Sopenharmony_ci struct s_phy *phy) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci phy->timer0_exp = FALSE ; /* clear timer event flag */ 20962306a36Sopenharmony_ci smt_timer_start(smc,&phy->pcm_timer0,value, 21062306a36Sopenharmony_ci EV_TOKEN(EVENT_PCM+phy->np,event)) ; 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci/* 21362306a36Sopenharmony_ci * SMT timer interface 21462306a36Sopenharmony_ci * stop PCM timer 0 21562306a36Sopenharmony_ci */ 21662306a36Sopenharmony_cistatic void stop_pcm_timer0(struct s_smc *smc, struct s_phy *phy) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci if (phy->pcm_timer0.tm_active) 21962306a36Sopenharmony_ci smt_timer_stop(smc,&phy->pcm_timer0) ; 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci/* 22362306a36Sopenharmony_ci init PCM state machine (called by driver) 22462306a36Sopenharmony_ci clear all PCM vars and flags 22562306a36Sopenharmony_ci*/ 22662306a36Sopenharmony_civoid pcm_init(struct s_smc *smc) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci int i ; 22962306a36Sopenharmony_ci int np ; 23062306a36Sopenharmony_ci struct s_phy *phy ; 23162306a36Sopenharmony_ci struct fddi_mib_p *mib ; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci for (np = 0,phy = smc->y ; np < NUMPHYS ; np++,phy++) { 23462306a36Sopenharmony_ci /* Indicates the type of PHY being used */ 23562306a36Sopenharmony_ci mib = phy->mib ; 23662306a36Sopenharmony_ci mib->fddiPORTPCMState = ACTIONS(PC0_OFF) ; 23762306a36Sopenharmony_ci phy->np = np ; 23862306a36Sopenharmony_ci switch (smc->s.sas) { 23962306a36Sopenharmony_ci#ifdef CONCENTRATOR 24062306a36Sopenharmony_ci case SMT_SAS : 24162306a36Sopenharmony_ci mib->fddiPORTMy_Type = (np == PS) ? TS : TM ; 24262306a36Sopenharmony_ci break ; 24362306a36Sopenharmony_ci case SMT_DAS : 24462306a36Sopenharmony_ci mib->fddiPORTMy_Type = (np == PA) ? TA : 24562306a36Sopenharmony_ci (np == PB) ? TB : TM ; 24662306a36Sopenharmony_ci break ; 24762306a36Sopenharmony_ci case SMT_NAC : 24862306a36Sopenharmony_ci mib->fddiPORTMy_Type = TM ; 24962306a36Sopenharmony_ci break; 25062306a36Sopenharmony_ci#else 25162306a36Sopenharmony_ci case SMT_SAS : 25262306a36Sopenharmony_ci mib->fddiPORTMy_Type = (np == PS) ? TS : TNONE ; 25362306a36Sopenharmony_ci mib->fddiPORTHardwarePresent = (np == PS) ? TRUE : 25462306a36Sopenharmony_ci FALSE ; 25562306a36Sopenharmony_ci#ifndef SUPERNET_3 25662306a36Sopenharmony_ci smc->y[PA].mib->fddiPORTPCMState = PC0_OFF ; 25762306a36Sopenharmony_ci#else 25862306a36Sopenharmony_ci smc->y[PB].mib->fddiPORTPCMState = PC0_OFF ; 25962306a36Sopenharmony_ci#endif 26062306a36Sopenharmony_ci break ; 26162306a36Sopenharmony_ci case SMT_DAS : 26262306a36Sopenharmony_ci mib->fddiPORTMy_Type = (np == PB) ? TB : TA ; 26362306a36Sopenharmony_ci break ; 26462306a36Sopenharmony_ci#endif 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci /* 26762306a36Sopenharmony_ci * set PMD-type 26862306a36Sopenharmony_ci */ 26962306a36Sopenharmony_ci phy->pmd_scramble = 0 ; 27062306a36Sopenharmony_ci switch (phy->pmd_type[PMD_SK_PMD]) { 27162306a36Sopenharmony_ci case 'P' : 27262306a36Sopenharmony_ci mib->fddiPORTPMDClass = MIB_PMDCLASS_MULTI ; 27362306a36Sopenharmony_ci break ; 27462306a36Sopenharmony_ci case 'L' : 27562306a36Sopenharmony_ci mib->fddiPORTPMDClass = MIB_PMDCLASS_LCF ; 27662306a36Sopenharmony_ci break ; 27762306a36Sopenharmony_ci case 'D' : 27862306a36Sopenharmony_ci mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ; 27962306a36Sopenharmony_ci break ; 28062306a36Sopenharmony_ci case 'S' : 28162306a36Sopenharmony_ci mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ; 28262306a36Sopenharmony_ci phy->pmd_scramble = TRUE ; 28362306a36Sopenharmony_ci break ; 28462306a36Sopenharmony_ci case 'U' : 28562306a36Sopenharmony_ci mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ; 28662306a36Sopenharmony_ci phy->pmd_scramble = TRUE ; 28762306a36Sopenharmony_ci break ; 28862306a36Sopenharmony_ci case '1' : 28962306a36Sopenharmony_ci mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE1 ; 29062306a36Sopenharmony_ci break ; 29162306a36Sopenharmony_ci case '2' : 29262306a36Sopenharmony_ci mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE2 ; 29362306a36Sopenharmony_ci break ; 29462306a36Sopenharmony_ci case '3' : 29562306a36Sopenharmony_ci mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE2 ; 29662306a36Sopenharmony_ci break ; 29762306a36Sopenharmony_ci case '4' : 29862306a36Sopenharmony_ci mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE1 ; 29962306a36Sopenharmony_ci break ; 30062306a36Sopenharmony_ci case 'H' : 30162306a36Sopenharmony_ci mib->fddiPORTPMDClass = MIB_PMDCLASS_UNKNOWN ; 30262306a36Sopenharmony_ci break ; 30362306a36Sopenharmony_ci case 'I' : 30462306a36Sopenharmony_ci mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ; 30562306a36Sopenharmony_ci break ; 30662306a36Sopenharmony_ci case 'G' : 30762306a36Sopenharmony_ci mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ; 30862306a36Sopenharmony_ci break ; 30962306a36Sopenharmony_ci default: 31062306a36Sopenharmony_ci mib->fddiPORTPMDClass = MIB_PMDCLASS_UNKNOWN ; 31162306a36Sopenharmony_ci break ; 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci /* 31462306a36Sopenharmony_ci * A and B port can be on primary and secondary path 31562306a36Sopenharmony_ci */ 31662306a36Sopenharmony_ci switch (mib->fddiPORTMy_Type) { 31762306a36Sopenharmony_ci case TA : 31862306a36Sopenharmony_ci mib->fddiPORTAvailablePaths |= MIB_PATH_S ; 31962306a36Sopenharmony_ci mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ; 32062306a36Sopenharmony_ci mib->fddiPORTRequestedPaths[2] = 32162306a36Sopenharmony_ci MIB_P_PATH_LOCAL | 32262306a36Sopenharmony_ci MIB_P_PATH_CON_ALTER | 32362306a36Sopenharmony_ci MIB_P_PATH_SEC_PREFER ; 32462306a36Sopenharmony_ci mib->fddiPORTRequestedPaths[3] = 32562306a36Sopenharmony_ci MIB_P_PATH_LOCAL | 32662306a36Sopenharmony_ci MIB_P_PATH_CON_ALTER | 32762306a36Sopenharmony_ci MIB_P_PATH_SEC_PREFER | 32862306a36Sopenharmony_ci MIB_P_PATH_THRU ; 32962306a36Sopenharmony_ci break ; 33062306a36Sopenharmony_ci case TB : 33162306a36Sopenharmony_ci mib->fddiPORTAvailablePaths |= MIB_PATH_S ; 33262306a36Sopenharmony_ci mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ; 33362306a36Sopenharmony_ci mib->fddiPORTRequestedPaths[2] = 33462306a36Sopenharmony_ci MIB_P_PATH_LOCAL | 33562306a36Sopenharmony_ci MIB_P_PATH_PRIM_PREFER ; 33662306a36Sopenharmony_ci mib->fddiPORTRequestedPaths[3] = 33762306a36Sopenharmony_ci MIB_P_PATH_LOCAL | 33862306a36Sopenharmony_ci MIB_P_PATH_PRIM_PREFER | 33962306a36Sopenharmony_ci MIB_P_PATH_CON_PREFER | 34062306a36Sopenharmony_ci MIB_P_PATH_THRU ; 34162306a36Sopenharmony_ci break ; 34262306a36Sopenharmony_ci case TS : 34362306a36Sopenharmony_ci mib->fddiPORTAvailablePaths |= MIB_PATH_S ; 34462306a36Sopenharmony_ci mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ; 34562306a36Sopenharmony_ci mib->fddiPORTRequestedPaths[2] = 34662306a36Sopenharmony_ci MIB_P_PATH_LOCAL | 34762306a36Sopenharmony_ci MIB_P_PATH_CON_ALTER | 34862306a36Sopenharmony_ci MIB_P_PATH_PRIM_PREFER ; 34962306a36Sopenharmony_ci mib->fddiPORTRequestedPaths[3] = 35062306a36Sopenharmony_ci MIB_P_PATH_LOCAL | 35162306a36Sopenharmony_ci MIB_P_PATH_CON_ALTER | 35262306a36Sopenharmony_ci MIB_P_PATH_PRIM_PREFER ; 35362306a36Sopenharmony_ci break ; 35462306a36Sopenharmony_ci case TM : 35562306a36Sopenharmony_ci mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ; 35662306a36Sopenharmony_ci mib->fddiPORTRequestedPaths[2] = 35762306a36Sopenharmony_ci MIB_P_PATH_LOCAL | 35862306a36Sopenharmony_ci MIB_P_PATH_SEC_ALTER | 35962306a36Sopenharmony_ci MIB_P_PATH_PRIM_ALTER ; 36062306a36Sopenharmony_ci mib->fddiPORTRequestedPaths[3] = 0 ; 36162306a36Sopenharmony_ci break ; 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci phy->pc_lem_fail = FALSE ; 36562306a36Sopenharmony_ci mib->fddiPORTPCMStateX = mib->fddiPORTPCMState ; 36662306a36Sopenharmony_ci mib->fddiPORTLCTFail_Ct = 0 ; 36762306a36Sopenharmony_ci mib->fddiPORTBS_Flag = 0 ; 36862306a36Sopenharmony_ci mib->fddiPORTCurrentPath = MIB_PATH_ISOLATED ; 36962306a36Sopenharmony_ci mib->fddiPORTNeighborType = TNONE ; 37062306a36Sopenharmony_ci phy->ls_flag = 0 ; 37162306a36Sopenharmony_ci phy->rc_flag = 0 ; 37262306a36Sopenharmony_ci phy->tc_flag = 0 ; 37362306a36Sopenharmony_ci phy->td_flag = 0 ; 37462306a36Sopenharmony_ci if (np >= PM) 37562306a36Sopenharmony_ci phy->phy_name = '0' + np - PM ; 37662306a36Sopenharmony_ci else 37762306a36Sopenharmony_ci phy->phy_name = 'A' + np ; 37862306a36Sopenharmony_ci phy->wc_flag = FALSE ; /* set by SMT */ 37962306a36Sopenharmony_ci memset((char *)&phy->lem,0,sizeof(struct lem_counter)) ; 38062306a36Sopenharmony_ci reset_lem_struct(phy) ; 38162306a36Sopenharmony_ci memset((char *)&phy->plc,0,sizeof(struct s_plc)) ; 38262306a36Sopenharmony_ci phy->plc.p_state = PS_OFF ; 38362306a36Sopenharmony_ci for (i = 0 ; i < NUMBITS ; i++) { 38462306a36Sopenharmony_ci phy->t_next[i] = 0 ; 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci real_init_plc(smc) ; 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_civoid init_plc(struct s_smc *smc) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci SK_UNUSED(smc) ; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci /* 39562306a36Sopenharmony_ci * dummy 39662306a36Sopenharmony_ci * this is an obsolete public entry point that has to remain 39762306a36Sopenharmony_ci * for compat. It is used by various drivers. 39862306a36Sopenharmony_ci * the work is now done in real_init_plc() 39962306a36Sopenharmony_ci * which is called from pcm_init() ; 40062306a36Sopenharmony_ci */ 40162306a36Sopenharmony_ci} 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_cistatic void real_init_plc(struct s_smc *smc) 40462306a36Sopenharmony_ci{ 40562306a36Sopenharmony_ci int p ; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci for (p = 0 ; p < NUMPHYS ; p++) 40862306a36Sopenharmony_ci plc_init(smc,p) ; 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cistatic void plc_init(struct s_smc *smc, int p) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci int i ; 41462306a36Sopenharmony_ci#ifndef MOT_ELM 41562306a36Sopenharmony_ci int rev ; /* Revision of PLC-x */ 41662306a36Sopenharmony_ci#endif /* MOT_ELM */ 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci /* transit PCM state machine to MAINT state */ 41962306a36Sopenharmony_ci outpw(PLC(p,PL_CNTRL_B),0) ; 42062306a36Sopenharmony_ci outpw(PLC(p,PL_CNTRL_B),PL_PCM_STOP) ; 42162306a36Sopenharmony_ci outpw(PLC(p,PL_CNTRL_A),0) ; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci /* 42462306a36Sopenharmony_ci * if PLC-S then set control register C 42562306a36Sopenharmony_ci */ 42662306a36Sopenharmony_ci#ifndef MOT_ELM 42762306a36Sopenharmony_ci rev = inpw(PLC(p,PL_STATUS_A)) & PLC_REV_MASK ; 42862306a36Sopenharmony_ci if (rev != PLC_REVISION_A) 42962306a36Sopenharmony_ci#endif /* MOT_ELM */ 43062306a36Sopenharmony_ci { 43162306a36Sopenharmony_ci if (smc->y[p].pmd_scramble) { 43262306a36Sopenharmony_ci outpw(PLC(p,PL_CNTRL_C),PLCS_CONTROL_C_S) ; 43362306a36Sopenharmony_ci#ifdef MOT_ELM 43462306a36Sopenharmony_ci outpw(PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_S) ; 43562306a36Sopenharmony_ci outpw(PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_S) ; 43662306a36Sopenharmony_ci#endif /* MOT_ELM */ 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci else { 43962306a36Sopenharmony_ci outpw(PLC(p,PL_CNTRL_C),PLCS_CONTROL_C_U) ; 44062306a36Sopenharmony_ci#ifdef MOT_ELM 44162306a36Sopenharmony_ci outpw(PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_U) ; 44262306a36Sopenharmony_ci outpw(PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_U) ; 44362306a36Sopenharmony_ci#endif /* MOT_ELM */ 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci /* 44862306a36Sopenharmony_ci * set timer register 44962306a36Sopenharmony_ci */ 45062306a36Sopenharmony_ci for ( i = 0 ; pltm[i].timer; i++) /* set timer parameter reg */ 45162306a36Sopenharmony_ci outpw(PLC(p,pltm[i].timer),pltm[i].para) ; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci (void)inpw(PLC(p,PL_INTR_EVENT)) ; /* clear interrupt event reg */ 45462306a36Sopenharmony_ci plc_clear_irq(smc,p) ; 45562306a36Sopenharmony_ci outpw(PLC(p,PL_INTR_MASK),plc_imsk_na); /* enable non active irq's */ 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci /* 45862306a36Sopenharmony_ci * if PCM is configured for class s, it will NOT go to the 45962306a36Sopenharmony_ci * REMOVE state if offline (page 3-36;) 46062306a36Sopenharmony_ci * in the concentrator, all inactive PHYS always must be in 46162306a36Sopenharmony_ci * the remove state 46262306a36Sopenharmony_ci * there's no real need to use this feature at all .. 46362306a36Sopenharmony_ci */ 46462306a36Sopenharmony_ci#ifndef CONCENTRATOR 46562306a36Sopenharmony_ci if ((smc->s.sas == SMT_SAS) && (p == PS)) { 46662306a36Sopenharmony_ci outpw(PLC(p,PL_CNTRL_B),PL_CLASS_S) ; 46762306a36Sopenharmony_ci } 46862306a36Sopenharmony_ci#endif 46962306a36Sopenharmony_ci} 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci/* 47262306a36Sopenharmony_ci * control PCM state machine 47362306a36Sopenharmony_ci */ 47462306a36Sopenharmony_cistatic void plc_go_state(struct s_smc *smc, int p, int state) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci HW_PTR port ; 47762306a36Sopenharmony_ci int val ; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci SK_UNUSED(smc) ; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci port = (HW_PTR) (PLC(p,PL_CNTRL_B)) ; 48262306a36Sopenharmony_ci val = inpw(port) & ~(PL_PCM_CNTRL | PL_MAINT) ; 48362306a36Sopenharmony_ci outpw(port,val) ; 48462306a36Sopenharmony_ci outpw(port,val | state) ; 48562306a36Sopenharmony_ci} 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci/* 48862306a36Sopenharmony_ci * read current line state (called by ECM & PCM) 48962306a36Sopenharmony_ci */ 49062306a36Sopenharmony_ciint sm_pm_get_ls(struct s_smc *smc, int phy) 49162306a36Sopenharmony_ci{ 49262306a36Sopenharmony_ci int state ; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci#ifdef CONCENTRATOR 49562306a36Sopenharmony_ci if (!plc_is_installed(smc,phy)) 49662306a36Sopenharmony_ci return PC_QLS; 49762306a36Sopenharmony_ci#endif 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci state = inpw(PLC(phy,PL_STATUS_A)) & PL_LINE_ST ; 50062306a36Sopenharmony_ci switch(state) { 50162306a36Sopenharmony_ci case PL_L_QLS: 50262306a36Sopenharmony_ci state = PC_QLS ; 50362306a36Sopenharmony_ci break ; 50462306a36Sopenharmony_ci case PL_L_MLS: 50562306a36Sopenharmony_ci state = PC_MLS ; 50662306a36Sopenharmony_ci break ; 50762306a36Sopenharmony_ci case PL_L_HLS: 50862306a36Sopenharmony_ci state = PC_HLS ; 50962306a36Sopenharmony_ci break ; 51062306a36Sopenharmony_ci case PL_L_ILS4: 51162306a36Sopenharmony_ci case PL_L_ILS16: 51262306a36Sopenharmony_ci state = PC_ILS ; 51362306a36Sopenharmony_ci break ; 51462306a36Sopenharmony_ci case PL_L_ALS: 51562306a36Sopenharmony_ci state = PC_LS_PDR ; 51662306a36Sopenharmony_ci break ; 51762306a36Sopenharmony_ci default : 51862306a36Sopenharmony_ci state = PC_LS_NONE ; 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci return state; 52162306a36Sopenharmony_ci} 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_cistatic int plc_send_bits(struct s_smc *smc, struct s_phy *phy, int len) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci int np = phy->np ; /* PHY index */ 52662306a36Sopenharmony_ci int n ; 52762306a36Sopenharmony_ci int i ; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci SK_UNUSED(smc) ; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci /* create bit vector */ 53262306a36Sopenharmony_ci for (i = len-1,n = 0 ; i >= 0 ; i--) { 53362306a36Sopenharmony_ci n = (n<<1) | phy->t_val[phy->bitn+i] ; 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) { 53662306a36Sopenharmony_ci#if 0 53762306a36Sopenharmony_ci printf("PL_PCM_SIGNAL is set\n") ; 53862306a36Sopenharmony_ci#endif 53962306a36Sopenharmony_ci return 1; 54062306a36Sopenharmony_ci } 54162306a36Sopenharmony_ci /* write bit[n] & length = 1 to regs */ 54262306a36Sopenharmony_ci outpw(PLC(np,PL_VECTOR_LEN),len-1) ; /* len=nr-1 */ 54362306a36Sopenharmony_ci outpw(PLC(np,PL_XMIT_VECTOR),n) ; 54462306a36Sopenharmony_ci#ifdef DEBUG 54562306a36Sopenharmony_ci#if 1 54662306a36Sopenharmony_ci#ifdef DEBUG_BRD 54762306a36Sopenharmony_ci if (smc->debug.d_plc & 0x80) 54862306a36Sopenharmony_ci#else 54962306a36Sopenharmony_ci if (debug.d_plc & 0x80) 55062306a36Sopenharmony_ci#endif 55162306a36Sopenharmony_ci printf("SIGNALING bit %d .. %d\n",phy->bitn,phy->bitn+len-1) ; 55262306a36Sopenharmony_ci#endif 55362306a36Sopenharmony_ci#endif 55462306a36Sopenharmony_ci return 0; 55562306a36Sopenharmony_ci} 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci/* 55862306a36Sopenharmony_ci * config plc muxes 55962306a36Sopenharmony_ci */ 56062306a36Sopenharmony_civoid plc_config_mux(struct s_smc *smc, int mux) 56162306a36Sopenharmony_ci{ 56262306a36Sopenharmony_ci if (smc->s.sas != SMT_DAS) 56362306a36Sopenharmony_ci return ; 56462306a36Sopenharmony_ci if (mux == MUX_WRAPB) { 56562306a36Sopenharmony_ci SETMASK(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ; 56662306a36Sopenharmony_ci SETMASK(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP,PL_SC_REM_LOOP) ; 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci else { 56962306a36Sopenharmony_ci CLEAR(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL) ; 57062306a36Sopenharmony_ci CLEAR(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP) ; 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci CLEAR(PLC(PB,PL_CNTRL_B),PL_CONFIG_CNTRL) ; 57362306a36Sopenharmony_ci CLEAR(PLC(PB,PL_CNTRL_A),PL_SC_REM_LOOP) ; 57462306a36Sopenharmony_ci} 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci/* 57762306a36Sopenharmony_ci PCM state machine 57862306a36Sopenharmony_ci called by dispatcher & fddi_init() (driver) 57962306a36Sopenharmony_ci do 58062306a36Sopenharmony_ci display state change 58162306a36Sopenharmony_ci process event 58262306a36Sopenharmony_ci until SM is stable 58362306a36Sopenharmony_ci*/ 58462306a36Sopenharmony_civoid pcm(struct s_smc *smc, const int np, int event) 58562306a36Sopenharmony_ci{ 58662306a36Sopenharmony_ci int state ; 58762306a36Sopenharmony_ci int oldstate ; 58862306a36Sopenharmony_ci struct s_phy *phy ; 58962306a36Sopenharmony_ci struct fddi_mib_p *mib ; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci#ifndef CONCENTRATOR 59262306a36Sopenharmony_ci /* 59362306a36Sopenharmony_ci * ignore 2nd PHY if SAS 59462306a36Sopenharmony_ci */ 59562306a36Sopenharmony_ci if ((np != PS) && (smc->s.sas == SMT_SAS)) 59662306a36Sopenharmony_ci return ; 59762306a36Sopenharmony_ci#endif 59862306a36Sopenharmony_ci phy = &smc->y[np] ; 59962306a36Sopenharmony_ci mib = phy->mib ; 60062306a36Sopenharmony_ci oldstate = mib->fddiPORTPCMState ; 60162306a36Sopenharmony_ci do { 60262306a36Sopenharmony_ci DB_PCM("PCM %c: state %s%s, event %s", 60362306a36Sopenharmony_ci phy->phy_name, 60462306a36Sopenharmony_ci mib->fddiPORTPCMState & AFLAG ? "ACTIONS " : "", 60562306a36Sopenharmony_ci pcm_states[mib->fddiPORTPCMState & ~AFLAG], 60662306a36Sopenharmony_ci pcm_events[event]); 60762306a36Sopenharmony_ci state = mib->fddiPORTPCMState ; 60862306a36Sopenharmony_ci pcm_fsm(smc,phy,event) ; 60962306a36Sopenharmony_ci event = 0 ; 61062306a36Sopenharmony_ci } while (state != mib->fddiPORTPCMState) ; 61162306a36Sopenharmony_ci /* 61262306a36Sopenharmony_ci * because the PLC does the bit signaling for us, 61362306a36Sopenharmony_ci * we're always in SIGNAL state 61462306a36Sopenharmony_ci * the MIB want's to see CONNECT 61562306a36Sopenharmony_ci * we therefore fake an entry in the MIB 61662306a36Sopenharmony_ci */ 61762306a36Sopenharmony_ci if (state == PC5_SIGNAL) 61862306a36Sopenharmony_ci mib->fddiPORTPCMStateX = PC3_CONNECT ; 61962306a36Sopenharmony_ci else 62062306a36Sopenharmony_ci mib->fddiPORTPCMStateX = state ; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci#ifndef SLIM_SMT 62362306a36Sopenharmony_ci /* 62462306a36Sopenharmony_ci * path change 62562306a36Sopenharmony_ci */ 62662306a36Sopenharmony_ci if ( mib->fddiPORTPCMState != oldstate && 62762306a36Sopenharmony_ci ((oldstate == PC8_ACTIVE) || (mib->fddiPORTPCMState == PC8_ACTIVE))) { 62862306a36Sopenharmony_ci smt_srf_event(smc,SMT_EVENT_PORT_PATH_CHANGE, 62962306a36Sopenharmony_ci (int) (INDEX_PORT+ phy->np),0) ; 63062306a36Sopenharmony_ci } 63162306a36Sopenharmony_ci#endif 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci#ifdef FDDI_MIB 63462306a36Sopenharmony_ci /* check whether a snmp-trap has to be sent */ 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci if ( mib->fddiPORTPCMState != oldstate ) { 63762306a36Sopenharmony_ci /* a real state change took place */ 63862306a36Sopenharmony_ci DB_SNMP ("PCM from %d to %d\n", oldstate, mib->fddiPORTPCMState); 63962306a36Sopenharmony_ci if ( mib->fddiPORTPCMState == PC0_OFF ) { 64062306a36Sopenharmony_ci /* send first trap */ 64162306a36Sopenharmony_ci snmp_fddi_trap (smc, 1, (int) mib->fddiPORTIndex ); 64262306a36Sopenharmony_ci } else if ( oldstate == PC0_OFF ) { 64362306a36Sopenharmony_ci /* send second trap */ 64462306a36Sopenharmony_ci snmp_fddi_trap (smc, 2, (int) mib->fddiPORTIndex ); 64562306a36Sopenharmony_ci } else if ( mib->fddiPORTPCMState != PC2_TRACE && 64662306a36Sopenharmony_ci oldstate == PC8_ACTIVE ) { 64762306a36Sopenharmony_ci /* send third trap */ 64862306a36Sopenharmony_ci snmp_fddi_trap (smc, 3, (int) mib->fddiPORTIndex ); 64962306a36Sopenharmony_ci } else if ( mib->fddiPORTPCMState == PC8_ACTIVE ) { 65062306a36Sopenharmony_ci /* send fourth trap */ 65162306a36Sopenharmony_ci snmp_fddi_trap (smc, 4, (int) mib->fddiPORTIndex ); 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci#endif 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci pcm_state_change(smc,np,state) ; 65762306a36Sopenharmony_ci} 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci/* 66062306a36Sopenharmony_ci * PCM state machine 66162306a36Sopenharmony_ci */ 66262306a36Sopenharmony_cistatic void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd) 66362306a36Sopenharmony_ci{ 66462306a36Sopenharmony_ci int i ; 66562306a36Sopenharmony_ci int np = phy->np ; /* PHY index */ 66662306a36Sopenharmony_ci struct s_plc *plc ; 66762306a36Sopenharmony_ci struct fddi_mib_p *mib ; 66862306a36Sopenharmony_ci#ifndef MOT_ELM 66962306a36Sopenharmony_ci u_short plc_rev ; /* Revision of the plc */ 67062306a36Sopenharmony_ci#endif /* nMOT_ELM */ 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci plc = &phy->plc ; 67362306a36Sopenharmony_ci mib = phy->mib ; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci /* 67662306a36Sopenharmony_ci * general transitions independent of state 67762306a36Sopenharmony_ci */ 67862306a36Sopenharmony_ci switch (cmd) { 67962306a36Sopenharmony_ci case PC_STOP : 68062306a36Sopenharmony_ci /*PC00-PC80*/ 68162306a36Sopenharmony_ci if (mib->fddiPORTPCMState != PC9_MAINT) { 68262306a36Sopenharmony_ci GO_STATE(PC0_OFF) ; 68362306a36Sopenharmony_ci AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long) 68462306a36Sopenharmony_ci FDDI_PORT_EVENT, (u_long) FDDI_PORT_STOP, 68562306a36Sopenharmony_ci smt_get_port_event_word(smc)); 68662306a36Sopenharmony_ci } 68762306a36Sopenharmony_ci return ; 68862306a36Sopenharmony_ci case PC_START : 68962306a36Sopenharmony_ci /*PC01-PC81*/ 69062306a36Sopenharmony_ci if (mib->fddiPORTPCMState != PC9_MAINT) 69162306a36Sopenharmony_ci GO_STATE(PC1_BREAK) ; 69262306a36Sopenharmony_ci return ; 69362306a36Sopenharmony_ci case PC_DISABLE : 69462306a36Sopenharmony_ci /* PC09-PC99 */ 69562306a36Sopenharmony_ci GO_STATE(PC9_MAINT) ; 69662306a36Sopenharmony_ci AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long) 69762306a36Sopenharmony_ci FDDI_PORT_EVENT, (u_long) FDDI_PORT_DISABLED, 69862306a36Sopenharmony_ci smt_get_port_event_word(smc)); 69962306a36Sopenharmony_ci return ; 70062306a36Sopenharmony_ci case PC_TIMEOUT_LCT : 70162306a36Sopenharmony_ci /* if long or extended LCT */ 70262306a36Sopenharmony_ci stop_pcm_timer0(smc,phy) ; 70362306a36Sopenharmony_ci CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ; 70462306a36Sopenharmony_ci /* end of LCT is indicate by PCM_CODE (initiate PCM event) */ 70562306a36Sopenharmony_ci return ; 70662306a36Sopenharmony_ci } 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci switch(mib->fddiPORTPCMState) { 70962306a36Sopenharmony_ci case ACTIONS(PC0_OFF) : 71062306a36Sopenharmony_ci stop_pcm_timer0(smc,phy) ; 71162306a36Sopenharmony_ci outpw(PLC(np,PL_CNTRL_A),0) ; 71262306a36Sopenharmony_ci CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ; 71362306a36Sopenharmony_ci CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ; 71462306a36Sopenharmony_ci sm_ph_lem_stop(smc,np) ; /* disable LEM */ 71562306a36Sopenharmony_ci phy->cf_loop = FALSE ; 71662306a36Sopenharmony_ci phy->cf_join = FALSE ; 71762306a36Sopenharmony_ci queue_event(smc,EVENT_CFM,CF_JOIN+np) ; 71862306a36Sopenharmony_ci plc_go_state(smc,np,PL_PCM_STOP) ; 71962306a36Sopenharmony_ci mib->fddiPORTConnectState = PCM_DISABLED ; 72062306a36Sopenharmony_ci ACTIONS_DONE() ; 72162306a36Sopenharmony_ci break ; 72262306a36Sopenharmony_ci case PC0_OFF: 72362306a36Sopenharmony_ci /*PC09*/ 72462306a36Sopenharmony_ci if (cmd == PC_MAINT) { 72562306a36Sopenharmony_ci GO_STATE(PC9_MAINT) ; 72662306a36Sopenharmony_ci break ; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci break ; 72962306a36Sopenharmony_ci case ACTIONS(PC1_BREAK) : 73062306a36Sopenharmony_ci /* Stop the LCT timer if we came from Signal state */ 73162306a36Sopenharmony_ci stop_pcm_timer0(smc,phy) ; 73262306a36Sopenharmony_ci ACTIONS_DONE() ; 73362306a36Sopenharmony_ci plc_go_state(smc,np,0) ; 73462306a36Sopenharmony_ci CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ; 73562306a36Sopenharmony_ci CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ; 73662306a36Sopenharmony_ci sm_ph_lem_stop(smc,np) ; /* disable LEM */ 73762306a36Sopenharmony_ci /* 73862306a36Sopenharmony_ci * if vector is already loaded, go to OFF to clear PCM_SIGNAL 73962306a36Sopenharmony_ci */ 74062306a36Sopenharmony_ci#if 0 74162306a36Sopenharmony_ci if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) { 74262306a36Sopenharmony_ci plc_go_state(smc,np,PL_PCM_STOP) ; 74362306a36Sopenharmony_ci /* TB_MIN ? */ 74462306a36Sopenharmony_ci } 74562306a36Sopenharmony_ci#endif 74662306a36Sopenharmony_ci /* 74762306a36Sopenharmony_ci * Go to OFF state in any case. 74862306a36Sopenharmony_ci */ 74962306a36Sopenharmony_ci plc_go_state(smc,np,PL_PCM_STOP) ; 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci if (mib->fddiPORTPC_Withhold == PC_WH_NONE) 75262306a36Sopenharmony_ci mib->fddiPORTConnectState = PCM_CONNECTING ; 75362306a36Sopenharmony_ci phy->cf_loop = FALSE ; 75462306a36Sopenharmony_ci phy->cf_join = FALSE ; 75562306a36Sopenharmony_ci queue_event(smc,EVENT_CFM,CF_JOIN+np) ; 75662306a36Sopenharmony_ci phy->ls_flag = FALSE ; 75762306a36Sopenharmony_ci phy->pc_mode = PM_NONE ; /* needed by CFM */ 75862306a36Sopenharmony_ci phy->bitn = 0 ; /* bit signaling start bit */ 75962306a36Sopenharmony_ci for (i = 0 ; i < 3 ; i++) 76062306a36Sopenharmony_ci pc_tcode_actions(smc,i,phy) ; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci /* Set the non-active interrupt mask register */ 76362306a36Sopenharmony_ci outpw(PLC(np,PL_INTR_MASK),plc_imsk_na) ; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci /* 76662306a36Sopenharmony_ci * If the LCT was stopped. There might be a 76762306a36Sopenharmony_ci * PCM_CODE interrupt event present. 76862306a36Sopenharmony_ci * This must be cleared. 76962306a36Sopenharmony_ci */ 77062306a36Sopenharmony_ci (void)inpw(PLC(np,PL_INTR_EVENT)) ; 77162306a36Sopenharmony_ci#ifndef MOT_ELM 77262306a36Sopenharmony_ci /* Get the plc revision for revision dependent code */ 77362306a36Sopenharmony_ci plc_rev = inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK ; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci if (plc_rev != PLC_REV_SN3) 77662306a36Sopenharmony_ci#endif /* MOT_ELM */ 77762306a36Sopenharmony_ci { 77862306a36Sopenharmony_ci /* 77962306a36Sopenharmony_ci * No supernet III PLC, so set Xmit verctor and 78062306a36Sopenharmony_ci * length BEFORE starting the state machine. 78162306a36Sopenharmony_ci */ 78262306a36Sopenharmony_ci if (plc_send_bits(smc,phy,3)) { 78362306a36Sopenharmony_ci return ; 78462306a36Sopenharmony_ci } 78562306a36Sopenharmony_ci } 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci /* 78862306a36Sopenharmony_ci * Now give the Start command. 78962306a36Sopenharmony_ci * - The start command shall be done before setting the bits 79062306a36Sopenharmony_ci * to be signaled. (In PLC-S description and PLCS in SN3. 79162306a36Sopenharmony_ci * - The start command shall be issued AFTER setting the 79262306a36Sopenharmony_ci * XMIT vector and the XMIT length register. 79362306a36Sopenharmony_ci * 79462306a36Sopenharmony_ci * We do it exactly according this specs for the old PLC and 79562306a36Sopenharmony_ci * the new PLCS inside the SN3. 79662306a36Sopenharmony_ci * For the usual PLCS we try it the way it is done for the 79762306a36Sopenharmony_ci * old PLC and set the XMIT registers again, if the PLC is 79862306a36Sopenharmony_ci * not in SIGNAL state. This is done according to an PLCS 79962306a36Sopenharmony_ci * errata workaround. 80062306a36Sopenharmony_ci */ 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci plc_go_state(smc,np,PL_PCM_START) ; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci /* 80562306a36Sopenharmony_ci * workaround for PLC-S eng. sample errata 80662306a36Sopenharmony_ci */ 80762306a36Sopenharmony_ci#ifdef MOT_ELM 80862306a36Sopenharmony_ci if (!(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL)) 80962306a36Sopenharmony_ci#else /* nMOT_ELM */ 81062306a36Sopenharmony_ci if (((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) != 81162306a36Sopenharmony_ci PLC_REVISION_A) && 81262306a36Sopenharmony_ci !(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL)) 81362306a36Sopenharmony_ci#endif /* nMOT_ELM */ 81462306a36Sopenharmony_ci { 81562306a36Sopenharmony_ci /* 81662306a36Sopenharmony_ci * Set register again (PLCS errata) or the first time 81762306a36Sopenharmony_ci * (new SN3 PLCS). 81862306a36Sopenharmony_ci */ 81962306a36Sopenharmony_ci (void) plc_send_bits(smc,phy,3) ; 82062306a36Sopenharmony_ci } 82162306a36Sopenharmony_ci /* 82262306a36Sopenharmony_ci * end of workaround 82362306a36Sopenharmony_ci */ 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci GO_STATE(PC5_SIGNAL) ; 82662306a36Sopenharmony_ci plc->p_state = PS_BIT3 ; 82762306a36Sopenharmony_ci plc->p_bits = 3 ; 82862306a36Sopenharmony_ci plc->p_start = 0 ; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci break ; 83162306a36Sopenharmony_ci case PC1_BREAK : 83262306a36Sopenharmony_ci break ; 83362306a36Sopenharmony_ci case ACTIONS(PC2_TRACE) : 83462306a36Sopenharmony_ci plc_go_state(smc,np,PL_PCM_TRACE) ; 83562306a36Sopenharmony_ci ACTIONS_DONE() ; 83662306a36Sopenharmony_ci break ; 83762306a36Sopenharmony_ci case PC2_TRACE : 83862306a36Sopenharmony_ci break ; 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci case PC3_CONNECT : /* these states are done by hardware */ 84162306a36Sopenharmony_ci case PC4_NEXT : 84262306a36Sopenharmony_ci break ; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci case ACTIONS(PC5_SIGNAL) : 84562306a36Sopenharmony_ci ACTIONS_DONE() ; 84662306a36Sopenharmony_ci fallthrough; 84762306a36Sopenharmony_ci case PC5_SIGNAL : 84862306a36Sopenharmony_ci if ((cmd != PC_SIGNAL) && (cmd != PC_TIMEOUT_LCT)) 84962306a36Sopenharmony_ci break ; 85062306a36Sopenharmony_ci switch (plc->p_state) { 85162306a36Sopenharmony_ci case PS_BIT3 : 85262306a36Sopenharmony_ci for (i = 0 ; i <= 2 ; i++) 85362306a36Sopenharmony_ci pc_rcode_actions(smc,i,phy) ; 85462306a36Sopenharmony_ci pc_tcode_actions(smc,3,phy) ; 85562306a36Sopenharmony_ci plc->p_state = PS_BIT4 ; 85662306a36Sopenharmony_ci plc->p_bits = 1 ; 85762306a36Sopenharmony_ci plc->p_start = 3 ; 85862306a36Sopenharmony_ci phy->bitn = 3 ; 85962306a36Sopenharmony_ci if (plc_send_bits(smc,phy,1)) { 86062306a36Sopenharmony_ci return ; 86162306a36Sopenharmony_ci } 86262306a36Sopenharmony_ci break ; 86362306a36Sopenharmony_ci case PS_BIT4 : 86462306a36Sopenharmony_ci pc_rcode_actions(smc,3,phy) ; 86562306a36Sopenharmony_ci for (i = 4 ; i <= 6 ; i++) 86662306a36Sopenharmony_ci pc_tcode_actions(smc,i,phy) ; 86762306a36Sopenharmony_ci plc->p_state = PS_BIT7 ; 86862306a36Sopenharmony_ci plc->p_bits = 3 ; 86962306a36Sopenharmony_ci plc->p_start = 4 ; 87062306a36Sopenharmony_ci phy->bitn = 4 ; 87162306a36Sopenharmony_ci if (plc_send_bits(smc,phy,3)) { 87262306a36Sopenharmony_ci return ; 87362306a36Sopenharmony_ci } 87462306a36Sopenharmony_ci break ; 87562306a36Sopenharmony_ci case PS_BIT7 : 87662306a36Sopenharmony_ci for (i = 3 ; i <= 6 ; i++) 87762306a36Sopenharmony_ci pc_rcode_actions(smc,i,phy) ; 87862306a36Sopenharmony_ci plc->p_state = PS_LCT ; 87962306a36Sopenharmony_ci plc->p_bits = 0 ; 88062306a36Sopenharmony_ci plc->p_start = 7 ; 88162306a36Sopenharmony_ci phy->bitn = 7 ; 88262306a36Sopenharmony_ci sm_ph_lem_start(smc,np,(int)smc->s.lct_short) ; /* enable LEM */ 88362306a36Sopenharmony_ci /* start LCT */ 88462306a36Sopenharmony_ci i = inpw(PLC(np,PL_CNTRL_B)) & ~PL_PC_LOOP ; 88562306a36Sopenharmony_ci outpw(PLC(np,PL_CNTRL_B),i) ; /* must be cleared */ 88662306a36Sopenharmony_ci outpw(PLC(np,PL_CNTRL_B),i | PL_RLBP) ; 88762306a36Sopenharmony_ci break ; 88862306a36Sopenharmony_ci case PS_LCT : 88962306a36Sopenharmony_ci /* check for local LCT failure */ 89062306a36Sopenharmony_ci pc_tcode_actions(smc,7,phy) ; 89162306a36Sopenharmony_ci /* 89262306a36Sopenharmony_ci * set tval[7] 89362306a36Sopenharmony_ci */ 89462306a36Sopenharmony_ci plc->p_state = PS_BIT8 ; 89562306a36Sopenharmony_ci plc->p_bits = 1 ; 89662306a36Sopenharmony_ci plc->p_start = 7 ; 89762306a36Sopenharmony_ci phy->bitn = 7 ; 89862306a36Sopenharmony_ci if (plc_send_bits(smc,phy,1)) { 89962306a36Sopenharmony_ci return ; 90062306a36Sopenharmony_ci } 90162306a36Sopenharmony_ci break ; 90262306a36Sopenharmony_ci case PS_BIT8 : 90362306a36Sopenharmony_ci /* check for remote LCT failure */ 90462306a36Sopenharmony_ci pc_rcode_actions(smc,7,phy) ; 90562306a36Sopenharmony_ci if (phy->t_val[7] || phy->r_val[7]) { 90662306a36Sopenharmony_ci plc_go_state(smc,np,PL_PCM_STOP) ; 90762306a36Sopenharmony_ci GO_STATE(PC1_BREAK) ; 90862306a36Sopenharmony_ci break ; 90962306a36Sopenharmony_ci } 91062306a36Sopenharmony_ci for (i = 8 ; i <= 9 ; i++) 91162306a36Sopenharmony_ci pc_tcode_actions(smc,i,phy) ; 91262306a36Sopenharmony_ci plc->p_state = PS_JOIN ; 91362306a36Sopenharmony_ci plc->p_bits = 2 ; 91462306a36Sopenharmony_ci plc->p_start = 8 ; 91562306a36Sopenharmony_ci phy->bitn = 8 ; 91662306a36Sopenharmony_ci if (plc_send_bits(smc,phy,2)) { 91762306a36Sopenharmony_ci return ; 91862306a36Sopenharmony_ci } 91962306a36Sopenharmony_ci break ; 92062306a36Sopenharmony_ci case PS_JOIN : 92162306a36Sopenharmony_ci for (i = 8 ; i <= 9 ; i++) 92262306a36Sopenharmony_ci pc_rcode_actions(smc,i,phy) ; 92362306a36Sopenharmony_ci plc->p_state = PS_ACTIVE ; 92462306a36Sopenharmony_ci GO_STATE(PC6_JOIN) ; 92562306a36Sopenharmony_ci break ; 92662306a36Sopenharmony_ci } 92762306a36Sopenharmony_ci break ; 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci case ACTIONS(PC6_JOIN) : 93062306a36Sopenharmony_ci /* 93162306a36Sopenharmony_ci * prevent mux error when going from WRAP_A to WRAP_B 93262306a36Sopenharmony_ci */ 93362306a36Sopenharmony_ci if (smc->s.sas == SMT_DAS && np == PB && 93462306a36Sopenharmony_ci (smc->y[PA].pc_mode == PM_TREE || 93562306a36Sopenharmony_ci smc->y[PB].pc_mode == PM_TREE)) { 93662306a36Sopenharmony_ci SETMASK(PLC(np,PL_CNTRL_A), 93762306a36Sopenharmony_ci PL_SC_REM_LOOP,PL_SC_REM_LOOP) ; 93862306a36Sopenharmony_ci SETMASK(PLC(np,PL_CNTRL_B), 93962306a36Sopenharmony_ci PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ; 94062306a36Sopenharmony_ci } 94162306a36Sopenharmony_ci SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ; 94262306a36Sopenharmony_ci SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ; 94362306a36Sopenharmony_ci ACTIONS_DONE() ; 94462306a36Sopenharmony_ci cmd = 0 ; 94562306a36Sopenharmony_ci fallthrough; 94662306a36Sopenharmony_ci case PC6_JOIN : 94762306a36Sopenharmony_ci switch (plc->p_state) { 94862306a36Sopenharmony_ci case PS_ACTIVE: 94962306a36Sopenharmony_ci /*PC88b*/ 95062306a36Sopenharmony_ci if (!phy->cf_join) { 95162306a36Sopenharmony_ci phy->cf_join = TRUE ; 95262306a36Sopenharmony_ci queue_event(smc,EVENT_CFM,CF_JOIN+np) ; 95362306a36Sopenharmony_ci } 95462306a36Sopenharmony_ci if (cmd == PC_JOIN) 95562306a36Sopenharmony_ci GO_STATE(PC8_ACTIVE) ; 95662306a36Sopenharmony_ci /*PC82*/ 95762306a36Sopenharmony_ci if (cmd == PC_TRACE) { 95862306a36Sopenharmony_ci GO_STATE(PC2_TRACE) ; 95962306a36Sopenharmony_ci break ; 96062306a36Sopenharmony_ci } 96162306a36Sopenharmony_ci break ; 96262306a36Sopenharmony_ci } 96362306a36Sopenharmony_ci break ; 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci case PC7_VERIFY : 96662306a36Sopenharmony_ci break ; 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci case ACTIONS(PC8_ACTIVE) : 96962306a36Sopenharmony_ci /* 97062306a36Sopenharmony_ci * start LEM for SMT 97162306a36Sopenharmony_ci */ 97262306a36Sopenharmony_ci sm_ph_lem_start(smc,(int)phy->np,LCT_LEM_MAX) ; 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci phy->tr_flag = FALSE ; 97562306a36Sopenharmony_ci mib->fddiPORTConnectState = PCM_ACTIVE ; 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci /* Set the active interrupt mask register */ 97862306a36Sopenharmony_ci outpw(PLC(np,PL_INTR_MASK),plc_imsk_act) ; 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci ACTIONS_DONE() ; 98162306a36Sopenharmony_ci break ; 98262306a36Sopenharmony_ci case PC8_ACTIVE : 98362306a36Sopenharmony_ci /*PC81 is done by PL_TNE_EXPIRED irq */ 98462306a36Sopenharmony_ci /*PC82*/ 98562306a36Sopenharmony_ci if (cmd == PC_TRACE) { 98662306a36Sopenharmony_ci GO_STATE(PC2_TRACE) ; 98762306a36Sopenharmony_ci break ; 98862306a36Sopenharmony_ci } 98962306a36Sopenharmony_ci /*PC88c: is done by TRACE_PROP irq */ 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci break ; 99262306a36Sopenharmony_ci case ACTIONS(PC9_MAINT) : 99362306a36Sopenharmony_ci stop_pcm_timer0(smc,phy) ; 99462306a36Sopenharmony_ci CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ; 99562306a36Sopenharmony_ci CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ; 99662306a36Sopenharmony_ci CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ; /* disable LEM int. */ 99762306a36Sopenharmony_ci sm_ph_lem_stop(smc,np) ; /* disable LEM */ 99862306a36Sopenharmony_ci phy->cf_loop = FALSE ; 99962306a36Sopenharmony_ci phy->cf_join = FALSE ; 100062306a36Sopenharmony_ci queue_event(smc,EVENT_CFM,CF_JOIN+np) ; 100162306a36Sopenharmony_ci plc_go_state(smc,np,PL_PCM_STOP) ; 100262306a36Sopenharmony_ci mib->fddiPORTConnectState = PCM_DISABLED ; 100362306a36Sopenharmony_ci SETMASK(PLC(np,PL_CNTRL_B),PL_MAINT,PL_MAINT) ; 100462306a36Sopenharmony_ci sm_ph_linestate(smc,np,(int) MIB2LS(mib->fddiPORTMaint_LS)) ; 100562306a36Sopenharmony_ci outpw(PLC(np,PL_CNTRL_A),PL_SC_BYPASS) ; 100662306a36Sopenharmony_ci ACTIONS_DONE() ; 100762306a36Sopenharmony_ci break ; 100862306a36Sopenharmony_ci case PC9_MAINT : 100962306a36Sopenharmony_ci DB_PCMN(1, "PCM %c : MAINT", phy->phy_name); 101062306a36Sopenharmony_ci /*PC90*/ 101162306a36Sopenharmony_ci if (cmd == PC_ENABLE) { 101262306a36Sopenharmony_ci GO_STATE(PC0_OFF) ; 101362306a36Sopenharmony_ci break ; 101462306a36Sopenharmony_ci } 101562306a36Sopenharmony_ci break ; 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci default: 101862306a36Sopenharmony_ci SMT_PANIC(smc,SMT_E0118, SMT_E0118_MSG) ; 101962306a36Sopenharmony_ci break ; 102062306a36Sopenharmony_ci } 102162306a36Sopenharmony_ci} 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci/* 102462306a36Sopenharmony_ci * force line state on a PHY output (only in MAINT state) 102562306a36Sopenharmony_ci */ 102662306a36Sopenharmony_cistatic void sm_ph_linestate(struct s_smc *smc, int phy, int ls) 102762306a36Sopenharmony_ci{ 102862306a36Sopenharmony_ci int cntrl ; 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci SK_UNUSED(smc) ; 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci cntrl = (inpw(PLC(phy,PL_CNTRL_B)) & ~PL_MAINT_LS) | 103362306a36Sopenharmony_ci PL_PCM_STOP | PL_MAINT ; 103462306a36Sopenharmony_ci switch(ls) { 103562306a36Sopenharmony_ci case PC_QLS: /* Force Quiet */ 103662306a36Sopenharmony_ci cntrl |= PL_M_QUI0 ; 103762306a36Sopenharmony_ci break ; 103862306a36Sopenharmony_ci case PC_MLS: /* Force Master */ 103962306a36Sopenharmony_ci cntrl |= PL_M_MASTR ; 104062306a36Sopenharmony_ci break ; 104162306a36Sopenharmony_ci case PC_HLS: /* Force Halt */ 104262306a36Sopenharmony_ci cntrl |= PL_M_HALT ; 104362306a36Sopenharmony_ci break ; 104462306a36Sopenharmony_ci default : 104562306a36Sopenharmony_ci case PC_ILS: /* Force Idle */ 104662306a36Sopenharmony_ci cntrl |= PL_M_IDLE ; 104762306a36Sopenharmony_ci break ; 104862306a36Sopenharmony_ci case PC_LS_PDR: /* Enable repeat filter */ 104962306a36Sopenharmony_ci cntrl |= PL_M_TPDR ; 105062306a36Sopenharmony_ci break ; 105162306a36Sopenharmony_ci } 105262306a36Sopenharmony_ci outpw(PLC(phy,PL_CNTRL_B),cntrl) ; 105362306a36Sopenharmony_ci} 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_cistatic void reset_lem_struct(struct s_phy *phy) 105662306a36Sopenharmony_ci{ 105762306a36Sopenharmony_ci struct lem_counter *lem = &phy->lem ; 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci phy->mib->fddiPORTLer_Estimate = 15 ; 106062306a36Sopenharmony_ci lem->lem_float_ber = 15 * 100 ; 106162306a36Sopenharmony_ci} 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci/* 106462306a36Sopenharmony_ci * link error monitor 106562306a36Sopenharmony_ci */ 106662306a36Sopenharmony_cistatic void lem_evaluate(struct s_smc *smc, struct s_phy *phy) 106762306a36Sopenharmony_ci{ 106862306a36Sopenharmony_ci int ber ; 106962306a36Sopenharmony_ci u_long errors ; 107062306a36Sopenharmony_ci struct lem_counter *lem = &phy->lem ; 107162306a36Sopenharmony_ci struct fddi_mib_p *mib ; 107262306a36Sopenharmony_ci int cond ; 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci mib = phy->mib ; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci if (!lem->lem_on) 107762306a36Sopenharmony_ci return ; 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci errors = inpw(PLC(((int) phy->np),PL_LINK_ERR_CTR)) ; 108062306a36Sopenharmony_ci lem->lem_errors += errors ; 108162306a36Sopenharmony_ci mib->fddiPORTLem_Ct += errors ; 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci errors = lem->lem_errors ; 108462306a36Sopenharmony_ci /* 108562306a36Sopenharmony_ci * calculation is called on a intervall of 8 seconds 108662306a36Sopenharmony_ci * -> this means, that one error in 8 sec. is one of 8*125*10E6 108762306a36Sopenharmony_ci * the same as BER = 10E-9 108862306a36Sopenharmony_ci * Please note: 108962306a36Sopenharmony_ci * -> 9 errors in 8 seconds mean: 109062306a36Sopenharmony_ci * BER = 9 * 10E-9 and this is 109162306a36Sopenharmony_ci * < 10E-8, so the limit of 10E-8 is not reached! 109262306a36Sopenharmony_ci */ 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci if (!errors) ber = 15 ; 109562306a36Sopenharmony_ci else if (errors <= 9) ber = 9 ; 109662306a36Sopenharmony_ci else if (errors <= 99) ber = 8 ; 109762306a36Sopenharmony_ci else if (errors <= 999) ber = 7 ; 109862306a36Sopenharmony_ci else if (errors <= 9999) ber = 6 ; 109962306a36Sopenharmony_ci else if (errors <= 99999) ber = 5 ; 110062306a36Sopenharmony_ci else if (errors <= 999999) ber = 4 ; 110162306a36Sopenharmony_ci else if (errors <= 9999999) ber = 3 ; 110262306a36Sopenharmony_ci else if (errors <= 99999999) ber = 2 ; 110362306a36Sopenharmony_ci else if (errors <= 999999999) ber = 1 ; 110462306a36Sopenharmony_ci else ber = 0 ; 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci /* 110762306a36Sopenharmony_ci * weighted average 110862306a36Sopenharmony_ci */ 110962306a36Sopenharmony_ci ber *= 100 ; 111062306a36Sopenharmony_ci lem->lem_float_ber = lem->lem_float_ber * 7 + ber * 3 ; 111162306a36Sopenharmony_ci lem->lem_float_ber /= 10 ; 111262306a36Sopenharmony_ci mib->fddiPORTLer_Estimate = lem->lem_float_ber / 100 ; 111362306a36Sopenharmony_ci if (mib->fddiPORTLer_Estimate < 4) { 111462306a36Sopenharmony_ci mib->fddiPORTLer_Estimate = 4 ; 111562306a36Sopenharmony_ci } 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci if (lem->lem_errors) { 111862306a36Sopenharmony_ci DB_PCMN(1, "LEM %c :", phy->np == PB ? 'B' : 'A'); 111962306a36Sopenharmony_ci DB_PCMN(1, "errors : %ld", lem->lem_errors); 112062306a36Sopenharmony_ci DB_PCMN(1, "sum_errors : %ld", mib->fddiPORTLem_Ct); 112162306a36Sopenharmony_ci DB_PCMN(1, "current BER : 10E-%d", ber / 100); 112262306a36Sopenharmony_ci DB_PCMN(1, "float BER : 10E-(%d/100)", lem->lem_float_ber); 112362306a36Sopenharmony_ci DB_PCMN(1, "avg. BER : 10E-%d", mib->fddiPORTLer_Estimate); 112462306a36Sopenharmony_ci } 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci lem->lem_errors = 0L ; 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci#ifndef SLIM_SMT 112962306a36Sopenharmony_ci cond = (mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Alarm) ? 113062306a36Sopenharmony_ci TRUE : FALSE ; 113162306a36Sopenharmony_ci#ifdef SMT_EXT_CUTOFF 113262306a36Sopenharmony_ci smt_ler_alarm_check(smc,phy,cond) ; 113362306a36Sopenharmony_ci#endif /* nSMT_EXT_CUTOFF */ 113462306a36Sopenharmony_ci if (cond != mib->fddiPORTLerFlag) { 113562306a36Sopenharmony_ci smt_srf_event(smc,SMT_COND_PORT_LER, 113662306a36Sopenharmony_ci (int) (INDEX_PORT+ phy->np) ,cond) ; 113762306a36Sopenharmony_ci } 113862306a36Sopenharmony_ci#endif 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci if ( mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Cutoff) { 114162306a36Sopenharmony_ci phy->pc_lem_fail = TRUE ; /* flag */ 114262306a36Sopenharmony_ci mib->fddiPORTLem_Reject_Ct++ ; 114362306a36Sopenharmony_ci /* 114462306a36Sopenharmony_ci * "forgive 10e-2" if we cutoff so we can come 114562306a36Sopenharmony_ci * up again .. 114662306a36Sopenharmony_ci */ 114762306a36Sopenharmony_ci lem->lem_float_ber += 2*100 ; 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci /*PC81b*/ 115062306a36Sopenharmony_ci#ifdef CONCENTRATOR 115162306a36Sopenharmony_ci DB_PCMN(1, "PCM: LER cutoff on port %d cutoff %d", 115262306a36Sopenharmony_ci phy->np, mib->fddiPORTLer_Cutoff); 115362306a36Sopenharmony_ci#endif 115462306a36Sopenharmony_ci#ifdef SMT_EXT_CUTOFF 115562306a36Sopenharmony_ci smt_port_off_event(smc,phy->np); 115662306a36Sopenharmony_ci#else /* nSMT_EXT_CUTOFF */ 115762306a36Sopenharmony_ci queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ; 115862306a36Sopenharmony_ci#endif /* nSMT_EXT_CUTOFF */ 115962306a36Sopenharmony_ci } 116062306a36Sopenharmony_ci} 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci/* 116362306a36Sopenharmony_ci * called by SMT to calculate LEM bit error rate 116462306a36Sopenharmony_ci */ 116562306a36Sopenharmony_civoid sm_lem_evaluate(struct s_smc *smc) 116662306a36Sopenharmony_ci{ 116762306a36Sopenharmony_ci int np ; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci for (np = 0 ; np < NUMPHYS ; np++) 117062306a36Sopenharmony_ci lem_evaluate(smc,&smc->y[np]) ; 117162306a36Sopenharmony_ci} 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_cistatic void lem_check_lct(struct s_smc *smc, struct s_phy *phy) 117462306a36Sopenharmony_ci{ 117562306a36Sopenharmony_ci struct lem_counter *lem = &phy->lem ; 117662306a36Sopenharmony_ci struct fddi_mib_p *mib ; 117762306a36Sopenharmony_ci int errors ; 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci mib = phy->mib ; 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci phy->pc_lem_fail = FALSE ; /* flag */ 118262306a36Sopenharmony_ci errors = inpw(PLC(((int)phy->np),PL_LINK_ERR_CTR)) ; 118362306a36Sopenharmony_ci lem->lem_errors += errors ; 118462306a36Sopenharmony_ci mib->fddiPORTLem_Ct += errors ; 118562306a36Sopenharmony_ci if (lem->lem_errors) { 118662306a36Sopenharmony_ci switch(phy->lc_test) { 118762306a36Sopenharmony_ci case LC_SHORT: 118862306a36Sopenharmony_ci if (lem->lem_errors >= smc->s.lct_short) 118962306a36Sopenharmony_ci phy->pc_lem_fail = TRUE ; 119062306a36Sopenharmony_ci break ; 119162306a36Sopenharmony_ci case LC_MEDIUM: 119262306a36Sopenharmony_ci if (lem->lem_errors >= smc->s.lct_medium) 119362306a36Sopenharmony_ci phy->pc_lem_fail = TRUE ; 119462306a36Sopenharmony_ci break ; 119562306a36Sopenharmony_ci case LC_LONG: 119662306a36Sopenharmony_ci if (lem->lem_errors >= smc->s.lct_long) 119762306a36Sopenharmony_ci phy->pc_lem_fail = TRUE ; 119862306a36Sopenharmony_ci break ; 119962306a36Sopenharmony_ci case LC_EXTENDED: 120062306a36Sopenharmony_ci if (lem->lem_errors >= smc->s.lct_extended) 120162306a36Sopenharmony_ci phy->pc_lem_fail = TRUE ; 120262306a36Sopenharmony_ci break ; 120362306a36Sopenharmony_ci } 120462306a36Sopenharmony_ci DB_PCMN(1, " >>errors : %lu", lem->lem_errors); 120562306a36Sopenharmony_ci } 120662306a36Sopenharmony_ci if (phy->pc_lem_fail) { 120762306a36Sopenharmony_ci mib->fddiPORTLCTFail_Ct++ ; 120862306a36Sopenharmony_ci mib->fddiPORTLem_Reject_Ct++ ; 120962306a36Sopenharmony_ci } 121062306a36Sopenharmony_ci else 121162306a36Sopenharmony_ci mib->fddiPORTLCTFail_Ct = 0 ; 121262306a36Sopenharmony_ci} 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci/* 121562306a36Sopenharmony_ci * LEM functions 121662306a36Sopenharmony_ci */ 121762306a36Sopenharmony_cistatic void sm_ph_lem_start(struct s_smc *smc, int np, int threshold) 121862306a36Sopenharmony_ci{ 121962306a36Sopenharmony_ci struct lem_counter *lem = &smc->y[np].lem ; 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci lem->lem_on = 1 ; 122262306a36Sopenharmony_ci lem->lem_errors = 0L ; 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci /* Do NOT reset mib->fddiPORTLer_Estimate here. It is called too 122562306a36Sopenharmony_ci * often. 122662306a36Sopenharmony_ci */ 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci outpw(PLC(np,PL_LE_THRESHOLD),threshold) ; 122962306a36Sopenharmony_ci (void)inpw(PLC(np,PL_LINK_ERR_CTR)) ; /* clear error counter */ 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci /* enable LE INT */ 123262306a36Sopenharmony_ci SETMASK(PLC(np,PL_INTR_MASK),PL_LE_CTR,PL_LE_CTR) ; 123362306a36Sopenharmony_ci} 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_cistatic void sm_ph_lem_stop(struct s_smc *smc, int np) 123662306a36Sopenharmony_ci{ 123762306a36Sopenharmony_ci struct lem_counter *lem = &smc->y[np].lem ; 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci lem->lem_on = 0 ; 124062306a36Sopenharmony_ci CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ; 124162306a36Sopenharmony_ci} 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ci/* 124462306a36Sopenharmony_ci * PCM pseudo code 124562306a36Sopenharmony_ci * receive actions are called AFTER the bit n is received, 124662306a36Sopenharmony_ci * i.e. if pc_rcode_actions(5) is called, bit 6 is the next bit to be received 124762306a36Sopenharmony_ci */ 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci/* 125062306a36Sopenharmony_ci * PCM pseudo code 5.1 .. 6.1 125162306a36Sopenharmony_ci */ 125262306a36Sopenharmony_cistatic void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy) 125362306a36Sopenharmony_ci{ 125462306a36Sopenharmony_ci struct fddi_mib_p *mib ; 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci mib = phy->mib ; 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci DB_PCMN(1, "SIG rec %x %x:", bit, phy->r_val[bit]); 125962306a36Sopenharmony_ci bit++ ; 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci switch(bit) { 126262306a36Sopenharmony_ci case 0: 126362306a36Sopenharmony_ci case 1: 126462306a36Sopenharmony_ci case 2: 126562306a36Sopenharmony_ci break ; 126662306a36Sopenharmony_ci case 3 : 126762306a36Sopenharmony_ci if (phy->r_val[1] == 0 && phy->r_val[2] == 0) 126862306a36Sopenharmony_ci mib->fddiPORTNeighborType = TA ; 126962306a36Sopenharmony_ci else if (phy->r_val[1] == 0 && phy->r_val[2] == 1) 127062306a36Sopenharmony_ci mib->fddiPORTNeighborType = TB ; 127162306a36Sopenharmony_ci else if (phy->r_val[1] == 1 && phy->r_val[2] == 0) 127262306a36Sopenharmony_ci mib->fddiPORTNeighborType = TS ; 127362306a36Sopenharmony_ci else if (phy->r_val[1] == 1 && phy->r_val[2] == 1) 127462306a36Sopenharmony_ci mib->fddiPORTNeighborType = TM ; 127562306a36Sopenharmony_ci break ; 127662306a36Sopenharmony_ci case 4: 127762306a36Sopenharmony_ci if (mib->fddiPORTMy_Type == TM && 127862306a36Sopenharmony_ci mib->fddiPORTNeighborType == TM) { 127962306a36Sopenharmony_ci DB_PCMN(1, "PCM %c : E100 withhold M-M", 128062306a36Sopenharmony_ci phy->phy_name); 128162306a36Sopenharmony_ci mib->fddiPORTPC_Withhold = PC_WH_M_M ; 128262306a36Sopenharmony_ci RS_SET(smc,RS_EVENT) ; 128362306a36Sopenharmony_ci } 128462306a36Sopenharmony_ci else if (phy->t_val[3] || phy->r_val[3]) { 128562306a36Sopenharmony_ci mib->fddiPORTPC_Withhold = PC_WH_NONE ; 128662306a36Sopenharmony_ci if (mib->fddiPORTMy_Type == TM || 128762306a36Sopenharmony_ci mib->fddiPORTNeighborType == TM) 128862306a36Sopenharmony_ci phy->pc_mode = PM_TREE ; 128962306a36Sopenharmony_ci else 129062306a36Sopenharmony_ci phy->pc_mode = PM_PEER ; 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci /* reevaluate the selection criteria (wc_flag) */ 129362306a36Sopenharmony_ci all_selection_criteria (smc); 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci if (phy->wc_flag) { 129662306a36Sopenharmony_ci mib->fddiPORTPC_Withhold = PC_WH_PATH ; 129762306a36Sopenharmony_ci } 129862306a36Sopenharmony_ci } 129962306a36Sopenharmony_ci else { 130062306a36Sopenharmony_ci mib->fddiPORTPC_Withhold = PC_WH_OTHER ; 130162306a36Sopenharmony_ci RS_SET(smc,RS_EVENT) ; 130262306a36Sopenharmony_ci DB_PCMN(1, "PCM %c : E101 withhold other", 130362306a36Sopenharmony_ci phy->phy_name); 130462306a36Sopenharmony_ci } 130562306a36Sopenharmony_ci phy->twisted = ((mib->fddiPORTMy_Type != TS) && 130662306a36Sopenharmony_ci (mib->fddiPORTMy_Type != TM) && 130762306a36Sopenharmony_ci (mib->fddiPORTNeighborType == 130862306a36Sopenharmony_ci mib->fddiPORTMy_Type)) ; 130962306a36Sopenharmony_ci if (phy->twisted) { 131062306a36Sopenharmony_ci DB_PCMN(1, "PCM %c : E102 !!! TWISTED !!!", 131162306a36Sopenharmony_ci phy->phy_name); 131262306a36Sopenharmony_ci } 131362306a36Sopenharmony_ci break ; 131462306a36Sopenharmony_ci case 5 : 131562306a36Sopenharmony_ci break ; 131662306a36Sopenharmony_ci case 6: 131762306a36Sopenharmony_ci if (phy->t_val[4] || phy->r_val[4]) { 131862306a36Sopenharmony_ci if ((phy->t_val[4] && phy->t_val[5]) || 131962306a36Sopenharmony_ci (phy->r_val[4] && phy->r_val[5]) ) 132062306a36Sopenharmony_ci phy->lc_test = LC_EXTENDED ; 132162306a36Sopenharmony_ci else 132262306a36Sopenharmony_ci phy->lc_test = LC_LONG ; 132362306a36Sopenharmony_ci } 132462306a36Sopenharmony_ci else if (phy->t_val[5] || phy->r_val[5]) 132562306a36Sopenharmony_ci phy->lc_test = LC_MEDIUM ; 132662306a36Sopenharmony_ci else 132762306a36Sopenharmony_ci phy->lc_test = LC_SHORT ; 132862306a36Sopenharmony_ci switch (phy->lc_test) { 132962306a36Sopenharmony_ci case LC_SHORT : /* 50ms */ 133062306a36Sopenharmony_ci outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LENGTH ) ; 133162306a36Sopenharmony_ci phy->t_next[7] = smc->s.pcm_lc_short ; 133262306a36Sopenharmony_ci break ; 133362306a36Sopenharmony_ci case LC_MEDIUM : /* 500ms */ 133462306a36Sopenharmony_ci outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LONGLN ) ; 133562306a36Sopenharmony_ci phy->t_next[7] = smc->s.pcm_lc_medium ; 133662306a36Sopenharmony_ci break ; 133762306a36Sopenharmony_ci case LC_LONG : 133862306a36Sopenharmony_ci SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ; 133962306a36Sopenharmony_ci phy->t_next[7] = smc->s.pcm_lc_long ; 134062306a36Sopenharmony_ci break ; 134162306a36Sopenharmony_ci case LC_EXTENDED : 134262306a36Sopenharmony_ci SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ; 134362306a36Sopenharmony_ci phy->t_next[7] = smc->s.pcm_lc_extended ; 134462306a36Sopenharmony_ci break ; 134562306a36Sopenharmony_ci } 134662306a36Sopenharmony_ci if (phy->t_next[7] > smc->s.pcm_lc_medium) { 134762306a36Sopenharmony_ci start_pcm_timer0(smc,phy->t_next[7],PC_TIMEOUT_LCT,phy); 134862306a36Sopenharmony_ci } 134962306a36Sopenharmony_ci DB_PCMN(1, "LCT timer = %ld us", phy->t_next[7]); 135062306a36Sopenharmony_ci phy->t_next[9] = smc->s.pcm_t_next_9 ; 135162306a36Sopenharmony_ci break ; 135262306a36Sopenharmony_ci case 7: 135362306a36Sopenharmony_ci if (phy->t_val[6]) { 135462306a36Sopenharmony_ci phy->cf_loop = TRUE ; 135562306a36Sopenharmony_ci } 135662306a36Sopenharmony_ci phy->td_flag = TRUE ; 135762306a36Sopenharmony_ci break ; 135862306a36Sopenharmony_ci case 8: 135962306a36Sopenharmony_ci if (phy->t_val[7] || phy->r_val[7]) { 136062306a36Sopenharmony_ci DB_PCMN(1, "PCM %c : E103 LCT fail %s", 136162306a36Sopenharmony_ci phy->phy_name, 136262306a36Sopenharmony_ci phy->t_val[7] ? "local" : "remote"); 136362306a36Sopenharmony_ci queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ; 136462306a36Sopenharmony_ci } 136562306a36Sopenharmony_ci break ; 136662306a36Sopenharmony_ci case 9: 136762306a36Sopenharmony_ci if (phy->t_val[8] || phy->r_val[8]) { 136862306a36Sopenharmony_ci if (phy->t_val[8]) 136962306a36Sopenharmony_ci phy->cf_loop = TRUE ; 137062306a36Sopenharmony_ci phy->td_flag = TRUE ; 137162306a36Sopenharmony_ci } 137262306a36Sopenharmony_ci break ; 137362306a36Sopenharmony_ci case 10: 137462306a36Sopenharmony_ci if (phy->r_val[9]) { 137562306a36Sopenharmony_ci /* neighbor intends to have MAC on output */ ; 137662306a36Sopenharmony_ci mib->fddiPORTMacIndicated.R_val = TRUE ; 137762306a36Sopenharmony_ci } 137862306a36Sopenharmony_ci else { 137962306a36Sopenharmony_ci /* neighbor does not intend to have MAC on output */ ; 138062306a36Sopenharmony_ci mib->fddiPORTMacIndicated.R_val = FALSE ; 138162306a36Sopenharmony_ci } 138262306a36Sopenharmony_ci break ; 138362306a36Sopenharmony_ci } 138462306a36Sopenharmony_ci} 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci/* 138762306a36Sopenharmony_ci * PCM pseudo code 5.1 .. 6.1 138862306a36Sopenharmony_ci */ 138962306a36Sopenharmony_cistatic void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy) 139062306a36Sopenharmony_ci{ 139162306a36Sopenharmony_ci int np = phy->np ; 139262306a36Sopenharmony_ci struct fddi_mib_p *mib ; 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci mib = phy->mib ; 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci switch(bit) { 139762306a36Sopenharmony_ci case 0: 139862306a36Sopenharmony_ci phy->t_val[0] = 0 ; /* no escape used */ 139962306a36Sopenharmony_ci break ; 140062306a36Sopenharmony_ci case 1: 140162306a36Sopenharmony_ci if (mib->fddiPORTMy_Type == TS || mib->fddiPORTMy_Type == TM) 140262306a36Sopenharmony_ci phy->t_val[1] = 1 ; 140362306a36Sopenharmony_ci else 140462306a36Sopenharmony_ci phy->t_val[1] = 0 ; 140562306a36Sopenharmony_ci break ; 140662306a36Sopenharmony_ci case 2 : 140762306a36Sopenharmony_ci if (mib->fddiPORTMy_Type == TB || mib->fddiPORTMy_Type == TM) 140862306a36Sopenharmony_ci phy->t_val[2] = 1 ; 140962306a36Sopenharmony_ci else 141062306a36Sopenharmony_ci phy->t_val[2] = 0 ; 141162306a36Sopenharmony_ci break ; 141262306a36Sopenharmony_ci case 3: 141362306a36Sopenharmony_ci { 141462306a36Sopenharmony_ci int type,ne ; 141562306a36Sopenharmony_ci int policy ; 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci type = mib->fddiPORTMy_Type ; 141862306a36Sopenharmony_ci ne = mib->fddiPORTNeighborType ; 141962306a36Sopenharmony_ci policy = smc->mib.fddiSMTConnectionPolicy ; 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci phy->t_val[3] = 1 ; /* Accept connection */ 142262306a36Sopenharmony_ci switch (type) { 142362306a36Sopenharmony_ci case TA : 142462306a36Sopenharmony_ci if ( 142562306a36Sopenharmony_ci ((policy & POLICY_AA) && ne == TA) || 142662306a36Sopenharmony_ci ((policy & POLICY_AB) && ne == TB) || 142762306a36Sopenharmony_ci ((policy & POLICY_AS) && ne == TS) || 142862306a36Sopenharmony_ci ((policy & POLICY_AM) && ne == TM) ) 142962306a36Sopenharmony_ci phy->t_val[3] = 0 ; /* Reject */ 143062306a36Sopenharmony_ci break ; 143162306a36Sopenharmony_ci case TB : 143262306a36Sopenharmony_ci if ( 143362306a36Sopenharmony_ci ((policy & POLICY_BA) && ne == TA) || 143462306a36Sopenharmony_ci ((policy & POLICY_BB) && ne == TB) || 143562306a36Sopenharmony_ci ((policy & POLICY_BS) && ne == TS) || 143662306a36Sopenharmony_ci ((policy & POLICY_BM) && ne == TM) ) 143762306a36Sopenharmony_ci phy->t_val[3] = 0 ; /* Reject */ 143862306a36Sopenharmony_ci break ; 143962306a36Sopenharmony_ci case TS : 144062306a36Sopenharmony_ci if ( 144162306a36Sopenharmony_ci ((policy & POLICY_SA) && ne == TA) || 144262306a36Sopenharmony_ci ((policy & POLICY_SB) && ne == TB) || 144362306a36Sopenharmony_ci ((policy & POLICY_SS) && ne == TS) || 144462306a36Sopenharmony_ci ((policy & POLICY_SM) && ne == TM) ) 144562306a36Sopenharmony_ci phy->t_val[3] = 0 ; /* Reject */ 144662306a36Sopenharmony_ci break ; 144762306a36Sopenharmony_ci case TM : 144862306a36Sopenharmony_ci if ( ne == TM || 144962306a36Sopenharmony_ci ((policy & POLICY_MA) && ne == TA) || 145062306a36Sopenharmony_ci ((policy & POLICY_MB) && ne == TB) || 145162306a36Sopenharmony_ci ((policy & POLICY_MS) && ne == TS) || 145262306a36Sopenharmony_ci ((policy & POLICY_MM) && ne == TM) ) 145362306a36Sopenharmony_ci phy->t_val[3] = 0 ; /* Reject */ 145462306a36Sopenharmony_ci break ; 145562306a36Sopenharmony_ci } 145662306a36Sopenharmony_ci#ifndef SLIM_SMT 145762306a36Sopenharmony_ci /* 145862306a36Sopenharmony_ci * detect undesirable connection attempt event 145962306a36Sopenharmony_ci */ 146062306a36Sopenharmony_ci if ( (type == TA && ne == TA ) || 146162306a36Sopenharmony_ci (type == TA && ne == TS ) || 146262306a36Sopenharmony_ci (type == TB && ne == TB ) || 146362306a36Sopenharmony_ci (type == TB && ne == TS ) || 146462306a36Sopenharmony_ci (type == TS && ne == TA ) || 146562306a36Sopenharmony_ci (type == TS && ne == TB ) ) { 146662306a36Sopenharmony_ci smt_srf_event(smc,SMT_EVENT_PORT_CONNECTION, 146762306a36Sopenharmony_ci (int) (INDEX_PORT+ phy->np) ,0) ; 146862306a36Sopenharmony_ci } 146962306a36Sopenharmony_ci#endif 147062306a36Sopenharmony_ci } 147162306a36Sopenharmony_ci break ; 147262306a36Sopenharmony_ci case 4: 147362306a36Sopenharmony_ci if (mib->fddiPORTPC_Withhold == PC_WH_NONE) { 147462306a36Sopenharmony_ci if (phy->pc_lem_fail) { 147562306a36Sopenharmony_ci phy->t_val[4] = 1 ; /* long */ 147662306a36Sopenharmony_ci phy->t_val[5] = 0 ; 147762306a36Sopenharmony_ci } 147862306a36Sopenharmony_ci else { 147962306a36Sopenharmony_ci phy->t_val[4] = 0 ; 148062306a36Sopenharmony_ci if (mib->fddiPORTLCTFail_Ct > 0) 148162306a36Sopenharmony_ci phy->t_val[5] = 1 ; /* medium */ 148262306a36Sopenharmony_ci else 148362306a36Sopenharmony_ci phy->t_val[5] = 0 ; /* short */ 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci /* 148662306a36Sopenharmony_ci * Implementers choice: use medium 148762306a36Sopenharmony_ci * instead of short when undesired 148862306a36Sopenharmony_ci * connection attempt is made. 148962306a36Sopenharmony_ci */ 149062306a36Sopenharmony_ci if (phy->wc_flag) 149162306a36Sopenharmony_ci phy->t_val[5] = 1 ; /* medium */ 149262306a36Sopenharmony_ci } 149362306a36Sopenharmony_ci mib->fddiPORTConnectState = PCM_CONNECTING ; 149462306a36Sopenharmony_ci } 149562306a36Sopenharmony_ci else { 149662306a36Sopenharmony_ci mib->fddiPORTConnectState = PCM_STANDBY ; 149762306a36Sopenharmony_ci phy->t_val[4] = 1 ; /* extended */ 149862306a36Sopenharmony_ci phy->t_val[5] = 1 ; 149962306a36Sopenharmony_ci } 150062306a36Sopenharmony_ci break ; 150162306a36Sopenharmony_ci case 5: 150262306a36Sopenharmony_ci break ; 150362306a36Sopenharmony_ci case 6: 150462306a36Sopenharmony_ci /* we do NOT have a MAC for LCT */ 150562306a36Sopenharmony_ci phy->t_val[6] = 0 ; 150662306a36Sopenharmony_ci break ; 150762306a36Sopenharmony_ci case 7: 150862306a36Sopenharmony_ci phy->cf_loop = FALSE ; 150962306a36Sopenharmony_ci lem_check_lct(smc,phy) ; 151062306a36Sopenharmony_ci if (phy->pc_lem_fail) { 151162306a36Sopenharmony_ci DB_PCMN(1, "PCM %c : E104 LCT failed", phy->phy_name); 151262306a36Sopenharmony_ci phy->t_val[7] = 1 ; 151362306a36Sopenharmony_ci } 151462306a36Sopenharmony_ci else 151562306a36Sopenharmony_ci phy->t_val[7] = 0 ; 151662306a36Sopenharmony_ci break ; 151762306a36Sopenharmony_ci case 8: 151862306a36Sopenharmony_ci phy->t_val[8] = 0 ; /* Don't request MAC loopback */ 151962306a36Sopenharmony_ci break ; 152062306a36Sopenharmony_ci case 9: 152162306a36Sopenharmony_ci phy->cf_loop = 0 ; 152262306a36Sopenharmony_ci if ((mib->fddiPORTPC_Withhold != PC_WH_NONE) || 152362306a36Sopenharmony_ci ((smc->s.sas == SMT_DAS) && (phy->wc_flag))) { 152462306a36Sopenharmony_ci queue_event(smc,EVENT_PCM+np,PC_START) ; 152562306a36Sopenharmony_ci break ; 152662306a36Sopenharmony_ci } 152762306a36Sopenharmony_ci phy->t_val[9] = FALSE ; 152862306a36Sopenharmony_ci switch (smc->s.sas) { 152962306a36Sopenharmony_ci case SMT_DAS : 153062306a36Sopenharmony_ci /* 153162306a36Sopenharmony_ci * MAC intended on output 153262306a36Sopenharmony_ci */ 153362306a36Sopenharmony_ci if (phy->pc_mode == PM_TREE) { 153462306a36Sopenharmony_ci if ((np == PB) || ((np == PA) && 153562306a36Sopenharmony_ci (smc->y[PB].mib->fddiPORTConnectState != 153662306a36Sopenharmony_ci PCM_ACTIVE))) 153762306a36Sopenharmony_ci phy->t_val[9] = TRUE ; 153862306a36Sopenharmony_ci } 153962306a36Sopenharmony_ci else { 154062306a36Sopenharmony_ci if (np == PB) 154162306a36Sopenharmony_ci phy->t_val[9] = TRUE ; 154262306a36Sopenharmony_ci } 154362306a36Sopenharmony_ci break ; 154462306a36Sopenharmony_ci case SMT_SAS : 154562306a36Sopenharmony_ci if (np == PS) 154662306a36Sopenharmony_ci phy->t_val[9] = TRUE ; 154762306a36Sopenharmony_ci break ; 154862306a36Sopenharmony_ci#ifdef CONCENTRATOR 154962306a36Sopenharmony_ci case SMT_NAC : 155062306a36Sopenharmony_ci /* 155162306a36Sopenharmony_ci * MAC intended on output 155262306a36Sopenharmony_ci */ 155362306a36Sopenharmony_ci if (np == PB) 155462306a36Sopenharmony_ci phy->t_val[9] = TRUE ; 155562306a36Sopenharmony_ci break ; 155662306a36Sopenharmony_ci#endif 155762306a36Sopenharmony_ci } 155862306a36Sopenharmony_ci mib->fddiPORTMacIndicated.T_val = phy->t_val[9] ; 155962306a36Sopenharmony_ci break ; 156062306a36Sopenharmony_ci } 156162306a36Sopenharmony_ci DB_PCMN(1, "SIG snd %x %x:", bit, phy->t_val[bit]); 156262306a36Sopenharmony_ci} 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci/* 156562306a36Sopenharmony_ci * return status twisted (called by SMT) 156662306a36Sopenharmony_ci */ 156762306a36Sopenharmony_ciint pcm_status_twisted(struct s_smc *smc) 156862306a36Sopenharmony_ci{ 156962306a36Sopenharmony_ci int twist = 0 ; 157062306a36Sopenharmony_ci if (smc->s.sas != SMT_DAS) 157162306a36Sopenharmony_ci return 0; 157262306a36Sopenharmony_ci if (smc->y[PA].twisted && (smc->y[PA].mib->fddiPORTPCMState == PC8_ACTIVE)) 157362306a36Sopenharmony_ci twist |= 1 ; 157462306a36Sopenharmony_ci if (smc->y[PB].twisted && (smc->y[PB].mib->fddiPORTPCMState == PC8_ACTIVE)) 157562306a36Sopenharmony_ci twist |= 2 ; 157662306a36Sopenharmony_ci return twist; 157762306a36Sopenharmony_ci} 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci/* 158062306a36Sopenharmony_ci * return status (called by SMT) 158162306a36Sopenharmony_ci * type 158262306a36Sopenharmony_ci * state 158362306a36Sopenharmony_ci * remote phy type 158462306a36Sopenharmony_ci * remote mac yes/no 158562306a36Sopenharmony_ci */ 158662306a36Sopenharmony_civoid pcm_status_state(struct s_smc *smc, int np, int *type, int *state, 158762306a36Sopenharmony_ci int *remote, int *mac) 158862306a36Sopenharmony_ci{ 158962306a36Sopenharmony_ci struct s_phy *phy = &smc->y[np] ; 159062306a36Sopenharmony_ci struct fddi_mib_p *mib ; 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci mib = phy->mib ; 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci /* remote PHY type and MAC - set only if active */ 159562306a36Sopenharmony_ci *mac = 0 ; 159662306a36Sopenharmony_ci *type = mib->fddiPORTMy_Type ; /* our PHY type */ 159762306a36Sopenharmony_ci *state = mib->fddiPORTConnectState ; 159862306a36Sopenharmony_ci *remote = mib->fddiPORTNeighborType ; 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci switch(mib->fddiPORTPCMState) { 160162306a36Sopenharmony_ci case PC8_ACTIVE : 160262306a36Sopenharmony_ci *mac = mib->fddiPORTMacIndicated.R_val ; 160362306a36Sopenharmony_ci break ; 160462306a36Sopenharmony_ci } 160562306a36Sopenharmony_ci} 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci/* 160862306a36Sopenharmony_ci * return rooted station status (called by SMT) 160962306a36Sopenharmony_ci */ 161062306a36Sopenharmony_ciint pcm_rooted_station(struct s_smc *smc) 161162306a36Sopenharmony_ci{ 161262306a36Sopenharmony_ci int n ; 161362306a36Sopenharmony_ci 161462306a36Sopenharmony_ci for (n = 0 ; n < NUMPHYS ; n++) { 161562306a36Sopenharmony_ci if (smc->y[n].mib->fddiPORTPCMState == PC8_ACTIVE && 161662306a36Sopenharmony_ci smc->y[n].mib->fddiPORTNeighborType == TM) 161762306a36Sopenharmony_ci return 0; 161862306a36Sopenharmony_ci } 161962306a36Sopenharmony_ci return 1; 162062306a36Sopenharmony_ci} 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci/* 162362306a36Sopenharmony_ci * Interrupt actions for PLC & PCM events 162462306a36Sopenharmony_ci */ 162562306a36Sopenharmony_civoid plc_irq(struct s_smc *smc, int np, unsigned int cmd) 162662306a36Sopenharmony_ci/* int np; PHY index */ 162762306a36Sopenharmony_ci{ 162862306a36Sopenharmony_ci struct s_phy *phy = &smc->y[np] ; 162962306a36Sopenharmony_ci struct s_plc *plc = &phy->plc ; 163062306a36Sopenharmony_ci int n ; 163162306a36Sopenharmony_ci#ifdef SUPERNET_3 163262306a36Sopenharmony_ci int corr_mask ; 163362306a36Sopenharmony_ci#endif /* SUPERNET_3 */ 163462306a36Sopenharmony_ci int i ; 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_ci if (np >= smc->s.numphys) { 163762306a36Sopenharmony_ci plc->soft_err++ ; 163862306a36Sopenharmony_ci return ; 163962306a36Sopenharmony_ci } 164062306a36Sopenharmony_ci if (cmd & PL_EBUF_ERR) { /* elastic buff. det. over-|underflow*/ 164162306a36Sopenharmony_ci /* 164262306a36Sopenharmony_ci * Check whether the SRF Condition occurred. 164362306a36Sopenharmony_ci */ 164462306a36Sopenharmony_ci if (!plc->ebuf_cont && phy->mib->fddiPORTPCMState == PC8_ACTIVE){ 164562306a36Sopenharmony_ci /* 164662306a36Sopenharmony_ci * This is the real Elasticity Error. 164762306a36Sopenharmony_ci * More than one in a row are treated as a 164862306a36Sopenharmony_ci * single one. 164962306a36Sopenharmony_ci * Only count this in the active state. 165062306a36Sopenharmony_ci */ 165162306a36Sopenharmony_ci phy->mib->fddiPORTEBError_Ct ++ ; 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_ci } 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_ci plc->ebuf_err++ ; 165662306a36Sopenharmony_ci if (plc->ebuf_cont <= 1000) { 165762306a36Sopenharmony_ci /* 165862306a36Sopenharmony_ci * Prevent counter from being wrapped after 165962306a36Sopenharmony_ci * hanging years in that interrupt. 166062306a36Sopenharmony_ci */ 166162306a36Sopenharmony_ci plc->ebuf_cont++ ; /* Ebuf continuous error */ 166262306a36Sopenharmony_ci } 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci#ifdef SUPERNET_3 166562306a36Sopenharmony_ci if (plc->ebuf_cont == 1000 && 166662306a36Sopenharmony_ci ((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) == 166762306a36Sopenharmony_ci PLC_REV_SN3)) { 166862306a36Sopenharmony_ci /* 166962306a36Sopenharmony_ci * This interrupt remeained high for at least 167062306a36Sopenharmony_ci * 1000 consecutive interrupt calls. 167162306a36Sopenharmony_ci * 167262306a36Sopenharmony_ci * This is caused by a hardware error of the 167362306a36Sopenharmony_ci * ORION part of the Supernet III chipset. 167462306a36Sopenharmony_ci * 167562306a36Sopenharmony_ci * Disable this bit from the mask. 167662306a36Sopenharmony_ci */ 167762306a36Sopenharmony_ci corr_mask = (plc_imsk_na & ~PL_EBUF_ERR) ; 167862306a36Sopenharmony_ci outpw(PLC(np,PL_INTR_MASK),corr_mask); 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_ci /* 168162306a36Sopenharmony_ci * Disconnect from the ring. 168262306a36Sopenharmony_ci * Call the driver with the reset indication. 168362306a36Sopenharmony_ci */ 168462306a36Sopenharmony_ci queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_ci /* 168762306a36Sopenharmony_ci * Make an error log entry. 168862306a36Sopenharmony_ci */ 168962306a36Sopenharmony_ci SMT_ERR_LOG(smc,SMT_E0136, SMT_E0136_MSG) ; 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci /* 169262306a36Sopenharmony_ci * Indicate the Reset. 169362306a36Sopenharmony_ci */ 169462306a36Sopenharmony_ci drv_reset_indication(smc) ; 169562306a36Sopenharmony_ci } 169662306a36Sopenharmony_ci#endif /* SUPERNET_3 */ 169762306a36Sopenharmony_ci } else { 169862306a36Sopenharmony_ci /* Reset the continuous error variable */ 169962306a36Sopenharmony_ci plc->ebuf_cont = 0 ; /* reset Ebuf continuous error */ 170062306a36Sopenharmony_ci } 170162306a36Sopenharmony_ci if (cmd & PL_PHYINV) { /* physical layer invalid signal */ 170262306a36Sopenharmony_ci plc->phyinv++ ; 170362306a36Sopenharmony_ci } 170462306a36Sopenharmony_ci if (cmd & PL_VSYM_CTR) { /* violation symbol counter has incr.*/ 170562306a36Sopenharmony_ci plc->vsym_ctr++ ; 170662306a36Sopenharmony_ci } 170762306a36Sopenharmony_ci if (cmd & PL_MINI_CTR) { /* dep. on PLC_CNTRL_A's MINI_CTR_INT*/ 170862306a36Sopenharmony_ci plc->mini_ctr++ ; 170962306a36Sopenharmony_ci } 171062306a36Sopenharmony_ci if (cmd & PL_LE_CTR) { /* link error event counter */ 171162306a36Sopenharmony_ci int j ; 171262306a36Sopenharmony_ci 171362306a36Sopenharmony_ci /* 171462306a36Sopenharmony_ci * note: PL_LINK_ERR_CTR MUST be read to clear it 171562306a36Sopenharmony_ci */ 171662306a36Sopenharmony_ci j = inpw(PLC(np,PL_LE_THRESHOLD)) ; 171762306a36Sopenharmony_ci i = inpw(PLC(np,PL_LINK_ERR_CTR)) ; 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci if (i < j) { 172062306a36Sopenharmony_ci /* wrapped around */ 172162306a36Sopenharmony_ci i += 256 ; 172262306a36Sopenharmony_ci } 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci if (phy->lem.lem_on) { 172562306a36Sopenharmony_ci /* Note: Lem errors shall only be counted when 172662306a36Sopenharmony_ci * link is ACTIVE or LCT is active. 172762306a36Sopenharmony_ci */ 172862306a36Sopenharmony_ci phy->lem.lem_errors += i ; 172962306a36Sopenharmony_ci phy->mib->fddiPORTLem_Ct += i ; 173062306a36Sopenharmony_ci } 173162306a36Sopenharmony_ci } 173262306a36Sopenharmony_ci if (cmd & PL_TPC_EXPIRED) { /* TPC timer reached zero */ 173362306a36Sopenharmony_ci if (plc->p_state == PS_LCT) { 173462306a36Sopenharmony_ci /* 173562306a36Sopenharmony_ci * end of LCT 173662306a36Sopenharmony_ci */ 173762306a36Sopenharmony_ci ; 173862306a36Sopenharmony_ci } 173962306a36Sopenharmony_ci plc->tpc_exp++ ; 174062306a36Sopenharmony_ci } 174162306a36Sopenharmony_ci if (cmd & PL_LS_MATCH) { /* LS == LS in PLC_CNTRL_B's MATCH_LS*/ 174262306a36Sopenharmony_ci switch (inpw(PLC(np,PL_CNTRL_B)) & PL_MATCH_LS) { 174362306a36Sopenharmony_ci case PL_I_IDLE : phy->curr_ls = PC_ILS ; break ; 174462306a36Sopenharmony_ci case PL_I_HALT : phy->curr_ls = PC_HLS ; break ; 174562306a36Sopenharmony_ci case PL_I_MASTR : phy->curr_ls = PC_MLS ; break ; 174662306a36Sopenharmony_ci case PL_I_QUIET : phy->curr_ls = PC_QLS ; break ; 174762306a36Sopenharmony_ci } 174862306a36Sopenharmony_ci } 174962306a36Sopenharmony_ci if (cmd & PL_PCM_BREAK) { /* PCM has entered the BREAK state */ 175062306a36Sopenharmony_ci int reason; 175162306a36Sopenharmony_ci 175262306a36Sopenharmony_ci reason = inpw(PLC(np,PL_STATUS_B)) & PL_BREAK_REASON ; 175362306a36Sopenharmony_ci 175462306a36Sopenharmony_ci switch (reason) { 175562306a36Sopenharmony_ci case PL_B_PCS : plc->b_pcs++ ; break ; 175662306a36Sopenharmony_ci case PL_B_TPC : plc->b_tpc++ ; break ; 175762306a36Sopenharmony_ci case PL_B_TNE : plc->b_tne++ ; break ; 175862306a36Sopenharmony_ci case PL_B_QLS : plc->b_qls++ ; break ; 175962306a36Sopenharmony_ci case PL_B_ILS : plc->b_ils++ ; break ; 176062306a36Sopenharmony_ci case PL_B_HLS : plc->b_hls++ ; break ; 176162306a36Sopenharmony_ci } 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci /*jd 05-Aug-1999 changed: Bug #10419 */ 176462306a36Sopenharmony_ci DB_PCMN(1, "PLC %d: MDcF = %x", np, smc->e.DisconnectFlag); 176562306a36Sopenharmony_ci if (smc->e.DisconnectFlag == FALSE) { 176662306a36Sopenharmony_ci DB_PCMN(1, "PLC %d: restart (reason %x)", np, reason); 176762306a36Sopenharmony_ci queue_event(smc,EVENT_PCM+np,PC_START) ; 176862306a36Sopenharmony_ci } 176962306a36Sopenharmony_ci else { 177062306a36Sopenharmony_ci DB_PCMN(1, "PLC %d: NO!! restart (reason %x)", 177162306a36Sopenharmony_ci np, reason); 177262306a36Sopenharmony_ci } 177362306a36Sopenharmony_ci return ; 177462306a36Sopenharmony_ci } 177562306a36Sopenharmony_ci /* 177662306a36Sopenharmony_ci * If both CODE & ENABLE are set ignore enable 177762306a36Sopenharmony_ci */ 177862306a36Sopenharmony_ci if (cmd & PL_PCM_CODE) { /* receive last sign.-bit | LCT complete */ 177962306a36Sopenharmony_ci queue_event(smc,EVENT_PCM+np,PC_SIGNAL) ; 178062306a36Sopenharmony_ci n = inpw(PLC(np,PL_RCV_VECTOR)) ; 178162306a36Sopenharmony_ci for (i = 0 ; i < plc->p_bits ; i++) { 178262306a36Sopenharmony_ci phy->r_val[plc->p_start+i] = n & 1 ; 178362306a36Sopenharmony_ci n >>= 1 ; 178462306a36Sopenharmony_ci } 178562306a36Sopenharmony_ci } 178662306a36Sopenharmony_ci else if (cmd & PL_PCM_ENABLED) { /* asserted SC_JOIN, scrub.completed*/ 178762306a36Sopenharmony_ci queue_event(smc,EVENT_PCM+np,PC_JOIN) ; 178862306a36Sopenharmony_ci } 178962306a36Sopenharmony_ci if (cmd & PL_TRACE_PROP) { /* MLS while PC8_ACTIV || PC2_TRACE */ 179062306a36Sopenharmony_ci /*PC22b*/ 179162306a36Sopenharmony_ci if (!phy->tr_flag) { 179262306a36Sopenharmony_ci DB_PCMN(1, "PCM : irq TRACE_PROP %d %d", 179362306a36Sopenharmony_ci np, smc->mib.fddiSMTECMState); 179462306a36Sopenharmony_ci phy->tr_flag = TRUE ; 179562306a36Sopenharmony_ci smc->e.trace_prop |= ENTITY_BIT(ENTITY_PHY(np)) ; 179662306a36Sopenharmony_ci queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ; 179762306a36Sopenharmony_ci } 179862306a36Sopenharmony_ci } 179962306a36Sopenharmony_ci /* 180062306a36Sopenharmony_ci * filter PLC glitch ??? 180162306a36Sopenharmony_ci * QLS || HLS only while in PC2_TRACE state 180262306a36Sopenharmony_ci */ 180362306a36Sopenharmony_ci if ((cmd & PL_SELF_TEST) && (phy->mib->fddiPORTPCMState == PC2_TRACE)) { 180462306a36Sopenharmony_ci /*PC22a*/ 180562306a36Sopenharmony_ci if (smc->e.path_test == PT_PASSED) { 180662306a36Sopenharmony_ci DB_PCMN(1, "PCM : state = %s %d", 180762306a36Sopenharmony_ci get_pcmstate(smc, np), 180862306a36Sopenharmony_ci phy->mib->fddiPORTPCMState); 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_ci smc->e.path_test = PT_PENDING ; 181162306a36Sopenharmony_ci queue_event(smc,EVENT_ECM,EC_PATH_TEST) ; 181262306a36Sopenharmony_ci } 181362306a36Sopenharmony_ci } 181462306a36Sopenharmony_ci if (cmd & PL_TNE_EXPIRED) { /* TNE: length of noise events */ 181562306a36Sopenharmony_ci /* break_required (TNE > NS_Max) */ 181662306a36Sopenharmony_ci if (phy->mib->fddiPORTPCMState == PC8_ACTIVE) { 181762306a36Sopenharmony_ci if (!phy->tr_flag) { 181862306a36Sopenharmony_ci DB_PCMN(1, "PCM %c : PC81 %s", 181962306a36Sopenharmony_ci phy->phy_name, "NSE"); 182062306a36Sopenharmony_ci queue_event(smc, EVENT_PCM + np, PC_START); 182162306a36Sopenharmony_ci return; 182262306a36Sopenharmony_ci } 182362306a36Sopenharmony_ci } 182462306a36Sopenharmony_ci } 182562306a36Sopenharmony_ci#if 0 182662306a36Sopenharmony_ci if (cmd & PL_NP_ERR) { /* NP has requested to r/w an inv reg*/ 182762306a36Sopenharmony_ci /* 182862306a36Sopenharmony_ci * It's a bug by AMD 182962306a36Sopenharmony_ci */ 183062306a36Sopenharmony_ci plc->np_err++ ; 183162306a36Sopenharmony_ci } 183262306a36Sopenharmony_ci /* pin inactiv (GND) */ 183362306a36Sopenharmony_ci if (cmd & PL_PARITY_ERR) { /* p. error dedected on TX9-0 inp */ 183462306a36Sopenharmony_ci plc->parity_err++ ; 183562306a36Sopenharmony_ci } 183662306a36Sopenharmony_ci if (cmd & PL_LSDO) { /* carrier detected */ 183762306a36Sopenharmony_ci ; 183862306a36Sopenharmony_ci } 183962306a36Sopenharmony_ci#endif 184062306a36Sopenharmony_ci} 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci#ifdef DEBUG 184362306a36Sopenharmony_ci/* 184462306a36Sopenharmony_ci * fill state struct 184562306a36Sopenharmony_ci */ 184662306a36Sopenharmony_civoid pcm_get_state(struct s_smc *smc, struct smt_state *state) 184762306a36Sopenharmony_ci{ 184862306a36Sopenharmony_ci struct s_phy *phy ; 184962306a36Sopenharmony_ci struct pcm_state *pcs ; 185062306a36Sopenharmony_ci int i ; 185162306a36Sopenharmony_ci int ii ; 185262306a36Sopenharmony_ci short rbits ; 185362306a36Sopenharmony_ci short tbits ; 185462306a36Sopenharmony_ci struct fddi_mib_p *mib ; 185562306a36Sopenharmony_ci 185662306a36Sopenharmony_ci for (i = 0, phy = smc->y, pcs = state->pcm_state ; i < NUMPHYS ; 185762306a36Sopenharmony_ci i++ , phy++, pcs++ ) { 185862306a36Sopenharmony_ci mib = phy->mib ; 185962306a36Sopenharmony_ci pcs->pcm_type = (u_char) mib->fddiPORTMy_Type ; 186062306a36Sopenharmony_ci pcs->pcm_state = (u_char) mib->fddiPORTPCMState ; 186162306a36Sopenharmony_ci pcs->pcm_mode = phy->pc_mode ; 186262306a36Sopenharmony_ci pcs->pcm_neighbor = (u_char) mib->fddiPORTNeighborType ; 186362306a36Sopenharmony_ci pcs->pcm_bsf = mib->fddiPORTBS_Flag ; 186462306a36Sopenharmony_ci pcs->pcm_lsf = phy->ls_flag ; 186562306a36Sopenharmony_ci pcs->pcm_lct_fail = (u_char) mib->fddiPORTLCTFail_Ct ; 186662306a36Sopenharmony_ci pcs->pcm_ls_rx = LS2MIB(sm_pm_get_ls(smc,i)) ; 186762306a36Sopenharmony_ci for (ii = 0, rbits = tbits = 0 ; ii < NUMBITS ; ii++) { 186862306a36Sopenharmony_ci rbits <<= 1 ; 186962306a36Sopenharmony_ci tbits <<= 1 ; 187062306a36Sopenharmony_ci if (phy->r_val[NUMBITS-1-ii]) 187162306a36Sopenharmony_ci rbits |= 1 ; 187262306a36Sopenharmony_ci if (phy->t_val[NUMBITS-1-ii]) 187362306a36Sopenharmony_ci tbits |= 1 ; 187462306a36Sopenharmony_ci } 187562306a36Sopenharmony_ci pcs->pcm_r_val = rbits ; 187662306a36Sopenharmony_ci pcs->pcm_t_val = tbits ; 187762306a36Sopenharmony_ci } 187862306a36Sopenharmony_ci} 187962306a36Sopenharmony_ci 188062306a36Sopenharmony_ciint get_pcm_state(struct s_smc *smc, int np) 188162306a36Sopenharmony_ci{ 188262306a36Sopenharmony_ci int pcs ; 188362306a36Sopenharmony_ci 188462306a36Sopenharmony_ci SK_UNUSED(smc) ; 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci switch (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_STATE) { 188762306a36Sopenharmony_ci case PL_PC0 : pcs = PC_STOP ; break ; 188862306a36Sopenharmony_ci case PL_PC1 : pcs = PC_START ; break ; 188962306a36Sopenharmony_ci case PL_PC2 : pcs = PC_TRACE ; break ; 189062306a36Sopenharmony_ci case PL_PC3 : pcs = PC_SIGNAL ; break ; 189162306a36Sopenharmony_ci case PL_PC4 : pcs = PC_SIGNAL ; break ; 189262306a36Sopenharmony_ci case PL_PC5 : pcs = PC_SIGNAL ; break ; 189362306a36Sopenharmony_ci case PL_PC6 : pcs = PC_JOIN ; break ; 189462306a36Sopenharmony_ci case PL_PC7 : pcs = PC_JOIN ; break ; 189562306a36Sopenharmony_ci case PL_PC8 : pcs = PC_ENABLE ; break ; 189662306a36Sopenharmony_ci case PL_PC9 : pcs = PC_MAINT ; break ; 189762306a36Sopenharmony_ci default : pcs = PC_DISABLE ; break ; 189862306a36Sopenharmony_ci } 189962306a36Sopenharmony_ci return pcs; 190062306a36Sopenharmony_ci} 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_cichar *get_linestate(struct s_smc *smc, int np) 190362306a36Sopenharmony_ci{ 190462306a36Sopenharmony_ci char *ls = "" ; 190562306a36Sopenharmony_ci 190662306a36Sopenharmony_ci SK_UNUSED(smc) ; 190762306a36Sopenharmony_ci 190862306a36Sopenharmony_ci switch (inpw(PLC(np,PL_STATUS_A)) & PL_LINE_ST) { 190962306a36Sopenharmony_ci case PL_L_NLS : ls = "NOISE" ; break ; 191062306a36Sopenharmony_ci case PL_L_ALS : ls = "ACTIV" ; break ; 191162306a36Sopenharmony_ci case PL_L_UND : ls = "UNDEF" ; break ; 191262306a36Sopenharmony_ci case PL_L_ILS4: ls = "ILS 4" ; break ; 191362306a36Sopenharmony_ci case PL_L_QLS : ls = "QLS" ; break ; 191462306a36Sopenharmony_ci case PL_L_MLS : ls = "MLS" ; break ; 191562306a36Sopenharmony_ci case PL_L_HLS : ls = "HLS" ; break ; 191662306a36Sopenharmony_ci case PL_L_ILS16:ls = "ILS16" ; break ; 191762306a36Sopenharmony_ci#ifdef lint 191862306a36Sopenharmony_ci default: ls = "unknown" ; break ; 191962306a36Sopenharmony_ci#endif 192062306a36Sopenharmony_ci } 192162306a36Sopenharmony_ci return ls; 192262306a36Sopenharmony_ci} 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_cichar *get_pcmstate(struct s_smc *smc, int np) 192562306a36Sopenharmony_ci{ 192662306a36Sopenharmony_ci char *pcs ; 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci SK_UNUSED(smc) ; 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci switch (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_STATE) { 193162306a36Sopenharmony_ci case PL_PC0 : pcs = "OFF" ; break ; 193262306a36Sopenharmony_ci case PL_PC1 : pcs = "BREAK" ; break ; 193362306a36Sopenharmony_ci case PL_PC2 : pcs = "TRACE" ; break ; 193462306a36Sopenharmony_ci case PL_PC3 : pcs = "CONNECT"; break ; 193562306a36Sopenharmony_ci case PL_PC4 : pcs = "NEXT" ; break ; 193662306a36Sopenharmony_ci case PL_PC5 : pcs = "SIGNAL" ; break ; 193762306a36Sopenharmony_ci case PL_PC6 : pcs = "JOIN" ; break ; 193862306a36Sopenharmony_ci case PL_PC7 : pcs = "VERIFY" ; break ; 193962306a36Sopenharmony_ci case PL_PC8 : pcs = "ACTIV" ; break ; 194062306a36Sopenharmony_ci case PL_PC9 : pcs = "MAINT" ; break ; 194162306a36Sopenharmony_ci default : pcs = "UNKNOWN" ; break ; 194262306a36Sopenharmony_ci } 194362306a36Sopenharmony_ci return pcs; 194462306a36Sopenharmony_ci} 194562306a36Sopenharmony_ci 194662306a36Sopenharmony_civoid list_phy(struct s_smc *smc) 194762306a36Sopenharmony_ci{ 194862306a36Sopenharmony_ci struct s_plc *plc ; 194962306a36Sopenharmony_ci int np ; 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_ci for (np = 0 ; np < NUMPHYS ; np++) { 195262306a36Sopenharmony_ci plc = &smc->y[np].plc ; 195362306a36Sopenharmony_ci printf("PHY %d:\tERRORS\t\t\tBREAK_REASONS\t\tSTATES:\n",np) ; 195462306a36Sopenharmony_ci printf("\tsoft_error: %ld \t\tPC_Start : %ld\n", 195562306a36Sopenharmony_ci plc->soft_err,plc->b_pcs); 195662306a36Sopenharmony_ci printf("\tparity_err: %ld \t\tTPC exp. : %ld\t\tLine: %s\n", 195762306a36Sopenharmony_ci plc->parity_err,plc->b_tpc,get_linestate(smc,np)) ; 195862306a36Sopenharmony_ci printf("\tebuf_error: %ld \t\tTNE exp. : %ld\n", 195962306a36Sopenharmony_ci plc->ebuf_err,plc->b_tne) ; 196062306a36Sopenharmony_ci printf("\tphyinvalid: %ld \t\tQLS det. : %ld\t\tPCM : %s\n", 196162306a36Sopenharmony_ci plc->phyinv,plc->b_qls,get_pcmstate(smc,np)) ; 196262306a36Sopenharmony_ci printf("\tviosym_ctr: %ld \t\tILS det. : %ld\n", 196362306a36Sopenharmony_ci plc->vsym_ctr,plc->b_ils) ; 196462306a36Sopenharmony_ci printf("\tmingap_ctr: %ld \t\tHLS det. : %ld\n", 196562306a36Sopenharmony_ci plc->mini_ctr,plc->b_hls) ; 196662306a36Sopenharmony_ci printf("\tnodepr_err: %ld\n",plc->np_err) ; 196762306a36Sopenharmony_ci printf("\tTPC_exp : %ld\n",plc->tpc_exp) ; 196862306a36Sopenharmony_ci printf("\tLEM_err : %ld\n",smc->y[np].lem.lem_errors) ; 196962306a36Sopenharmony_ci } 197062306a36Sopenharmony_ci} 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_ci 197362306a36Sopenharmony_ci#ifdef CONCENTRATOR 197462306a36Sopenharmony_civoid pcm_lem_dump(struct s_smc *smc) 197562306a36Sopenharmony_ci{ 197662306a36Sopenharmony_ci int i ; 197762306a36Sopenharmony_ci struct s_phy *phy ; 197862306a36Sopenharmony_ci struct fddi_mib_p *mib ; 197962306a36Sopenharmony_ci 198062306a36Sopenharmony_ci char *entostring() ; 198162306a36Sopenharmony_ci 198262306a36Sopenharmony_ci printf("PHY errors BER\n") ; 198362306a36Sopenharmony_ci printf("----------------------\n") ; 198462306a36Sopenharmony_ci for (i = 0,phy = smc->y ; i < NUMPHYS ; i++,phy++) { 198562306a36Sopenharmony_ci if (!plc_is_installed(smc,i)) 198662306a36Sopenharmony_ci continue ; 198762306a36Sopenharmony_ci mib = phy->mib ; 198862306a36Sopenharmony_ci printf("%s\t%ld\t10E-%d\n", 198962306a36Sopenharmony_ci entostring(smc,ENTITY_PHY(i)), 199062306a36Sopenharmony_ci mib->fddiPORTLem_Ct, 199162306a36Sopenharmony_ci mib->fddiPORTLer_Estimate) ; 199262306a36Sopenharmony_ci } 199362306a36Sopenharmony_ci} 199462306a36Sopenharmony_ci#endif 199562306a36Sopenharmony_ci#endif 1996