54 static const char ID_sccs[] =
"@(#)pcmplc.c 2.55 99/08/05 (C) SK " ;
58 extern int snmp_fddi_trap(
65 extern int plc_is_installed(
76 #define GO_STATE(x) (mib->fddiPORTPCMState = (x)|AFLAG)
77 #define ACTIONS_DONE() (mib->fddiPORTPCMState &= ~AFLAG)
78 #define ACTIONS(x) (x|AFLAG)
98 static const char *
const pcm_states[] = {
99 "PC0_OFF",
"PC1_BREAK",
"PC2_TRACE",
"PC3_CONNECT",
"PC4_NEXT",
100 "PC5_SIGNAL",
"PC6_JOIN",
"PC7_VERIFY",
"PC8_ACTIVE",
"PC9_MAINT"
106 static const char *
const pcm_events[] = {
107 "NONE",
"PC_START",
"PC_STOP",
"PC_LOOP",
"PC_JOIN",
"PC_SIGNAL",
108 "PC_REJECT",
"PC_MAINT",
"PC_TRACE",
"PC_PDR",
109 "PC_ENABLE",
"PC_DISABLE",
110 "PC_QLS",
"PC_ILS",
"PC_MLS",
"PC_HLS",
"PC_LS_PDR",
"PC_LS_NONE",
111 "PC_TIMEOUT_TB_MAX",
"PC_TIMEOUT_TB_MIN",
112 "PC_TIMEOUT_C_MIN",
"PC_TIMEOUT_T_OUT",
113 "PC_TIMEOUT_TL_MIN",
"PC_TIMEOUT_T_NEXT",
"PC_TIMEOUT_LCT",
123 #define PLCS_CONTROL_C_U 0
124 #define PLCS_CONTROL_C_S (PL_C_SDOFF_ENABLE | PL_C_SDON_ENABLE | \
126 #define PLCS_FASSERT_U 0
127 #define PLCS_FASSERT_S 0xFd76
128 #define PLCS_FDEASSERT_U 0
129 #define PLCS_FDEASSERT_S 0
136 static const u_char plcs_control_c_u[17] =
"PLC_CNTRL_C_U=\0\0" ;
137 static const u_char plcs_control_c_s[17] =
"PLC_CNTRL_C_S=\01\02" ;
139 #define PLCS_CONTROL_C_U (plcs_control_c_u[14] | (plcs_control_c_u[15]<<8))
140 #define PLCS_CONTROL_C_S (plcs_control_c_s[14] | (plcs_control_c_s[15]<<8))
157 #define LCT_LEM_MAX 255
163 #define PLC_MS(m) ((int)((0x10000L-(m*100000L/2048))))
164 #define SLOW_TL_MIN PLC_MS(6)
165 #define SLOW_C_MIN PLC_MS(10)
167 static const struct plt {
205 static void reset_lem_struct(
struct s_phy *
phy);
206 static void plc_init(
struct s_smc *
smc,
int p);
208 static void sm_ph_lem_stop(
struct s_smc *
smc,
int np);
209 static void sm_ph_linestate(
struct s_smc *
smc,
int phy,
int ls);
210 static void real_init_plc(
struct s_smc *
smc);
227 static void stop_pcm_timer0(
struct s_smc *smc,
struct s_phy *phy)
242 struct fddi_mib_p *mib ;
244 for (np = 0,phy = smc->
y ; np <
NUMPHYS ; np++,phy++) {
249 switch (smc->
s.sas) {
252 mib->fddiPORTMy_Type = (np ==
PS) ?
TS :
TM ;
255 mib->fddiPORTMy_Type = (np ==
PA) ?
TA :
259 mib->fddiPORTMy_Type =
TM ;
263 mib->fddiPORTMy_Type = (np ==
PS) ?
TS :
TNONE ;
264 mib->fddiPORTHardwarePresent = (np ==
PS) ?
TRUE :
273 mib->fddiPORTMy_Type = (np ==
PB) ?
TB :
TA ;
327 switch (mib->fddiPORTMy_Type) {
331 mib->fddiPORTRequestedPaths[2] =
335 mib->fddiPORTRequestedPaths[3] =
344 mib->fddiPORTRequestedPaths[2] =
347 mib->fddiPORTRequestedPaths[3] =
356 mib->fddiPORTRequestedPaths[2] =
360 mib->fddiPORTRequestedPaths[3] =
367 mib->fddiPORTRequestedPaths[2] =
371 mib->fddiPORTRequestedPaths[3] = 0 ;
376 mib->fddiPORTPCMStateX = mib->fddiPORTPCMState ;
377 mib->fddiPORTLCTFail_Ct = 0 ;
378 mib->fddiPORTBS_Flag = 0 ;
380 mib->fddiPORTNeighborType =
TNONE ;
391 reset_lem_struct(phy) ;
394 for (i = 0 ; i <
NUMBITS ; i++) {
414 static void real_init_plc(
struct s_smc *smc)
418 for (p = 0 ; p <
NUMPHYS ; p++)
422 static void plc_init(
struct s_smc *smc,
int p)
442 if (smc->
y[p].pmd_scramble) {
445 outpw(
PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_S) ;
446 outpw(
PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_S) ;
452 outpw(
PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_U) ;
453 outpw(
PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_U) ;
461 for ( i = 0 ; pltm[
i].timer; i++)
485 static void plc_go_state(
struct s_smc *smc,
int p,
int state)
495 outpw(port,val | state) ;
506 if (!plc_is_installed(smc,phy))
534 static int plc_send_bits(
struct s_smc *smc,
struct s_phy *phy,
int len)
543 for (i = len-1,n = 0 ; i >= 0 ; i--) {
548 printf(
"PL_PCM_SIGNAL is set\n") ;
558 if (smc->debug.d_plc & 0x80)
560 if (
debug.d_plc & 0x80)
595 void pcm(
struct s_smc *smc,
const int np,
int event)
600 struct fddi_mib_p *mib ;
611 oldstate = mib->fddiPORTPCMState ;
613 DB_PCM(
"PCM %c: state %s",
615 (mib->fddiPORTPCMState &
AFLAG) ?
"ACTIONS " :
"") ;
617 pcm_states[mib->fddiPORTPCMState & ~
AFLAG],
619 state = mib->fddiPORTPCMState ;
620 pcm_fsm(smc,phy,event) ;
622 }
while (state != mib->fddiPORTPCMState) ;
632 mib->fddiPORTPCMStateX =
state ;
638 if ( mib->fddiPORTPCMState != oldstate &&
648 if ( mib->fddiPORTPCMState != oldstate ) {
650 DB_SNMP (
"PCM from %d to %d\n", oldstate, mib->fddiPORTPCMState);
651 if ( mib->fddiPORTPCMState ==
PC0_OFF ) {
653 snmp_fddi_trap (smc, 1, (
int) mib->fddiPORTIndex );
654 }
else if ( oldstate ==
PC0_OFF ) {
656 snmp_fddi_trap (smc, 2, (
int) mib->fddiPORTIndex );
657 }
else if ( mib->fddiPORTPCMState !=
PC2_TRACE &&
660 snmp_fddi_trap (smc, 3, (
int) mib->fddiPORTIndex );
661 }
else if ( mib->fddiPORTPCMState ==
PC8_ACTIVE ) {
663 snmp_fddi_trap (smc, 4, (
int) mib->fddiPORTIndex );
674 static void pcm_fsm(
struct s_smc *smc,
struct s_phy *phy,
int cmd)
679 struct fddi_mib_p *mib ;
693 if (mib->fddiPORTPCMState !=
PC9_MAINT) {
696 FDDI_PORT_EVENT, (
u_long) FDDI_PORT_STOP,
697 smt_get_port_event_word(smc));
709 FDDI_PORT_EVENT, (
u_long) FDDI_PORT_DISABLED,
710 smt_get_port_event_word(smc));
714 stop_pcm_timer0(smc,phy) ;
720 switch(mib->fddiPORTPCMState) {
722 stop_pcm_timer0(smc,phy) ;
726 sm_ph_lem_stop(smc,np) ;
743 stop_pcm_timer0(smc,phy) ;
745 plc_go_state(smc,np,0) ;
748 sm_ph_lem_stop(smc,np) ;
771 for (i = 0 ; i < 3 ; i++)
772 pc_tcode_actions(smc,i,phy) ;
794 if (plc_send_bits(smc,phy,3)) {
831 (
void) plc_send_bits(smc,phy,3) ;
863 for (i = 0 ; i <= 2 ; i++)
864 pc_rcode_actions(smc,i,phy) ;
865 pc_tcode_actions(smc,3,phy) ;
870 if (plc_send_bits(smc,phy,1)) {
875 pc_rcode_actions(smc,3,phy) ;
876 for (i = 4 ; i <= 6 ; i++)
877 pc_tcode_actions(smc,i,phy) ;
882 if (plc_send_bits(smc,phy,3)) {
887 for (i = 3 ; i <= 6 ; i++)
888 pc_rcode_actions(smc,i,phy) ;
893 sm_ph_lem_start(smc,np,(
int)smc->
s.lct_short) ;
901 pc_tcode_actions(smc,7,phy) ;
909 if (plc_send_bits(smc,phy,1)) {
915 pc_rcode_actions(smc,7,phy) ;
921 for (i = 8 ; i <= 9 ; i++)
922 pc_tcode_actions(smc,i,phy) ;
927 if (plc_send_bits(smc,phy,2)) {
932 for (i = 8 ; i <= 9 ; i++)
933 pc_rcode_actions(smc,i,phy) ;
1004 stop_pcm_timer0(smc,phy) ;
1008 sm_ph_lem_stop(smc,np) ;
1015 sm_ph_linestate(smc,np,(
int)
MIB2LS(mib->fddiPORTMaint_LS)) ;
1037 static void sm_ph_linestate(
struct s_smc *smc,
int phy,
int ls)
1066 static void reset_lem_struct(
struct s_phy *phy)
1070 phy->
mib->fddiPORTLer_Estimate = 15 ;
1077 static void lem_evaluate(
struct s_smc *smc,
struct s_phy *phy)
1082 struct fddi_mib_p *mib ;
1092 mib->fddiPORTLem_Ct +=
errors ;
1105 if (!errors) ber = 15 ;
1106 else if (errors <= 9) ber = 9 ;
1107 else if (errors <= 99) ber = 8 ;
1108 else if (errors <= 999) ber = 7 ;
1109 else if (errors <= 9999) ber = 6 ;
1110 else if (errors <= 99999) ber = 5 ;
1111 else if (errors <= 999999) ber = 4 ;
1112 else if (errors <= 9999999) ber = 3 ;
1113 else if (errors <= 99999999) ber = 2 ;
1114 else if (errors <= 999999999) ber = 1 ;
1124 if (mib->fddiPORTLer_Estimate < 4) {
1125 mib->fddiPORTLer_Estimate = 4 ;
1129 DB_PCMN(1,
"LEM %c :\n",phy->
np ==
PB?
'B' :
'A',0) ;
1131 DB_PCMN(1,
"sum_errors : %ld\n",mib->fddiPORTLem_Ct,0) ;
1132 DB_PCMN(1,
"current BER : 10E-%d\n",ber/100,0) ;
1134 DB_PCMN(1,
"avg. BER : 10E-%d\n",
1135 mib->fddiPORTLer_Estimate,0) ;
1141 cond = (mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Alarm) ?
1143 #ifdef SMT_EXT_CUTOFF
1144 smt_ler_alarm_check(smc,phy,cond) ;
1146 if (cond != mib->fddiPORTLerFlag) {
1152 if ( mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Cutoff) {
1154 mib->fddiPORTLem_Reject_Ct++ ;
1163 DB_PCMN(1,
"PCM: LER cutoff on port %d cutoff %d\n",
1164 phy->
np, mib->fddiPORTLer_Cutoff) ;
1166 #ifdef SMT_EXT_CUTOFF
1167 smt_port_off_event(smc,phy->
np);
1181 for (np = 0 ; np <
NUMPHYS ; np++)
1182 lem_evaluate(smc,&smc->
y[np]) ;
1185 static void lem_check_lct(
struct s_smc *smc,
struct s_phy *phy)
1188 struct fddi_mib_p *mib ;
1196 mib->fddiPORTLem_Ct +=
errors ;
1219 mib->fddiPORTLCTFail_Ct++ ;
1220 mib->fddiPORTLem_Reject_Ct++ ;
1223 mib->fddiPORTLCTFail_Ct = 0 ;
1229 static void sm_ph_lem_start(
struct s_smc *smc,
int np,
int threshold)
1247 static void sm_ph_lem_stop(
struct s_smc *smc,
int np)
1261 phy =
phy ; on_off = on_off ;
1274 static void pc_rcode_actions(
struct s_smc *smc,
int bit,
struct s_phy *phy)
1276 struct fddi_mib_p *mib ;
1289 if (phy->
r_val[1] == 0 && phy->
r_val[2] == 0)
1290 mib->fddiPORTNeighborType =
TA ;
1291 else if (phy->
r_val[1] == 0 && phy->
r_val[2] == 1)
1292 mib->fddiPORTNeighborType =
TB ;
1293 else if (phy->
r_val[1] == 1 && phy->
r_val[2] == 0)
1294 mib->fddiPORTNeighborType =
TS ;
1295 else if (phy->
r_val[1] == 1 && phy->
r_val[2] == 1)
1296 mib->fddiPORTNeighborType =
TM ;
1299 if (mib->fddiPORTMy_Type ==
TM &&
1300 mib->fddiPORTNeighborType ==
TM) {
1301 DB_PCMN(1,
"PCM %c : E100 withhold M-M\n",
1308 if (mib->fddiPORTMy_Type ==
TM ||
1309 mib->fddiPORTNeighborType ==
TM)
1324 DB_PCMN(1,
"PCM %c : E101 withhold other\n",
1327 phy->
twisted = ((mib->fddiPORTMy_Type !=
TS) &&
1328 (mib->fddiPORTMy_Type !=
TM) &&
1329 (mib->fddiPORTNeighborType ==
1330 mib->fddiPORTMy_Type)) ;
1332 DB_PCMN(1,
"PCM %c : E102 !!! TWISTED !!!\n",
1353 phy->
t_next[7] = smc->
s.pcm_lc_short ;
1357 phy->
t_next[7] = smc->
s.pcm_lc_medium ;
1361 phy->
t_next[7] = smc->
s.pcm_lc_long ;
1365 phy->
t_next[7] = smc->
s.pcm_lc_extended ;
1368 if (phy->
t_next[7] > smc->
s.pcm_lc_medium) {
1372 phy->
t_next[9] = smc->
s.pcm_t_next_9 ;
1375 if (phy->
t_val[6]) {
1382 DB_PCMN(1,
"PCM %c : E103 LCT fail %s\n",
1395 if (phy->
r_val[9]) {
1397 mib->fddiPORTMacIndicated.R_val =
TRUE ;
1401 mib->fddiPORTMacIndicated.R_val =
FALSE ;
1410 static void pc_tcode_actions(
struct s_smc *smc,
const int bit,
struct s_phy *phy)
1413 struct fddi_mib_p *mib ;
1422 if (mib->fddiPORTMy_Type ==
TS || mib->fddiPORTMy_Type ==
TM)
1428 if (mib->fddiPORTMy_Type ==
TB || mib->fddiPORTMy_Type ==
TM)
1438 type = mib->fddiPORTMy_Type ;
1439 ne = mib->fddiPORTNeighborType ;
1440 policy = smc->
mib.fddiSMTConnectionPolicy ;
1481 if ( (type ==
TA && ne ==
TA ) ||
1482 (type ==
TA && ne ==
TS ) ||
1483 (type ==
TB && ne ==
TB ) ||
1484 (type ==
TB && ne ==
TS ) ||
1485 (type ==
TS && ne ==
TA ) ||
1486 (type ==
TS && ne ==
TB ) ) {
1494 if (mib->fddiPORTPC_Withhold ==
PC_WH_NONE) {
1501 if (mib->fddiPORTLCTFail_Ct > 0)
1530 lem_check_lct(smc,phy) ;
1532 DB_PCMN(1,
"PCM %c : E104 LCT failed\n",
1544 if ((mib->fddiPORTPC_Withhold !=
PC_WH_NONE) ||
1550 switch (smc->
s.sas) {
1556 if ((np ==
PB) || ((np ==
PA) &&
1557 (smc->
y[
PB].mib->fddiPORTConnectState !=
1580 mib->fddiPORTMacIndicated.T_val = phy->
t_val[9] ;
1594 if (smc->
y[
PA].twisted && (smc->
y[
PA].mib->fddiPORTPCMState ==
PC8_ACTIVE))
1596 if (smc->
y[
PB].twisted && (smc->
y[
PB].mib->fddiPORTPCMState ==
PC8_ACTIVE))
1609 int *remote,
int *
mac)
1612 struct fddi_mib_p *mib ;
1618 *type = mib->fddiPORTMy_Type ;
1619 *state = mib->fddiPORTConnectState ;
1620 *remote = mib->fddiPORTNeighborType ;
1622 switch(mib->fddiPORTPCMState) {
1624 *mac = mib->fddiPORTMacIndicated.R_val ;
1636 for (n = 0 ; n <
NUMPHYS ; n++) {
1637 if (smc->
y[n].mib->fddiPORTPCMState ==
PC8_ACTIVE &&
1638 smc->
y[n].mib->fddiPORTNeighborType ==
TM)
1658 if (np >= smc->
s.numphys) {
1673 phy->
mib->fddiPORTEBError_Ct ++ ;
1699 corr_mask = (plc_imsk_na & ~PL_EBUF_ERR) ;
1746 if (phy->
lem.lem_on) {
1750 phy->
lem.lem_errors +=
i ;
1751 phy->
mib->fddiPORTLem_Ct +=
i ;
1786 DB_PCMN(1,
"PLC %d: MDcF = %x\n", np, smc->
e.DisconnectFlag);
1787 if (smc->
e.DisconnectFlag ==
FALSE) {
1788 DB_PCMN(1,
"PLC %d: restart (reason %x)\n", np, reason);
1792 DB_PCMN(1,
"PLC %d: NO!! restart (reason %x)\n", np, reason);
1802 for (i = 0 ; i < plc->
p_bits ; i++) {
1813 DB_PCMN(1,
"PCM : irq TRACE_PROP %d %d\n",
1814 np,smc->
mib.fddiSMTECMState) ;
1828 phy->
mib->fddiPORTPCMState) ;
1873 struct fddi_mib_p *mib ;
1875 for (i = 0, phy = smc->
y, pcs = state->
pcm_state ; i < NUMPHYS ;
1876 i++ , phy++, pcs++ ) {
1882 pcs->
pcm_bsf = mib->fddiPORTBS_Flag ;
1886 for (ii = 0, rbits = tbits = 0 ; ii <
NUMBITS ; ii++) {
1889 if (phy->
r_val[NUMBITS-1-ii])
1891 if (phy->
t_val[NUMBITS-1-ii])
1899 int get_pcm_state(
struct s_smc *smc,
int np)
1921 char *get_linestate(
struct s_smc *smc,
int np)
1928 case PL_L_NLS : ls =
"NOISE" ; break ;
1929 case PL_L_ALS : ls =
"ACTIV" ; break ;
1930 case PL_L_UND : ls =
"UNDEF" ; break ;
1932 case PL_L_QLS : ls =
"QLS" ; break ;
1933 case PL_L_MLS : ls =
"MLS" ; break ;
1934 case PL_L_HLS : ls =
"HLS" ; break ;
1937 default: ls =
"unknown" ; break ;
1950 case PL_PC0 : pcs =
"OFF" ; break ;
1951 case PL_PC1 : pcs =
"BREAK" ; break ;
1952 case PL_PC2 : pcs =
"TRACE" ; break ;
1953 case PL_PC3 : pcs =
"CONNECT"; break ;
1954 case PL_PC4 : pcs =
"NEXT" ; break ;
1955 case PL_PC5 : pcs =
"SIGNAL" ; break ;
1956 case PL_PC6 : pcs =
"JOIN" ; break ;
1957 case PL_PC7 : pcs =
"VERIFY" ; break ;
1958 case PL_PC8 : pcs =
"ACTIV" ; break ;
1959 case PL_PC9 : pcs =
"MAINT" ; break ;
1960 default : pcs =
"UNKNOWN" ; break ;
1965 void list_phy(
struct s_smc *smc)
1970 for (np = 0 ; np <
NUMPHYS ; np++) {
1971 plc = &smc->
y[np].plc ;
1972 printf(
"PHY %d:\tERRORS\t\t\tBREAK_REASONS\t\tSTATES:\n",np) ;
1973 printf(
"\tsoft_error: %ld \t\tPC_Start : %ld\n",
1975 printf(
"\tparity_err: %ld \t\tTPC exp. : %ld\t\tLine: %s\n",
1977 printf(
"\tebuf_error: %ld \t\tTNE exp. : %ld\n",
1979 printf(
"\tphyinvalid: %ld \t\tQLS det. : %ld\t\tPCM : %s\n",
1981 printf(
"\tviosym_ctr: %ld \t\tILS det. : %ld\n",
1983 printf(
"\tmingap_ctr: %ld \t\tHLS det. : %ld\n",
1987 printf(
"\tLEM_err : %ld\n",smc->
y[np].lem.lem_errors) ;
1993 void pcm_lem_dump(
struct s_smc *smc)
1997 struct fddi_mib_p *mib ;
1999 char *entostring() ;
2001 printf(
"PHY errors BER\n") ;
2002 printf(
"----------------------\n") ;
2003 for (i = 0,phy = smc->
y ; i < NUMPHYS ; i++,phy++) {
2004 if (!plc_is_installed(smc,i))
2007 printf(
"%s\t%ld\t10E-%d\n",
2009 mib->fddiPORTLem_Ct,
2010 mib->fddiPORTLer_Estimate) ;