12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
233f810b2SJeff Kirsher /******************************************************************************
333f810b2SJeff Kirsher *
433f810b2SJeff Kirsher * (C)Copyright 1998,1999 SysKonnect,
533f810b2SJeff Kirsher * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
633f810b2SJeff Kirsher *
733f810b2SJeff Kirsher * See the file "skfddi.c" for further information.
833f810b2SJeff Kirsher *
933f810b2SJeff Kirsher * The information in this file is provided "AS IS" without warranty.
1033f810b2SJeff Kirsher *
1133f810b2SJeff Kirsher ******************************************************************************/
1233f810b2SJeff Kirsher
1333f810b2SJeff Kirsher /*
1433f810b2SJeff Kirsher PCM
1533f810b2SJeff Kirsher Physical Connection Management
1633f810b2SJeff Kirsher */
1733f810b2SJeff Kirsher
1833f810b2SJeff Kirsher /*
1933f810b2SJeff Kirsher * Hardware independent state machine implemantation
2033f810b2SJeff Kirsher * The following external SMT functions are referenced :
2133f810b2SJeff Kirsher *
2233f810b2SJeff Kirsher * queue_event()
2333f810b2SJeff Kirsher * smt_timer_start()
2433f810b2SJeff Kirsher * smt_timer_stop()
2533f810b2SJeff Kirsher *
2633f810b2SJeff Kirsher * The following external HW dependent functions are referenced :
2733f810b2SJeff Kirsher * sm_pm_control()
2833f810b2SJeff Kirsher * sm_ph_linestate()
2933f810b2SJeff Kirsher *
3033f810b2SJeff Kirsher * The following HW dependent events are required :
3133f810b2SJeff Kirsher * PC_QLS
3233f810b2SJeff Kirsher * PC_ILS
3333f810b2SJeff Kirsher * PC_HLS
3433f810b2SJeff Kirsher * PC_MLS
3533f810b2SJeff Kirsher * PC_NSE
3633f810b2SJeff Kirsher * PC_LEM
3733f810b2SJeff Kirsher *
3833f810b2SJeff Kirsher */
3933f810b2SJeff Kirsher
4033f810b2SJeff Kirsher
4133f810b2SJeff Kirsher #include "h/types.h"
4233f810b2SJeff Kirsher #include "h/fddi.h"
4333f810b2SJeff Kirsher #include "h/smc.h"
4433f810b2SJeff Kirsher #include "h/supern_2.h"
4533f810b2SJeff Kirsher #define KERNEL
4633f810b2SJeff Kirsher #include "h/smtstate.h"
4733f810b2SJeff Kirsher
4833f810b2SJeff Kirsher #ifdef FDDI_MIB
4933f810b2SJeff Kirsher extern int snmp_fddi_trap(
5033f810b2SJeff Kirsher #ifdef ANSIC
5133f810b2SJeff Kirsher struct s_smc * smc, int type, int index
5233f810b2SJeff Kirsher #endif
5333f810b2SJeff Kirsher );
5433f810b2SJeff Kirsher #endif
5533f810b2SJeff Kirsher #ifdef CONCENTRATOR
5633f810b2SJeff Kirsher extern int plc_is_installed(
5733f810b2SJeff Kirsher #ifdef ANSIC
5833f810b2SJeff Kirsher struct s_smc *smc ,
5933f810b2SJeff Kirsher int p
6033f810b2SJeff Kirsher #endif
6133f810b2SJeff Kirsher ) ;
6233f810b2SJeff Kirsher #endif
6333f810b2SJeff Kirsher /*
6433f810b2SJeff Kirsher * FSM Macros
6533f810b2SJeff Kirsher */
6633f810b2SJeff Kirsher #define AFLAG (0x20)
6733f810b2SJeff Kirsher #define GO_STATE(x) (mib->fddiPORTPCMState = (x)|AFLAG)
6833f810b2SJeff Kirsher #define ACTIONS_DONE() (mib->fddiPORTPCMState &= ~AFLAG)
6933f810b2SJeff Kirsher #define ACTIONS(x) (x|AFLAG)
7033f810b2SJeff Kirsher
7133f810b2SJeff Kirsher /*
7233f810b2SJeff Kirsher * PCM states
7333f810b2SJeff Kirsher */
7433f810b2SJeff Kirsher #define PC0_OFF 0
7533f810b2SJeff Kirsher #define PC1_BREAK 1
7633f810b2SJeff Kirsher #define PC2_TRACE 2
7733f810b2SJeff Kirsher #define PC3_CONNECT 3
7833f810b2SJeff Kirsher #define PC4_NEXT 4
7933f810b2SJeff Kirsher #define PC5_SIGNAL 5
8033f810b2SJeff Kirsher #define PC6_JOIN 6
8133f810b2SJeff Kirsher #define PC7_VERIFY 7
8233f810b2SJeff Kirsher #define PC8_ACTIVE 8
8333f810b2SJeff Kirsher #define PC9_MAINT 9
8433f810b2SJeff Kirsher
8533f810b2SJeff Kirsher /*
8633f810b2SJeff Kirsher * symbolic state names
8733f810b2SJeff Kirsher */
8833f810b2SJeff Kirsher static const char * const pcm_states[] = {
8933f810b2SJeff Kirsher "PC0_OFF","PC1_BREAK","PC2_TRACE","PC3_CONNECT","PC4_NEXT",
9033f810b2SJeff Kirsher "PC5_SIGNAL","PC6_JOIN","PC7_VERIFY","PC8_ACTIVE","PC9_MAINT"
9133f810b2SJeff Kirsher } ;
9233f810b2SJeff Kirsher
9333f810b2SJeff Kirsher /*
9433f810b2SJeff Kirsher * symbolic event names
9533f810b2SJeff Kirsher */
9633f810b2SJeff Kirsher static const char * const pcm_events[] = {
9733f810b2SJeff Kirsher "NONE","PC_START","PC_STOP","PC_LOOP","PC_JOIN","PC_SIGNAL",
9833f810b2SJeff Kirsher "PC_REJECT","PC_MAINT","PC_TRACE","PC_PDR",
9933f810b2SJeff Kirsher "PC_ENABLE","PC_DISABLE",
10033f810b2SJeff Kirsher "PC_QLS","PC_ILS","PC_MLS","PC_HLS","PC_LS_PDR","PC_LS_NONE",
10133f810b2SJeff Kirsher "PC_TIMEOUT_TB_MAX","PC_TIMEOUT_TB_MIN",
10233f810b2SJeff Kirsher "PC_TIMEOUT_C_MIN","PC_TIMEOUT_T_OUT",
10333f810b2SJeff Kirsher "PC_TIMEOUT_TL_MIN","PC_TIMEOUT_T_NEXT","PC_TIMEOUT_LCT",
10433f810b2SJeff Kirsher "PC_NSE","PC_LEM"
10533f810b2SJeff Kirsher } ;
10633f810b2SJeff Kirsher
10733f810b2SJeff Kirsher #ifdef MOT_ELM
10833f810b2SJeff Kirsher /*
10933f810b2SJeff Kirsher * PCL-S control register
11033f810b2SJeff Kirsher * this register in the PLC-S controls the scrambling parameters
11133f810b2SJeff Kirsher */
11233f810b2SJeff Kirsher #define PLCS_CONTROL_C_U 0
11333f810b2SJeff Kirsher #define PLCS_CONTROL_C_S (PL_C_SDOFF_ENABLE | PL_C_SDON_ENABLE | \
11433f810b2SJeff Kirsher PL_C_CIPHER_ENABLE)
11533f810b2SJeff Kirsher #define PLCS_FASSERT_U 0
11633f810b2SJeff Kirsher #define PLCS_FASSERT_S 0xFd76 /* 52.0 us */
11733f810b2SJeff Kirsher #define PLCS_FDEASSERT_U 0
11833f810b2SJeff Kirsher #define PLCS_FDEASSERT_S 0
11933f810b2SJeff Kirsher #else /* nMOT_ELM */
12033f810b2SJeff Kirsher /*
12133f810b2SJeff Kirsher * PCL-S control register
12233f810b2SJeff Kirsher * this register in the PLC-S controls the scrambling parameters
12333f810b2SJeff Kirsher * can be patched for ANSI compliance if standard changes
12433f810b2SJeff Kirsher */
12533f810b2SJeff Kirsher static const u_char plcs_control_c_u[17] = "PLC_CNTRL_C_U=\0\0" ;
12633f810b2SJeff Kirsher static const u_char plcs_control_c_s[17] = "PLC_CNTRL_C_S=\01\02" ;
12733f810b2SJeff Kirsher
12833f810b2SJeff Kirsher #define PLCS_CONTROL_C_U (plcs_control_c_u[14] | (plcs_control_c_u[15]<<8))
12933f810b2SJeff Kirsher #define PLCS_CONTROL_C_S (plcs_control_c_s[14] | (plcs_control_c_s[15]<<8))
13033f810b2SJeff Kirsher #endif /* nMOT_ELM */
13133f810b2SJeff Kirsher
13233f810b2SJeff Kirsher /*
13333f810b2SJeff Kirsher * external vars
13433f810b2SJeff Kirsher */
13533f810b2SJeff Kirsher /* struct definition see 'cmtdef.h' (also used by CFM) */
13633f810b2SJeff Kirsher
13733f810b2SJeff Kirsher #define PS_OFF 0
13833f810b2SJeff Kirsher #define PS_BIT3 1
13933f810b2SJeff Kirsher #define PS_BIT4 2
14033f810b2SJeff Kirsher #define PS_BIT7 3
14133f810b2SJeff Kirsher #define PS_LCT 4
14233f810b2SJeff Kirsher #define PS_BIT8 5
14333f810b2SJeff Kirsher #define PS_JOIN 6
14433f810b2SJeff Kirsher #define PS_ACTIVE 7
14533f810b2SJeff Kirsher
14633f810b2SJeff Kirsher #define LCT_LEM_MAX 255
14733f810b2SJeff Kirsher
14833f810b2SJeff Kirsher /*
14933f810b2SJeff Kirsher * PLC timing parameter
15033f810b2SJeff Kirsher */
15133f810b2SJeff Kirsher
15233f810b2SJeff Kirsher #define PLC_MS(m) ((int)((0x10000L-(m*100000L/2048))))
15333f810b2SJeff Kirsher #define SLOW_TL_MIN PLC_MS(6)
15433f810b2SJeff Kirsher #define SLOW_C_MIN PLC_MS(10)
15533f810b2SJeff Kirsher
15633f810b2SJeff Kirsher static const struct plt {
15733f810b2SJeff Kirsher int timer ; /* relative plc timer address */
15833f810b2SJeff Kirsher int para ; /* default timing parameters */
15933f810b2SJeff Kirsher } pltm[] = {
16033f810b2SJeff Kirsher { PL_C_MIN, SLOW_C_MIN }, /* min t. to remain Connect State */
16133f810b2SJeff Kirsher { PL_TL_MIN, SLOW_TL_MIN }, /* min t. to transmit a Line State */
16233f810b2SJeff Kirsher { PL_TB_MIN, TP_TB_MIN }, /* min break time */
16333f810b2SJeff Kirsher { PL_T_OUT, TP_T_OUT }, /* Signaling timeout */
16433f810b2SJeff Kirsher { PL_LC_LENGTH, TP_LC_LENGTH }, /* Link Confidence Test Time */
16533f810b2SJeff Kirsher { PL_T_SCRUB, TP_T_SCRUB }, /* Scrub Time == MAC TVX time ! */
16633f810b2SJeff Kirsher { PL_NS_MAX, TP_NS_MAX }, /* max t. that noise is tolerated */
16733f810b2SJeff Kirsher { 0,0 }
16833f810b2SJeff Kirsher } ;
16933f810b2SJeff Kirsher
17033f810b2SJeff Kirsher /*
17133f810b2SJeff Kirsher * interrupt mask
17233f810b2SJeff Kirsher */
17333f810b2SJeff Kirsher #ifdef SUPERNET_3
17433f810b2SJeff Kirsher /*
17533f810b2SJeff Kirsher * Do we need the EBUF error during signaling, too, to detect SUPERNET_3
17633f810b2SJeff Kirsher * PLL bug?
17733f810b2SJeff Kirsher */
17833f810b2SJeff Kirsher static const int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
17933f810b2SJeff Kirsher PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR;
18033f810b2SJeff Kirsher #else /* SUPERNET_3 */
18133f810b2SJeff Kirsher /*
18233f810b2SJeff Kirsher * We do NOT need the elasticity buffer error during signaling.
18333f810b2SJeff Kirsher */
18433f810b2SJeff Kirsher static int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
18533f810b2SJeff Kirsher PL_PCM_ENABLED | PL_SELF_TEST ;
18633f810b2SJeff Kirsher #endif /* SUPERNET_3 */
18733f810b2SJeff Kirsher static const int plc_imsk_act = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
18833f810b2SJeff Kirsher PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR;
18933f810b2SJeff Kirsher
19033f810b2SJeff Kirsher /* internal functions */
19133f810b2SJeff Kirsher static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd);
19233f810b2SJeff Kirsher static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy);
19333f810b2SJeff Kirsher static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy);
19433f810b2SJeff Kirsher static void reset_lem_struct(struct s_phy *phy);
19533f810b2SJeff Kirsher static void plc_init(struct s_smc *smc, int p);
19633f810b2SJeff Kirsher static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold);
19733f810b2SJeff Kirsher static void sm_ph_lem_stop(struct s_smc *smc, int np);
19833f810b2SJeff Kirsher static void sm_ph_linestate(struct s_smc *smc, int phy, int ls);
19933f810b2SJeff Kirsher static void real_init_plc(struct s_smc *smc);
20033f810b2SJeff Kirsher
20133f810b2SJeff Kirsher /*
20233f810b2SJeff Kirsher * SMT timer interface
20333f810b2SJeff Kirsher * start PCM timer 0
20433f810b2SJeff Kirsher */
start_pcm_timer0(struct s_smc * smc,u_long value,int event,struct s_phy * phy)20533f810b2SJeff Kirsher static void start_pcm_timer0(struct s_smc *smc, u_long value, int event,
20633f810b2SJeff Kirsher struct s_phy *phy)
20733f810b2SJeff Kirsher {
20833f810b2SJeff Kirsher phy->timer0_exp = FALSE ; /* clear timer event flag */
20933f810b2SJeff Kirsher smt_timer_start(smc,&phy->pcm_timer0,value,
21033f810b2SJeff Kirsher EV_TOKEN(EVENT_PCM+phy->np,event)) ;
21133f810b2SJeff Kirsher }
21233f810b2SJeff Kirsher /*
21333f810b2SJeff Kirsher * SMT timer interface
21433f810b2SJeff Kirsher * stop PCM timer 0
21533f810b2SJeff Kirsher */
stop_pcm_timer0(struct s_smc * smc,struct s_phy * phy)21633f810b2SJeff Kirsher static void stop_pcm_timer0(struct s_smc *smc, struct s_phy *phy)
21733f810b2SJeff Kirsher {
21833f810b2SJeff Kirsher if (phy->pcm_timer0.tm_active)
21933f810b2SJeff Kirsher smt_timer_stop(smc,&phy->pcm_timer0) ;
22033f810b2SJeff Kirsher }
22133f810b2SJeff Kirsher
22233f810b2SJeff Kirsher /*
22333f810b2SJeff Kirsher init PCM state machine (called by driver)
22433f810b2SJeff Kirsher clear all PCM vars and flags
22533f810b2SJeff Kirsher */
pcm_init(struct s_smc * smc)22633f810b2SJeff Kirsher void pcm_init(struct s_smc *smc)
22733f810b2SJeff Kirsher {
22833f810b2SJeff Kirsher int i ;
22933f810b2SJeff Kirsher int np ;
23033f810b2SJeff Kirsher struct s_phy *phy ;
23133f810b2SJeff Kirsher struct fddi_mib_p *mib ;
23233f810b2SJeff Kirsher
23333f810b2SJeff Kirsher for (np = 0,phy = smc->y ; np < NUMPHYS ; np++,phy++) {
23433f810b2SJeff Kirsher /* Indicates the type of PHY being used */
23533f810b2SJeff Kirsher mib = phy->mib ;
23633f810b2SJeff Kirsher mib->fddiPORTPCMState = ACTIONS(PC0_OFF) ;
23733f810b2SJeff Kirsher phy->np = np ;
23833f810b2SJeff Kirsher switch (smc->s.sas) {
23933f810b2SJeff Kirsher #ifdef CONCENTRATOR
24033f810b2SJeff Kirsher case SMT_SAS :
24133f810b2SJeff Kirsher mib->fddiPORTMy_Type = (np == PS) ? TS : TM ;
24233f810b2SJeff Kirsher break ;
24333f810b2SJeff Kirsher case SMT_DAS :
24433f810b2SJeff Kirsher mib->fddiPORTMy_Type = (np == PA) ? TA :
24533f810b2SJeff Kirsher (np == PB) ? TB : TM ;
24633f810b2SJeff Kirsher break ;
24733f810b2SJeff Kirsher case SMT_NAC :
24833f810b2SJeff Kirsher mib->fddiPORTMy_Type = TM ;
24933f810b2SJeff Kirsher break;
25033f810b2SJeff Kirsher #else
25133f810b2SJeff Kirsher case SMT_SAS :
25233f810b2SJeff Kirsher mib->fddiPORTMy_Type = (np == PS) ? TS : TNONE ;
25333f810b2SJeff Kirsher mib->fddiPORTHardwarePresent = (np == PS) ? TRUE :
25433f810b2SJeff Kirsher FALSE ;
25533f810b2SJeff Kirsher #ifndef SUPERNET_3
25633f810b2SJeff Kirsher smc->y[PA].mib->fddiPORTPCMState = PC0_OFF ;
25733f810b2SJeff Kirsher #else
25833f810b2SJeff Kirsher smc->y[PB].mib->fddiPORTPCMState = PC0_OFF ;
25933f810b2SJeff Kirsher #endif
26033f810b2SJeff Kirsher break ;
26133f810b2SJeff Kirsher case SMT_DAS :
26233f810b2SJeff Kirsher mib->fddiPORTMy_Type = (np == PB) ? TB : TA ;
26333f810b2SJeff Kirsher break ;
26433f810b2SJeff Kirsher #endif
26533f810b2SJeff Kirsher }
26633f810b2SJeff Kirsher /*
26733f810b2SJeff Kirsher * set PMD-type
26833f810b2SJeff Kirsher */
26933f810b2SJeff Kirsher phy->pmd_scramble = 0 ;
27033f810b2SJeff Kirsher switch (phy->pmd_type[PMD_SK_PMD]) {
27133f810b2SJeff Kirsher case 'P' :
27233f810b2SJeff Kirsher mib->fddiPORTPMDClass = MIB_PMDCLASS_MULTI ;
27333f810b2SJeff Kirsher break ;
27433f810b2SJeff Kirsher case 'L' :
27533f810b2SJeff Kirsher mib->fddiPORTPMDClass = MIB_PMDCLASS_LCF ;
27633f810b2SJeff Kirsher break ;
27733f810b2SJeff Kirsher case 'D' :
27833f810b2SJeff Kirsher mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
27933f810b2SJeff Kirsher break ;
28033f810b2SJeff Kirsher case 'S' :
28133f810b2SJeff Kirsher mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
28233f810b2SJeff Kirsher phy->pmd_scramble = TRUE ;
28333f810b2SJeff Kirsher break ;
28433f810b2SJeff Kirsher case 'U' :
28533f810b2SJeff Kirsher mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
28633f810b2SJeff Kirsher phy->pmd_scramble = TRUE ;
28733f810b2SJeff Kirsher break ;
28833f810b2SJeff Kirsher case '1' :
28933f810b2SJeff Kirsher mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE1 ;
29033f810b2SJeff Kirsher break ;
29133f810b2SJeff Kirsher case '2' :
29233f810b2SJeff Kirsher mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE2 ;
29333f810b2SJeff Kirsher break ;
29433f810b2SJeff Kirsher case '3' :
29533f810b2SJeff Kirsher mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE2 ;
29633f810b2SJeff Kirsher break ;
29733f810b2SJeff Kirsher case '4' :
29833f810b2SJeff Kirsher mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE1 ;
29933f810b2SJeff Kirsher break ;
30033f810b2SJeff Kirsher case 'H' :
30133f810b2SJeff Kirsher mib->fddiPORTPMDClass = MIB_PMDCLASS_UNKNOWN ;
30233f810b2SJeff Kirsher break ;
30333f810b2SJeff Kirsher case 'I' :
30433f810b2SJeff Kirsher mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
30533f810b2SJeff Kirsher break ;
30633f810b2SJeff Kirsher case 'G' :
30733f810b2SJeff Kirsher mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
30833f810b2SJeff Kirsher break ;
30933f810b2SJeff Kirsher default:
31033f810b2SJeff Kirsher mib->fddiPORTPMDClass = MIB_PMDCLASS_UNKNOWN ;
31133f810b2SJeff Kirsher break ;
31233f810b2SJeff Kirsher }
31333f810b2SJeff Kirsher /*
31433f810b2SJeff Kirsher * A and B port can be on primary and secondary path
31533f810b2SJeff Kirsher */
31633f810b2SJeff Kirsher switch (mib->fddiPORTMy_Type) {
31733f810b2SJeff Kirsher case TA :
31833f810b2SJeff Kirsher mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
31933f810b2SJeff Kirsher mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
32033f810b2SJeff Kirsher mib->fddiPORTRequestedPaths[2] =
32133f810b2SJeff Kirsher MIB_P_PATH_LOCAL |
32233f810b2SJeff Kirsher MIB_P_PATH_CON_ALTER |
32333f810b2SJeff Kirsher MIB_P_PATH_SEC_PREFER ;
32433f810b2SJeff Kirsher mib->fddiPORTRequestedPaths[3] =
32533f810b2SJeff Kirsher MIB_P_PATH_LOCAL |
32633f810b2SJeff Kirsher MIB_P_PATH_CON_ALTER |
32733f810b2SJeff Kirsher MIB_P_PATH_SEC_PREFER |
32833f810b2SJeff Kirsher MIB_P_PATH_THRU ;
32933f810b2SJeff Kirsher break ;
33033f810b2SJeff Kirsher case TB :
33133f810b2SJeff Kirsher mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
33233f810b2SJeff Kirsher mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
33333f810b2SJeff Kirsher mib->fddiPORTRequestedPaths[2] =
33433f810b2SJeff Kirsher MIB_P_PATH_LOCAL |
33533f810b2SJeff Kirsher MIB_P_PATH_PRIM_PREFER ;
33633f810b2SJeff Kirsher mib->fddiPORTRequestedPaths[3] =
33733f810b2SJeff Kirsher MIB_P_PATH_LOCAL |
33833f810b2SJeff Kirsher MIB_P_PATH_PRIM_PREFER |
33933f810b2SJeff Kirsher MIB_P_PATH_CON_PREFER |
34033f810b2SJeff Kirsher MIB_P_PATH_THRU ;
34133f810b2SJeff Kirsher break ;
34233f810b2SJeff Kirsher case TS :
34333f810b2SJeff Kirsher mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
34433f810b2SJeff Kirsher mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
34533f810b2SJeff Kirsher mib->fddiPORTRequestedPaths[2] =
34633f810b2SJeff Kirsher MIB_P_PATH_LOCAL |
34733f810b2SJeff Kirsher MIB_P_PATH_CON_ALTER |
34833f810b2SJeff Kirsher MIB_P_PATH_PRIM_PREFER ;
34933f810b2SJeff Kirsher mib->fddiPORTRequestedPaths[3] =
35033f810b2SJeff Kirsher MIB_P_PATH_LOCAL |
35133f810b2SJeff Kirsher MIB_P_PATH_CON_ALTER |
35233f810b2SJeff Kirsher MIB_P_PATH_PRIM_PREFER ;
35333f810b2SJeff Kirsher break ;
35433f810b2SJeff Kirsher case TM :
35533f810b2SJeff Kirsher mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
35633f810b2SJeff Kirsher mib->fddiPORTRequestedPaths[2] =
35733f810b2SJeff Kirsher MIB_P_PATH_LOCAL |
35833f810b2SJeff Kirsher MIB_P_PATH_SEC_ALTER |
35933f810b2SJeff Kirsher MIB_P_PATH_PRIM_ALTER ;
36033f810b2SJeff Kirsher mib->fddiPORTRequestedPaths[3] = 0 ;
36133f810b2SJeff Kirsher break ;
36233f810b2SJeff Kirsher }
36333f810b2SJeff Kirsher
36433f810b2SJeff Kirsher phy->pc_lem_fail = FALSE ;
36533f810b2SJeff Kirsher mib->fddiPORTPCMStateX = mib->fddiPORTPCMState ;
36633f810b2SJeff Kirsher mib->fddiPORTLCTFail_Ct = 0 ;
36733f810b2SJeff Kirsher mib->fddiPORTBS_Flag = 0 ;
36833f810b2SJeff Kirsher mib->fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
36933f810b2SJeff Kirsher mib->fddiPORTNeighborType = TNONE ;
37033f810b2SJeff Kirsher phy->ls_flag = 0 ;
37133f810b2SJeff Kirsher phy->rc_flag = 0 ;
37233f810b2SJeff Kirsher phy->tc_flag = 0 ;
37333f810b2SJeff Kirsher phy->td_flag = 0 ;
37433f810b2SJeff Kirsher if (np >= PM)
37533f810b2SJeff Kirsher phy->phy_name = '0' + np - PM ;
37633f810b2SJeff Kirsher else
37733f810b2SJeff Kirsher phy->phy_name = 'A' + np ;
37833f810b2SJeff Kirsher phy->wc_flag = FALSE ; /* set by SMT */
37933f810b2SJeff Kirsher memset((char *)&phy->lem,0,sizeof(struct lem_counter)) ;
38033f810b2SJeff Kirsher reset_lem_struct(phy) ;
38133f810b2SJeff Kirsher memset((char *)&phy->plc,0,sizeof(struct s_plc)) ;
38233f810b2SJeff Kirsher phy->plc.p_state = PS_OFF ;
38333f810b2SJeff Kirsher for (i = 0 ; i < NUMBITS ; i++) {
38433f810b2SJeff Kirsher phy->t_next[i] = 0 ;
38533f810b2SJeff Kirsher }
38633f810b2SJeff Kirsher }
38733f810b2SJeff Kirsher real_init_plc(smc) ;
38833f810b2SJeff Kirsher }
38933f810b2SJeff Kirsher
init_plc(struct s_smc * smc)39033f810b2SJeff Kirsher void init_plc(struct s_smc *smc)
39133f810b2SJeff Kirsher {
39233f810b2SJeff Kirsher SK_UNUSED(smc) ;
39333f810b2SJeff Kirsher
39433f810b2SJeff Kirsher /*
39533f810b2SJeff Kirsher * dummy
39633f810b2SJeff Kirsher * this is an obsolete public entry point that has to remain
39733f810b2SJeff Kirsher * for compat. It is used by various drivers.
39833f810b2SJeff Kirsher * the work is now done in real_init_plc()
39933f810b2SJeff Kirsher * which is called from pcm_init() ;
40033f810b2SJeff Kirsher */
40133f810b2SJeff Kirsher }
40233f810b2SJeff Kirsher
real_init_plc(struct s_smc * smc)40333f810b2SJeff Kirsher static void real_init_plc(struct s_smc *smc)
40433f810b2SJeff Kirsher {
40533f810b2SJeff Kirsher int p ;
40633f810b2SJeff Kirsher
40733f810b2SJeff Kirsher for (p = 0 ; p < NUMPHYS ; p++)
40833f810b2SJeff Kirsher plc_init(smc,p) ;
40933f810b2SJeff Kirsher }
41033f810b2SJeff Kirsher
plc_init(struct s_smc * smc,int p)41133f810b2SJeff Kirsher static void plc_init(struct s_smc *smc, int p)
41233f810b2SJeff Kirsher {
41333f810b2SJeff Kirsher int i ;
41433f810b2SJeff Kirsher #ifndef MOT_ELM
41533f810b2SJeff Kirsher int rev ; /* Revision of PLC-x */
41633f810b2SJeff Kirsher #endif /* MOT_ELM */
41733f810b2SJeff Kirsher
41833f810b2SJeff Kirsher /* transit PCM state machine to MAINT state */
41933f810b2SJeff Kirsher outpw(PLC(p,PL_CNTRL_B),0) ;
42033f810b2SJeff Kirsher outpw(PLC(p,PL_CNTRL_B),PL_PCM_STOP) ;
42133f810b2SJeff Kirsher outpw(PLC(p,PL_CNTRL_A),0) ;
42233f810b2SJeff Kirsher
42333f810b2SJeff Kirsher /*
42433f810b2SJeff Kirsher * if PLC-S then set control register C
42533f810b2SJeff Kirsher */
42633f810b2SJeff Kirsher #ifndef MOT_ELM
42733f810b2SJeff Kirsher rev = inpw(PLC(p,PL_STATUS_A)) & PLC_REV_MASK ;
42833f810b2SJeff Kirsher if (rev != PLC_REVISION_A)
42933f810b2SJeff Kirsher #endif /* MOT_ELM */
43033f810b2SJeff Kirsher {
43133f810b2SJeff Kirsher if (smc->y[p].pmd_scramble) {
43233f810b2SJeff Kirsher outpw(PLC(p,PL_CNTRL_C),PLCS_CONTROL_C_S) ;
43333f810b2SJeff Kirsher #ifdef MOT_ELM
43433f810b2SJeff Kirsher outpw(PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_S) ;
43533f810b2SJeff Kirsher outpw(PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_S) ;
43633f810b2SJeff Kirsher #endif /* MOT_ELM */
43733f810b2SJeff Kirsher }
43833f810b2SJeff Kirsher else {
43933f810b2SJeff Kirsher outpw(PLC(p,PL_CNTRL_C),PLCS_CONTROL_C_U) ;
44033f810b2SJeff Kirsher #ifdef MOT_ELM
44133f810b2SJeff Kirsher outpw(PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_U) ;
44233f810b2SJeff Kirsher outpw(PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_U) ;
44333f810b2SJeff Kirsher #endif /* MOT_ELM */
44433f810b2SJeff Kirsher }
44533f810b2SJeff Kirsher }
44633f810b2SJeff Kirsher
44733f810b2SJeff Kirsher /*
44833f810b2SJeff Kirsher * set timer register
44933f810b2SJeff Kirsher */
45033f810b2SJeff Kirsher for ( i = 0 ; pltm[i].timer; i++) /* set timer parameter reg */
45133f810b2SJeff Kirsher outpw(PLC(p,pltm[i].timer),pltm[i].para) ;
45233f810b2SJeff Kirsher
45333f810b2SJeff Kirsher (void)inpw(PLC(p,PL_INTR_EVENT)) ; /* clear interrupt event reg */
45433f810b2SJeff Kirsher plc_clear_irq(smc,p) ;
45533f810b2SJeff Kirsher outpw(PLC(p,PL_INTR_MASK),plc_imsk_na); /* enable non active irq's */
45633f810b2SJeff Kirsher
45733f810b2SJeff Kirsher /*
45833f810b2SJeff Kirsher * if PCM is configured for class s, it will NOT go to the
45933f810b2SJeff Kirsher * REMOVE state if offline (page 3-36;)
46033f810b2SJeff Kirsher * in the concentrator, all inactive PHYS always must be in
46133f810b2SJeff Kirsher * the remove state
46233f810b2SJeff Kirsher * there's no real need to use this feature at all ..
46333f810b2SJeff Kirsher */
46433f810b2SJeff Kirsher #ifndef CONCENTRATOR
46533f810b2SJeff Kirsher if ((smc->s.sas == SMT_SAS) && (p == PS)) {
46633f810b2SJeff Kirsher outpw(PLC(p,PL_CNTRL_B),PL_CLASS_S) ;
46733f810b2SJeff Kirsher }
46833f810b2SJeff Kirsher #endif
46933f810b2SJeff Kirsher }
47033f810b2SJeff Kirsher
47133f810b2SJeff Kirsher /*
47233f810b2SJeff Kirsher * control PCM state machine
47333f810b2SJeff Kirsher */
plc_go_state(struct s_smc * smc,int p,int state)47433f810b2SJeff Kirsher static void plc_go_state(struct s_smc *smc, int p, int state)
47533f810b2SJeff Kirsher {
47633f810b2SJeff Kirsher HW_PTR port ;
47733f810b2SJeff Kirsher int val ;
47833f810b2SJeff Kirsher
47933f810b2SJeff Kirsher SK_UNUSED(smc) ;
48033f810b2SJeff Kirsher
48133f810b2SJeff Kirsher port = (HW_PTR) (PLC(p,PL_CNTRL_B)) ;
48233f810b2SJeff Kirsher val = inpw(port) & ~(PL_PCM_CNTRL | PL_MAINT) ;
48333f810b2SJeff Kirsher outpw(port,val) ;
48433f810b2SJeff Kirsher outpw(port,val | state) ;
48533f810b2SJeff Kirsher }
48633f810b2SJeff Kirsher
48733f810b2SJeff Kirsher /*
48833f810b2SJeff Kirsher * read current line state (called by ECM & PCM)
48933f810b2SJeff Kirsher */
sm_pm_get_ls(struct s_smc * smc,int phy)49033f810b2SJeff Kirsher int sm_pm_get_ls(struct s_smc *smc, int phy)
49133f810b2SJeff Kirsher {
49233f810b2SJeff Kirsher int state ;
49333f810b2SJeff Kirsher
49433f810b2SJeff Kirsher #ifdef CONCENTRATOR
49533f810b2SJeff Kirsher if (!plc_is_installed(smc,phy))
49633f810b2SJeff Kirsher return PC_QLS;
49733f810b2SJeff Kirsher #endif
49833f810b2SJeff Kirsher
49933f810b2SJeff Kirsher state = inpw(PLC(phy,PL_STATUS_A)) & PL_LINE_ST ;
50033f810b2SJeff Kirsher switch(state) {
50133f810b2SJeff Kirsher case PL_L_QLS:
50233f810b2SJeff Kirsher state = PC_QLS ;
50333f810b2SJeff Kirsher break ;
50433f810b2SJeff Kirsher case PL_L_MLS:
50533f810b2SJeff Kirsher state = PC_MLS ;
50633f810b2SJeff Kirsher break ;
50733f810b2SJeff Kirsher case PL_L_HLS:
50833f810b2SJeff Kirsher state = PC_HLS ;
50933f810b2SJeff Kirsher break ;
51033f810b2SJeff Kirsher case PL_L_ILS4:
51133f810b2SJeff Kirsher case PL_L_ILS16:
51233f810b2SJeff Kirsher state = PC_ILS ;
51333f810b2SJeff Kirsher break ;
51433f810b2SJeff Kirsher case PL_L_ALS:
51533f810b2SJeff Kirsher state = PC_LS_PDR ;
51633f810b2SJeff Kirsher break ;
51733f810b2SJeff Kirsher default :
51833f810b2SJeff Kirsher state = PC_LS_NONE ;
51933f810b2SJeff Kirsher }
52033f810b2SJeff Kirsher return state;
52133f810b2SJeff Kirsher }
52233f810b2SJeff Kirsher
plc_send_bits(struct s_smc * smc,struct s_phy * phy,int len)52333f810b2SJeff Kirsher static int plc_send_bits(struct s_smc *smc, struct s_phy *phy, int len)
52433f810b2SJeff Kirsher {
52533f810b2SJeff Kirsher int np = phy->np ; /* PHY index */
52633f810b2SJeff Kirsher int n ;
52733f810b2SJeff Kirsher int i ;
52833f810b2SJeff Kirsher
52933f810b2SJeff Kirsher SK_UNUSED(smc) ;
53033f810b2SJeff Kirsher
53133f810b2SJeff Kirsher /* create bit vector */
53233f810b2SJeff Kirsher for (i = len-1,n = 0 ; i >= 0 ; i--) {
53333f810b2SJeff Kirsher n = (n<<1) | phy->t_val[phy->bitn+i] ;
53433f810b2SJeff Kirsher }
53533f810b2SJeff Kirsher if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) {
53633f810b2SJeff Kirsher #if 0
53733f810b2SJeff Kirsher printf("PL_PCM_SIGNAL is set\n") ;
53833f810b2SJeff Kirsher #endif
53933f810b2SJeff Kirsher return 1;
54033f810b2SJeff Kirsher }
54133f810b2SJeff Kirsher /* write bit[n] & length = 1 to regs */
54233f810b2SJeff Kirsher outpw(PLC(np,PL_VECTOR_LEN),len-1) ; /* len=nr-1 */
54333f810b2SJeff Kirsher outpw(PLC(np,PL_XMIT_VECTOR),n) ;
54433f810b2SJeff Kirsher #ifdef DEBUG
54533f810b2SJeff Kirsher #if 1
54633f810b2SJeff Kirsher #ifdef DEBUG_BRD
54733f810b2SJeff Kirsher if (smc->debug.d_plc & 0x80)
54833f810b2SJeff Kirsher #else
54933f810b2SJeff Kirsher if (debug.d_plc & 0x80)
55033f810b2SJeff Kirsher #endif
55133f810b2SJeff Kirsher printf("SIGNALING bit %d .. %d\n",phy->bitn,phy->bitn+len-1) ;
55233f810b2SJeff Kirsher #endif
55333f810b2SJeff Kirsher #endif
55433f810b2SJeff Kirsher return 0;
55533f810b2SJeff Kirsher }
55633f810b2SJeff Kirsher
55733f810b2SJeff Kirsher /*
55833f810b2SJeff Kirsher * config plc muxes
55933f810b2SJeff Kirsher */
plc_config_mux(struct s_smc * smc,int mux)56033f810b2SJeff Kirsher void plc_config_mux(struct s_smc *smc, int mux)
56133f810b2SJeff Kirsher {
56233f810b2SJeff Kirsher if (smc->s.sas != SMT_DAS)
56333f810b2SJeff Kirsher return ;
56433f810b2SJeff Kirsher if (mux == MUX_WRAPB) {
56533f810b2SJeff Kirsher SETMASK(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ;
56633f810b2SJeff Kirsher SETMASK(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP,PL_SC_REM_LOOP) ;
56733f810b2SJeff Kirsher }
56833f810b2SJeff Kirsher else {
56933f810b2SJeff Kirsher CLEAR(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL) ;
57033f810b2SJeff Kirsher CLEAR(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP) ;
57133f810b2SJeff Kirsher }
57233f810b2SJeff Kirsher CLEAR(PLC(PB,PL_CNTRL_B),PL_CONFIG_CNTRL) ;
57333f810b2SJeff Kirsher CLEAR(PLC(PB,PL_CNTRL_A),PL_SC_REM_LOOP) ;
57433f810b2SJeff Kirsher }
57533f810b2SJeff Kirsher
57633f810b2SJeff Kirsher /*
57733f810b2SJeff Kirsher PCM state machine
57833f810b2SJeff Kirsher called by dispatcher & fddi_init() (driver)
57933f810b2SJeff Kirsher do
58033f810b2SJeff Kirsher display state change
58133f810b2SJeff Kirsher process event
58233f810b2SJeff Kirsher until SM is stable
58333f810b2SJeff Kirsher */
pcm(struct s_smc * smc,const int np,int event)58433f810b2SJeff Kirsher void pcm(struct s_smc *smc, const int np, int event)
58533f810b2SJeff Kirsher {
58633f810b2SJeff Kirsher int state ;
58733f810b2SJeff Kirsher int oldstate ;
58833f810b2SJeff Kirsher struct s_phy *phy ;
58933f810b2SJeff Kirsher struct fddi_mib_p *mib ;
59033f810b2SJeff Kirsher
59133f810b2SJeff Kirsher #ifndef CONCENTRATOR
59233f810b2SJeff Kirsher /*
59333f810b2SJeff Kirsher * ignore 2nd PHY if SAS
59433f810b2SJeff Kirsher */
59533f810b2SJeff Kirsher if ((np != PS) && (smc->s.sas == SMT_SAS))
59633f810b2SJeff Kirsher return ;
59733f810b2SJeff Kirsher #endif
59833f810b2SJeff Kirsher phy = &smc->y[np] ;
59933f810b2SJeff Kirsher mib = phy->mib ;
60033f810b2SJeff Kirsher oldstate = mib->fddiPORTPCMState ;
60133f810b2SJeff Kirsher do {
6025671e8c1SJoe Perches DB_PCM("PCM %c: state %s%s, event %s",
60333f810b2SJeff Kirsher phy->phy_name,
6045671e8c1SJoe Perches mib->fddiPORTPCMState & AFLAG ? "ACTIONS " : "",
60533f810b2SJeff Kirsher pcm_states[mib->fddiPORTPCMState & ~AFLAG],
60633f810b2SJeff Kirsher pcm_events[event]);
60733f810b2SJeff Kirsher state = mib->fddiPORTPCMState ;
60833f810b2SJeff Kirsher pcm_fsm(smc,phy,event) ;
60933f810b2SJeff Kirsher event = 0 ;
61033f810b2SJeff Kirsher } while (state != mib->fddiPORTPCMState) ;
61133f810b2SJeff Kirsher /*
61233f810b2SJeff Kirsher * because the PLC does the bit signaling for us,
61333f810b2SJeff Kirsher * we're always in SIGNAL state
61433f810b2SJeff Kirsher * the MIB want's to see CONNECT
61533f810b2SJeff Kirsher * we therefore fake an entry in the MIB
61633f810b2SJeff Kirsher */
61733f810b2SJeff Kirsher if (state == PC5_SIGNAL)
61833f810b2SJeff Kirsher mib->fddiPORTPCMStateX = PC3_CONNECT ;
61933f810b2SJeff Kirsher else
62033f810b2SJeff Kirsher mib->fddiPORTPCMStateX = state ;
62133f810b2SJeff Kirsher
62233f810b2SJeff Kirsher #ifndef SLIM_SMT
62333f810b2SJeff Kirsher /*
62433f810b2SJeff Kirsher * path change
62533f810b2SJeff Kirsher */
62633f810b2SJeff Kirsher if ( mib->fddiPORTPCMState != oldstate &&
62733f810b2SJeff Kirsher ((oldstate == PC8_ACTIVE) || (mib->fddiPORTPCMState == PC8_ACTIVE))) {
62833f810b2SJeff Kirsher smt_srf_event(smc,SMT_EVENT_PORT_PATH_CHANGE,
62933f810b2SJeff Kirsher (int) (INDEX_PORT+ phy->np),0) ;
63033f810b2SJeff Kirsher }
63133f810b2SJeff Kirsher #endif
63233f810b2SJeff Kirsher
63333f810b2SJeff Kirsher #ifdef FDDI_MIB
63433f810b2SJeff Kirsher /* check whether a snmp-trap has to be sent */
63533f810b2SJeff Kirsher
63633f810b2SJeff Kirsher if ( mib->fddiPORTPCMState != oldstate ) {
63733f810b2SJeff Kirsher /* a real state change took place */
63833f810b2SJeff Kirsher DB_SNMP ("PCM from %d to %d\n", oldstate, mib->fddiPORTPCMState);
63933f810b2SJeff Kirsher if ( mib->fddiPORTPCMState == PC0_OFF ) {
64033f810b2SJeff Kirsher /* send first trap */
64133f810b2SJeff Kirsher snmp_fddi_trap (smc, 1, (int) mib->fddiPORTIndex );
64233f810b2SJeff Kirsher } else if ( oldstate == PC0_OFF ) {
64333f810b2SJeff Kirsher /* send second trap */
64433f810b2SJeff Kirsher snmp_fddi_trap (smc, 2, (int) mib->fddiPORTIndex );
64533f810b2SJeff Kirsher } else if ( mib->fddiPORTPCMState != PC2_TRACE &&
64633f810b2SJeff Kirsher oldstate == PC8_ACTIVE ) {
64733f810b2SJeff Kirsher /* send third trap */
64833f810b2SJeff Kirsher snmp_fddi_trap (smc, 3, (int) mib->fddiPORTIndex );
64933f810b2SJeff Kirsher } else if ( mib->fddiPORTPCMState == PC8_ACTIVE ) {
65033f810b2SJeff Kirsher /* send fourth trap */
65133f810b2SJeff Kirsher snmp_fddi_trap (smc, 4, (int) mib->fddiPORTIndex );
65233f810b2SJeff Kirsher }
65333f810b2SJeff Kirsher }
65433f810b2SJeff Kirsher #endif
65533f810b2SJeff Kirsher
65633f810b2SJeff Kirsher pcm_state_change(smc,np,state) ;
65733f810b2SJeff Kirsher }
65833f810b2SJeff Kirsher
65933f810b2SJeff Kirsher /*
66033f810b2SJeff Kirsher * PCM state machine
66133f810b2SJeff Kirsher */
pcm_fsm(struct s_smc * smc,struct s_phy * phy,int cmd)66233f810b2SJeff Kirsher static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd)
66333f810b2SJeff Kirsher {
66433f810b2SJeff Kirsher int i ;
66533f810b2SJeff Kirsher int np = phy->np ; /* PHY index */
66633f810b2SJeff Kirsher struct s_plc *plc ;
66733f810b2SJeff Kirsher struct fddi_mib_p *mib ;
66833f810b2SJeff Kirsher #ifndef MOT_ELM
66933f810b2SJeff Kirsher u_short plc_rev ; /* Revision of the plc */
67033f810b2SJeff Kirsher #endif /* nMOT_ELM */
67133f810b2SJeff Kirsher
67233f810b2SJeff Kirsher plc = &phy->plc ;
67333f810b2SJeff Kirsher mib = phy->mib ;
67433f810b2SJeff Kirsher
67533f810b2SJeff Kirsher /*
67633f810b2SJeff Kirsher * general transitions independent of state
67733f810b2SJeff Kirsher */
67833f810b2SJeff Kirsher switch (cmd) {
67933f810b2SJeff Kirsher case PC_STOP :
68033f810b2SJeff Kirsher /*PC00-PC80*/
68133f810b2SJeff Kirsher if (mib->fddiPORTPCMState != PC9_MAINT) {
68233f810b2SJeff Kirsher GO_STATE(PC0_OFF) ;
68333f810b2SJeff Kirsher AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
68433f810b2SJeff Kirsher FDDI_PORT_EVENT, (u_long) FDDI_PORT_STOP,
68533f810b2SJeff Kirsher smt_get_port_event_word(smc));
68633f810b2SJeff Kirsher }
68733f810b2SJeff Kirsher return ;
68833f810b2SJeff Kirsher case PC_START :
68933f810b2SJeff Kirsher /*PC01-PC81*/
69033f810b2SJeff Kirsher if (mib->fddiPORTPCMState != PC9_MAINT)
69133f810b2SJeff Kirsher GO_STATE(PC1_BREAK) ;
69233f810b2SJeff Kirsher return ;
69333f810b2SJeff Kirsher case PC_DISABLE :
69433f810b2SJeff Kirsher /* PC09-PC99 */
69533f810b2SJeff Kirsher GO_STATE(PC9_MAINT) ;
69633f810b2SJeff Kirsher AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
69733f810b2SJeff Kirsher FDDI_PORT_EVENT, (u_long) FDDI_PORT_DISABLED,
69833f810b2SJeff Kirsher smt_get_port_event_word(smc));
69933f810b2SJeff Kirsher return ;
70033f810b2SJeff Kirsher case PC_TIMEOUT_LCT :
70133f810b2SJeff Kirsher /* if long or extended LCT */
70233f810b2SJeff Kirsher stop_pcm_timer0(smc,phy) ;
70333f810b2SJeff Kirsher CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
70433f810b2SJeff Kirsher /* end of LCT is indicate by PCM_CODE (initiate PCM event) */
70533f810b2SJeff Kirsher return ;
70633f810b2SJeff Kirsher }
70733f810b2SJeff Kirsher
70833f810b2SJeff Kirsher switch(mib->fddiPORTPCMState) {
70933f810b2SJeff Kirsher case ACTIONS(PC0_OFF) :
71033f810b2SJeff Kirsher stop_pcm_timer0(smc,phy) ;
71133f810b2SJeff Kirsher outpw(PLC(np,PL_CNTRL_A),0) ;
71233f810b2SJeff Kirsher CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
71333f810b2SJeff Kirsher CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
71433f810b2SJeff Kirsher sm_ph_lem_stop(smc,np) ; /* disable LEM */
71533f810b2SJeff Kirsher phy->cf_loop = FALSE ;
71633f810b2SJeff Kirsher phy->cf_join = FALSE ;
71733f810b2SJeff Kirsher queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
71833f810b2SJeff Kirsher plc_go_state(smc,np,PL_PCM_STOP) ;
71933f810b2SJeff Kirsher mib->fddiPORTConnectState = PCM_DISABLED ;
72033f810b2SJeff Kirsher ACTIONS_DONE() ;
72133f810b2SJeff Kirsher break ;
72233f810b2SJeff Kirsher case PC0_OFF:
72333f810b2SJeff Kirsher /*PC09*/
72433f810b2SJeff Kirsher if (cmd == PC_MAINT) {
72533f810b2SJeff Kirsher GO_STATE(PC9_MAINT) ;
72633f810b2SJeff Kirsher break ;
72733f810b2SJeff Kirsher }
72833f810b2SJeff Kirsher break ;
72933f810b2SJeff Kirsher case ACTIONS(PC1_BREAK) :
73033f810b2SJeff Kirsher /* Stop the LCT timer if we came from Signal state */
73133f810b2SJeff Kirsher stop_pcm_timer0(smc,phy) ;
73233f810b2SJeff Kirsher ACTIONS_DONE() ;
73333f810b2SJeff Kirsher plc_go_state(smc,np,0) ;
73433f810b2SJeff Kirsher CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
73533f810b2SJeff Kirsher CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
73633f810b2SJeff Kirsher sm_ph_lem_stop(smc,np) ; /* disable LEM */
73733f810b2SJeff Kirsher /*
73833f810b2SJeff Kirsher * if vector is already loaded, go to OFF to clear PCM_SIGNAL
73933f810b2SJeff Kirsher */
74033f810b2SJeff Kirsher #if 0
74133f810b2SJeff Kirsher if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) {
74233f810b2SJeff Kirsher plc_go_state(smc,np,PL_PCM_STOP) ;
74333f810b2SJeff Kirsher /* TB_MIN ? */
74433f810b2SJeff Kirsher }
74533f810b2SJeff Kirsher #endif
74633f810b2SJeff Kirsher /*
74733f810b2SJeff Kirsher * Go to OFF state in any case.
74833f810b2SJeff Kirsher */
74933f810b2SJeff Kirsher plc_go_state(smc,np,PL_PCM_STOP) ;
75033f810b2SJeff Kirsher
75133f810b2SJeff Kirsher if (mib->fddiPORTPC_Withhold == PC_WH_NONE)
75233f810b2SJeff Kirsher mib->fddiPORTConnectState = PCM_CONNECTING ;
75333f810b2SJeff Kirsher phy->cf_loop = FALSE ;
75433f810b2SJeff Kirsher phy->cf_join = FALSE ;
75533f810b2SJeff Kirsher queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
75633f810b2SJeff Kirsher phy->ls_flag = FALSE ;
75733f810b2SJeff Kirsher phy->pc_mode = PM_NONE ; /* needed by CFM */
75833f810b2SJeff Kirsher phy->bitn = 0 ; /* bit signaling start bit */
75933f810b2SJeff Kirsher for (i = 0 ; i < 3 ; i++)
76033f810b2SJeff Kirsher pc_tcode_actions(smc,i,phy) ;
76133f810b2SJeff Kirsher
76233f810b2SJeff Kirsher /* Set the non-active interrupt mask register */
76333f810b2SJeff Kirsher outpw(PLC(np,PL_INTR_MASK),plc_imsk_na) ;
76433f810b2SJeff Kirsher
76533f810b2SJeff Kirsher /*
76633f810b2SJeff Kirsher * If the LCT was stopped. There might be a
76733f810b2SJeff Kirsher * PCM_CODE interrupt event present.
76833f810b2SJeff Kirsher * This must be cleared.
76933f810b2SJeff Kirsher */
77033f810b2SJeff Kirsher (void)inpw(PLC(np,PL_INTR_EVENT)) ;
77133f810b2SJeff Kirsher #ifndef MOT_ELM
77233f810b2SJeff Kirsher /* Get the plc revision for revision dependent code */
77333f810b2SJeff Kirsher plc_rev = inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK ;
77433f810b2SJeff Kirsher
77533f810b2SJeff Kirsher if (plc_rev != PLC_REV_SN3)
77633f810b2SJeff Kirsher #endif /* MOT_ELM */
77733f810b2SJeff Kirsher {
77833f810b2SJeff Kirsher /*
77933f810b2SJeff Kirsher * No supernet III PLC, so set Xmit verctor and
78033f810b2SJeff Kirsher * length BEFORE starting the state machine.
78133f810b2SJeff Kirsher */
78233f810b2SJeff Kirsher if (plc_send_bits(smc,phy,3)) {
78333f810b2SJeff Kirsher return ;
78433f810b2SJeff Kirsher }
78533f810b2SJeff Kirsher }
78633f810b2SJeff Kirsher
78733f810b2SJeff Kirsher /*
78833f810b2SJeff Kirsher * Now give the Start command.
78933f810b2SJeff Kirsher * - The start command shall be done before setting the bits
79033f810b2SJeff Kirsher * to be signaled. (In PLC-S description and PLCS in SN3.
79133f810b2SJeff Kirsher * - The start command shall be issued AFTER setting the
79233f810b2SJeff Kirsher * XMIT vector and the XMIT length register.
79333f810b2SJeff Kirsher *
79433f810b2SJeff Kirsher * We do it exactly according this specs for the old PLC and
79533f810b2SJeff Kirsher * the new PLCS inside the SN3.
79633f810b2SJeff Kirsher * For the usual PLCS we try it the way it is done for the
79733f810b2SJeff Kirsher * old PLC and set the XMIT registers again, if the PLC is
79833f810b2SJeff Kirsher * not in SIGNAL state. This is done according to an PLCS
79933f810b2SJeff Kirsher * errata workaround.
80033f810b2SJeff Kirsher */
80133f810b2SJeff Kirsher
80233f810b2SJeff Kirsher plc_go_state(smc,np,PL_PCM_START) ;
80333f810b2SJeff Kirsher
80433f810b2SJeff Kirsher /*
80533f810b2SJeff Kirsher * workaround for PLC-S eng. sample errata
80633f810b2SJeff Kirsher */
80733f810b2SJeff Kirsher #ifdef MOT_ELM
80833f810b2SJeff Kirsher if (!(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL))
80933f810b2SJeff Kirsher #else /* nMOT_ELM */
81033f810b2SJeff Kirsher if (((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) !=
81133f810b2SJeff Kirsher PLC_REVISION_A) &&
81233f810b2SJeff Kirsher !(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL))
81333f810b2SJeff Kirsher #endif /* nMOT_ELM */
81433f810b2SJeff Kirsher {
81533f810b2SJeff Kirsher /*
81633f810b2SJeff Kirsher * Set register again (PLCS errata) or the first time
81733f810b2SJeff Kirsher * (new SN3 PLCS).
81833f810b2SJeff Kirsher */
81933f810b2SJeff Kirsher (void) plc_send_bits(smc,phy,3) ;
82033f810b2SJeff Kirsher }
82133f810b2SJeff Kirsher /*
82233f810b2SJeff Kirsher * end of workaround
82333f810b2SJeff Kirsher */
82433f810b2SJeff Kirsher
82533f810b2SJeff Kirsher GO_STATE(PC5_SIGNAL) ;
82633f810b2SJeff Kirsher plc->p_state = PS_BIT3 ;
82733f810b2SJeff Kirsher plc->p_bits = 3 ;
82833f810b2SJeff Kirsher plc->p_start = 0 ;
82933f810b2SJeff Kirsher
83033f810b2SJeff Kirsher break ;
83133f810b2SJeff Kirsher case PC1_BREAK :
83233f810b2SJeff Kirsher break ;
83333f810b2SJeff Kirsher case ACTIONS(PC2_TRACE) :
83433f810b2SJeff Kirsher plc_go_state(smc,np,PL_PCM_TRACE) ;
83533f810b2SJeff Kirsher ACTIONS_DONE() ;
83633f810b2SJeff Kirsher break ;
83733f810b2SJeff Kirsher case PC2_TRACE :
83833f810b2SJeff Kirsher break ;
83933f810b2SJeff Kirsher
84033f810b2SJeff Kirsher case PC3_CONNECT : /* these states are done by hardware */
84133f810b2SJeff Kirsher case PC4_NEXT :
84233f810b2SJeff Kirsher break ;
84333f810b2SJeff Kirsher
84433f810b2SJeff Kirsher case ACTIONS(PC5_SIGNAL) :
84533f810b2SJeff Kirsher ACTIONS_DONE() ;
846*df561f66SGustavo A. R. Silva fallthrough;
84733f810b2SJeff Kirsher case PC5_SIGNAL :
84833f810b2SJeff Kirsher if ((cmd != PC_SIGNAL) && (cmd != PC_TIMEOUT_LCT))
84933f810b2SJeff Kirsher break ;
85033f810b2SJeff Kirsher switch (plc->p_state) {
85133f810b2SJeff Kirsher case PS_BIT3 :
85233f810b2SJeff Kirsher for (i = 0 ; i <= 2 ; i++)
85333f810b2SJeff Kirsher pc_rcode_actions(smc,i,phy) ;
85433f810b2SJeff Kirsher pc_tcode_actions(smc,3,phy) ;
85533f810b2SJeff Kirsher plc->p_state = PS_BIT4 ;
85633f810b2SJeff Kirsher plc->p_bits = 1 ;
85733f810b2SJeff Kirsher plc->p_start = 3 ;
85833f810b2SJeff Kirsher phy->bitn = 3 ;
85933f810b2SJeff Kirsher if (plc_send_bits(smc,phy,1)) {
86033f810b2SJeff Kirsher return ;
86133f810b2SJeff Kirsher }
86233f810b2SJeff Kirsher break ;
86333f810b2SJeff Kirsher case PS_BIT4 :
86433f810b2SJeff Kirsher pc_rcode_actions(smc,3,phy) ;
86533f810b2SJeff Kirsher for (i = 4 ; i <= 6 ; i++)
86633f810b2SJeff Kirsher pc_tcode_actions(smc,i,phy) ;
86733f810b2SJeff Kirsher plc->p_state = PS_BIT7 ;
86833f810b2SJeff Kirsher plc->p_bits = 3 ;
86933f810b2SJeff Kirsher plc->p_start = 4 ;
87033f810b2SJeff Kirsher phy->bitn = 4 ;
87133f810b2SJeff Kirsher if (plc_send_bits(smc,phy,3)) {
87233f810b2SJeff Kirsher return ;
87333f810b2SJeff Kirsher }
87433f810b2SJeff Kirsher break ;
87533f810b2SJeff Kirsher case PS_BIT7 :
87633f810b2SJeff Kirsher for (i = 3 ; i <= 6 ; i++)
87733f810b2SJeff Kirsher pc_rcode_actions(smc,i,phy) ;
87833f810b2SJeff Kirsher plc->p_state = PS_LCT ;
87933f810b2SJeff Kirsher plc->p_bits = 0 ;
88033f810b2SJeff Kirsher plc->p_start = 7 ;
88133f810b2SJeff Kirsher phy->bitn = 7 ;
88233f810b2SJeff Kirsher sm_ph_lem_start(smc,np,(int)smc->s.lct_short) ; /* enable LEM */
88333f810b2SJeff Kirsher /* start LCT */
88433f810b2SJeff Kirsher i = inpw(PLC(np,PL_CNTRL_B)) & ~PL_PC_LOOP ;
88533f810b2SJeff Kirsher outpw(PLC(np,PL_CNTRL_B),i) ; /* must be cleared */
88633f810b2SJeff Kirsher outpw(PLC(np,PL_CNTRL_B),i | PL_RLBP) ;
88733f810b2SJeff Kirsher break ;
88833f810b2SJeff Kirsher case PS_LCT :
88933f810b2SJeff Kirsher /* check for local LCT failure */
89033f810b2SJeff Kirsher pc_tcode_actions(smc,7,phy) ;
89133f810b2SJeff Kirsher /*
89233f810b2SJeff Kirsher * set tval[7]
89333f810b2SJeff Kirsher */
89433f810b2SJeff Kirsher plc->p_state = PS_BIT8 ;
89533f810b2SJeff Kirsher plc->p_bits = 1 ;
89633f810b2SJeff Kirsher plc->p_start = 7 ;
89733f810b2SJeff Kirsher phy->bitn = 7 ;
89833f810b2SJeff Kirsher if (plc_send_bits(smc,phy,1)) {
89933f810b2SJeff Kirsher return ;
90033f810b2SJeff Kirsher }
90133f810b2SJeff Kirsher break ;
90233f810b2SJeff Kirsher case PS_BIT8 :
90333f810b2SJeff Kirsher /* check for remote LCT failure */
90433f810b2SJeff Kirsher pc_rcode_actions(smc,7,phy) ;
90533f810b2SJeff Kirsher if (phy->t_val[7] || phy->r_val[7]) {
90633f810b2SJeff Kirsher plc_go_state(smc,np,PL_PCM_STOP) ;
90733f810b2SJeff Kirsher GO_STATE(PC1_BREAK) ;
90833f810b2SJeff Kirsher break ;
90933f810b2SJeff Kirsher }
91033f810b2SJeff Kirsher for (i = 8 ; i <= 9 ; i++)
91133f810b2SJeff Kirsher pc_tcode_actions(smc,i,phy) ;
91233f810b2SJeff Kirsher plc->p_state = PS_JOIN ;
91333f810b2SJeff Kirsher plc->p_bits = 2 ;
91433f810b2SJeff Kirsher plc->p_start = 8 ;
91533f810b2SJeff Kirsher phy->bitn = 8 ;
91633f810b2SJeff Kirsher if (plc_send_bits(smc,phy,2)) {
91733f810b2SJeff Kirsher return ;
91833f810b2SJeff Kirsher }
91933f810b2SJeff Kirsher break ;
92033f810b2SJeff Kirsher case PS_JOIN :
92133f810b2SJeff Kirsher for (i = 8 ; i <= 9 ; i++)
92233f810b2SJeff Kirsher pc_rcode_actions(smc,i,phy) ;
92333f810b2SJeff Kirsher plc->p_state = PS_ACTIVE ;
92433f810b2SJeff Kirsher GO_STATE(PC6_JOIN) ;
92533f810b2SJeff Kirsher break ;
92633f810b2SJeff Kirsher }
92733f810b2SJeff Kirsher break ;
92833f810b2SJeff Kirsher
92933f810b2SJeff Kirsher case ACTIONS(PC6_JOIN) :
93033f810b2SJeff Kirsher /*
93133f810b2SJeff Kirsher * prevent mux error when going from WRAP_A to WRAP_B
93233f810b2SJeff Kirsher */
93333f810b2SJeff Kirsher if (smc->s.sas == SMT_DAS && np == PB &&
93433f810b2SJeff Kirsher (smc->y[PA].pc_mode == PM_TREE ||
93533f810b2SJeff Kirsher smc->y[PB].pc_mode == PM_TREE)) {
93633f810b2SJeff Kirsher SETMASK(PLC(np,PL_CNTRL_A),
93733f810b2SJeff Kirsher PL_SC_REM_LOOP,PL_SC_REM_LOOP) ;
93833f810b2SJeff Kirsher SETMASK(PLC(np,PL_CNTRL_B),
93933f810b2SJeff Kirsher PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ;
94033f810b2SJeff Kirsher }
94133f810b2SJeff Kirsher SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ;
94233f810b2SJeff Kirsher SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ;
94333f810b2SJeff Kirsher ACTIONS_DONE() ;
94433f810b2SJeff Kirsher cmd = 0 ;
945*df561f66SGustavo A. R. Silva fallthrough;
94633f810b2SJeff Kirsher case PC6_JOIN :
94733f810b2SJeff Kirsher switch (plc->p_state) {
94833f810b2SJeff Kirsher case PS_ACTIVE:
94933f810b2SJeff Kirsher /*PC88b*/
95033f810b2SJeff Kirsher if (!phy->cf_join) {
95133f810b2SJeff Kirsher phy->cf_join = TRUE ;
95233f810b2SJeff Kirsher queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
95333f810b2SJeff Kirsher }
95433f810b2SJeff Kirsher if (cmd == PC_JOIN)
95533f810b2SJeff Kirsher GO_STATE(PC8_ACTIVE) ;
95633f810b2SJeff Kirsher /*PC82*/
95733f810b2SJeff Kirsher if (cmd == PC_TRACE) {
95833f810b2SJeff Kirsher GO_STATE(PC2_TRACE) ;
95933f810b2SJeff Kirsher break ;
96033f810b2SJeff Kirsher }
96133f810b2SJeff Kirsher break ;
96233f810b2SJeff Kirsher }
96333f810b2SJeff Kirsher break ;
96433f810b2SJeff Kirsher
96533f810b2SJeff Kirsher case PC7_VERIFY :
96633f810b2SJeff Kirsher break ;
96733f810b2SJeff Kirsher
96833f810b2SJeff Kirsher case ACTIONS(PC8_ACTIVE) :
96933f810b2SJeff Kirsher /*
97033f810b2SJeff Kirsher * start LEM for SMT
97133f810b2SJeff Kirsher */
97233f810b2SJeff Kirsher sm_ph_lem_start(smc,(int)phy->np,LCT_LEM_MAX) ;
97333f810b2SJeff Kirsher
97433f810b2SJeff Kirsher phy->tr_flag = FALSE ;
97533f810b2SJeff Kirsher mib->fddiPORTConnectState = PCM_ACTIVE ;
97633f810b2SJeff Kirsher
97733f810b2SJeff Kirsher /* Set the active interrupt mask register */
97833f810b2SJeff Kirsher outpw(PLC(np,PL_INTR_MASK),plc_imsk_act) ;
97933f810b2SJeff Kirsher
98033f810b2SJeff Kirsher ACTIONS_DONE() ;
98133f810b2SJeff Kirsher break ;
98233f810b2SJeff Kirsher case PC8_ACTIVE :
98333f810b2SJeff Kirsher /*PC81 is done by PL_TNE_EXPIRED irq */
98433f810b2SJeff Kirsher /*PC82*/
98533f810b2SJeff Kirsher if (cmd == PC_TRACE) {
98633f810b2SJeff Kirsher GO_STATE(PC2_TRACE) ;
98733f810b2SJeff Kirsher break ;
98833f810b2SJeff Kirsher }
98933f810b2SJeff Kirsher /*PC88c: is done by TRACE_PROP irq */
99033f810b2SJeff Kirsher
99133f810b2SJeff Kirsher break ;
99233f810b2SJeff Kirsher case ACTIONS(PC9_MAINT) :
99333f810b2SJeff Kirsher stop_pcm_timer0(smc,phy) ;
99433f810b2SJeff Kirsher CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
99533f810b2SJeff Kirsher CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
99633f810b2SJeff Kirsher CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ; /* disable LEM int. */
99733f810b2SJeff Kirsher sm_ph_lem_stop(smc,np) ; /* disable LEM */
99833f810b2SJeff Kirsher phy->cf_loop = FALSE ;
99933f810b2SJeff Kirsher phy->cf_join = FALSE ;
100033f810b2SJeff Kirsher queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
100133f810b2SJeff Kirsher plc_go_state(smc,np,PL_PCM_STOP) ;
100233f810b2SJeff Kirsher mib->fddiPORTConnectState = PCM_DISABLED ;
100333f810b2SJeff Kirsher SETMASK(PLC(np,PL_CNTRL_B),PL_MAINT,PL_MAINT) ;
100433f810b2SJeff Kirsher sm_ph_linestate(smc,np,(int) MIB2LS(mib->fddiPORTMaint_LS)) ;
100533f810b2SJeff Kirsher outpw(PLC(np,PL_CNTRL_A),PL_SC_BYPASS) ;
100633f810b2SJeff Kirsher ACTIONS_DONE() ;
100733f810b2SJeff Kirsher break ;
100833f810b2SJeff Kirsher case PC9_MAINT :
10095671e8c1SJoe Perches DB_PCMN(1, "PCM %c : MAINT", phy->phy_name);
101033f810b2SJeff Kirsher /*PC90*/
101133f810b2SJeff Kirsher if (cmd == PC_ENABLE) {
101233f810b2SJeff Kirsher GO_STATE(PC0_OFF) ;
101333f810b2SJeff Kirsher break ;
101433f810b2SJeff Kirsher }
101533f810b2SJeff Kirsher break ;
101633f810b2SJeff Kirsher
101733f810b2SJeff Kirsher default:
101833f810b2SJeff Kirsher SMT_PANIC(smc,SMT_E0118, SMT_E0118_MSG) ;
101933f810b2SJeff Kirsher break ;
102033f810b2SJeff Kirsher }
102133f810b2SJeff Kirsher }
102233f810b2SJeff Kirsher
102333f810b2SJeff Kirsher /*
102433f810b2SJeff Kirsher * force line state on a PHY output (only in MAINT state)
102533f810b2SJeff Kirsher */
sm_ph_linestate(struct s_smc * smc,int phy,int ls)102633f810b2SJeff Kirsher static void sm_ph_linestate(struct s_smc *smc, int phy, int ls)
102733f810b2SJeff Kirsher {
102833f810b2SJeff Kirsher int cntrl ;
102933f810b2SJeff Kirsher
103033f810b2SJeff Kirsher SK_UNUSED(smc) ;
103133f810b2SJeff Kirsher
103233f810b2SJeff Kirsher cntrl = (inpw(PLC(phy,PL_CNTRL_B)) & ~PL_MAINT_LS) |
103333f810b2SJeff Kirsher PL_PCM_STOP | PL_MAINT ;
103433f810b2SJeff Kirsher switch(ls) {
103533f810b2SJeff Kirsher case PC_QLS: /* Force Quiet */
103633f810b2SJeff Kirsher cntrl |= PL_M_QUI0 ;
103733f810b2SJeff Kirsher break ;
103833f810b2SJeff Kirsher case PC_MLS: /* Force Master */
103933f810b2SJeff Kirsher cntrl |= PL_M_MASTR ;
104033f810b2SJeff Kirsher break ;
104133f810b2SJeff Kirsher case PC_HLS: /* Force Halt */
104233f810b2SJeff Kirsher cntrl |= PL_M_HALT ;
104333f810b2SJeff Kirsher break ;
104433f810b2SJeff Kirsher default :
104533f810b2SJeff Kirsher case PC_ILS: /* Force Idle */
104633f810b2SJeff Kirsher cntrl |= PL_M_IDLE ;
104733f810b2SJeff Kirsher break ;
104833f810b2SJeff Kirsher case PC_LS_PDR: /* Enable repeat filter */
104933f810b2SJeff Kirsher cntrl |= PL_M_TPDR ;
105033f810b2SJeff Kirsher break ;
105133f810b2SJeff Kirsher }
105233f810b2SJeff Kirsher outpw(PLC(phy,PL_CNTRL_B),cntrl) ;
105333f810b2SJeff Kirsher }
105433f810b2SJeff Kirsher
reset_lem_struct(struct s_phy * phy)105533f810b2SJeff Kirsher static void reset_lem_struct(struct s_phy *phy)
105633f810b2SJeff Kirsher {
105733f810b2SJeff Kirsher struct lem_counter *lem = &phy->lem ;
105833f810b2SJeff Kirsher
105933f810b2SJeff Kirsher phy->mib->fddiPORTLer_Estimate = 15 ;
106033f810b2SJeff Kirsher lem->lem_float_ber = 15 * 100 ;
106133f810b2SJeff Kirsher }
106233f810b2SJeff Kirsher
106333f810b2SJeff Kirsher /*
106433f810b2SJeff Kirsher * link error monitor
106533f810b2SJeff Kirsher */
lem_evaluate(struct s_smc * smc,struct s_phy * phy)106633f810b2SJeff Kirsher static void lem_evaluate(struct s_smc *smc, struct s_phy *phy)
106733f810b2SJeff Kirsher {
106833f810b2SJeff Kirsher int ber ;
106933f810b2SJeff Kirsher u_long errors ;
107033f810b2SJeff Kirsher struct lem_counter *lem = &phy->lem ;
107133f810b2SJeff Kirsher struct fddi_mib_p *mib ;
107233f810b2SJeff Kirsher int cond ;
107333f810b2SJeff Kirsher
107433f810b2SJeff Kirsher mib = phy->mib ;
107533f810b2SJeff Kirsher
107633f810b2SJeff Kirsher if (!lem->lem_on)
107733f810b2SJeff Kirsher return ;
107833f810b2SJeff Kirsher
107933f810b2SJeff Kirsher errors = inpw(PLC(((int) phy->np),PL_LINK_ERR_CTR)) ;
108033f810b2SJeff Kirsher lem->lem_errors += errors ;
108133f810b2SJeff Kirsher mib->fddiPORTLem_Ct += errors ;
108233f810b2SJeff Kirsher
108333f810b2SJeff Kirsher errors = lem->lem_errors ;
108433f810b2SJeff Kirsher /*
108533f810b2SJeff Kirsher * calculation is called on a intervall of 8 seconds
108633f810b2SJeff Kirsher * -> this means, that one error in 8 sec. is one of 8*125*10E6
108733f810b2SJeff Kirsher * the same as BER = 10E-9
108833f810b2SJeff Kirsher * Please note:
108933f810b2SJeff Kirsher * -> 9 errors in 8 seconds mean:
109033f810b2SJeff Kirsher * BER = 9 * 10E-9 and this is
109133f810b2SJeff Kirsher * < 10E-8, so the limit of 10E-8 is not reached!
109233f810b2SJeff Kirsher */
109333f810b2SJeff Kirsher
109433f810b2SJeff Kirsher if (!errors) ber = 15 ;
109533f810b2SJeff Kirsher else if (errors <= 9) ber = 9 ;
109633f810b2SJeff Kirsher else if (errors <= 99) ber = 8 ;
109733f810b2SJeff Kirsher else if (errors <= 999) ber = 7 ;
109833f810b2SJeff Kirsher else if (errors <= 9999) ber = 6 ;
109933f810b2SJeff Kirsher else if (errors <= 99999) ber = 5 ;
110033f810b2SJeff Kirsher else if (errors <= 999999) ber = 4 ;
110133f810b2SJeff Kirsher else if (errors <= 9999999) ber = 3 ;
110233f810b2SJeff Kirsher else if (errors <= 99999999) ber = 2 ;
110333f810b2SJeff Kirsher else if (errors <= 999999999) ber = 1 ;
110433f810b2SJeff Kirsher else ber = 0 ;
110533f810b2SJeff Kirsher
110633f810b2SJeff Kirsher /*
110733f810b2SJeff Kirsher * weighted average
110833f810b2SJeff Kirsher */
110933f810b2SJeff Kirsher ber *= 100 ;
111033f810b2SJeff Kirsher lem->lem_float_ber = lem->lem_float_ber * 7 + ber * 3 ;
111133f810b2SJeff Kirsher lem->lem_float_ber /= 10 ;
111233f810b2SJeff Kirsher mib->fddiPORTLer_Estimate = lem->lem_float_ber / 100 ;
111333f810b2SJeff Kirsher if (mib->fddiPORTLer_Estimate < 4) {
111433f810b2SJeff Kirsher mib->fddiPORTLer_Estimate = 4 ;
111533f810b2SJeff Kirsher }
111633f810b2SJeff Kirsher
111733f810b2SJeff Kirsher if (lem->lem_errors) {
11185671e8c1SJoe Perches DB_PCMN(1, "LEM %c :", phy->np == PB ? 'B' : 'A');
11195671e8c1SJoe Perches DB_PCMN(1, "errors : %ld", lem->lem_errors);
11205671e8c1SJoe Perches DB_PCMN(1, "sum_errors : %ld", mib->fddiPORTLem_Ct);
11215671e8c1SJoe Perches DB_PCMN(1, "current BER : 10E-%d", ber / 100);
11225671e8c1SJoe Perches DB_PCMN(1, "float BER : 10E-(%d/100)", lem->lem_float_ber);
11235671e8c1SJoe Perches DB_PCMN(1, "avg. BER : 10E-%d", mib->fddiPORTLer_Estimate);
112433f810b2SJeff Kirsher }
112533f810b2SJeff Kirsher
112633f810b2SJeff Kirsher lem->lem_errors = 0L ;
112733f810b2SJeff Kirsher
112833f810b2SJeff Kirsher #ifndef SLIM_SMT
112933f810b2SJeff Kirsher cond = (mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Alarm) ?
113033f810b2SJeff Kirsher TRUE : FALSE ;
113133f810b2SJeff Kirsher #ifdef SMT_EXT_CUTOFF
113233f810b2SJeff Kirsher smt_ler_alarm_check(smc,phy,cond) ;
113333f810b2SJeff Kirsher #endif /* nSMT_EXT_CUTOFF */
113433f810b2SJeff Kirsher if (cond != mib->fddiPORTLerFlag) {
113533f810b2SJeff Kirsher smt_srf_event(smc,SMT_COND_PORT_LER,
113633f810b2SJeff Kirsher (int) (INDEX_PORT+ phy->np) ,cond) ;
113733f810b2SJeff Kirsher }
113833f810b2SJeff Kirsher #endif
113933f810b2SJeff Kirsher
114033f810b2SJeff Kirsher if ( mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Cutoff) {
114133f810b2SJeff Kirsher phy->pc_lem_fail = TRUE ; /* flag */
114233f810b2SJeff Kirsher mib->fddiPORTLem_Reject_Ct++ ;
114333f810b2SJeff Kirsher /*
114433f810b2SJeff Kirsher * "forgive 10e-2" if we cutoff so we can come
114533f810b2SJeff Kirsher * up again ..
114633f810b2SJeff Kirsher */
114733f810b2SJeff Kirsher lem->lem_float_ber += 2*100 ;
114833f810b2SJeff Kirsher
114933f810b2SJeff Kirsher /*PC81b*/
115033f810b2SJeff Kirsher #ifdef CONCENTRATOR
11515671e8c1SJoe Perches DB_PCMN(1, "PCM: LER cutoff on port %d cutoff %d",
115233f810b2SJeff Kirsher phy->np, mib->fddiPORTLer_Cutoff);
115333f810b2SJeff Kirsher #endif
115433f810b2SJeff Kirsher #ifdef SMT_EXT_CUTOFF
115533f810b2SJeff Kirsher smt_port_off_event(smc,phy->np);
115633f810b2SJeff Kirsher #else /* nSMT_EXT_CUTOFF */
115733f810b2SJeff Kirsher queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ;
115833f810b2SJeff Kirsher #endif /* nSMT_EXT_CUTOFF */
115933f810b2SJeff Kirsher }
116033f810b2SJeff Kirsher }
116133f810b2SJeff Kirsher
116233f810b2SJeff Kirsher /*
116333f810b2SJeff Kirsher * called by SMT to calculate LEM bit error rate
116433f810b2SJeff Kirsher */
sm_lem_evaluate(struct s_smc * smc)116533f810b2SJeff Kirsher void sm_lem_evaluate(struct s_smc *smc)
116633f810b2SJeff Kirsher {
116733f810b2SJeff Kirsher int np ;
116833f810b2SJeff Kirsher
116933f810b2SJeff Kirsher for (np = 0 ; np < NUMPHYS ; np++)
117033f810b2SJeff Kirsher lem_evaluate(smc,&smc->y[np]) ;
117133f810b2SJeff Kirsher }
117233f810b2SJeff Kirsher
lem_check_lct(struct s_smc * smc,struct s_phy * phy)117333f810b2SJeff Kirsher static void lem_check_lct(struct s_smc *smc, struct s_phy *phy)
117433f810b2SJeff Kirsher {
117533f810b2SJeff Kirsher struct lem_counter *lem = &phy->lem ;
117633f810b2SJeff Kirsher struct fddi_mib_p *mib ;
117733f810b2SJeff Kirsher int errors ;
117833f810b2SJeff Kirsher
117933f810b2SJeff Kirsher mib = phy->mib ;
118033f810b2SJeff Kirsher
118133f810b2SJeff Kirsher phy->pc_lem_fail = FALSE ; /* flag */
118233f810b2SJeff Kirsher errors = inpw(PLC(((int)phy->np),PL_LINK_ERR_CTR)) ;
118333f810b2SJeff Kirsher lem->lem_errors += errors ;
118433f810b2SJeff Kirsher mib->fddiPORTLem_Ct += errors ;
118533f810b2SJeff Kirsher if (lem->lem_errors) {
118633f810b2SJeff Kirsher switch(phy->lc_test) {
118733f810b2SJeff Kirsher case LC_SHORT:
118833f810b2SJeff Kirsher if (lem->lem_errors >= smc->s.lct_short)
118933f810b2SJeff Kirsher phy->pc_lem_fail = TRUE ;
119033f810b2SJeff Kirsher break ;
119133f810b2SJeff Kirsher case LC_MEDIUM:
119233f810b2SJeff Kirsher if (lem->lem_errors >= smc->s.lct_medium)
119333f810b2SJeff Kirsher phy->pc_lem_fail = TRUE ;
119433f810b2SJeff Kirsher break ;
119533f810b2SJeff Kirsher case LC_LONG:
119633f810b2SJeff Kirsher if (lem->lem_errors >= smc->s.lct_long)
119733f810b2SJeff Kirsher phy->pc_lem_fail = TRUE ;
119833f810b2SJeff Kirsher break ;
119933f810b2SJeff Kirsher case LC_EXTENDED:
120033f810b2SJeff Kirsher if (lem->lem_errors >= smc->s.lct_extended)
120133f810b2SJeff Kirsher phy->pc_lem_fail = TRUE ;
120233f810b2SJeff Kirsher break ;
120333f810b2SJeff Kirsher }
12045671e8c1SJoe Perches DB_PCMN(1, " >>errors : %lu", lem->lem_errors);
120533f810b2SJeff Kirsher }
120633f810b2SJeff Kirsher if (phy->pc_lem_fail) {
120733f810b2SJeff Kirsher mib->fddiPORTLCTFail_Ct++ ;
120833f810b2SJeff Kirsher mib->fddiPORTLem_Reject_Ct++ ;
120933f810b2SJeff Kirsher }
121033f810b2SJeff Kirsher else
121133f810b2SJeff Kirsher mib->fddiPORTLCTFail_Ct = 0 ;
121233f810b2SJeff Kirsher }
121333f810b2SJeff Kirsher
121433f810b2SJeff Kirsher /*
121533f810b2SJeff Kirsher * LEM functions
121633f810b2SJeff Kirsher */
sm_ph_lem_start(struct s_smc * smc,int np,int threshold)121733f810b2SJeff Kirsher static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold)
121833f810b2SJeff Kirsher {
121933f810b2SJeff Kirsher struct lem_counter *lem = &smc->y[np].lem ;
122033f810b2SJeff Kirsher
122133f810b2SJeff Kirsher lem->lem_on = 1 ;
122233f810b2SJeff Kirsher lem->lem_errors = 0L ;
122333f810b2SJeff Kirsher
122433f810b2SJeff Kirsher /* Do NOT reset mib->fddiPORTLer_Estimate here. It is called too
122533f810b2SJeff Kirsher * often.
122633f810b2SJeff Kirsher */
122733f810b2SJeff Kirsher
122833f810b2SJeff Kirsher outpw(PLC(np,PL_LE_THRESHOLD),threshold) ;
122933f810b2SJeff Kirsher (void)inpw(PLC(np,PL_LINK_ERR_CTR)) ; /* clear error counter */
123033f810b2SJeff Kirsher
123133f810b2SJeff Kirsher /* enable LE INT */
123233f810b2SJeff Kirsher SETMASK(PLC(np,PL_INTR_MASK),PL_LE_CTR,PL_LE_CTR) ;
123333f810b2SJeff Kirsher }
123433f810b2SJeff Kirsher
sm_ph_lem_stop(struct s_smc * smc,int np)123533f810b2SJeff Kirsher static void sm_ph_lem_stop(struct s_smc *smc, int np)
123633f810b2SJeff Kirsher {
123733f810b2SJeff Kirsher struct lem_counter *lem = &smc->y[np].lem ;
123833f810b2SJeff Kirsher
123933f810b2SJeff Kirsher lem->lem_on = 0 ;
124033f810b2SJeff Kirsher CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ;
124133f810b2SJeff Kirsher }
124233f810b2SJeff Kirsher
124333f810b2SJeff Kirsher /*
124433f810b2SJeff Kirsher * PCM pseudo code
124533f810b2SJeff Kirsher * receive actions are called AFTER the bit n is received,
124633f810b2SJeff Kirsher * i.e. if pc_rcode_actions(5) is called, bit 6 is the next bit to be received
124733f810b2SJeff Kirsher */
124833f810b2SJeff Kirsher
124933f810b2SJeff Kirsher /*
125033f810b2SJeff Kirsher * PCM pseudo code 5.1 .. 6.1
125133f810b2SJeff Kirsher */
pc_rcode_actions(struct s_smc * smc,int bit,struct s_phy * phy)125233f810b2SJeff Kirsher static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy)
125333f810b2SJeff Kirsher {
125433f810b2SJeff Kirsher struct fddi_mib_p *mib ;
125533f810b2SJeff Kirsher
125633f810b2SJeff Kirsher mib = phy->mib ;
125733f810b2SJeff Kirsher
12585671e8c1SJoe Perches DB_PCMN(1, "SIG rec %x %x:", bit, phy->r_val[bit]);
125933f810b2SJeff Kirsher bit++ ;
126033f810b2SJeff Kirsher
126133f810b2SJeff Kirsher switch(bit) {
126233f810b2SJeff Kirsher case 0:
126333f810b2SJeff Kirsher case 1:
126433f810b2SJeff Kirsher case 2:
126533f810b2SJeff Kirsher break ;
126633f810b2SJeff Kirsher case 3 :
126733f810b2SJeff Kirsher if (phy->r_val[1] == 0 && phy->r_val[2] == 0)
126833f810b2SJeff Kirsher mib->fddiPORTNeighborType = TA ;
126933f810b2SJeff Kirsher else if (phy->r_val[1] == 0 && phy->r_val[2] == 1)
127033f810b2SJeff Kirsher mib->fddiPORTNeighborType = TB ;
127133f810b2SJeff Kirsher else if (phy->r_val[1] == 1 && phy->r_val[2] == 0)
127233f810b2SJeff Kirsher mib->fddiPORTNeighborType = TS ;
127333f810b2SJeff Kirsher else if (phy->r_val[1] == 1 && phy->r_val[2] == 1)
127433f810b2SJeff Kirsher mib->fddiPORTNeighborType = TM ;
127533f810b2SJeff Kirsher break ;
127633f810b2SJeff Kirsher case 4:
127733f810b2SJeff Kirsher if (mib->fddiPORTMy_Type == TM &&
127833f810b2SJeff Kirsher mib->fddiPORTNeighborType == TM) {
12795671e8c1SJoe Perches DB_PCMN(1, "PCM %c : E100 withhold M-M",
12805671e8c1SJoe Perches phy->phy_name);
128133f810b2SJeff Kirsher mib->fddiPORTPC_Withhold = PC_WH_M_M ;
128233f810b2SJeff Kirsher RS_SET(smc,RS_EVENT) ;
128333f810b2SJeff Kirsher }
128433f810b2SJeff Kirsher else if (phy->t_val[3] || phy->r_val[3]) {
128533f810b2SJeff Kirsher mib->fddiPORTPC_Withhold = PC_WH_NONE ;
128633f810b2SJeff Kirsher if (mib->fddiPORTMy_Type == TM ||
128733f810b2SJeff Kirsher mib->fddiPORTNeighborType == TM)
128833f810b2SJeff Kirsher phy->pc_mode = PM_TREE ;
128933f810b2SJeff Kirsher else
129033f810b2SJeff Kirsher phy->pc_mode = PM_PEER ;
129133f810b2SJeff Kirsher
129233f810b2SJeff Kirsher /* reevaluate the selection criteria (wc_flag) */
129333f810b2SJeff Kirsher all_selection_criteria (smc);
129433f810b2SJeff Kirsher
129533f810b2SJeff Kirsher if (phy->wc_flag) {
129633f810b2SJeff Kirsher mib->fddiPORTPC_Withhold = PC_WH_PATH ;
129733f810b2SJeff Kirsher }
129833f810b2SJeff Kirsher }
129933f810b2SJeff Kirsher else {
130033f810b2SJeff Kirsher mib->fddiPORTPC_Withhold = PC_WH_OTHER ;
130133f810b2SJeff Kirsher RS_SET(smc,RS_EVENT) ;
13025671e8c1SJoe Perches DB_PCMN(1, "PCM %c : E101 withhold other",
13035671e8c1SJoe Perches phy->phy_name);
130433f810b2SJeff Kirsher }
130533f810b2SJeff Kirsher phy->twisted = ((mib->fddiPORTMy_Type != TS) &&
130633f810b2SJeff Kirsher (mib->fddiPORTMy_Type != TM) &&
130733f810b2SJeff Kirsher (mib->fddiPORTNeighborType ==
130833f810b2SJeff Kirsher mib->fddiPORTMy_Type)) ;
130933f810b2SJeff Kirsher if (phy->twisted) {
13105671e8c1SJoe Perches DB_PCMN(1, "PCM %c : E102 !!! TWISTED !!!",
13115671e8c1SJoe Perches phy->phy_name);
131233f810b2SJeff Kirsher }
131333f810b2SJeff Kirsher break ;
131433f810b2SJeff Kirsher case 5 :
131533f810b2SJeff Kirsher break ;
131633f810b2SJeff Kirsher case 6:
131733f810b2SJeff Kirsher if (phy->t_val[4] || phy->r_val[4]) {
131833f810b2SJeff Kirsher if ((phy->t_val[4] && phy->t_val[5]) ||
131933f810b2SJeff Kirsher (phy->r_val[4] && phy->r_val[5]) )
132033f810b2SJeff Kirsher phy->lc_test = LC_EXTENDED ;
132133f810b2SJeff Kirsher else
132233f810b2SJeff Kirsher phy->lc_test = LC_LONG ;
132333f810b2SJeff Kirsher }
132433f810b2SJeff Kirsher else if (phy->t_val[5] || phy->r_val[5])
132533f810b2SJeff Kirsher phy->lc_test = LC_MEDIUM ;
132633f810b2SJeff Kirsher else
132733f810b2SJeff Kirsher phy->lc_test = LC_SHORT ;
132833f810b2SJeff Kirsher switch (phy->lc_test) {
132933f810b2SJeff Kirsher case LC_SHORT : /* 50ms */
133033f810b2SJeff Kirsher outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LENGTH ) ;
133133f810b2SJeff Kirsher phy->t_next[7] = smc->s.pcm_lc_short ;
133233f810b2SJeff Kirsher break ;
133333f810b2SJeff Kirsher case LC_MEDIUM : /* 500ms */
133433f810b2SJeff Kirsher outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LONGLN ) ;
133533f810b2SJeff Kirsher phy->t_next[7] = smc->s.pcm_lc_medium ;
133633f810b2SJeff Kirsher break ;
133733f810b2SJeff Kirsher case LC_LONG :
133833f810b2SJeff Kirsher SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ;
133933f810b2SJeff Kirsher phy->t_next[7] = smc->s.pcm_lc_long ;
134033f810b2SJeff Kirsher break ;
134133f810b2SJeff Kirsher case LC_EXTENDED :
134233f810b2SJeff Kirsher SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ;
134333f810b2SJeff Kirsher phy->t_next[7] = smc->s.pcm_lc_extended ;
134433f810b2SJeff Kirsher break ;
134533f810b2SJeff Kirsher }
134633f810b2SJeff Kirsher if (phy->t_next[7] > smc->s.pcm_lc_medium) {
134733f810b2SJeff Kirsher start_pcm_timer0(smc,phy->t_next[7],PC_TIMEOUT_LCT,phy);
134833f810b2SJeff Kirsher }
13495671e8c1SJoe Perches DB_PCMN(1, "LCT timer = %ld us", phy->t_next[7]);
135033f810b2SJeff Kirsher phy->t_next[9] = smc->s.pcm_t_next_9 ;
135133f810b2SJeff Kirsher break ;
135233f810b2SJeff Kirsher case 7:
135333f810b2SJeff Kirsher if (phy->t_val[6]) {
135433f810b2SJeff Kirsher phy->cf_loop = TRUE ;
135533f810b2SJeff Kirsher }
135633f810b2SJeff Kirsher phy->td_flag = TRUE ;
135733f810b2SJeff Kirsher break ;
135833f810b2SJeff Kirsher case 8:
135933f810b2SJeff Kirsher if (phy->t_val[7] || phy->r_val[7]) {
13605671e8c1SJoe Perches DB_PCMN(1, "PCM %c : E103 LCT fail %s",
13615671e8c1SJoe Perches phy->phy_name,
13625671e8c1SJoe Perches phy->t_val[7] ? "local" : "remote");
136333f810b2SJeff Kirsher queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ;
136433f810b2SJeff Kirsher }
136533f810b2SJeff Kirsher break ;
136633f810b2SJeff Kirsher case 9:
136733f810b2SJeff Kirsher if (phy->t_val[8] || phy->r_val[8]) {
136833f810b2SJeff Kirsher if (phy->t_val[8])
136933f810b2SJeff Kirsher phy->cf_loop = TRUE ;
137033f810b2SJeff Kirsher phy->td_flag = TRUE ;
137133f810b2SJeff Kirsher }
137233f810b2SJeff Kirsher break ;
137333f810b2SJeff Kirsher case 10:
137433f810b2SJeff Kirsher if (phy->r_val[9]) {
137533f810b2SJeff Kirsher /* neighbor intends to have MAC on output */ ;
137633f810b2SJeff Kirsher mib->fddiPORTMacIndicated.R_val = TRUE ;
137733f810b2SJeff Kirsher }
137833f810b2SJeff Kirsher else {
137933f810b2SJeff Kirsher /* neighbor does not intend to have MAC on output */ ;
138033f810b2SJeff Kirsher mib->fddiPORTMacIndicated.R_val = FALSE ;
138133f810b2SJeff Kirsher }
138233f810b2SJeff Kirsher break ;
138333f810b2SJeff Kirsher }
138433f810b2SJeff Kirsher }
138533f810b2SJeff Kirsher
138633f810b2SJeff Kirsher /*
138733f810b2SJeff Kirsher * PCM pseudo code 5.1 .. 6.1
138833f810b2SJeff Kirsher */
pc_tcode_actions(struct s_smc * smc,const int bit,struct s_phy * phy)138933f810b2SJeff Kirsher static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy)
139033f810b2SJeff Kirsher {
139133f810b2SJeff Kirsher int np = phy->np ;
139233f810b2SJeff Kirsher struct fddi_mib_p *mib ;
139333f810b2SJeff Kirsher
139433f810b2SJeff Kirsher mib = phy->mib ;
139533f810b2SJeff Kirsher
139633f810b2SJeff Kirsher switch(bit) {
139733f810b2SJeff Kirsher case 0:
139833f810b2SJeff Kirsher phy->t_val[0] = 0 ; /* no escape used */
139933f810b2SJeff Kirsher break ;
140033f810b2SJeff Kirsher case 1:
140133f810b2SJeff Kirsher if (mib->fddiPORTMy_Type == TS || mib->fddiPORTMy_Type == TM)
140233f810b2SJeff Kirsher phy->t_val[1] = 1 ;
140333f810b2SJeff Kirsher else
140433f810b2SJeff Kirsher phy->t_val[1] = 0 ;
140533f810b2SJeff Kirsher break ;
140633f810b2SJeff Kirsher case 2 :
140733f810b2SJeff Kirsher if (mib->fddiPORTMy_Type == TB || mib->fddiPORTMy_Type == TM)
140833f810b2SJeff Kirsher phy->t_val[2] = 1 ;
140933f810b2SJeff Kirsher else
141033f810b2SJeff Kirsher phy->t_val[2] = 0 ;
141133f810b2SJeff Kirsher break ;
141233f810b2SJeff Kirsher case 3:
141333f810b2SJeff Kirsher {
141433f810b2SJeff Kirsher int type,ne ;
141533f810b2SJeff Kirsher int policy ;
141633f810b2SJeff Kirsher
141733f810b2SJeff Kirsher type = mib->fddiPORTMy_Type ;
141833f810b2SJeff Kirsher ne = mib->fddiPORTNeighborType ;
141933f810b2SJeff Kirsher policy = smc->mib.fddiSMTConnectionPolicy ;
142033f810b2SJeff Kirsher
142133f810b2SJeff Kirsher phy->t_val[3] = 1 ; /* Accept connection */
142233f810b2SJeff Kirsher switch (type) {
142333f810b2SJeff Kirsher case TA :
142433f810b2SJeff Kirsher if (
142533f810b2SJeff Kirsher ((policy & POLICY_AA) && ne == TA) ||
142633f810b2SJeff Kirsher ((policy & POLICY_AB) && ne == TB) ||
142733f810b2SJeff Kirsher ((policy & POLICY_AS) && ne == TS) ||
142833f810b2SJeff Kirsher ((policy & POLICY_AM) && ne == TM) )
142933f810b2SJeff Kirsher phy->t_val[3] = 0 ; /* Reject */
143033f810b2SJeff Kirsher break ;
143133f810b2SJeff Kirsher case TB :
143233f810b2SJeff Kirsher if (
143333f810b2SJeff Kirsher ((policy & POLICY_BA) && ne == TA) ||
143433f810b2SJeff Kirsher ((policy & POLICY_BB) && ne == TB) ||
143533f810b2SJeff Kirsher ((policy & POLICY_BS) && ne == TS) ||
143633f810b2SJeff Kirsher ((policy & POLICY_BM) && ne == TM) )
143733f810b2SJeff Kirsher phy->t_val[3] = 0 ; /* Reject */
143833f810b2SJeff Kirsher break ;
143933f810b2SJeff Kirsher case TS :
144033f810b2SJeff Kirsher if (
144133f810b2SJeff Kirsher ((policy & POLICY_SA) && ne == TA) ||
144233f810b2SJeff Kirsher ((policy & POLICY_SB) && ne == TB) ||
144333f810b2SJeff Kirsher ((policy & POLICY_SS) && ne == TS) ||
144433f810b2SJeff Kirsher ((policy & POLICY_SM) && ne == TM) )
144533f810b2SJeff Kirsher phy->t_val[3] = 0 ; /* Reject */
144633f810b2SJeff Kirsher break ;
144733f810b2SJeff Kirsher case TM :
144833f810b2SJeff Kirsher if ( ne == TM ||
144933f810b2SJeff Kirsher ((policy & POLICY_MA) && ne == TA) ||
145033f810b2SJeff Kirsher ((policy & POLICY_MB) && ne == TB) ||
145133f810b2SJeff Kirsher ((policy & POLICY_MS) && ne == TS) ||
145233f810b2SJeff Kirsher ((policy & POLICY_MM) && ne == TM) )
145333f810b2SJeff Kirsher phy->t_val[3] = 0 ; /* Reject */
145433f810b2SJeff Kirsher break ;
145533f810b2SJeff Kirsher }
145633f810b2SJeff Kirsher #ifndef SLIM_SMT
145733f810b2SJeff Kirsher /*
145833f810b2SJeff Kirsher * detect undesirable connection attempt event
145933f810b2SJeff Kirsher */
146033f810b2SJeff Kirsher if ( (type == TA && ne == TA ) ||
146133f810b2SJeff Kirsher (type == TA && ne == TS ) ||
146233f810b2SJeff Kirsher (type == TB && ne == TB ) ||
146333f810b2SJeff Kirsher (type == TB && ne == TS ) ||
146433f810b2SJeff Kirsher (type == TS && ne == TA ) ||
146533f810b2SJeff Kirsher (type == TS && ne == TB ) ) {
146633f810b2SJeff Kirsher smt_srf_event(smc,SMT_EVENT_PORT_CONNECTION,
146733f810b2SJeff Kirsher (int) (INDEX_PORT+ phy->np) ,0) ;
146833f810b2SJeff Kirsher }
146933f810b2SJeff Kirsher #endif
147033f810b2SJeff Kirsher }
147133f810b2SJeff Kirsher break ;
147233f810b2SJeff Kirsher case 4:
147333f810b2SJeff Kirsher if (mib->fddiPORTPC_Withhold == PC_WH_NONE) {
147433f810b2SJeff Kirsher if (phy->pc_lem_fail) {
147533f810b2SJeff Kirsher phy->t_val[4] = 1 ; /* long */
147633f810b2SJeff Kirsher phy->t_val[5] = 0 ;
147733f810b2SJeff Kirsher }
147833f810b2SJeff Kirsher else {
147933f810b2SJeff Kirsher phy->t_val[4] = 0 ;
148033f810b2SJeff Kirsher if (mib->fddiPORTLCTFail_Ct > 0)
148133f810b2SJeff Kirsher phy->t_val[5] = 1 ; /* medium */
148233f810b2SJeff Kirsher else
148333f810b2SJeff Kirsher phy->t_val[5] = 0 ; /* short */
148433f810b2SJeff Kirsher
148533f810b2SJeff Kirsher /*
148633f810b2SJeff Kirsher * Implementers choice: use medium
148733f810b2SJeff Kirsher * instead of short when undesired
148833f810b2SJeff Kirsher * connection attempt is made.
148933f810b2SJeff Kirsher */
149033f810b2SJeff Kirsher if (phy->wc_flag)
149133f810b2SJeff Kirsher phy->t_val[5] = 1 ; /* medium */
149233f810b2SJeff Kirsher }
149333f810b2SJeff Kirsher mib->fddiPORTConnectState = PCM_CONNECTING ;
149433f810b2SJeff Kirsher }
149533f810b2SJeff Kirsher else {
149633f810b2SJeff Kirsher mib->fddiPORTConnectState = PCM_STANDBY ;
149733f810b2SJeff Kirsher phy->t_val[4] = 1 ; /* extended */
149833f810b2SJeff Kirsher phy->t_val[5] = 1 ;
149933f810b2SJeff Kirsher }
150033f810b2SJeff Kirsher break ;
150133f810b2SJeff Kirsher case 5:
150233f810b2SJeff Kirsher break ;
150333f810b2SJeff Kirsher case 6:
150433f810b2SJeff Kirsher /* we do NOT have a MAC for LCT */
150533f810b2SJeff Kirsher phy->t_val[6] = 0 ;
150633f810b2SJeff Kirsher break ;
150733f810b2SJeff Kirsher case 7:
150833f810b2SJeff Kirsher phy->cf_loop = FALSE ;
150933f810b2SJeff Kirsher lem_check_lct(smc,phy) ;
151033f810b2SJeff Kirsher if (phy->pc_lem_fail) {
15115671e8c1SJoe Perches DB_PCMN(1, "PCM %c : E104 LCT failed", phy->phy_name);
151233f810b2SJeff Kirsher phy->t_val[7] = 1 ;
151333f810b2SJeff Kirsher }
151433f810b2SJeff Kirsher else
151533f810b2SJeff Kirsher phy->t_val[7] = 0 ;
151633f810b2SJeff Kirsher break ;
151733f810b2SJeff Kirsher case 8:
151833f810b2SJeff Kirsher phy->t_val[8] = 0 ; /* Don't request MAC loopback */
151933f810b2SJeff Kirsher break ;
152033f810b2SJeff Kirsher case 9:
152133f810b2SJeff Kirsher phy->cf_loop = 0 ;
152233f810b2SJeff Kirsher if ((mib->fddiPORTPC_Withhold != PC_WH_NONE) ||
152333f810b2SJeff Kirsher ((smc->s.sas == SMT_DAS) && (phy->wc_flag))) {
152433f810b2SJeff Kirsher queue_event(smc,EVENT_PCM+np,PC_START) ;
152533f810b2SJeff Kirsher break ;
152633f810b2SJeff Kirsher }
152733f810b2SJeff Kirsher phy->t_val[9] = FALSE ;
152833f810b2SJeff Kirsher switch (smc->s.sas) {
152933f810b2SJeff Kirsher case SMT_DAS :
153033f810b2SJeff Kirsher /*
153133f810b2SJeff Kirsher * MAC intended on output
153233f810b2SJeff Kirsher */
153333f810b2SJeff Kirsher if (phy->pc_mode == PM_TREE) {
153433f810b2SJeff Kirsher if ((np == PB) || ((np == PA) &&
153533f810b2SJeff Kirsher (smc->y[PB].mib->fddiPORTConnectState !=
153633f810b2SJeff Kirsher PCM_ACTIVE)))
153733f810b2SJeff Kirsher phy->t_val[9] = TRUE ;
153833f810b2SJeff Kirsher }
153933f810b2SJeff Kirsher else {
154033f810b2SJeff Kirsher if (np == PB)
154133f810b2SJeff Kirsher phy->t_val[9] = TRUE ;
154233f810b2SJeff Kirsher }
154333f810b2SJeff Kirsher break ;
154433f810b2SJeff Kirsher case SMT_SAS :
154533f810b2SJeff Kirsher if (np == PS)
154633f810b2SJeff Kirsher phy->t_val[9] = TRUE ;
154733f810b2SJeff Kirsher break ;
154833f810b2SJeff Kirsher #ifdef CONCENTRATOR
154933f810b2SJeff Kirsher case SMT_NAC :
155033f810b2SJeff Kirsher /*
155133f810b2SJeff Kirsher * MAC intended on output
155233f810b2SJeff Kirsher */
155333f810b2SJeff Kirsher if (np == PB)
155433f810b2SJeff Kirsher phy->t_val[9] = TRUE ;
155533f810b2SJeff Kirsher break ;
155633f810b2SJeff Kirsher #endif
155733f810b2SJeff Kirsher }
155833f810b2SJeff Kirsher mib->fddiPORTMacIndicated.T_val = phy->t_val[9] ;
155933f810b2SJeff Kirsher break ;
156033f810b2SJeff Kirsher }
15615671e8c1SJoe Perches DB_PCMN(1, "SIG snd %x %x:", bit, phy->t_val[bit]);
156233f810b2SJeff Kirsher }
156333f810b2SJeff Kirsher
156433f810b2SJeff Kirsher /*
156533f810b2SJeff Kirsher * return status twisted (called by SMT)
156633f810b2SJeff Kirsher */
pcm_status_twisted(struct s_smc * smc)156733f810b2SJeff Kirsher int pcm_status_twisted(struct s_smc *smc)
156833f810b2SJeff Kirsher {
156933f810b2SJeff Kirsher int twist = 0 ;
157033f810b2SJeff Kirsher if (smc->s.sas != SMT_DAS)
157133f810b2SJeff Kirsher return 0;
157233f810b2SJeff Kirsher if (smc->y[PA].twisted && (smc->y[PA].mib->fddiPORTPCMState == PC8_ACTIVE))
157333f810b2SJeff Kirsher twist |= 1 ;
157433f810b2SJeff Kirsher if (smc->y[PB].twisted && (smc->y[PB].mib->fddiPORTPCMState == PC8_ACTIVE))
157533f810b2SJeff Kirsher twist |= 2 ;
157633f810b2SJeff Kirsher return twist;
157733f810b2SJeff Kirsher }
157833f810b2SJeff Kirsher
157933f810b2SJeff Kirsher /*
158033f810b2SJeff Kirsher * return status (called by SMT)
158133f810b2SJeff Kirsher * type
158233f810b2SJeff Kirsher * state
158333f810b2SJeff Kirsher * remote phy type
158433f810b2SJeff Kirsher * remote mac yes/no
158533f810b2SJeff Kirsher */
pcm_status_state(struct s_smc * smc,int np,int * type,int * state,int * remote,int * mac)158633f810b2SJeff Kirsher void pcm_status_state(struct s_smc *smc, int np, int *type, int *state,
158733f810b2SJeff Kirsher int *remote, int *mac)
158833f810b2SJeff Kirsher {
158933f810b2SJeff Kirsher struct s_phy *phy = &smc->y[np] ;
159033f810b2SJeff Kirsher struct fddi_mib_p *mib ;
159133f810b2SJeff Kirsher
159233f810b2SJeff Kirsher mib = phy->mib ;
159333f810b2SJeff Kirsher
159433f810b2SJeff Kirsher /* remote PHY type and MAC - set only if active */
159533f810b2SJeff Kirsher *mac = 0 ;
159633f810b2SJeff Kirsher *type = mib->fddiPORTMy_Type ; /* our PHY type */
159733f810b2SJeff Kirsher *state = mib->fddiPORTConnectState ;
159833f810b2SJeff Kirsher *remote = mib->fddiPORTNeighborType ;
159933f810b2SJeff Kirsher
160033f810b2SJeff Kirsher switch(mib->fddiPORTPCMState) {
160133f810b2SJeff Kirsher case PC8_ACTIVE :
160233f810b2SJeff Kirsher *mac = mib->fddiPORTMacIndicated.R_val ;
160333f810b2SJeff Kirsher break ;
160433f810b2SJeff Kirsher }
160533f810b2SJeff Kirsher }
160633f810b2SJeff Kirsher
160733f810b2SJeff Kirsher /*
160833f810b2SJeff Kirsher * return rooted station status (called by SMT)
160933f810b2SJeff Kirsher */
pcm_rooted_station(struct s_smc * smc)161033f810b2SJeff Kirsher int pcm_rooted_station(struct s_smc *smc)
161133f810b2SJeff Kirsher {
161233f810b2SJeff Kirsher int n ;
161333f810b2SJeff Kirsher
161433f810b2SJeff Kirsher for (n = 0 ; n < NUMPHYS ; n++) {
161533f810b2SJeff Kirsher if (smc->y[n].mib->fddiPORTPCMState == PC8_ACTIVE &&
161633f810b2SJeff Kirsher smc->y[n].mib->fddiPORTNeighborType == TM)
161733f810b2SJeff Kirsher return 0;
161833f810b2SJeff Kirsher }
161933f810b2SJeff Kirsher return 1;
162033f810b2SJeff Kirsher }
162133f810b2SJeff Kirsher
162233f810b2SJeff Kirsher /*
162333f810b2SJeff Kirsher * Interrupt actions for PLC & PCM events
162433f810b2SJeff Kirsher */
plc_irq(struct s_smc * smc,int np,unsigned int cmd)162533f810b2SJeff Kirsher void plc_irq(struct s_smc *smc, int np, unsigned int cmd)
162633f810b2SJeff Kirsher /* int np; PHY index */
162733f810b2SJeff Kirsher {
162833f810b2SJeff Kirsher struct s_phy *phy = &smc->y[np] ;
162933f810b2SJeff Kirsher struct s_plc *plc = &phy->plc ;
163033f810b2SJeff Kirsher int n ;
163133f810b2SJeff Kirsher #ifdef SUPERNET_3
163233f810b2SJeff Kirsher int corr_mask ;
163333f810b2SJeff Kirsher #endif /* SUPERNET_3 */
163433f810b2SJeff Kirsher int i ;
163533f810b2SJeff Kirsher
163633f810b2SJeff Kirsher if (np >= smc->s.numphys) {
163733f810b2SJeff Kirsher plc->soft_err++ ;
163833f810b2SJeff Kirsher return ;
163933f810b2SJeff Kirsher }
164033f810b2SJeff Kirsher if (cmd & PL_EBUF_ERR) { /* elastic buff. det. over-|underflow*/
164133f810b2SJeff Kirsher /*
164233f810b2SJeff Kirsher * Check whether the SRF Condition occurred.
164333f810b2SJeff Kirsher */
164433f810b2SJeff Kirsher if (!plc->ebuf_cont && phy->mib->fddiPORTPCMState == PC8_ACTIVE){
164533f810b2SJeff Kirsher /*
164633f810b2SJeff Kirsher * This is the real Elasticity Error.
164733f810b2SJeff Kirsher * More than one in a row are treated as a
164833f810b2SJeff Kirsher * single one.
164933f810b2SJeff Kirsher * Only count this in the active state.
165033f810b2SJeff Kirsher */
165133f810b2SJeff Kirsher phy->mib->fddiPORTEBError_Ct ++ ;
165233f810b2SJeff Kirsher
165333f810b2SJeff Kirsher }
165433f810b2SJeff Kirsher
165533f810b2SJeff Kirsher plc->ebuf_err++ ;
165633f810b2SJeff Kirsher if (plc->ebuf_cont <= 1000) {
165733f810b2SJeff Kirsher /*
165833f810b2SJeff Kirsher * Prevent counter from being wrapped after
165933f810b2SJeff Kirsher * hanging years in that interrupt.
166033f810b2SJeff Kirsher */
166133f810b2SJeff Kirsher plc->ebuf_cont++ ; /* Ebuf continuous error */
166233f810b2SJeff Kirsher }
166333f810b2SJeff Kirsher
166433f810b2SJeff Kirsher #ifdef SUPERNET_3
166533f810b2SJeff Kirsher if (plc->ebuf_cont == 1000 &&
166633f810b2SJeff Kirsher ((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) ==
166733f810b2SJeff Kirsher PLC_REV_SN3)) {
166833f810b2SJeff Kirsher /*
166933f810b2SJeff Kirsher * This interrupt remeained high for at least
167033f810b2SJeff Kirsher * 1000 consecutive interrupt calls.
167133f810b2SJeff Kirsher *
167233f810b2SJeff Kirsher * This is caused by a hardware error of the
167333f810b2SJeff Kirsher * ORION part of the Supernet III chipset.
167433f810b2SJeff Kirsher *
167533f810b2SJeff Kirsher * Disable this bit from the mask.
167633f810b2SJeff Kirsher */
167733f810b2SJeff Kirsher corr_mask = (plc_imsk_na & ~PL_EBUF_ERR) ;
167833f810b2SJeff Kirsher outpw(PLC(np,PL_INTR_MASK),corr_mask);
167933f810b2SJeff Kirsher
168033f810b2SJeff Kirsher /*
168133f810b2SJeff Kirsher * Disconnect from the ring.
168233f810b2SJeff Kirsher * Call the driver with the reset indication.
168333f810b2SJeff Kirsher */
168433f810b2SJeff Kirsher queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
168533f810b2SJeff Kirsher
168633f810b2SJeff Kirsher /*
168733f810b2SJeff Kirsher * Make an error log entry.
168833f810b2SJeff Kirsher */
168933f810b2SJeff Kirsher SMT_ERR_LOG(smc,SMT_E0136, SMT_E0136_MSG) ;
169033f810b2SJeff Kirsher
169133f810b2SJeff Kirsher /*
169233f810b2SJeff Kirsher * Indicate the Reset.
169333f810b2SJeff Kirsher */
169433f810b2SJeff Kirsher drv_reset_indication(smc) ;
169533f810b2SJeff Kirsher }
169633f810b2SJeff Kirsher #endif /* SUPERNET_3 */
169733f810b2SJeff Kirsher } else {
169833f810b2SJeff Kirsher /* Reset the continuous error variable */
169933f810b2SJeff Kirsher plc->ebuf_cont = 0 ; /* reset Ebuf continuous error */
170033f810b2SJeff Kirsher }
170133f810b2SJeff Kirsher if (cmd & PL_PHYINV) { /* physical layer invalid signal */
170233f810b2SJeff Kirsher plc->phyinv++ ;
170333f810b2SJeff Kirsher }
170433f810b2SJeff Kirsher if (cmd & PL_VSYM_CTR) { /* violation symbol counter has incr.*/
170533f810b2SJeff Kirsher plc->vsym_ctr++ ;
170633f810b2SJeff Kirsher }
170733f810b2SJeff Kirsher if (cmd & PL_MINI_CTR) { /* dep. on PLC_CNTRL_A's MINI_CTR_INT*/
170833f810b2SJeff Kirsher plc->mini_ctr++ ;
170933f810b2SJeff Kirsher }
171033f810b2SJeff Kirsher if (cmd & PL_LE_CTR) { /* link error event counter */
171133f810b2SJeff Kirsher int j ;
171233f810b2SJeff Kirsher
171333f810b2SJeff Kirsher /*
171433f810b2SJeff Kirsher * note: PL_LINK_ERR_CTR MUST be read to clear it
171533f810b2SJeff Kirsher */
171633f810b2SJeff Kirsher j = inpw(PLC(np,PL_LE_THRESHOLD)) ;
171733f810b2SJeff Kirsher i = inpw(PLC(np,PL_LINK_ERR_CTR)) ;
171833f810b2SJeff Kirsher
171933f810b2SJeff Kirsher if (i < j) {
172033f810b2SJeff Kirsher /* wrapped around */
172133f810b2SJeff Kirsher i += 256 ;
172233f810b2SJeff Kirsher }
172333f810b2SJeff Kirsher
172433f810b2SJeff Kirsher if (phy->lem.lem_on) {
172533f810b2SJeff Kirsher /* Note: Lem errors shall only be counted when
172633f810b2SJeff Kirsher * link is ACTIVE or LCT is active.
172733f810b2SJeff Kirsher */
172833f810b2SJeff Kirsher phy->lem.lem_errors += i ;
172933f810b2SJeff Kirsher phy->mib->fddiPORTLem_Ct += i ;
173033f810b2SJeff Kirsher }
173133f810b2SJeff Kirsher }
173233f810b2SJeff Kirsher if (cmd & PL_TPC_EXPIRED) { /* TPC timer reached zero */
173333f810b2SJeff Kirsher if (plc->p_state == PS_LCT) {
173433f810b2SJeff Kirsher /*
173533f810b2SJeff Kirsher * end of LCT
173633f810b2SJeff Kirsher */
173733f810b2SJeff Kirsher ;
173833f810b2SJeff Kirsher }
173933f810b2SJeff Kirsher plc->tpc_exp++ ;
174033f810b2SJeff Kirsher }
174133f810b2SJeff Kirsher if (cmd & PL_LS_MATCH) { /* LS == LS in PLC_CNTRL_B's MATCH_LS*/
174233f810b2SJeff Kirsher switch (inpw(PLC(np,PL_CNTRL_B)) & PL_MATCH_LS) {
174333f810b2SJeff Kirsher case PL_I_IDLE : phy->curr_ls = PC_ILS ; break ;
174433f810b2SJeff Kirsher case PL_I_HALT : phy->curr_ls = PC_HLS ; break ;
174533f810b2SJeff Kirsher case PL_I_MASTR : phy->curr_ls = PC_MLS ; break ;
174633f810b2SJeff Kirsher case PL_I_QUIET : phy->curr_ls = PC_QLS ; break ;
174733f810b2SJeff Kirsher }
174833f810b2SJeff Kirsher }
174933f810b2SJeff Kirsher if (cmd & PL_PCM_BREAK) { /* PCM has entered the BREAK state */
175033f810b2SJeff Kirsher int reason;
175133f810b2SJeff Kirsher
175233f810b2SJeff Kirsher reason = inpw(PLC(np,PL_STATUS_B)) & PL_BREAK_REASON ;
175333f810b2SJeff Kirsher
175433f810b2SJeff Kirsher switch (reason) {
175533f810b2SJeff Kirsher case PL_B_PCS : plc->b_pcs++ ; break ;
175633f810b2SJeff Kirsher case PL_B_TPC : plc->b_tpc++ ; break ;
175733f810b2SJeff Kirsher case PL_B_TNE : plc->b_tne++ ; break ;
175833f810b2SJeff Kirsher case PL_B_QLS : plc->b_qls++ ; break ;
175933f810b2SJeff Kirsher case PL_B_ILS : plc->b_ils++ ; break ;
176033f810b2SJeff Kirsher case PL_B_HLS : plc->b_hls++ ; break ;
176133f810b2SJeff Kirsher }
176233f810b2SJeff Kirsher
176333f810b2SJeff Kirsher /*jd 05-Aug-1999 changed: Bug #10419 */
17645671e8c1SJoe Perches DB_PCMN(1, "PLC %d: MDcF = %x", np, smc->e.DisconnectFlag);
176533f810b2SJeff Kirsher if (smc->e.DisconnectFlag == FALSE) {
17665671e8c1SJoe Perches DB_PCMN(1, "PLC %d: restart (reason %x)", np, reason);
176733f810b2SJeff Kirsher queue_event(smc,EVENT_PCM+np,PC_START) ;
176833f810b2SJeff Kirsher }
176933f810b2SJeff Kirsher else {
17705671e8c1SJoe Perches DB_PCMN(1, "PLC %d: NO!! restart (reason %x)",
17715671e8c1SJoe Perches np, reason);
177233f810b2SJeff Kirsher }
177333f810b2SJeff Kirsher return ;
177433f810b2SJeff Kirsher }
177533f810b2SJeff Kirsher /*
177633f810b2SJeff Kirsher * If both CODE & ENABLE are set ignore enable
177733f810b2SJeff Kirsher */
177833f810b2SJeff Kirsher if (cmd & PL_PCM_CODE) { /* receive last sign.-bit | LCT complete */
177933f810b2SJeff Kirsher queue_event(smc,EVENT_PCM+np,PC_SIGNAL) ;
178033f810b2SJeff Kirsher n = inpw(PLC(np,PL_RCV_VECTOR)) ;
178133f810b2SJeff Kirsher for (i = 0 ; i < plc->p_bits ; i++) {
178233f810b2SJeff Kirsher phy->r_val[plc->p_start+i] = n & 1 ;
178333f810b2SJeff Kirsher n >>= 1 ;
178433f810b2SJeff Kirsher }
178533f810b2SJeff Kirsher }
178633f810b2SJeff Kirsher else if (cmd & PL_PCM_ENABLED) { /* asserted SC_JOIN, scrub.completed*/
178733f810b2SJeff Kirsher queue_event(smc,EVENT_PCM+np,PC_JOIN) ;
178833f810b2SJeff Kirsher }
178933f810b2SJeff Kirsher if (cmd & PL_TRACE_PROP) { /* MLS while PC8_ACTIV || PC2_TRACE */
179033f810b2SJeff Kirsher /*PC22b*/
179133f810b2SJeff Kirsher if (!phy->tr_flag) {
17925671e8c1SJoe Perches DB_PCMN(1, "PCM : irq TRACE_PROP %d %d",
179333f810b2SJeff Kirsher np, smc->mib.fddiSMTECMState);
179433f810b2SJeff Kirsher phy->tr_flag = TRUE ;
179533f810b2SJeff Kirsher smc->e.trace_prop |= ENTITY_BIT(ENTITY_PHY(np)) ;
179633f810b2SJeff Kirsher queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ;
179733f810b2SJeff Kirsher }
179833f810b2SJeff Kirsher }
179933f810b2SJeff Kirsher /*
180033f810b2SJeff Kirsher * filter PLC glitch ???
180133f810b2SJeff Kirsher * QLS || HLS only while in PC2_TRACE state
180233f810b2SJeff Kirsher */
180333f810b2SJeff Kirsher if ((cmd & PL_SELF_TEST) && (phy->mib->fddiPORTPCMState == PC2_TRACE)) {
180433f810b2SJeff Kirsher /*PC22a*/
180533f810b2SJeff Kirsher if (smc->e.path_test == PT_PASSED) {
18065671e8c1SJoe Perches DB_PCMN(1, "PCM : state = %s %d",
18075671e8c1SJoe Perches get_pcmstate(smc, np),
180833f810b2SJeff Kirsher phy->mib->fddiPORTPCMState);
180933f810b2SJeff Kirsher
181033f810b2SJeff Kirsher smc->e.path_test = PT_PENDING ;
181133f810b2SJeff Kirsher queue_event(smc,EVENT_ECM,EC_PATH_TEST) ;
181233f810b2SJeff Kirsher }
181333f810b2SJeff Kirsher }
181433f810b2SJeff Kirsher if (cmd & PL_TNE_EXPIRED) { /* TNE: length of noise events */
181533f810b2SJeff Kirsher /* break_required (TNE > NS_Max) */
181633f810b2SJeff Kirsher if (phy->mib->fddiPORTPCMState == PC8_ACTIVE) {
181733f810b2SJeff Kirsher if (!phy->tr_flag) {
18185671e8c1SJoe Perches DB_PCMN(1, "PCM %c : PC81 %s",
18195671e8c1SJoe Perches phy->phy_name, "NSE");
182033f810b2SJeff Kirsher queue_event(smc, EVENT_PCM + np, PC_START);
182133f810b2SJeff Kirsher return;
182233f810b2SJeff Kirsher }
182333f810b2SJeff Kirsher }
182433f810b2SJeff Kirsher }
182533f810b2SJeff Kirsher #if 0
182633f810b2SJeff Kirsher if (cmd & PL_NP_ERR) { /* NP has requested to r/w an inv reg*/
182733f810b2SJeff Kirsher /*
182833f810b2SJeff Kirsher * It's a bug by AMD
182933f810b2SJeff Kirsher */
183033f810b2SJeff Kirsher plc->np_err++ ;
183133f810b2SJeff Kirsher }
183233f810b2SJeff Kirsher /* pin inactiv (GND) */
183333f810b2SJeff Kirsher if (cmd & PL_PARITY_ERR) { /* p. error dedected on TX9-0 inp */
183433f810b2SJeff Kirsher plc->parity_err++ ;
183533f810b2SJeff Kirsher }
183633f810b2SJeff Kirsher if (cmd & PL_LSDO) { /* carrier detected */
183733f810b2SJeff Kirsher ;
183833f810b2SJeff Kirsher }
183933f810b2SJeff Kirsher #endif
184033f810b2SJeff Kirsher }
184133f810b2SJeff Kirsher
184233f810b2SJeff Kirsher #ifdef DEBUG
184333f810b2SJeff Kirsher /*
184433f810b2SJeff Kirsher * fill state struct
184533f810b2SJeff Kirsher */
pcm_get_state(struct s_smc * smc,struct smt_state * state)184633f810b2SJeff Kirsher void pcm_get_state(struct s_smc *smc, struct smt_state *state)
184733f810b2SJeff Kirsher {
184833f810b2SJeff Kirsher struct s_phy *phy ;
184933f810b2SJeff Kirsher struct pcm_state *pcs ;
185033f810b2SJeff Kirsher int i ;
185133f810b2SJeff Kirsher int ii ;
185233f810b2SJeff Kirsher short rbits ;
185333f810b2SJeff Kirsher short tbits ;
185433f810b2SJeff Kirsher struct fddi_mib_p *mib ;
185533f810b2SJeff Kirsher
185633f810b2SJeff Kirsher for (i = 0, phy = smc->y, pcs = state->pcm_state ; i < NUMPHYS ;
185733f810b2SJeff Kirsher i++ , phy++, pcs++ ) {
185833f810b2SJeff Kirsher mib = phy->mib ;
185933f810b2SJeff Kirsher pcs->pcm_type = (u_char) mib->fddiPORTMy_Type ;
186033f810b2SJeff Kirsher pcs->pcm_state = (u_char) mib->fddiPORTPCMState ;
186133f810b2SJeff Kirsher pcs->pcm_mode = phy->pc_mode ;
186233f810b2SJeff Kirsher pcs->pcm_neighbor = (u_char) mib->fddiPORTNeighborType ;
186333f810b2SJeff Kirsher pcs->pcm_bsf = mib->fddiPORTBS_Flag ;
186433f810b2SJeff Kirsher pcs->pcm_lsf = phy->ls_flag ;
186533f810b2SJeff Kirsher pcs->pcm_lct_fail = (u_char) mib->fddiPORTLCTFail_Ct ;
186633f810b2SJeff Kirsher pcs->pcm_ls_rx = LS2MIB(sm_pm_get_ls(smc,i)) ;
186733f810b2SJeff Kirsher for (ii = 0, rbits = tbits = 0 ; ii < NUMBITS ; ii++) {
186833f810b2SJeff Kirsher rbits <<= 1 ;
186933f810b2SJeff Kirsher tbits <<= 1 ;
187033f810b2SJeff Kirsher if (phy->r_val[NUMBITS-1-ii])
187133f810b2SJeff Kirsher rbits |= 1 ;
187233f810b2SJeff Kirsher if (phy->t_val[NUMBITS-1-ii])
187333f810b2SJeff Kirsher tbits |= 1 ;
187433f810b2SJeff Kirsher }
187533f810b2SJeff Kirsher pcs->pcm_r_val = rbits ;
187633f810b2SJeff Kirsher pcs->pcm_t_val = tbits ;
187733f810b2SJeff Kirsher }
187833f810b2SJeff Kirsher }
187933f810b2SJeff Kirsher
get_pcm_state(struct s_smc * smc,int np)188033f810b2SJeff Kirsher int get_pcm_state(struct s_smc *smc, int np)
188133f810b2SJeff Kirsher {
188233f810b2SJeff Kirsher int pcs ;
188333f810b2SJeff Kirsher
188433f810b2SJeff Kirsher SK_UNUSED(smc) ;
188533f810b2SJeff Kirsher
188633f810b2SJeff Kirsher switch (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_STATE) {
188733f810b2SJeff Kirsher case PL_PC0 : pcs = PC_STOP ; break ;
188833f810b2SJeff Kirsher case PL_PC1 : pcs = PC_START ; break ;
188933f810b2SJeff Kirsher case PL_PC2 : pcs = PC_TRACE ; break ;
189033f810b2SJeff Kirsher case PL_PC3 : pcs = PC_SIGNAL ; break ;
189133f810b2SJeff Kirsher case PL_PC4 : pcs = PC_SIGNAL ; break ;
189233f810b2SJeff Kirsher case PL_PC5 : pcs = PC_SIGNAL ; break ;
189333f810b2SJeff Kirsher case PL_PC6 : pcs = PC_JOIN ; break ;
189433f810b2SJeff Kirsher case PL_PC7 : pcs = PC_JOIN ; break ;
189533f810b2SJeff Kirsher case PL_PC8 : pcs = PC_ENABLE ; break ;
189633f810b2SJeff Kirsher case PL_PC9 : pcs = PC_MAINT ; break ;
189733f810b2SJeff Kirsher default : pcs = PC_DISABLE ; break ;
189833f810b2SJeff Kirsher }
189933f810b2SJeff Kirsher return pcs;
190033f810b2SJeff Kirsher }
190133f810b2SJeff Kirsher
get_linestate(struct s_smc * smc,int np)190233f810b2SJeff Kirsher char *get_linestate(struct s_smc *smc, int np)
190333f810b2SJeff Kirsher {
190433f810b2SJeff Kirsher char *ls = "" ;
190533f810b2SJeff Kirsher
190633f810b2SJeff Kirsher SK_UNUSED(smc) ;
190733f810b2SJeff Kirsher
190833f810b2SJeff Kirsher switch (inpw(PLC(np,PL_STATUS_A)) & PL_LINE_ST) {
190933f810b2SJeff Kirsher case PL_L_NLS : ls = "NOISE" ; break ;
191033f810b2SJeff Kirsher case PL_L_ALS : ls = "ACTIV" ; break ;
191133f810b2SJeff Kirsher case PL_L_UND : ls = "UNDEF" ; break ;
191233f810b2SJeff Kirsher case PL_L_ILS4: ls = "ILS 4" ; break ;
191333f810b2SJeff Kirsher case PL_L_QLS : ls = "QLS" ; break ;
191433f810b2SJeff Kirsher case PL_L_MLS : ls = "MLS" ; break ;
191533f810b2SJeff Kirsher case PL_L_HLS : ls = "HLS" ; break ;
191633f810b2SJeff Kirsher case PL_L_ILS16:ls = "ILS16" ; break ;
191733f810b2SJeff Kirsher #ifdef lint
191833f810b2SJeff Kirsher default: ls = "unknown" ; break ;
191933f810b2SJeff Kirsher #endif
192033f810b2SJeff Kirsher }
192133f810b2SJeff Kirsher return ls;
192233f810b2SJeff Kirsher }
192333f810b2SJeff Kirsher
get_pcmstate(struct s_smc * smc,int np)192433f810b2SJeff Kirsher char *get_pcmstate(struct s_smc *smc, int np)
192533f810b2SJeff Kirsher {
192633f810b2SJeff Kirsher char *pcs ;
192733f810b2SJeff Kirsher
192833f810b2SJeff Kirsher SK_UNUSED(smc) ;
192933f810b2SJeff Kirsher
193033f810b2SJeff Kirsher switch (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_STATE) {
193133f810b2SJeff Kirsher case PL_PC0 : pcs = "OFF" ; break ;
193233f810b2SJeff Kirsher case PL_PC1 : pcs = "BREAK" ; break ;
193333f810b2SJeff Kirsher case PL_PC2 : pcs = "TRACE" ; break ;
193433f810b2SJeff Kirsher case PL_PC3 : pcs = "CONNECT"; break ;
193533f810b2SJeff Kirsher case PL_PC4 : pcs = "NEXT" ; break ;
193633f810b2SJeff Kirsher case PL_PC5 : pcs = "SIGNAL" ; break ;
193733f810b2SJeff Kirsher case PL_PC6 : pcs = "JOIN" ; break ;
193833f810b2SJeff Kirsher case PL_PC7 : pcs = "VERIFY" ; break ;
193933f810b2SJeff Kirsher case PL_PC8 : pcs = "ACTIV" ; break ;
194033f810b2SJeff Kirsher case PL_PC9 : pcs = "MAINT" ; break ;
194133f810b2SJeff Kirsher default : pcs = "UNKNOWN" ; break ;
194233f810b2SJeff Kirsher }
194333f810b2SJeff Kirsher return pcs;
194433f810b2SJeff Kirsher }
194533f810b2SJeff Kirsher
list_phy(struct s_smc * smc)194633f810b2SJeff Kirsher void list_phy(struct s_smc *smc)
194733f810b2SJeff Kirsher {
194833f810b2SJeff Kirsher struct s_plc *plc ;
194933f810b2SJeff Kirsher int np ;
195033f810b2SJeff Kirsher
195133f810b2SJeff Kirsher for (np = 0 ; np < NUMPHYS ; np++) {
195233f810b2SJeff Kirsher plc = &smc->y[np].plc ;
195333f810b2SJeff Kirsher printf("PHY %d:\tERRORS\t\t\tBREAK_REASONS\t\tSTATES:\n",np) ;
195433f810b2SJeff Kirsher printf("\tsoft_error: %ld \t\tPC_Start : %ld\n",
195533f810b2SJeff Kirsher plc->soft_err,plc->b_pcs);
195633f810b2SJeff Kirsher printf("\tparity_err: %ld \t\tTPC exp. : %ld\t\tLine: %s\n",
195733f810b2SJeff Kirsher plc->parity_err,plc->b_tpc,get_linestate(smc,np)) ;
195833f810b2SJeff Kirsher printf("\tebuf_error: %ld \t\tTNE exp. : %ld\n",
195933f810b2SJeff Kirsher plc->ebuf_err,plc->b_tne) ;
196033f810b2SJeff Kirsher printf("\tphyinvalid: %ld \t\tQLS det. : %ld\t\tPCM : %s\n",
196133f810b2SJeff Kirsher plc->phyinv,plc->b_qls,get_pcmstate(smc,np)) ;
196233f810b2SJeff Kirsher printf("\tviosym_ctr: %ld \t\tILS det. : %ld\n",
196333f810b2SJeff Kirsher plc->vsym_ctr,plc->b_ils) ;
196433f810b2SJeff Kirsher printf("\tmingap_ctr: %ld \t\tHLS det. : %ld\n",
196533f810b2SJeff Kirsher plc->mini_ctr,plc->b_hls) ;
196633f810b2SJeff Kirsher printf("\tnodepr_err: %ld\n",plc->np_err) ;
196733f810b2SJeff Kirsher printf("\tTPC_exp : %ld\n",plc->tpc_exp) ;
196833f810b2SJeff Kirsher printf("\tLEM_err : %ld\n",smc->y[np].lem.lem_errors) ;
196933f810b2SJeff Kirsher }
197033f810b2SJeff Kirsher }
197133f810b2SJeff Kirsher
197233f810b2SJeff Kirsher
197333f810b2SJeff Kirsher #ifdef CONCENTRATOR
pcm_lem_dump(struct s_smc * smc)197433f810b2SJeff Kirsher void pcm_lem_dump(struct s_smc *smc)
197533f810b2SJeff Kirsher {
197633f810b2SJeff Kirsher int i ;
197733f810b2SJeff Kirsher struct s_phy *phy ;
197833f810b2SJeff Kirsher struct fddi_mib_p *mib ;
197933f810b2SJeff Kirsher
198033f810b2SJeff Kirsher char *entostring() ;
198133f810b2SJeff Kirsher
198233f810b2SJeff Kirsher printf("PHY errors BER\n") ;
198333f810b2SJeff Kirsher printf("----------------------\n") ;
198433f810b2SJeff Kirsher for (i = 0,phy = smc->y ; i < NUMPHYS ; i++,phy++) {
198533f810b2SJeff Kirsher if (!plc_is_installed(smc,i))
198633f810b2SJeff Kirsher continue ;
198733f810b2SJeff Kirsher mib = phy->mib ;
198833f810b2SJeff Kirsher printf("%s\t%ld\t10E-%d\n",
198933f810b2SJeff Kirsher entostring(smc,ENTITY_PHY(i)),
199033f810b2SJeff Kirsher mib->fddiPORTLem_Ct,
199133f810b2SJeff Kirsher mib->fddiPORTLer_Estimate) ;
199233f810b2SJeff Kirsher }
199333f810b2SJeff Kirsher }
199433f810b2SJeff Kirsher #endif
199533f810b2SJeff Kirsher #endif
1996