0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 #include "h/types.h"
0042 #include "h/fddi.h"
0043 #include "h/smc.h"
0044 #include "h/supern_2.h"
0045 #define KERNEL
0046 #include "h/smtstate.h"
0047
0048 #ifdef FDDI_MIB
0049 extern int snmp_fddi_trap(
0050 #ifdef ANSIC
0051 struct s_smc * smc, int type, int index
0052 #endif
0053 );
0054 #endif
0055 #ifdef CONCENTRATOR
0056 extern int plc_is_installed(
0057 #ifdef ANSIC
0058 struct s_smc *smc ,
0059 int p
0060 #endif
0061 ) ;
0062 #endif
0063
0064
0065
0066 #define AFLAG (0x20)
0067 #define GO_STATE(x) (mib->fddiPORTPCMState = (x)|AFLAG)
0068 #define ACTIONS_DONE() (mib->fddiPORTPCMState &= ~AFLAG)
0069 #define ACTIONS(x) (x|AFLAG)
0070
0071
0072
0073
0074 #define PC0_OFF 0
0075 #define PC1_BREAK 1
0076 #define PC2_TRACE 2
0077 #define PC3_CONNECT 3
0078 #define PC4_NEXT 4
0079 #define PC5_SIGNAL 5
0080 #define PC6_JOIN 6
0081 #define PC7_VERIFY 7
0082 #define PC8_ACTIVE 8
0083 #define PC9_MAINT 9
0084
0085
0086
0087
0088 static const char * const pcm_states[] = {
0089 "PC0_OFF","PC1_BREAK","PC2_TRACE","PC3_CONNECT","PC4_NEXT",
0090 "PC5_SIGNAL","PC6_JOIN","PC7_VERIFY","PC8_ACTIVE","PC9_MAINT"
0091 } ;
0092
0093
0094
0095
0096 static const char * const pcm_events[] = {
0097 "NONE","PC_START","PC_STOP","PC_LOOP","PC_JOIN","PC_SIGNAL",
0098 "PC_REJECT","PC_MAINT","PC_TRACE","PC_PDR",
0099 "PC_ENABLE","PC_DISABLE",
0100 "PC_QLS","PC_ILS","PC_MLS","PC_HLS","PC_LS_PDR","PC_LS_NONE",
0101 "PC_TIMEOUT_TB_MAX","PC_TIMEOUT_TB_MIN",
0102 "PC_TIMEOUT_C_MIN","PC_TIMEOUT_T_OUT",
0103 "PC_TIMEOUT_TL_MIN","PC_TIMEOUT_T_NEXT","PC_TIMEOUT_LCT",
0104 "PC_NSE","PC_LEM"
0105 } ;
0106
0107 #ifdef MOT_ELM
0108
0109
0110
0111
0112 #define PLCS_CONTROL_C_U 0
0113 #define PLCS_CONTROL_C_S (PL_C_SDOFF_ENABLE | PL_C_SDON_ENABLE | \
0114 PL_C_CIPHER_ENABLE)
0115 #define PLCS_FASSERT_U 0
0116 #define PLCS_FASSERT_S 0xFd76
0117 #define PLCS_FDEASSERT_U 0
0118 #define PLCS_FDEASSERT_S 0
0119 #else
0120
0121
0122
0123
0124
0125 static const u_char plcs_control_c_u[17] = "PLC_CNTRL_C_U=\0\0" ;
0126 static const u_char plcs_control_c_s[17] = "PLC_CNTRL_C_S=\01\02" ;
0127
0128 #define PLCS_CONTROL_C_U (plcs_control_c_u[14] | (plcs_control_c_u[15]<<8))
0129 #define PLCS_CONTROL_C_S (plcs_control_c_s[14] | (plcs_control_c_s[15]<<8))
0130 #endif
0131
0132
0133
0134
0135
0136
0137 #define PS_OFF 0
0138 #define PS_BIT3 1
0139 #define PS_BIT4 2
0140 #define PS_BIT7 3
0141 #define PS_LCT 4
0142 #define PS_BIT8 5
0143 #define PS_JOIN 6
0144 #define PS_ACTIVE 7
0145
0146 #define LCT_LEM_MAX 255
0147
0148
0149
0150
0151
0152 #define PLC_MS(m) ((int)((0x10000L-(m*100000L/2048))))
0153 #define SLOW_TL_MIN PLC_MS(6)
0154 #define SLOW_C_MIN PLC_MS(10)
0155
0156 static const struct plt {
0157 int timer ;
0158 int para ;
0159 } pltm[] = {
0160 { PL_C_MIN, SLOW_C_MIN },
0161 { PL_TL_MIN, SLOW_TL_MIN },
0162 { PL_TB_MIN, TP_TB_MIN },
0163 { PL_T_OUT, TP_T_OUT },
0164 { PL_LC_LENGTH, TP_LC_LENGTH },
0165 { PL_T_SCRUB, TP_T_SCRUB },
0166 { PL_NS_MAX, TP_NS_MAX },
0167 { 0,0 }
0168 } ;
0169
0170
0171
0172
0173 #ifdef SUPERNET_3
0174
0175
0176
0177
0178 static const int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
0179 PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR;
0180 #else
0181
0182
0183
0184 static int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
0185 PL_PCM_ENABLED | PL_SELF_TEST ;
0186 #endif
0187 static const int plc_imsk_act = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
0188 PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR;
0189
0190
0191 static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd);
0192 static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy);
0193 static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy);
0194 static void reset_lem_struct(struct s_phy *phy);
0195 static void plc_init(struct s_smc *smc, int p);
0196 static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold);
0197 static void sm_ph_lem_stop(struct s_smc *smc, int np);
0198 static void sm_ph_linestate(struct s_smc *smc, int phy, int ls);
0199 static void real_init_plc(struct s_smc *smc);
0200
0201
0202
0203
0204
0205 static void start_pcm_timer0(struct s_smc *smc, u_long value, int event,
0206 struct s_phy *phy)
0207 {
0208 phy->timer0_exp = FALSE ;
0209 smt_timer_start(smc,&phy->pcm_timer0,value,
0210 EV_TOKEN(EVENT_PCM+phy->np,event)) ;
0211 }
0212
0213
0214
0215
0216 static void stop_pcm_timer0(struct s_smc *smc, struct s_phy *phy)
0217 {
0218 if (phy->pcm_timer0.tm_active)
0219 smt_timer_stop(smc,&phy->pcm_timer0) ;
0220 }
0221
0222
0223
0224
0225
0226 void pcm_init(struct s_smc *smc)
0227 {
0228 int i ;
0229 int np ;
0230 struct s_phy *phy ;
0231 struct fddi_mib_p *mib ;
0232
0233 for (np = 0,phy = smc->y ; np < NUMPHYS ; np++,phy++) {
0234
0235 mib = phy->mib ;
0236 mib->fddiPORTPCMState = ACTIONS(PC0_OFF) ;
0237 phy->np = np ;
0238 switch (smc->s.sas) {
0239 #ifdef CONCENTRATOR
0240 case SMT_SAS :
0241 mib->fddiPORTMy_Type = (np == PS) ? TS : TM ;
0242 break ;
0243 case SMT_DAS :
0244 mib->fddiPORTMy_Type = (np == PA) ? TA :
0245 (np == PB) ? TB : TM ;
0246 break ;
0247 case SMT_NAC :
0248 mib->fddiPORTMy_Type = TM ;
0249 break;
0250 #else
0251 case SMT_SAS :
0252 mib->fddiPORTMy_Type = (np == PS) ? TS : TNONE ;
0253 mib->fddiPORTHardwarePresent = (np == PS) ? TRUE :
0254 FALSE ;
0255 #ifndef SUPERNET_3
0256 smc->y[PA].mib->fddiPORTPCMState = PC0_OFF ;
0257 #else
0258 smc->y[PB].mib->fddiPORTPCMState = PC0_OFF ;
0259 #endif
0260 break ;
0261 case SMT_DAS :
0262 mib->fddiPORTMy_Type = (np == PB) ? TB : TA ;
0263 break ;
0264 #endif
0265 }
0266
0267
0268
0269 phy->pmd_scramble = 0 ;
0270 switch (phy->pmd_type[PMD_SK_PMD]) {
0271 case 'P' :
0272 mib->fddiPORTPMDClass = MIB_PMDCLASS_MULTI ;
0273 break ;
0274 case 'L' :
0275 mib->fddiPORTPMDClass = MIB_PMDCLASS_LCF ;
0276 break ;
0277 case 'D' :
0278 mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
0279 break ;
0280 case 'S' :
0281 mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
0282 phy->pmd_scramble = TRUE ;
0283 break ;
0284 case 'U' :
0285 mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
0286 phy->pmd_scramble = TRUE ;
0287 break ;
0288 case '1' :
0289 mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE1 ;
0290 break ;
0291 case '2' :
0292 mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE2 ;
0293 break ;
0294 case '3' :
0295 mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE2 ;
0296 break ;
0297 case '4' :
0298 mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE1 ;
0299 break ;
0300 case 'H' :
0301 mib->fddiPORTPMDClass = MIB_PMDCLASS_UNKNOWN ;
0302 break ;
0303 case 'I' :
0304 mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
0305 break ;
0306 case 'G' :
0307 mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
0308 break ;
0309 default:
0310 mib->fddiPORTPMDClass = MIB_PMDCLASS_UNKNOWN ;
0311 break ;
0312 }
0313
0314
0315
0316 switch (mib->fddiPORTMy_Type) {
0317 case TA :
0318 mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
0319 mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
0320 mib->fddiPORTRequestedPaths[2] =
0321 MIB_P_PATH_LOCAL |
0322 MIB_P_PATH_CON_ALTER |
0323 MIB_P_PATH_SEC_PREFER ;
0324 mib->fddiPORTRequestedPaths[3] =
0325 MIB_P_PATH_LOCAL |
0326 MIB_P_PATH_CON_ALTER |
0327 MIB_P_PATH_SEC_PREFER |
0328 MIB_P_PATH_THRU ;
0329 break ;
0330 case TB :
0331 mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
0332 mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
0333 mib->fddiPORTRequestedPaths[2] =
0334 MIB_P_PATH_LOCAL |
0335 MIB_P_PATH_PRIM_PREFER ;
0336 mib->fddiPORTRequestedPaths[3] =
0337 MIB_P_PATH_LOCAL |
0338 MIB_P_PATH_PRIM_PREFER |
0339 MIB_P_PATH_CON_PREFER |
0340 MIB_P_PATH_THRU ;
0341 break ;
0342 case TS :
0343 mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
0344 mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
0345 mib->fddiPORTRequestedPaths[2] =
0346 MIB_P_PATH_LOCAL |
0347 MIB_P_PATH_CON_ALTER |
0348 MIB_P_PATH_PRIM_PREFER ;
0349 mib->fddiPORTRequestedPaths[3] =
0350 MIB_P_PATH_LOCAL |
0351 MIB_P_PATH_CON_ALTER |
0352 MIB_P_PATH_PRIM_PREFER ;
0353 break ;
0354 case TM :
0355 mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
0356 mib->fddiPORTRequestedPaths[2] =
0357 MIB_P_PATH_LOCAL |
0358 MIB_P_PATH_SEC_ALTER |
0359 MIB_P_PATH_PRIM_ALTER ;
0360 mib->fddiPORTRequestedPaths[3] = 0 ;
0361 break ;
0362 }
0363
0364 phy->pc_lem_fail = FALSE ;
0365 mib->fddiPORTPCMStateX = mib->fddiPORTPCMState ;
0366 mib->fddiPORTLCTFail_Ct = 0 ;
0367 mib->fddiPORTBS_Flag = 0 ;
0368 mib->fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
0369 mib->fddiPORTNeighborType = TNONE ;
0370 phy->ls_flag = 0 ;
0371 phy->rc_flag = 0 ;
0372 phy->tc_flag = 0 ;
0373 phy->td_flag = 0 ;
0374 if (np >= PM)
0375 phy->phy_name = '0' + np - PM ;
0376 else
0377 phy->phy_name = 'A' + np ;
0378 phy->wc_flag = FALSE ;
0379 memset((char *)&phy->lem,0,sizeof(struct lem_counter)) ;
0380 reset_lem_struct(phy) ;
0381 memset((char *)&phy->plc,0,sizeof(struct s_plc)) ;
0382 phy->plc.p_state = PS_OFF ;
0383 for (i = 0 ; i < NUMBITS ; i++) {
0384 phy->t_next[i] = 0 ;
0385 }
0386 }
0387 real_init_plc(smc) ;
0388 }
0389
0390 void init_plc(struct s_smc *smc)
0391 {
0392 SK_UNUSED(smc) ;
0393
0394
0395
0396
0397
0398
0399
0400
0401 }
0402
0403 static void real_init_plc(struct s_smc *smc)
0404 {
0405 int p ;
0406
0407 for (p = 0 ; p < NUMPHYS ; p++)
0408 plc_init(smc,p) ;
0409 }
0410
0411 static void plc_init(struct s_smc *smc, int p)
0412 {
0413 int i ;
0414 #ifndef MOT_ELM
0415 int rev ;
0416 #endif
0417
0418
0419 outpw(PLC(p,PL_CNTRL_B),0) ;
0420 outpw(PLC(p,PL_CNTRL_B),PL_PCM_STOP) ;
0421 outpw(PLC(p,PL_CNTRL_A),0) ;
0422
0423
0424
0425
0426 #ifndef MOT_ELM
0427 rev = inpw(PLC(p,PL_STATUS_A)) & PLC_REV_MASK ;
0428 if (rev != PLC_REVISION_A)
0429 #endif
0430 {
0431 if (smc->y[p].pmd_scramble) {
0432 outpw(PLC(p,PL_CNTRL_C),PLCS_CONTROL_C_S) ;
0433 #ifdef MOT_ELM
0434 outpw(PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_S) ;
0435 outpw(PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_S) ;
0436 #endif
0437 }
0438 else {
0439 outpw(PLC(p,PL_CNTRL_C),PLCS_CONTROL_C_U) ;
0440 #ifdef MOT_ELM
0441 outpw(PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_U) ;
0442 outpw(PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_U) ;
0443 #endif
0444 }
0445 }
0446
0447
0448
0449
0450 for ( i = 0 ; pltm[i].timer; i++)
0451 outpw(PLC(p,pltm[i].timer),pltm[i].para) ;
0452
0453 (void)inpw(PLC(p,PL_INTR_EVENT)) ;
0454 plc_clear_irq(smc,p) ;
0455 outpw(PLC(p,PL_INTR_MASK),plc_imsk_na);
0456
0457
0458
0459
0460
0461
0462
0463
0464 #ifndef CONCENTRATOR
0465 if ((smc->s.sas == SMT_SAS) && (p == PS)) {
0466 outpw(PLC(p,PL_CNTRL_B),PL_CLASS_S) ;
0467 }
0468 #endif
0469 }
0470
0471
0472
0473
0474 static void plc_go_state(struct s_smc *smc, int p, int state)
0475 {
0476 HW_PTR port ;
0477 int val ;
0478
0479 SK_UNUSED(smc) ;
0480
0481 port = (HW_PTR) (PLC(p,PL_CNTRL_B)) ;
0482 val = inpw(port) & ~(PL_PCM_CNTRL | PL_MAINT) ;
0483 outpw(port,val) ;
0484 outpw(port,val | state) ;
0485 }
0486
0487
0488
0489
0490 int sm_pm_get_ls(struct s_smc *smc, int phy)
0491 {
0492 int state ;
0493
0494 #ifdef CONCENTRATOR
0495 if (!plc_is_installed(smc,phy))
0496 return PC_QLS;
0497 #endif
0498
0499 state = inpw(PLC(phy,PL_STATUS_A)) & PL_LINE_ST ;
0500 switch(state) {
0501 case PL_L_QLS:
0502 state = PC_QLS ;
0503 break ;
0504 case PL_L_MLS:
0505 state = PC_MLS ;
0506 break ;
0507 case PL_L_HLS:
0508 state = PC_HLS ;
0509 break ;
0510 case PL_L_ILS4:
0511 case PL_L_ILS16:
0512 state = PC_ILS ;
0513 break ;
0514 case PL_L_ALS:
0515 state = PC_LS_PDR ;
0516 break ;
0517 default :
0518 state = PC_LS_NONE ;
0519 }
0520 return state;
0521 }
0522
0523 static int plc_send_bits(struct s_smc *smc, struct s_phy *phy, int len)
0524 {
0525 int np = phy->np ;
0526 int n ;
0527 int i ;
0528
0529 SK_UNUSED(smc) ;
0530
0531
0532 for (i = len-1,n = 0 ; i >= 0 ; i--) {
0533 n = (n<<1) | phy->t_val[phy->bitn+i] ;
0534 }
0535 if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) {
0536 #if 0
0537 printf("PL_PCM_SIGNAL is set\n") ;
0538 #endif
0539 return 1;
0540 }
0541
0542 outpw(PLC(np,PL_VECTOR_LEN),len-1) ;
0543 outpw(PLC(np,PL_XMIT_VECTOR),n) ;
0544 #ifdef DEBUG
0545 #if 1
0546 #ifdef DEBUG_BRD
0547 if (smc->debug.d_plc & 0x80)
0548 #else
0549 if (debug.d_plc & 0x80)
0550 #endif
0551 printf("SIGNALING bit %d .. %d\n",phy->bitn,phy->bitn+len-1) ;
0552 #endif
0553 #endif
0554 return 0;
0555 }
0556
0557
0558
0559
0560 void plc_config_mux(struct s_smc *smc, int mux)
0561 {
0562 if (smc->s.sas != SMT_DAS)
0563 return ;
0564 if (mux == MUX_WRAPB) {
0565 SETMASK(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ;
0566 SETMASK(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP,PL_SC_REM_LOOP) ;
0567 }
0568 else {
0569 CLEAR(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL) ;
0570 CLEAR(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP) ;
0571 }
0572 CLEAR(PLC(PB,PL_CNTRL_B),PL_CONFIG_CNTRL) ;
0573 CLEAR(PLC(PB,PL_CNTRL_A),PL_SC_REM_LOOP) ;
0574 }
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584 void pcm(struct s_smc *smc, const int np, int event)
0585 {
0586 int state ;
0587 int oldstate ;
0588 struct s_phy *phy ;
0589 struct fddi_mib_p *mib ;
0590
0591 #ifndef CONCENTRATOR
0592
0593
0594
0595 if ((np != PS) && (smc->s.sas == SMT_SAS))
0596 return ;
0597 #endif
0598 phy = &smc->y[np] ;
0599 mib = phy->mib ;
0600 oldstate = mib->fddiPORTPCMState ;
0601 do {
0602 DB_PCM("PCM %c: state %s%s, event %s",
0603 phy->phy_name,
0604 mib->fddiPORTPCMState & AFLAG ? "ACTIONS " : "",
0605 pcm_states[mib->fddiPORTPCMState & ~AFLAG],
0606 pcm_events[event]);
0607 state = mib->fddiPORTPCMState ;
0608 pcm_fsm(smc,phy,event) ;
0609 event = 0 ;
0610 } while (state != mib->fddiPORTPCMState) ;
0611
0612
0613
0614
0615
0616
0617 if (state == PC5_SIGNAL)
0618 mib->fddiPORTPCMStateX = PC3_CONNECT ;
0619 else
0620 mib->fddiPORTPCMStateX = state ;
0621
0622 #ifndef SLIM_SMT
0623
0624
0625
0626 if ( mib->fddiPORTPCMState != oldstate &&
0627 ((oldstate == PC8_ACTIVE) || (mib->fddiPORTPCMState == PC8_ACTIVE))) {
0628 smt_srf_event(smc,SMT_EVENT_PORT_PATH_CHANGE,
0629 (int) (INDEX_PORT+ phy->np),0) ;
0630 }
0631 #endif
0632
0633 #ifdef FDDI_MIB
0634
0635
0636 if ( mib->fddiPORTPCMState != oldstate ) {
0637
0638 DB_SNMP ("PCM from %d to %d\n", oldstate, mib->fddiPORTPCMState);
0639 if ( mib->fddiPORTPCMState == PC0_OFF ) {
0640
0641 snmp_fddi_trap (smc, 1, (int) mib->fddiPORTIndex );
0642 } else if ( oldstate == PC0_OFF ) {
0643
0644 snmp_fddi_trap (smc, 2, (int) mib->fddiPORTIndex );
0645 } else if ( mib->fddiPORTPCMState != PC2_TRACE &&
0646 oldstate == PC8_ACTIVE ) {
0647
0648 snmp_fddi_trap (smc, 3, (int) mib->fddiPORTIndex );
0649 } else if ( mib->fddiPORTPCMState == PC8_ACTIVE ) {
0650
0651 snmp_fddi_trap (smc, 4, (int) mib->fddiPORTIndex );
0652 }
0653 }
0654 #endif
0655
0656 pcm_state_change(smc,np,state) ;
0657 }
0658
0659
0660
0661
0662 static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd)
0663 {
0664 int i ;
0665 int np = phy->np ;
0666 struct s_plc *plc ;
0667 struct fddi_mib_p *mib ;
0668 #ifndef MOT_ELM
0669 u_short plc_rev ;
0670 #endif
0671
0672 plc = &phy->plc ;
0673 mib = phy->mib ;
0674
0675
0676
0677
0678 switch (cmd) {
0679 case PC_STOP :
0680
0681 if (mib->fddiPORTPCMState != PC9_MAINT) {
0682 GO_STATE(PC0_OFF) ;
0683 AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
0684 FDDI_PORT_EVENT, (u_long) FDDI_PORT_STOP,
0685 smt_get_port_event_word(smc));
0686 }
0687 return ;
0688 case PC_START :
0689
0690 if (mib->fddiPORTPCMState != PC9_MAINT)
0691 GO_STATE(PC1_BREAK) ;
0692 return ;
0693 case PC_DISABLE :
0694
0695 GO_STATE(PC9_MAINT) ;
0696 AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
0697 FDDI_PORT_EVENT, (u_long) FDDI_PORT_DISABLED,
0698 smt_get_port_event_word(smc));
0699 return ;
0700 case PC_TIMEOUT_LCT :
0701
0702 stop_pcm_timer0(smc,phy) ;
0703 CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
0704
0705 return ;
0706 }
0707
0708 switch(mib->fddiPORTPCMState) {
0709 case ACTIONS(PC0_OFF) :
0710 stop_pcm_timer0(smc,phy) ;
0711 outpw(PLC(np,PL_CNTRL_A),0) ;
0712 CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
0713 CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
0714 sm_ph_lem_stop(smc,np) ;
0715 phy->cf_loop = FALSE ;
0716 phy->cf_join = FALSE ;
0717 queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
0718 plc_go_state(smc,np,PL_PCM_STOP) ;
0719 mib->fddiPORTConnectState = PCM_DISABLED ;
0720 ACTIONS_DONE() ;
0721 break ;
0722 case PC0_OFF:
0723
0724 if (cmd == PC_MAINT) {
0725 GO_STATE(PC9_MAINT) ;
0726 break ;
0727 }
0728 break ;
0729 case ACTIONS(PC1_BREAK) :
0730
0731 stop_pcm_timer0(smc,phy) ;
0732 ACTIONS_DONE() ;
0733 plc_go_state(smc,np,0) ;
0734 CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
0735 CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
0736 sm_ph_lem_stop(smc,np) ;
0737
0738
0739
0740 #if 0
0741 if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) {
0742 plc_go_state(smc,np,PL_PCM_STOP) ;
0743
0744 }
0745 #endif
0746
0747
0748
0749 plc_go_state(smc,np,PL_PCM_STOP) ;
0750
0751 if (mib->fddiPORTPC_Withhold == PC_WH_NONE)
0752 mib->fddiPORTConnectState = PCM_CONNECTING ;
0753 phy->cf_loop = FALSE ;
0754 phy->cf_join = FALSE ;
0755 queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
0756 phy->ls_flag = FALSE ;
0757 phy->pc_mode = PM_NONE ;
0758 phy->bitn = 0 ;
0759 for (i = 0 ; i < 3 ; i++)
0760 pc_tcode_actions(smc,i,phy) ;
0761
0762
0763 outpw(PLC(np,PL_INTR_MASK),plc_imsk_na) ;
0764
0765
0766
0767
0768
0769
0770 (void)inpw(PLC(np,PL_INTR_EVENT)) ;
0771 #ifndef MOT_ELM
0772
0773 plc_rev = inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK ;
0774
0775 if (plc_rev != PLC_REV_SN3)
0776 #endif
0777 {
0778
0779
0780
0781
0782 if (plc_send_bits(smc,phy,3)) {
0783 return ;
0784 }
0785 }
0786
0787
0788
0789
0790
0791
0792
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802 plc_go_state(smc,np,PL_PCM_START) ;
0803
0804
0805
0806
0807 #ifdef MOT_ELM
0808 if (!(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL))
0809 #else
0810 if (((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) !=
0811 PLC_REVISION_A) &&
0812 !(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL))
0813 #endif
0814 {
0815
0816
0817
0818
0819 (void) plc_send_bits(smc,phy,3) ;
0820 }
0821
0822
0823
0824
0825 GO_STATE(PC5_SIGNAL) ;
0826 plc->p_state = PS_BIT3 ;
0827 plc->p_bits = 3 ;
0828 plc->p_start = 0 ;
0829
0830 break ;
0831 case PC1_BREAK :
0832 break ;
0833 case ACTIONS(PC2_TRACE) :
0834 plc_go_state(smc,np,PL_PCM_TRACE) ;
0835 ACTIONS_DONE() ;
0836 break ;
0837 case PC2_TRACE :
0838 break ;
0839
0840 case PC3_CONNECT :
0841 case PC4_NEXT :
0842 break ;
0843
0844 case ACTIONS(PC5_SIGNAL) :
0845 ACTIONS_DONE() ;
0846 fallthrough;
0847 case PC5_SIGNAL :
0848 if ((cmd != PC_SIGNAL) && (cmd != PC_TIMEOUT_LCT))
0849 break ;
0850 switch (plc->p_state) {
0851 case PS_BIT3 :
0852 for (i = 0 ; i <= 2 ; i++)
0853 pc_rcode_actions(smc,i,phy) ;
0854 pc_tcode_actions(smc,3,phy) ;
0855 plc->p_state = PS_BIT4 ;
0856 plc->p_bits = 1 ;
0857 plc->p_start = 3 ;
0858 phy->bitn = 3 ;
0859 if (plc_send_bits(smc,phy,1)) {
0860 return ;
0861 }
0862 break ;
0863 case PS_BIT4 :
0864 pc_rcode_actions(smc,3,phy) ;
0865 for (i = 4 ; i <= 6 ; i++)
0866 pc_tcode_actions(smc,i,phy) ;
0867 plc->p_state = PS_BIT7 ;
0868 plc->p_bits = 3 ;
0869 plc->p_start = 4 ;
0870 phy->bitn = 4 ;
0871 if (plc_send_bits(smc,phy,3)) {
0872 return ;
0873 }
0874 break ;
0875 case PS_BIT7 :
0876 for (i = 3 ; i <= 6 ; i++)
0877 pc_rcode_actions(smc,i,phy) ;
0878 plc->p_state = PS_LCT ;
0879 plc->p_bits = 0 ;
0880 plc->p_start = 7 ;
0881 phy->bitn = 7 ;
0882 sm_ph_lem_start(smc,np,(int)smc->s.lct_short) ;
0883
0884 i = inpw(PLC(np,PL_CNTRL_B)) & ~PL_PC_LOOP ;
0885 outpw(PLC(np,PL_CNTRL_B),i) ;
0886 outpw(PLC(np,PL_CNTRL_B),i | PL_RLBP) ;
0887 break ;
0888 case PS_LCT :
0889
0890 pc_tcode_actions(smc,7,phy) ;
0891
0892
0893
0894 plc->p_state = PS_BIT8 ;
0895 plc->p_bits = 1 ;
0896 plc->p_start = 7 ;
0897 phy->bitn = 7 ;
0898 if (plc_send_bits(smc,phy,1)) {
0899 return ;
0900 }
0901 break ;
0902 case PS_BIT8 :
0903
0904 pc_rcode_actions(smc,7,phy) ;
0905 if (phy->t_val[7] || phy->r_val[7]) {
0906 plc_go_state(smc,np,PL_PCM_STOP) ;
0907 GO_STATE(PC1_BREAK) ;
0908 break ;
0909 }
0910 for (i = 8 ; i <= 9 ; i++)
0911 pc_tcode_actions(smc,i,phy) ;
0912 plc->p_state = PS_JOIN ;
0913 plc->p_bits = 2 ;
0914 plc->p_start = 8 ;
0915 phy->bitn = 8 ;
0916 if (plc_send_bits(smc,phy,2)) {
0917 return ;
0918 }
0919 break ;
0920 case PS_JOIN :
0921 for (i = 8 ; i <= 9 ; i++)
0922 pc_rcode_actions(smc,i,phy) ;
0923 plc->p_state = PS_ACTIVE ;
0924 GO_STATE(PC6_JOIN) ;
0925 break ;
0926 }
0927 break ;
0928
0929 case ACTIONS(PC6_JOIN) :
0930
0931
0932
0933 if (smc->s.sas == SMT_DAS && np == PB &&
0934 (smc->y[PA].pc_mode == PM_TREE ||
0935 smc->y[PB].pc_mode == PM_TREE)) {
0936 SETMASK(PLC(np,PL_CNTRL_A),
0937 PL_SC_REM_LOOP,PL_SC_REM_LOOP) ;
0938 SETMASK(PLC(np,PL_CNTRL_B),
0939 PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ;
0940 }
0941 SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ;
0942 SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ;
0943 ACTIONS_DONE() ;
0944 cmd = 0 ;
0945 fallthrough;
0946 case PC6_JOIN :
0947 switch (plc->p_state) {
0948 case PS_ACTIVE:
0949
0950 if (!phy->cf_join) {
0951 phy->cf_join = TRUE ;
0952 queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
0953 }
0954 if (cmd == PC_JOIN)
0955 GO_STATE(PC8_ACTIVE) ;
0956
0957 if (cmd == PC_TRACE) {
0958 GO_STATE(PC2_TRACE) ;
0959 break ;
0960 }
0961 break ;
0962 }
0963 break ;
0964
0965 case PC7_VERIFY :
0966 break ;
0967
0968 case ACTIONS(PC8_ACTIVE) :
0969
0970
0971
0972 sm_ph_lem_start(smc,(int)phy->np,LCT_LEM_MAX) ;
0973
0974 phy->tr_flag = FALSE ;
0975 mib->fddiPORTConnectState = PCM_ACTIVE ;
0976
0977
0978 outpw(PLC(np,PL_INTR_MASK),plc_imsk_act) ;
0979
0980 ACTIONS_DONE() ;
0981 break ;
0982 case PC8_ACTIVE :
0983
0984
0985 if (cmd == PC_TRACE) {
0986 GO_STATE(PC2_TRACE) ;
0987 break ;
0988 }
0989
0990
0991 break ;
0992 case ACTIONS(PC9_MAINT) :
0993 stop_pcm_timer0(smc,phy) ;
0994 CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
0995 CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
0996 CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ;
0997 sm_ph_lem_stop(smc,np) ;
0998 phy->cf_loop = FALSE ;
0999 phy->cf_join = FALSE ;
1000 queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
1001 plc_go_state(smc,np,PL_PCM_STOP) ;
1002 mib->fddiPORTConnectState = PCM_DISABLED ;
1003 SETMASK(PLC(np,PL_CNTRL_B),PL_MAINT,PL_MAINT) ;
1004 sm_ph_linestate(smc,np,(int) MIB2LS(mib->fddiPORTMaint_LS)) ;
1005 outpw(PLC(np,PL_CNTRL_A),PL_SC_BYPASS) ;
1006 ACTIONS_DONE() ;
1007 break ;
1008 case PC9_MAINT :
1009 DB_PCMN(1, "PCM %c : MAINT", phy->phy_name);
1010
1011 if (cmd == PC_ENABLE) {
1012 GO_STATE(PC0_OFF) ;
1013 break ;
1014 }
1015 break ;
1016
1017 default:
1018 SMT_PANIC(smc,SMT_E0118, SMT_E0118_MSG) ;
1019 break ;
1020 }
1021 }
1022
1023
1024
1025
1026 static void sm_ph_linestate(struct s_smc *smc, int phy, int ls)
1027 {
1028 int cntrl ;
1029
1030 SK_UNUSED(smc) ;
1031
1032 cntrl = (inpw(PLC(phy,PL_CNTRL_B)) & ~PL_MAINT_LS) |
1033 PL_PCM_STOP | PL_MAINT ;
1034 switch(ls) {
1035 case PC_QLS:
1036 cntrl |= PL_M_QUI0 ;
1037 break ;
1038 case PC_MLS:
1039 cntrl |= PL_M_MASTR ;
1040 break ;
1041 case PC_HLS:
1042 cntrl |= PL_M_HALT ;
1043 break ;
1044 default :
1045 case PC_ILS:
1046 cntrl |= PL_M_IDLE ;
1047 break ;
1048 case PC_LS_PDR:
1049 cntrl |= PL_M_TPDR ;
1050 break ;
1051 }
1052 outpw(PLC(phy,PL_CNTRL_B),cntrl) ;
1053 }
1054
1055 static void reset_lem_struct(struct s_phy *phy)
1056 {
1057 struct lem_counter *lem = &phy->lem ;
1058
1059 phy->mib->fddiPORTLer_Estimate = 15 ;
1060 lem->lem_float_ber = 15 * 100 ;
1061 }
1062
1063
1064
1065
1066 static void lem_evaluate(struct s_smc *smc, struct s_phy *phy)
1067 {
1068 int ber ;
1069 u_long errors ;
1070 struct lem_counter *lem = &phy->lem ;
1071 struct fddi_mib_p *mib ;
1072 int cond ;
1073
1074 mib = phy->mib ;
1075
1076 if (!lem->lem_on)
1077 return ;
1078
1079 errors = inpw(PLC(((int) phy->np),PL_LINK_ERR_CTR)) ;
1080 lem->lem_errors += errors ;
1081 mib->fddiPORTLem_Ct += errors ;
1082
1083 errors = lem->lem_errors ;
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094 if (!errors) ber = 15 ;
1095 else if (errors <= 9) ber = 9 ;
1096 else if (errors <= 99) ber = 8 ;
1097 else if (errors <= 999) ber = 7 ;
1098 else if (errors <= 9999) ber = 6 ;
1099 else if (errors <= 99999) ber = 5 ;
1100 else if (errors <= 999999) ber = 4 ;
1101 else if (errors <= 9999999) ber = 3 ;
1102 else if (errors <= 99999999) ber = 2 ;
1103 else if (errors <= 999999999) ber = 1 ;
1104 else ber = 0 ;
1105
1106
1107
1108
1109 ber *= 100 ;
1110 lem->lem_float_ber = lem->lem_float_ber * 7 + ber * 3 ;
1111 lem->lem_float_ber /= 10 ;
1112 mib->fddiPORTLer_Estimate = lem->lem_float_ber / 100 ;
1113 if (mib->fddiPORTLer_Estimate < 4) {
1114 mib->fddiPORTLer_Estimate = 4 ;
1115 }
1116
1117 if (lem->lem_errors) {
1118 DB_PCMN(1, "LEM %c :", phy->np == PB ? 'B' : 'A');
1119 DB_PCMN(1, "errors : %ld", lem->lem_errors);
1120 DB_PCMN(1, "sum_errors : %ld", mib->fddiPORTLem_Ct);
1121 DB_PCMN(1, "current BER : 10E-%d", ber / 100);
1122 DB_PCMN(1, "float BER : 10E-(%d/100)", lem->lem_float_ber);
1123 DB_PCMN(1, "avg. BER : 10E-%d", mib->fddiPORTLer_Estimate);
1124 }
1125
1126 lem->lem_errors = 0L ;
1127
1128 #ifndef SLIM_SMT
1129 cond = (mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Alarm) ?
1130 TRUE : FALSE ;
1131 #ifdef SMT_EXT_CUTOFF
1132 smt_ler_alarm_check(smc,phy,cond) ;
1133 #endif
1134 if (cond != mib->fddiPORTLerFlag) {
1135 smt_srf_event(smc,SMT_COND_PORT_LER,
1136 (int) (INDEX_PORT+ phy->np) ,cond) ;
1137 }
1138 #endif
1139
1140 if ( mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Cutoff) {
1141 phy->pc_lem_fail = TRUE ;
1142 mib->fddiPORTLem_Reject_Ct++ ;
1143
1144
1145
1146
1147 lem->lem_float_ber += 2*100 ;
1148
1149
1150 #ifdef CONCENTRATOR
1151 DB_PCMN(1, "PCM: LER cutoff on port %d cutoff %d",
1152 phy->np, mib->fddiPORTLer_Cutoff);
1153 #endif
1154 #ifdef SMT_EXT_CUTOFF
1155 smt_port_off_event(smc,phy->np);
1156 #else
1157 queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ;
1158 #endif
1159 }
1160 }
1161
1162
1163
1164
1165 void sm_lem_evaluate(struct s_smc *smc)
1166 {
1167 int np ;
1168
1169 for (np = 0 ; np < NUMPHYS ; np++)
1170 lem_evaluate(smc,&smc->y[np]) ;
1171 }
1172
1173 static void lem_check_lct(struct s_smc *smc, struct s_phy *phy)
1174 {
1175 struct lem_counter *lem = &phy->lem ;
1176 struct fddi_mib_p *mib ;
1177 int errors ;
1178
1179 mib = phy->mib ;
1180
1181 phy->pc_lem_fail = FALSE ;
1182 errors = inpw(PLC(((int)phy->np),PL_LINK_ERR_CTR)) ;
1183 lem->lem_errors += errors ;
1184 mib->fddiPORTLem_Ct += errors ;
1185 if (lem->lem_errors) {
1186 switch(phy->lc_test) {
1187 case LC_SHORT:
1188 if (lem->lem_errors >= smc->s.lct_short)
1189 phy->pc_lem_fail = TRUE ;
1190 break ;
1191 case LC_MEDIUM:
1192 if (lem->lem_errors >= smc->s.lct_medium)
1193 phy->pc_lem_fail = TRUE ;
1194 break ;
1195 case LC_LONG:
1196 if (lem->lem_errors >= smc->s.lct_long)
1197 phy->pc_lem_fail = TRUE ;
1198 break ;
1199 case LC_EXTENDED:
1200 if (lem->lem_errors >= smc->s.lct_extended)
1201 phy->pc_lem_fail = TRUE ;
1202 break ;
1203 }
1204 DB_PCMN(1, " >>errors : %lu", lem->lem_errors);
1205 }
1206 if (phy->pc_lem_fail) {
1207 mib->fddiPORTLCTFail_Ct++ ;
1208 mib->fddiPORTLem_Reject_Ct++ ;
1209 }
1210 else
1211 mib->fddiPORTLCTFail_Ct = 0 ;
1212 }
1213
1214
1215
1216
1217 static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold)
1218 {
1219 struct lem_counter *lem = &smc->y[np].lem ;
1220
1221 lem->lem_on = 1 ;
1222 lem->lem_errors = 0L ;
1223
1224
1225
1226
1227
1228 outpw(PLC(np,PL_LE_THRESHOLD),threshold) ;
1229 (void)inpw(PLC(np,PL_LINK_ERR_CTR)) ;
1230
1231
1232 SETMASK(PLC(np,PL_INTR_MASK),PL_LE_CTR,PL_LE_CTR) ;
1233 }
1234
1235 static void sm_ph_lem_stop(struct s_smc *smc, int np)
1236 {
1237 struct lem_counter *lem = &smc->y[np].lem ;
1238
1239 lem->lem_on = 0 ;
1240 CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ;
1241 }
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252 static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy)
1253 {
1254 struct fddi_mib_p *mib ;
1255
1256 mib = phy->mib ;
1257
1258 DB_PCMN(1, "SIG rec %x %x:", bit, phy->r_val[bit]);
1259 bit++ ;
1260
1261 switch(bit) {
1262 case 0:
1263 case 1:
1264 case 2:
1265 break ;
1266 case 3 :
1267 if (phy->r_val[1] == 0 && phy->r_val[2] == 0)
1268 mib->fddiPORTNeighborType = TA ;
1269 else if (phy->r_val[1] == 0 && phy->r_val[2] == 1)
1270 mib->fddiPORTNeighborType = TB ;
1271 else if (phy->r_val[1] == 1 && phy->r_val[2] == 0)
1272 mib->fddiPORTNeighborType = TS ;
1273 else if (phy->r_val[1] == 1 && phy->r_val[2] == 1)
1274 mib->fddiPORTNeighborType = TM ;
1275 break ;
1276 case 4:
1277 if (mib->fddiPORTMy_Type == TM &&
1278 mib->fddiPORTNeighborType == TM) {
1279 DB_PCMN(1, "PCM %c : E100 withhold M-M",
1280 phy->phy_name);
1281 mib->fddiPORTPC_Withhold = PC_WH_M_M ;
1282 RS_SET(smc,RS_EVENT) ;
1283 }
1284 else if (phy->t_val[3] || phy->r_val[3]) {
1285 mib->fddiPORTPC_Withhold = PC_WH_NONE ;
1286 if (mib->fddiPORTMy_Type == TM ||
1287 mib->fddiPORTNeighborType == TM)
1288 phy->pc_mode = PM_TREE ;
1289 else
1290 phy->pc_mode = PM_PEER ;
1291
1292
1293 all_selection_criteria (smc);
1294
1295 if (phy->wc_flag) {
1296 mib->fddiPORTPC_Withhold = PC_WH_PATH ;
1297 }
1298 }
1299 else {
1300 mib->fddiPORTPC_Withhold = PC_WH_OTHER ;
1301 RS_SET(smc,RS_EVENT) ;
1302 DB_PCMN(1, "PCM %c : E101 withhold other",
1303 phy->phy_name);
1304 }
1305 phy->twisted = ((mib->fddiPORTMy_Type != TS) &&
1306 (mib->fddiPORTMy_Type != TM) &&
1307 (mib->fddiPORTNeighborType ==
1308 mib->fddiPORTMy_Type)) ;
1309 if (phy->twisted) {
1310 DB_PCMN(1, "PCM %c : E102 !!! TWISTED !!!",
1311 phy->phy_name);
1312 }
1313 break ;
1314 case 5 :
1315 break ;
1316 case 6:
1317 if (phy->t_val[4] || phy->r_val[4]) {
1318 if ((phy->t_val[4] && phy->t_val[5]) ||
1319 (phy->r_val[4] && phy->r_val[5]) )
1320 phy->lc_test = LC_EXTENDED ;
1321 else
1322 phy->lc_test = LC_LONG ;
1323 }
1324 else if (phy->t_val[5] || phy->r_val[5])
1325 phy->lc_test = LC_MEDIUM ;
1326 else
1327 phy->lc_test = LC_SHORT ;
1328 switch (phy->lc_test) {
1329 case LC_SHORT :
1330 outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LENGTH ) ;
1331 phy->t_next[7] = smc->s.pcm_lc_short ;
1332 break ;
1333 case LC_MEDIUM :
1334 outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LONGLN ) ;
1335 phy->t_next[7] = smc->s.pcm_lc_medium ;
1336 break ;
1337 case LC_LONG :
1338 SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ;
1339 phy->t_next[7] = smc->s.pcm_lc_long ;
1340 break ;
1341 case LC_EXTENDED :
1342 SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ;
1343 phy->t_next[7] = smc->s.pcm_lc_extended ;
1344 break ;
1345 }
1346 if (phy->t_next[7] > smc->s.pcm_lc_medium) {
1347 start_pcm_timer0(smc,phy->t_next[7],PC_TIMEOUT_LCT,phy);
1348 }
1349 DB_PCMN(1, "LCT timer = %ld us", phy->t_next[7]);
1350 phy->t_next[9] = smc->s.pcm_t_next_9 ;
1351 break ;
1352 case 7:
1353 if (phy->t_val[6]) {
1354 phy->cf_loop = TRUE ;
1355 }
1356 phy->td_flag = TRUE ;
1357 break ;
1358 case 8:
1359 if (phy->t_val[7] || phy->r_val[7]) {
1360 DB_PCMN(1, "PCM %c : E103 LCT fail %s",
1361 phy->phy_name,
1362 phy->t_val[7] ? "local" : "remote");
1363 queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ;
1364 }
1365 break ;
1366 case 9:
1367 if (phy->t_val[8] || phy->r_val[8]) {
1368 if (phy->t_val[8])
1369 phy->cf_loop = TRUE ;
1370 phy->td_flag = TRUE ;
1371 }
1372 break ;
1373 case 10:
1374 if (phy->r_val[9]) {
1375 ;
1376 mib->fddiPORTMacIndicated.R_val = TRUE ;
1377 }
1378 else {
1379 ;
1380 mib->fddiPORTMacIndicated.R_val = FALSE ;
1381 }
1382 break ;
1383 }
1384 }
1385
1386
1387
1388
1389 static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy)
1390 {
1391 int np = phy->np ;
1392 struct fddi_mib_p *mib ;
1393
1394 mib = phy->mib ;
1395
1396 switch(bit) {
1397 case 0:
1398 phy->t_val[0] = 0 ;
1399 break ;
1400 case 1:
1401 if (mib->fddiPORTMy_Type == TS || mib->fddiPORTMy_Type == TM)
1402 phy->t_val[1] = 1 ;
1403 else
1404 phy->t_val[1] = 0 ;
1405 break ;
1406 case 2 :
1407 if (mib->fddiPORTMy_Type == TB || mib->fddiPORTMy_Type == TM)
1408 phy->t_val[2] = 1 ;
1409 else
1410 phy->t_val[2] = 0 ;
1411 break ;
1412 case 3:
1413 {
1414 int type,ne ;
1415 int policy ;
1416
1417 type = mib->fddiPORTMy_Type ;
1418 ne = mib->fddiPORTNeighborType ;
1419 policy = smc->mib.fddiSMTConnectionPolicy ;
1420
1421 phy->t_val[3] = 1 ;
1422 switch (type) {
1423 case TA :
1424 if (
1425 ((policy & POLICY_AA) && ne == TA) ||
1426 ((policy & POLICY_AB) && ne == TB) ||
1427 ((policy & POLICY_AS) && ne == TS) ||
1428 ((policy & POLICY_AM) && ne == TM) )
1429 phy->t_val[3] = 0 ;
1430 break ;
1431 case TB :
1432 if (
1433 ((policy & POLICY_BA) && ne == TA) ||
1434 ((policy & POLICY_BB) && ne == TB) ||
1435 ((policy & POLICY_BS) && ne == TS) ||
1436 ((policy & POLICY_BM) && ne == TM) )
1437 phy->t_val[3] = 0 ;
1438 break ;
1439 case TS :
1440 if (
1441 ((policy & POLICY_SA) && ne == TA) ||
1442 ((policy & POLICY_SB) && ne == TB) ||
1443 ((policy & POLICY_SS) && ne == TS) ||
1444 ((policy & POLICY_SM) && ne == TM) )
1445 phy->t_val[3] = 0 ;
1446 break ;
1447 case TM :
1448 if ( ne == TM ||
1449 ((policy & POLICY_MA) && ne == TA) ||
1450 ((policy & POLICY_MB) && ne == TB) ||
1451 ((policy & POLICY_MS) && ne == TS) ||
1452 ((policy & POLICY_MM) && ne == TM) )
1453 phy->t_val[3] = 0 ;
1454 break ;
1455 }
1456 #ifndef SLIM_SMT
1457
1458
1459
1460 if ( (type == TA && ne == TA ) ||
1461 (type == TA && ne == TS ) ||
1462 (type == TB && ne == TB ) ||
1463 (type == TB && ne == TS ) ||
1464 (type == TS && ne == TA ) ||
1465 (type == TS && ne == TB ) ) {
1466 smt_srf_event(smc,SMT_EVENT_PORT_CONNECTION,
1467 (int) (INDEX_PORT+ phy->np) ,0) ;
1468 }
1469 #endif
1470 }
1471 break ;
1472 case 4:
1473 if (mib->fddiPORTPC_Withhold == PC_WH_NONE) {
1474 if (phy->pc_lem_fail) {
1475 phy->t_val[4] = 1 ;
1476 phy->t_val[5] = 0 ;
1477 }
1478 else {
1479 phy->t_val[4] = 0 ;
1480 if (mib->fddiPORTLCTFail_Ct > 0)
1481 phy->t_val[5] = 1 ;
1482 else
1483 phy->t_val[5] = 0 ;
1484
1485
1486
1487
1488
1489
1490 if (phy->wc_flag)
1491 phy->t_val[5] = 1 ;
1492 }
1493 mib->fddiPORTConnectState = PCM_CONNECTING ;
1494 }
1495 else {
1496 mib->fddiPORTConnectState = PCM_STANDBY ;
1497 phy->t_val[4] = 1 ;
1498 phy->t_val[5] = 1 ;
1499 }
1500 break ;
1501 case 5:
1502 break ;
1503 case 6:
1504
1505 phy->t_val[6] = 0 ;
1506 break ;
1507 case 7:
1508 phy->cf_loop = FALSE ;
1509 lem_check_lct(smc,phy) ;
1510 if (phy->pc_lem_fail) {
1511 DB_PCMN(1, "PCM %c : E104 LCT failed", phy->phy_name);
1512 phy->t_val[7] = 1 ;
1513 }
1514 else
1515 phy->t_val[7] = 0 ;
1516 break ;
1517 case 8:
1518 phy->t_val[8] = 0 ;
1519 break ;
1520 case 9:
1521 phy->cf_loop = 0 ;
1522 if ((mib->fddiPORTPC_Withhold != PC_WH_NONE) ||
1523 ((smc->s.sas == SMT_DAS) && (phy->wc_flag))) {
1524 queue_event(smc,EVENT_PCM+np,PC_START) ;
1525 break ;
1526 }
1527 phy->t_val[9] = FALSE ;
1528 switch (smc->s.sas) {
1529 case SMT_DAS :
1530
1531
1532
1533 if (phy->pc_mode == PM_TREE) {
1534 if ((np == PB) || ((np == PA) &&
1535 (smc->y[PB].mib->fddiPORTConnectState !=
1536 PCM_ACTIVE)))
1537 phy->t_val[9] = TRUE ;
1538 }
1539 else {
1540 if (np == PB)
1541 phy->t_val[9] = TRUE ;
1542 }
1543 break ;
1544 case SMT_SAS :
1545 if (np == PS)
1546 phy->t_val[9] = TRUE ;
1547 break ;
1548 #ifdef CONCENTRATOR
1549 case SMT_NAC :
1550
1551
1552
1553 if (np == PB)
1554 phy->t_val[9] = TRUE ;
1555 break ;
1556 #endif
1557 }
1558 mib->fddiPORTMacIndicated.T_val = phy->t_val[9] ;
1559 break ;
1560 }
1561 DB_PCMN(1, "SIG snd %x %x:", bit, phy->t_val[bit]);
1562 }
1563
1564
1565
1566
1567 int pcm_status_twisted(struct s_smc *smc)
1568 {
1569 int twist = 0 ;
1570 if (smc->s.sas != SMT_DAS)
1571 return 0;
1572 if (smc->y[PA].twisted && (smc->y[PA].mib->fddiPORTPCMState == PC8_ACTIVE))
1573 twist |= 1 ;
1574 if (smc->y[PB].twisted && (smc->y[PB].mib->fddiPORTPCMState == PC8_ACTIVE))
1575 twist |= 2 ;
1576 return twist;
1577 }
1578
1579
1580
1581
1582
1583
1584
1585
1586 void pcm_status_state(struct s_smc *smc, int np, int *type, int *state,
1587 int *remote, int *mac)
1588 {
1589 struct s_phy *phy = &smc->y[np] ;
1590 struct fddi_mib_p *mib ;
1591
1592 mib = phy->mib ;
1593
1594
1595 *mac = 0 ;
1596 *type = mib->fddiPORTMy_Type ;
1597 *state = mib->fddiPORTConnectState ;
1598 *remote = mib->fddiPORTNeighborType ;
1599
1600 switch(mib->fddiPORTPCMState) {
1601 case PC8_ACTIVE :
1602 *mac = mib->fddiPORTMacIndicated.R_val ;
1603 break ;
1604 }
1605 }
1606
1607
1608
1609
1610 int pcm_rooted_station(struct s_smc *smc)
1611 {
1612 int n ;
1613
1614 for (n = 0 ; n < NUMPHYS ; n++) {
1615 if (smc->y[n].mib->fddiPORTPCMState == PC8_ACTIVE &&
1616 smc->y[n].mib->fddiPORTNeighborType == TM)
1617 return 0;
1618 }
1619 return 1;
1620 }
1621
1622
1623
1624
1625 void plc_irq(struct s_smc *smc, int np, unsigned int cmd)
1626
1627 {
1628 struct s_phy *phy = &smc->y[np] ;
1629 struct s_plc *plc = &phy->plc ;
1630 int n ;
1631 #ifdef SUPERNET_3
1632 int corr_mask ;
1633 #endif
1634 int i ;
1635
1636 if (np >= smc->s.numphys) {
1637 plc->soft_err++ ;
1638 return ;
1639 }
1640 if (cmd & PL_EBUF_ERR) {
1641
1642
1643
1644 if (!plc->ebuf_cont && phy->mib->fddiPORTPCMState == PC8_ACTIVE){
1645
1646
1647
1648
1649
1650
1651 phy->mib->fddiPORTEBError_Ct ++ ;
1652
1653 }
1654
1655 plc->ebuf_err++ ;
1656 if (plc->ebuf_cont <= 1000) {
1657
1658
1659
1660
1661 plc->ebuf_cont++ ;
1662 }
1663
1664 #ifdef SUPERNET_3
1665 if (plc->ebuf_cont == 1000 &&
1666 ((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) ==
1667 PLC_REV_SN3)) {
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677 corr_mask = (plc_imsk_na & ~PL_EBUF_ERR) ;
1678 outpw(PLC(np,PL_INTR_MASK),corr_mask);
1679
1680
1681
1682
1683
1684 queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
1685
1686
1687
1688
1689 SMT_ERR_LOG(smc,SMT_E0136, SMT_E0136_MSG) ;
1690
1691
1692
1693
1694 drv_reset_indication(smc) ;
1695 }
1696 #endif
1697 } else {
1698
1699 plc->ebuf_cont = 0 ;
1700 }
1701 if (cmd & PL_PHYINV) {
1702 plc->phyinv++ ;
1703 }
1704 if (cmd & PL_VSYM_CTR) {
1705 plc->vsym_ctr++ ;
1706 }
1707 if (cmd & PL_MINI_CTR) {
1708 plc->mini_ctr++ ;
1709 }
1710 if (cmd & PL_LE_CTR) {
1711 int j ;
1712
1713
1714
1715
1716 j = inpw(PLC(np,PL_LE_THRESHOLD)) ;
1717 i = inpw(PLC(np,PL_LINK_ERR_CTR)) ;
1718
1719 if (i < j) {
1720
1721 i += 256 ;
1722 }
1723
1724 if (phy->lem.lem_on) {
1725
1726
1727
1728 phy->lem.lem_errors += i ;
1729 phy->mib->fddiPORTLem_Ct += i ;
1730 }
1731 }
1732 if (cmd & PL_TPC_EXPIRED) {
1733 if (plc->p_state == PS_LCT) {
1734
1735
1736
1737 ;
1738 }
1739 plc->tpc_exp++ ;
1740 }
1741 if (cmd & PL_LS_MATCH) {
1742 switch (inpw(PLC(np,PL_CNTRL_B)) & PL_MATCH_LS) {
1743 case PL_I_IDLE : phy->curr_ls = PC_ILS ; break ;
1744 case PL_I_HALT : phy->curr_ls = PC_HLS ; break ;
1745 case PL_I_MASTR : phy->curr_ls = PC_MLS ; break ;
1746 case PL_I_QUIET : phy->curr_ls = PC_QLS ; break ;
1747 }
1748 }
1749 if (cmd & PL_PCM_BREAK) {
1750 int reason;
1751
1752 reason = inpw(PLC(np,PL_STATUS_B)) & PL_BREAK_REASON ;
1753
1754 switch (reason) {
1755 case PL_B_PCS : plc->b_pcs++ ; break ;
1756 case PL_B_TPC : plc->b_tpc++ ; break ;
1757 case PL_B_TNE : plc->b_tne++ ; break ;
1758 case PL_B_QLS : plc->b_qls++ ; break ;
1759 case PL_B_ILS : plc->b_ils++ ; break ;
1760 case PL_B_HLS : plc->b_hls++ ; break ;
1761 }
1762
1763
1764 DB_PCMN(1, "PLC %d: MDcF = %x", np, smc->e.DisconnectFlag);
1765 if (smc->e.DisconnectFlag == FALSE) {
1766 DB_PCMN(1, "PLC %d: restart (reason %x)", np, reason);
1767 queue_event(smc,EVENT_PCM+np,PC_START) ;
1768 }
1769 else {
1770 DB_PCMN(1, "PLC %d: NO!! restart (reason %x)",
1771 np, reason);
1772 }
1773 return ;
1774 }
1775
1776
1777
1778 if (cmd & PL_PCM_CODE) {
1779 queue_event(smc,EVENT_PCM+np,PC_SIGNAL) ;
1780 n = inpw(PLC(np,PL_RCV_VECTOR)) ;
1781 for (i = 0 ; i < plc->p_bits ; i++) {
1782 phy->r_val[plc->p_start+i] = n & 1 ;
1783 n >>= 1 ;
1784 }
1785 }
1786 else if (cmd & PL_PCM_ENABLED) {
1787 queue_event(smc,EVENT_PCM+np,PC_JOIN) ;
1788 }
1789 if (cmd & PL_TRACE_PROP) {
1790
1791 if (!phy->tr_flag) {
1792 DB_PCMN(1, "PCM : irq TRACE_PROP %d %d",
1793 np, smc->mib.fddiSMTECMState);
1794 phy->tr_flag = TRUE ;
1795 smc->e.trace_prop |= ENTITY_BIT(ENTITY_PHY(np)) ;
1796 queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ;
1797 }
1798 }
1799
1800
1801
1802
1803 if ((cmd & PL_SELF_TEST) && (phy->mib->fddiPORTPCMState == PC2_TRACE)) {
1804
1805 if (smc->e.path_test == PT_PASSED) {
1806 DB_PCMN(1, "PCM : state = %s %d",
1807 get_pcmstate(smc, np),
1808 phy->mib->fddiPORTPCMState);
1809
1810 smc->e.path_test = PT_PENDING ;
1811 queue_event(smc,EVENT_ECM,EC_PATH_TEST) ;
1812 }
1813 }
1814 if (cmd & PL_TNE_EXPIRED) {
1815
1816 if (phy->mib->fddiPORTPCMState == PC8_ACTIVE) {
1817 if (!phy->tr_flag) {
1818 DB_PCMN(1, "PCM %c : PC81 %s",
1819 phy->phy_name, "NSE");
1820 queue_event(smc, EVENT_PCM + np, PC_START);
1821 return;
1822 }
1823 }
1824 }
1825 #if 0
1826 if (cmd & PL_NP_ERR) {
1827
1828
1829
1830 plc->np_err++ ;
1831 }
1832
1833 if (cmd & PL_PARITY_ERR) {
1834 plc->parity_err++ ;
1835 }
1836 if (cmd & PL_LSDO) {
1837 ;
1838 }
1839 #endif
1840 }
1841
1842 #ifdef DEBUG
1843
1844
1845
1846 void pcm_get_state(struct s_smc *smc, struct smt_state *state)
1847 {
1848 struct s_phy *phy ;
1849 struct pcm_state *pcs ;
1850 int i ;
1851 int ii ;
1852 short rbits ;
1853 short tbits ;
1854 struct fddi_mib_p *mib ;
1855
1856 for (i = 0, phy = smc->y, pcs = state->pcm_state ; i < NUMPHYS ;
1857 i++ , phy++, pcs++ ) {
1858 mib = phy->mib ;
1859 pcs->pcm_type = (u_char) mib->fddiPORTMy_Type ;
1860 pcs->pcm_state = (u_char) mib->fddiPORTPCMState ;
1861 pcs->pcm_mode = phy->pc_mode ;
1862 pcs->pcm_neighbor = (u_char) mib->fddiPORTNeighborType ;
1863 pcs->pcm_bsf = mib->fddiPORTBS_Flag ;
1864 pcs->pcm_lsf = phy->ls_flag ;
1865 pcs->pcm_lct_fail = (u_char) mib->fddiPORTLCTFail_Ct ;
1866 pcs->pcm_ls_rx = LS2MIB(sm_pm_get_ls(smc,i)) ;
1867 for (ii = 0, rbits = tbits = 0 ; ii < NUMBITS ; ii++) {
1868 rbits <<= 1 ;
1869 tbits <<= 1 ;
1870 if (phy->r_val[NUMBITS-1-ii])
1871 rbits |= 1 ;
1872 if (phy->t_val[NUMBITS-1-ii])
1873 tbits |= 1 ;
1874 }
1875 pcs->pcm_r_val = rbits ;
1876 pcs->pcm_t_val = tbits ;
1877 }
1878 }
1879
1880 int get_pcm_state(struct s_smc *smc, int np)
1881 {
1882 int pcs ;
1883
1884 SK_UNUSED(smc) ;
1885
1886 switch (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_STATE) {
1887 case PL_PC0 : pcs = PC_STOP ; break ;
1888 case PL_PC1 : pcs = PC_START ; break ;
1889 case PL_PC2 : pcs = PC_TRACE ; break ;
1890 case PL_PC3 : pcs = PC_SIGNAL ; break ;
1891 case PL_PC4 : pcs = PC_SIGNAL ; break ;
1892 case PL_PC5 : pcs = PC_SIGNAL ; break ;
1893 case PL_PC6 : pcs = PC_JOIN ; break ;
1894 case PL_PC7 : pcs = PC_JOIN ; break ;
1895 case PL_PC8 : pcs = PC_ENABLE ; break ;
1896 case PL_PC9 : pcs = PC_MAINT ; break ;
1897 default : pcs = PC_DISABLE ; break ;
1898 }
1899 return pcs;
1900 }
1901
1902 char *get_linestate(struct s_smc *smc, int np)
1903 {
1904 char *ls = "" ;
1905
1906 SK_UNUSED(smc) ;
1907
1908 switch (inpw(PLC(np,PL_STATUS_A)) & PL_LINE_ST) {
1909 case PL_L_NLS : ls = "NOISE" ; break ;
1910 case PL_L_ALS : ls = "ACTIV" ; break ;
1911 case PL_L_UND : ls = "UNDEF" ; break ;
1912 case PL_L_ILS4: ls = "ILS 4" ; break ;
1913 case PL_L_QLS : ls = "QLS" ; break ;
1914 case PL_L_MLS : ls = "MLS" ; break ;
1915 case PL_L_HLS : ls = "HLS" ; break ;
1916 case PL_L_ILS16:ls = "ILS16" ; break ;
1917 #ifdef lint
1918 default: ls = "unknown" ; break ;
1919 #endif
1920 }
1921 return ls;
1922 }
1923
1924 char *get_pcmstate(struct s_smc *smc, int np)
1925 {
1926 char *pcs ;
1927
1928 SK_UNUSED(smc) ;
1929
1930 switch (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_STATE) {
1931 case PL_PC0 : pcs = "OFF" ; break ;
1932 case PL_PC1 : pcs = "BREAK" ; break ;
1933 case PL_PC2 : pcs = "TRACE" ; break ;
1934 case PL_PC3 : pcs = "CONNECT"; break ;
1935 case PL_PC4 : pcs = "NEXT" ; break ;
1936 case PL_PC5 : pcs = "SIGNAL" ; break ;
1937 case PL_PC6 : pcs = "JOIN" ; break ;
1938 case PL_PC7 : pcs = "VERIFY" ; break ;
1939 case PL_PC8 : pcs = "ACTIV" ; break ;
1940 case PL_PC9 : pcs = "MAINT" ; break ;
1941 default : pcs = "UNKNOWN" ; break ;
1942 }
1943 return pcs;
1944 }
1945
1946 void list_phy(struct s_smc *smc)
1947 {
1948 struct s_plc *plc ;
1949 int np ;
1950
1951 for (np = 0 ; np < NUMPHYS ; np++) {
1952 plc = &smc->y[np].plc ;
1953 printf("PHY %d:\tERRORS\t\t\tBREAK_REASONS\t\tSTATES:\n",np) ;
1954 printf("\tsoft_error: %ld \t\tPC_Start : %ld\n",
1955 plc->soft_err,plc->b_pcs);
1956 printf("\tparity_err: %ld \t\tTPC exp. : %ld\t\tLine: %s\n",
1957 plc->parity_err,plc->b_tpc,get_linestate(smc,np)) ;
1958 printf("\tebuf_error: %ld \t\tTNE exp. : %ld\n",
1959 plc->ebuf_err,plc->b_tne) ;
1960 printf("\tphyinvalid: %ld \t\tQLS det. : %ld\t\tPCM : %s\n",
1961 plc->phyinv,plc->b_qls,get_pcmstate(smc,np)) ;
1962 printf("\tviosym_ctr: %ld \t\tILS det. : %ld\n",
1963 plc->vsym_ctr,plc->b_ils) ;
1964 printf("\tmingap_ctr: %ld \t\tHLS det. : %ld\n",
1965 plc->mini_ctr,plc->b_hls) ;
1966 printf("\tnodepr_err: %ld\n",plc->np_err) ;
1967 printf("\tTPC_exp : %ld\n",plc->tpc_exp) ;
1968 printf("\tLEM_err : %ld\n",smc->y[np].lem.lem_errors) ;
1969 }
1970 }
1971
1972
1973 #ifdef CONCENTRATOR
1974 void pcm_lem_dump(struct s_smc *smc)
1975 {
1976 int i ;
1977 struct s_phy *phy ;
1978 struct fddi_mib_p *mib ;
1979
1980 char *entostring() ;
1981
1982 printf("PHY errors BER\n") ;
1983 printf("----------------------\n") ;
1984 for (i = 0,phy = smc->y ; i < NUMPHYS ; i++,phy++) {
1985 if (!plc_is_installed(smc,i))
1986 continue ;
1987 mib = phy->mib ;
1988 printf("%s\t%ld\t10E-%d\n",
1989 entostring(smc,ENTITY_PHY(i)),
1990 mib->fddiPORTLem_Ct,
1991 mib->fddiPORTLer_Estimate) ;
1992 }
1993 }
1994 #endif
1995 #endif