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 #include "h/types.h"
0033 #include "h/fddi.h"
0034 #include "h/smc.h"
0035
0036 #define KERNEL
0037 #include "h/smtstate.h"
0038
0039
0040
0041
0042 #define AFLAG 0x10
0043 #define GO_STATE(x) (smc->mib.fddiSMTCF_State = (x)|AFLAG)
0044 #define ACTIONS_DONE() (smc->mib.fddiSMTCF_State &= ~AFLAG)
0045 #define ACTIONS(x) (x|AFLAG)
0046
0047
0048
0049
0050 static const char * const cfm_states[] = {
0051 "SC0_ISOLATED","CF1","CF2","CF3","CF4",
0052 "SC1_WRAP_A","SC2_WRAP_B","SC5_TRHU_B","SC7_WRAP_S",
0053 "SC9_C_WRAP_A","SC10_C_WRAP_B","SC11_C_WRAP_S","SC4_THRU_A"
0054 } ;
0055
0056
0057
0058
0059 static const char * const cfm_events[] = {
0060 "NONE","CF_LOOP_A","CF_LOOP_B","CF_JOIN_A","CF_JOIN_B"
0061 } ;
0062
0063
0064
0065
0066 static const unsigned char cf_to_ptype[] = {
0067 TNONE,TNONE,TNONE,TNONE,TNONE,
0068 TNONE,TB,TB,TS,
0069 TA,TB,TS,TB
0070 } ;
0071
0072
0073
0074
0075 #define CEM_PST_DOWN 0
0076 #define CEM_PST_UP 1
0077 #define CEM_PST_HOLD 2
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 static void cfm_fsm(struct s_smc *smc, int cmd);
0090
0091
0092
0093
0094
0095 void cfm_init(struct s_smc *smc)
0096 {
0097 smc->mib.fddiSMTCF_State = ACTIONS(SC0_ISOLATED) ;
0098 smc->r.rm_join = 0 ;
0099 smc->r.rm_loop = 0 ;
0100 smc->y[PA].scrub = 0 ;
0101 smc->y[PB].scrub = 0 ;
0102 smc->y[PA].cem_pst = CEM_PST_DOWN ;
0103 smc->y[PB].cem_pst = CEM_PST_DOWN ;
0104 }
0105
0106
0107 #define THRU_ENABLED(smc) (smc->y[PA].pc_mode != PM_TREE && \
0108 smc->y[PB].pc_mode != PM_TREE)
0109
0110 static void selection_criteria (struct s_smc *smc, struct s_phy *phy)
0111 {
0112
0113 switch (phy->mib->fddiPORTMy_Type) {
0114 case TA:
0115 if ( !THRU_ENABLED(smc) && smc->y[PB].cf_join ) {
0116 phy->wc_flag = TRUE ;
0117 } else {
0118 phy->wc_flag = FALSE ;
0119 }
0120
0121 break;
0122 case TB:
0123
0124 phy->wc_flag = FALSE ;
0125 break;
0126 case TS:
0127 phy->wc_flag = FALSE ;
0128 break;
0129 case TM:
0130 phy->wc_flag = FALSE ;
0131 break;
0132 }
0133
0134 }
0135
0136 void all_selection_criteria(struct s_smc *smc)
0137 {
0138 struct s_phy *phy ;
0139 int p ;
0140
0141 for ( p = 0,phy = smc->y ; p < NUMPHYS; p++, phy++ ) {
0142
0143 selection_criteria (smc,phy);
0144 }
0145 }
0146
0147 static void cem_priv_state(struct s_smc *smc, int event)
0148
0149 {
0150 int np;
0151 int i;
0152
0153
0154 if (smc->s.sas != SMT_DAS )
0155 return ;
0156
0157 np = event - CF_JOIN;
0158
0159 if (np != PA && np != PB) {
0160 return ;
0161 }
0162
0163 if (smc->y[np].cf_join) {
0164 smc->y[np].cem_pst = CEM_PST_UP ;
0165 } else if (!smc->y[np].wc_flag) {
0166
0167 smc->y[np].cem_pst = CEM_PST_DOWN ;
0168 }
0169
0170
0171
0172
0173 for (i = 0 ; i < 2 ; i ++ ) {
0174
0175 if ( smc->y[i].cem_pst == CEM_PST_HOLD && !smc->y[i].wc_flag ) {
0176 smc->y[i].cem_pst = CEM_PST_DOWN;
0177 queue_event(smc,(int)(EVENT_PCM+i),PC_START) ;
0178 }
0179 if ( smc->y[i].cem_pst == CEM_PST_UP && smc->y[i].wc_flag ) {
0180 smc->y[i].cem_pst = CEM_PST_HOLD;
0181 queue_event(smc,(int)(EVENT_PCM+i),PC_START) ;
0182 }
0183 if ( smc->y[i].cem_pst == CEM_PST_DOWN && smc->y[i].wc_flag ) {
0184
0185
0186
0187
0188 smc->y[i].cem_pst = CEM_PST_HOLD;
0189 }
0190 }
0191 return ;
0192 }
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203 void cfm(struct s_smc *smc, int event)
0204 {
0205 int state ;
0206 int cond ;
0207
0208
0209
0210
0211
0212
0213
0214 all_selection_criteria (smc);
0215
0216
0217
0218 cem_priv_state (smc, event);
0219
0220 do {
0221 DB_CFM("CFM : state %s%s event %s",
0222 smc->mib.fddiSMTCF_State & AFLAG ? "ACTIONS " : "",
0223 cfm_states[smc->mib.fddiSMTCF_State & ~AFLAG],
0224 cfm_events[event]);
0225 state = smc->mib.fddiSMTCF_State ;
0226 cfm_fsm(smc,event) ;
0227 event = 0 ;
0228 } while (state != smc->mib.fddiSMTCF_State) ;
0229
0230 #ifndef SLIM_SMT
0231
0232
0233
0234 cond = FALSE ;
0235 if ( (smc->mib.fddiSMTCF_State == SC9_C_WRAP_A &&
0236 smc->y[PA].pc_mode == PM_PEER) ||
0237 (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B &&
0238 smc->y[PB].pc_mode == PM_PEER) ||
0239 (smc->mib.fddiSMTCF_State == SC11_C_WRAP_S &&
0240 smc->y[PS].pc_mode == PM_PEER &&
0241 smc->y[PS].mib->fddiPORTNeighborType != TS ) ) {
0242 cond = TRUE ;
0243 }
0244 if (cond != smc->mib.fddiSMTPeerWrapFlag)
0245 smt_srf_event(smc,SMT_COND_SMT_PEER_WRAP,0,cond) ;
0246
0247
0248
0249
0250
0251
0252 #endif
0253
0254
0255
0256
0257 smc->mib.m[MAC0].fddiMACDownstreamPORTType =
0258 cf_to_ptype[smc->mib.fddiSMTCF_State] ;
0259 cfm_state_change(smc,(int)smc->mib.fddiSMTCF_State) ;
0260 }
0261
0262
0263
0264
0265
0266 static void cfm_fsm(struct s_smc *smc, int cmd)
0267 {
0268 switch(smc->mib.fddiSMTCF_State) {
0269 case ACTIONS(SC0_ISOLATED) :
0270 smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
0271 smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
0272 smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
0273 smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
0274 smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_SEPA ;
0275 config_mux(smc,MUX_ISOLATE) ;
0276 smc->r.rm_loop = FALSE ;
0277 smc->r.rm_join = FALSE ;
0278 queue_event(smc,EVENT_RMT,RM_JOIN) ;
0279
0280 ACTIONS_DONE() ;
0281 DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]);
0282 break;
0283 case SC0_ISOLATED :
0284
0285
0286 if (smc->s.sas && (smc->y[PA].cf_join || smc->y[PA].cf_loop ||
0287 smc->y[PB].cf_join || smc->y[PB].cf_loop)) {
0288 GO_STATE(SC11_C_WRAP_S) ;
0289 break ;
0290 }
0291
0292 if ((smc->y[PA].cem_pst == CEM_PST_UP && smc->y[PA].cf_join &&
0293 !smc->y[PA].wc_flag) || smc->y[PA].cf_loop) {
0294 GO_STATE(SC9_C_WRAP_A) ;
0295 break ;
0296 }
0297
0298 if ((smc->y[PB].cem_pst == CEM_PST_UP && smc->y[PB].cf_join &&
0299 !smc->y[PB].wc_flag) || smc->y[PB].cf_loop) {
0300 GO_STATE(SC10_C_WRAP_B) ;
0301 break ;
0302 }
0303 break ;
0304 case ACTIONS(SC9_C_WRAP_A) :
0305 smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
0306 smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
0307 smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
0308 smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
0309 smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
0310 config_mux(smc,MUX_WRAPA) ;
0311 if (smc->y[PA].cf_loop) {
0312 smc->r.rm_join = FALSE ;
0313 smc->r.rm_loop = TRUE ;
0314 queue_event(smc,EVENT_RMT,RM_LOOP) ;
0315 }
0316 if (smc->y[PA].cf_join) {
0317 smc->r.rm_loop = FALSE ;
0318 smc->r.rm_join = TRUE ;
0319 queue_event(smc,EVENT_RMT,RM_JOIN) ;
0320 }
0321 ACTIONS_DONE() ;
0322 DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]);
0323 break ;
0324 case SC9_C_WRAP_A :
0325
0326 if ( (smc->y[PA].wc_flag || !smc->y[PA].cf_join) &&
0327 !smc->y[PA].cf_loop ) {
0328 GO_STATE(SC0_ISOLATED) ;
0329 break ;
0330 }
0331
0332 else if ( (smc->y[PB].cf_loop && smc->y[PA].cf_join &&
0333 smc->y[PA].cem_pst == CEM_PST_UP) ||
0334 ((smc->y[PB].cf_loop ||
0335 (smc->y[PB].cf_join &&
0336 smc->y[PB].cem_pst == CEM_PST_UP)) &&
0337 (smc->y[PA].pc_mode == PM_TREE ||
0338 smc->y[PB].pc_mode == PM_TREE))) {
0339 smc->y[PA].scrub = TRUE ;
0340 GO_STATE(SC10_C_WRAP_B) ;
0341 break ;
0342 }
0343
0344 else if (!smc->s.attach_s &&
0345 smc->y[PA].cf_join &&
0346 smc->y[PA].cem_pst == CEM_PST_UP &&
0347 smc->y[PA].pc_mode == PM_PEER && smc->y[PB].cf_join &&
0348 smc->y[PB].cem_pst == CEM_PST_UP &&
0349 smc->y[PB].pc_mode == PM_PEER) {
0350 smc->y[PA].scrub = TRUE ;
0351 smc->y[PB].scrub = TRUE ;
0352 GO_STATE(SC4_THRU_A) ;
0353 break ;
0354 }
0355
0356 else if ( smc->s.attach_s &&
0357 smc->y[PA].cf_join &&
0358 smc->y[PA].cem_pst == CEM_PST_UP &&
0359 smc->y[PA].pc_mode == PM_PEER &&
0360 smc->y[PB].cf_join &&
0361 smc->y[PB].cem_pst == CEM_PST_UP &&
0362 smc->y[PB].pc_mode == PM_PEER) {
0363 smc->y[PA].scrub = TRUE ;
0364 smc->y[PB].scrub = TRUE ;
0365 GO_STATE(SC5_THRU_B) ;
0366 break ;
0367 }
0368 break ;
0369 case ACTIONS(SC10_C_WRAP_B) :
0370 smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
0371 smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
0372 smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
0373 smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
0374 smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
0375 config_mux(smc,MUX_WRAPB) ;
0376 if (smc->y[PB].cf_loop) {
0377 smc->r.rm_join = FALSE ;
0378 smc->r.rm_loop = TRUE ;
0379 queue_event(smc,EVENT_RMT,RM_LOOP) ;
0380 }
0381 if (smc->y[PB].cf_join) {
0382 smc->r.rm_loop = FALSE ;
0383 smc->r.rm_join = TRUE ;
0384 queue_event(smc,EVENT_RMT,RM_JOIN) ;
0385 }
0386 ACTIONS_DONE() ;
0387 DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]);
0388 break ;
0389 case SC10_C_WRAP_B :
0390
0391 if ( !smc->y[PB].cf_join && !smc->y[PB].cf_loop ) {
0392 GO_STATE(SC0_ISOLATED) ;
0393 break ;
0394 }
0395
0396 else if ( smc->y[PA].cf_loop && smc->y[PA].pc_mode == PM_PEER &&
0397 smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
0398 smc->y[PB].scrub = TRUE ;
0399 GO_STATE(SC9_C_WRAP_A) ;
0400 break ;
0401 }
0402
0403 else if (!smc->s.attach_s &&
0404 smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
0405 smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
0406 smc->y[PA].scrub = TRUE ;
0407 smc->y[PB].scrub = TRUE ;
0408 GO_STATE(SC4_THRU_A) ;
0409 break ;
0410 }
0411
0412 else if ( smc->s.attach_s &&
0413 smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
0414 smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
0415 smc->y[PA].scrub = TRUE ;
0416 smc->y[PB].scrub = TRUE ;
0417 GO_STATE(SC5_THRU_B) ;
0418 break ;
0419 }
0420 break ;
0421 case ACTIONS(SC4_THRU_A) :
0422 smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
0423 smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
0424 smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
0425 smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
0426 smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
0427 config_mux(smc,MUX_THRUA) ;
0428 smc->r.rm_loop = FALSE ;
0429 smc->r.rm_join = TRUE ;
0430 queue_event(smc,EVENT_RMT,RM_JOIN) ;
0431 ACTIONS_DONE() ;
0432 DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]);
0433 break ;
0434 case SC4_THRU_A :
0435
0436 if (smc->y[PB].wc_flag || !smc->y[PB].cf_join) {
0437 smc->y[PA].scrub = TRUE ;
0438 GO_STATE(SC9_C_WRAP_A) ;
0439 break ;
0440 }
0441
0442 else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
0443 smc->y[PB].scrub = TRUE ;
0444 GO_STATE(SC10_C_WRAP_B) ;
0445 break ;
0446 }
0447
0448 else if (smc->s.attach_s) {
0449 smc->y[PB].scrub = TRUE ;
0450 GO_STATE(SC5_THRU_B) ;
0451 break ;
0452 }
0453 break ;
0454 case ACTIONS(SC5_THRU_B) :
0455 smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
0456 smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
0457 smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
0458 smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
0459 smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
0460 config_mux(smc,MUX_THRUB) ;
0461 smc->r.rm_loop = FALSE ;
0462 smc->r.rm_join = TRUE ;
0463 queue_event(smc,EVENT_RMT,RM_JOIN) ;
0464 ACTIONS_DONE() ;
0465 DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]);
0466 break ;
0467 case SC5_THRU_B :
0468
0469 if (!smc->y[PB].cf_join || smc->y[PB].wc_flag) {
0470 smc->y[PA].scrub = TRUE ;
0471 GO_STATE(SC9_C_WRAP_A) ;
0472 break ;
0473 }
0474
0475 else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
0476 smc->y[PB].scrub = TRUE ;
0477 GO_STATE(SC10_C_WRAP_B) ;
0478 break ;
0479 }
0480
0481 else if (!smc->s.attach_s) {
0482 smc->y[PA].scrub = TRUE ;
0483 GO_STATE(SC4_THRU_A) ;
0484 break ;
0485 }
0486 break ;
0487 case ACTIONS(SC11_C_WRAP_S) :
0488 smc->mib.p[PS].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
0489 smc->mib.p[PS].fddiPORTMACPlacement = INDEX_MAC ;
0490 smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
0491 config_mux(smc,MUX_WRAPS) ;
0492 if (smc->y[PA].cf_loop || smc->y[PB].cf_loop) {
0493 smc->r.rm_join = FALSE ;
0494 smc->r.rm_loop = TRUE ;
0495 queue_event(smc,EVENT_RMT,RM_LOOP) ;
0496 }
0497 if (smc->y[PA].cf_join || smc->y[PB].cf_join) {
0498 smc->r.rm_loop = FALSE ;
0499 smc->r.rm_join = TRUE ;
0500 queue_event(smc,EVENT_RMT,RM_JOIN) ;
0501 }
0502 ACTIONS_DONE() ;
0503 DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]);
0504 break ;
0505 case SC11_C_WRAP_S :
0506
0507 if ( !smc->y[PA].cf_join && !smc->y[PA].cf_loop &&
0508 !smc->y[PB].cf_join && !smc->y[PB].cf_loop) {
0509 GO_STATE(SC0_ISOLATED) ;
0510 break ;
0511 }
0512 break ;
0513 default:
0514 SMT_PANIC(smc,SMT_E0106, SMT_E0106_MSG) ;
0515 break;
0516 }
0517 }
0518
0519
0520
0521
0522
0523
0524 int cfm_get_mac_input(struct s_smc *smc)
0525 {
0526 return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
0527 smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA;
0528 }
0529
0530
0531
0532
0533
0534
0535 int cfm_get_mac_output(struct s_smc *smc)
0536 {
0537 return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
0538 smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA;
0539 }
0540
0541 static char path_iso[] = {
0542 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_ISO,
0543 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_ISO,
0544 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_ISO
0545 } ;
0546
0547 static char path_wrap_a[] = {
0548 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_PRIM,
0549 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
0550 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_ISO
0551 } ;
0552
0553 static char path_wrap_b[] = {
0554 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_PRIM,
0555 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
0556 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_ISO
0557 } ;
0558
0559 static char path_thru[] = {
0560 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_PRIM,
0561 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
0562 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_PRIM
0563 } ;
0564
0565 static char path_wrap_s[] = {
0566 0,0, 0,RES_PORT, 0,PS + INDEX_PORT, 0,PATH_PRIM,
0567 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
0568 } ;
0569
0570 static char path_iso_s[] = {
0571 0,0, 0,RES_PORT, 0,PS + INDEX_PORT, 0,PATH_ISO,
0572 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_ISO,
0573 } ;
0574
0575 int cem_build_path(struct s_smc *smc, char *to, int path_index)
0576 {
0577 char *path ;
0578 int len ;
0579
0580 switch (smc->mib.fddiSMTCF_State) {
0581 default :
0582 case SC0_ISOLATED :
0583 path = smc->s.sas ? path_iso_s : path_iso ;
0584 len = smc->s.sas ? sizeof(path_iso_s) : sizeof(path_iso) ;
0585 break ;
0586 case SC9_C_WRAP_A :
0587 path = path_wrap_a ;
0588 len = sizeof(path_wrap_a) ;
0589 break ;
0590 case SC10_C_WRAP_B :
0591 path = path_wrap_b ;
0592 len = sizeof(path_wrap_b) ;
0593 break ;
0594 case SC4_THRU_A :
0595 path = path_thru ;
0596 len = sizeof(path_thru) ;
0597 break ;
0598 case SC11_C_WRAP_S :
0599 path = path_wrap_s ;
0600 len = sizeof(path_wrap_s) ;
0601 break ;
0602 }
0603 memcpy(to,path,len) ;
0604
0605 LINT_USE(path_index);
0606
0607 return len;
0608 }