1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /****************************************************************************** 3 * 4 * (C)Copyright 1998,1999 SysKonnect, 5 * a business unit of Schneider & Koch & Co. Datensysteme GmbH. 6 * 7 * See the file "skfddi.c" for further information. 8 * 9 * The information in this file is provided "AS IS" without warranty. 10 * 11 ******************************************************************************/ 12 13 /* 14 SMT CFM 15 Configuration Management 16 DAS with single MAC 17 */ 18 19 /* 20 * Hardware independent state machine implemantation 21 * The following external SMT functions are referenced : 22 * 23 * queue_event() 24 * 25 * The following external HW dependent functions are referenced : 26 * config_mux() 27 * 28 * The following HW dependent events are required : 29 * NONE 30 */ 31 32 #include "h/types.h" 33 #include "h/fddi.h" 34 #include "h/smc.h" 35 36 #define KERNEL 37 #include "h/smtstate.h" 38 39 #ifndef lint 40 static const char ID_sccs[] = "@(#)cfm.c 2.18 98/10/06 (C) SK " ; 41 #endif 42 43 /* 44 * FSM Macros 45 */ 46 #define AFLAG 0x10 47 #define GO_STATE(x) (smc->mib.fddiSMTCF_State = (x)|AFLAG) 48 #define ACTIONS_DONE() (smc->mib.fddiSMTCF_State &= ~AFLAG) 49 #define ACTIONS(x) (x|AFLAG) 50 51 /* 52 * symbolic state names 53 */ 54 static const char * const cfm_states[] = { 55 "SC0_ISOLATED","CF1","CF2","CF3","CF4", 56 "SC1_WRAP_A","SC2_WRAP_B","SC5_TRHU_B","SC7_WRAP_S", 57 "SC9_C_WRAP_A","SC10_C_WRAP_B","SC11_C_WRAP_S","SC4_THRU_A" 58 } ; 59 60 /* 61 * symbolic event names 62 */ 63 static const char * const cfm_events[] = { 64 "NONE","CF_LOOP_A","CF_LOOP_B","CF_JOIN_A","CF_JOIN_B" 65 } ; 66 67 /* 68 * map from state to downstream port type 69 */ 70 static const unsigned char cf_to_ptype[] = { 71 TNONE,TNONE,TNONE,TNONE,TNONE, 72 TNONE,TB,TB,TS, 73 TA,TB,TS,TB 74 } ; 75 76 /* 77 * CEM port states 78 */ 79 #define CEM_PST_DOWN 0 80 #define CEM_PST_UP 1 81 #define CEM_PST_HOLD 2 82 /* define portstate array only for A and B port */ 83 /* Do this within the smc structure (use in multiple cards) */ 84 85 /* 86 * all Globals are defined in smc.h 87 * struct s_cfm 88 */ 89 90 /* 91 * function declarations 92 */ 93 static void cfm_fsm(struct s_smc *smc, int cmd); 94 95 /* 96 init CFM state machine 97 clear all CFM vars and flags 98 */ 99 void cfm_init(struct s_smc *smc) 100 { 101 smc->mib.fddiSMTCF_State = ACTIONS(SC0_ISOLATED) ; 102 smc->r.rm_join = 0 ; 103 smc->r.rm_loop = 0 ; 104 smc->y[PA].scrub = 0 ; 105 smc->y[PB].scrub = 0 ; 106 smc->y[PA].cem_pst = CEM_PST_DOWN ; 107 smc->y[PB].cem_pst = CEM_PST_DOWN ; 108 } 109 110 /* Some terms conditions used by the selection criteria */ 111 #define THRU_ENABLED(smc) (smc->y[PA].pc_mode != PM_TREE && \ 112 smc->y[PB].pc_mode != PM_TREE) 113 /* Selection criteria for the ports */ 114 static void selection_criteria (struct s_smc *smc, struct s_phy *phy) 115 { 116 117 switch (phy->mib->fddiPORTMy_Type) { 118 case TA: 119 if ( !THRU_ENABLED(smc) && smc->y[PB].cf_join ) { 120 phy->wc_flag = TRUE ; 121 } else { 122 phy->wc_flag = FALSE ; 123 } 124 125 break; 126 case TB: 127 /* take precedence over PA */ 128 phy->wc_flag = FALSE ; 129 break; 130 case TS: 131 phy->wc_flag = FALSE ; 132 break; 133 case TM: 134 phy->wc_flag = FALSE ; 135 break; 136 } 137 138 } 139 140 void all_selection_criteria(struct s_smc *smc) 141 { 142 struct s_phy *phy ; 143 int p ; 144 145 for ( p = 0,phy = smc->y ; p < NUMPHYS; p++, phy++ ) { 146 /* Do the selection criteria */ 147 selection_criteria (smc,phy); 148 } 149 } 150 151 static void cem_priv_state(struct s_smc *smc, int event) 152 /* State machine for private PORT states: used to optimize dual homing */ 153 { 154 int np; /* Number of the port */ 155 int i; 156 157 /* Do this only in a DAS */ 158 if (smc->s.sas != SMT_DAS ) 159 return ; 160 161 np = event - CF_JOIN; 162 163 if (np != PA && np != PB) { 164 return ; 165 } 166 /* Change the port state according to the event (portnumber) */ 167 if (smc->y[np].cf_join) { 168 smc->y[np].cem_pst = CEM_PST_UP ; 169 } else if (!smc->y[np].wc_flag) { 170 /* set the port to done only if it is not withheld */ 171 smc->y[np].cem_pst = CEM_PST_DOWN ; 172 } 173 174 /* Don't set an hold port to down */ 175 176 /* Check all ports of restart conditions */ 177 for (i = 0 ; i < 2 ; i ++ ) { 178 /* Check all port for PORT is on hold and no withhold is done */ 179 if ( smc->y[i].cem_pst == CEM_PST_HOLD && !smc->y[i].wc_flag ) { 180 smc->y[i].cem_pst = CEM_PST_DOWN; 181 queue_event(smc,(int)(EVENT_PCM+i),PC_START) ; 182 } 183 if ( smc->y[i].cem_pst == CEM_PST_UP && smc->y[i].wc_flag ) { 184 smc->y[i].cem_pst = CEM_PST_HOLD; 185 queue_event(smc,(int)(EVENT_PCM+i),PC_START) ; 186 } 187 if ( smc->y[i].cem_pst == CEM_PST_DOWN && smc->y[i].wc_flag ) { 188 /* 189 * The port must be restarted when the wc_flag 190 * will be reset. So set the port on hold. 191 */ 192 smc->y[i].cem_pst = CEM_PST_HOLD; 193 } 194 } 195 return ; 196 } 197 198 /* 199 CFM state machine 200 called by dispatcher 201 202 do 203 display state change 204 process event 205 until SM is stable 206 */ 207 void cfm(struct s_smc *smc, int event) 208 { 209 int state ; /* remember last state */ 210 int cond ; 211 int oldstate ; 212 213 /* We will do the following: */ 214 /* - compute the variable WC_Flag for every port (This is where */ 215 /* we can extend the requested path checking !!) */ 216 /* - do the old (SMT 6.2 like) state machine */ 217 /* - do the resulting station states */ 218 219 all_selection_criteria (smc); 220 221 /* We will check now whether a state transition is allowed or not */ 222 /* - change the portstates */ 223 cem_priv_state (smc, event); 224 225 oldstate = smc->mib.fddiSMTCF_State ; 226 do { 227 DB_CFM("CFM : state %s%s event %s", 228 smc->mib.fddiSMTCF_State & AFLAG ? "ACTIONS " : "", 229 cfm_states[smc->mib.fddiSMTCF_State & ~AFLAG], 230 cfm_events[event]); 231 state = smc->mib.fddiSMTCF_State ; 232 cfm_fsm(smc,event) ; 233 event = 0 ; 234 } while (state != smc->mib.fddiSMTCF_State) ; 235 236 #ifndef SLIM_SMT 237 /* 238 * check peer wrap condition 239 */ 240 cond = FALSE ; 241 if ( (smc->mib.fddiSMTCF_State == SC9_C_WRAP_A && 242 smc->y[PA].pc_mode == PM_PEER) || 243 (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B && 244 smc->y[PB].pc_mode == PM_PEER) || 245 (smc->mib.fddiSMTCF_State == SC11_C_WRAP_S && 246 smc->y[PS].pc_mode == PM_PEER && 247 smc->y[PS].mib->fddiPORTNeighborType != TS ) ) { 248 cond = TRUE ; 249 } 250 if (cond != smc->mib.fddiSMTPeerWrapFlag) 251 smt_srf_event(smc,SMT_COND_SMT_PEER_WRAP,0,cond) ; 252 253 #if 0 254 /* 255 * Don't send ever MAC_PATH_CHANGE events. Our MAC is hard-wired 256 * to the primary path. 257 */ 258 /* 259 * path change 260 */ 261 if (smc->mib.fddiSMTCF_State != oldstate) { 262 smt_srf_event(smc,SMT_EVENT_MAC_PATH_CHANGE,INDEX_MAC,0) ; 263 } 264 #endif 265 #endif /* no SLIM_SMT */ 266 267 /* 268 * set MAC port type 269 */ 270 smc->mib.m[MAC0].fddiMACDownstreamPORTType = 271 cf_to_ptype[smc->mib.fddiSMTCF_State] ; 272 cfm_state_change(smc,(int)smc->mib.fddiSMTCF_State) ; 273 } 274 275 /* 276 process CFM event 277 */ 278 /*ARGSUSED1*/ 279 static void cfm_fsm(struct s_smc *smc, int cmd) 280 { 281 switch(smc->mib.fddiSMTCF_State) { 282 case ACTIONS(SC0_ISOLATED) : 283 smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ; 284 smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ; 285 smc->mib.p[PA].fddiPORTMACPlacement = 0 ; 286 smc->mib.p[PB].fddiPORTMACPlacement = 0 ; 287 smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_SEPA ; 288 config_mux(smc,MUX_ISOLATE) ; /* configure PHY Mux */ 289 smc->r.rm_loop = FALSE ; 290 smc->r.rm_join = FALSE ; 291 queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ 292 /* Don't do the WC-Flag changing here */ 293 ACTIONS_DONE() ; 294 DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]); 295 break; 296 case SC0_ISOLATED : 297 /*SC07*/ 298 /*SAS port can be PA or PB ! */ 299 if (smc->s.sas && (smc->y[PA].cf_join || smc->y[PA].cf_loop || 300 smc->y[PB].cf_join || smc->y[PB].cf_loop)) { 301 GO_STATE(SC11_C_WRAP_S) ; 302 break ; 303 } 304 /*SC01*/ 305 if ((smc->y[PA].cem_pst == CEM_PST_UP && smc->y[PA].cf_join && 306 !smc->y[PA].wc_flag) || smc->y[PA].cf_loop) { 307 GO_STATE(SC9_C_WRAP_A) ; 308 break ; 309 } 310 /*SC02*/ 311 if ((smc->y[PB].cem_pst == CEM_PST_UP && smc->y[PB].cf_join && 312 !smc->y[PB].wc_flag) || smc->y[PB].cf_loop) { 313 GO_STATE(SC10_C_WRAP_B) ; 314 break ; 315 } 316 break ; 317 case ACTIONS(SC9_C_WRAP_A) : 318 smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ; 319 smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ; 320 smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ; 321 smc->mib.p[PB].fddiPORTMACPlacement = 0 ; 322 smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ; 323 config_mux(smc,MUX_WRAPA) ; /* configure PHY mux */ 324 if (smc->y[PA].cf_loop) { 325 smc->r.rm_join = FALSE ; 326 smc->r.rm_loop = TRUE ; 327 queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */ 328 } 329 if (smc->y[PA].cf_join) { 330 smc->r.rm_loop = FALSE ; 331 smc->r.rm_join = TRUE ; 332 queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ 333 } 334 ACTIONS_DONE() ; 335 DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]); 336 break ; 337 case SC9_C_WRAP_A : 338 /*SC10*/ 339 if ( (smc->y[PA].wc_flag || !smc->y[PA].cf_join) && 340 !smc->y[PA].cf_loop ) { 341 GO_STATE(SC0_ISOLATED) ; 342 break ; 343 } 344 /*SC12*/ 345 else if ( (smc->y[PB].cf_loop && smc->y[PA].cf_join && 346 smc->y[PA].cem_pst == CEM_PST_UP) || 347 ((smc->y[PB].cf_loop || 348 (smc->y[PB].cf_join && 349 smc->y[PB].cem_pst == CEM_PST_UP)) && 350 (smc->y[PA].pc_mode == PM_TREE || 351 smc->y[PB].pc_mode == PM_TREE))) { 352 smc->y[PA].scrub = TRUE ; 353 GO_STATE(SC10_C_WRAP_B) ; 354 break ; 355 } 356 /*SC14*/ 357 else if (!smc->s.attach_s && 358 smc->y[PA].cf_join && 359 smc->y[PA].cem_pst == CEM_PST_UP && 360 smc->y[PA].pc_mode == PM_PEER && smc->y[PB].cf_join && 361 smc->y[PB].cem_pst == CEM_PST_UP && 362 smc->y[PB].pc_mode == PM_PEER) { 363 smc->y[PA].scrub = TRUE ; 364 smc->y[PB].scrub = TRUE ; 365 GO_STATE(SC4_THRU_A) ; 366 break ; 367 } 368 /*SC15*/ 369 else if ( smc->s.attach_s && 370 smc->y[PA].cf_join && 371 smc->y[PA].cem_pst == CEM_PST_UP && 372 smc->y[PA].pc_mode == PM_PEER && 373 smc->y[PB].cf_join && 374 smc->y[PB].cem_pst == CEM_PST_UP && 375 smc->y[PB].pc_mode == PM_PEER) { 376 smc->y[PA].scrub = TRUE ; 377 smc->y[PB].scrub = TRUE ; 378 GO_STATE(SC5_THRU_B) ; 379 break ; 380 } 381 break ; 382 case ACTIONS(SC10_C_WRAP_B) : 383 smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ; 384 smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ; 385 smc->mib.p[PA].fddiPORTMACPlacement = 0 ; 386 smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ; 387 smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ; 388 config_mux(smc,MUX_WRAPB) ; /* configure PHY mux */ 389 if (smc->y[PB].cf_loop) { 390 smc->r.rm_join = FALSE ; 391 smc->r.rm_loop = TRUE ; 392 queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */ 393 } 394 if (smc->y[PB].cf_join) { 395 smc->r.rm_loop = FALSE ; 396 smc->r.rm_join = TRUE ; 397 queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ 398 } 399 ACTIONS_DONE() ; 400 DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]); 401 break ; 402 case SC10_C_WRAP_B : 403 /*SC20*/ 404 if ( !smc->y[PB].cf_join && !smc->y[PB].cf_loop ) { 405 GO_STATE(SC0_ISOLATED) ; 406 break ; 407 } 408 /*SC21*/ 409 else if ( smc->y[PA].cf_loop && smc->y[PA].pc_mode == PM_PEER && 410 smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) { 411 smc->y[PB].scrub = TRUE ; 412 GO_STATE(SC9_C_WRAP_A) ; 413 break ; 414 } 415 /*SC24*/ 416 else if (!smc->s.attach_s && 417 smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER && 418 smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) { 419 smc->y[PA].scrub = TRUE ; 420 smc->y[PB].scrub = TRUE ; 421 GO_STATE(SC4_THRU_A) ; 422 break ; 423 } 424 /*SC25*/ 425 else if ( smc->s.attach_s && 426 smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER && 427 smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) { 428 smc->y[PA].scrub = TRUE ; 429 smc->y[PB].scrub = TRUE ; 430 GO_STATE(SC5_THRU_B) ; 431 break ; 432 } 433 break ; 434 case ACTIONS(SC4_THRU_A) : 435 smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ; 436 smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ; 437 smc->mib.p[PA].fddiPORTMACPlacement = 0 ; 438 smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ; 439 smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ; 440 config_mux(smc,MUX_THRUA) ; /* configure PHY mux */ 441 smc->r.rm_loop = FALSE ; 442 smc->r.rm_join = TRUE ; 443 queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ 444 ACTIONS_DONE() ; 445 DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]); 446 break ; 447 case SC4_THRU_A : 448 /*SC41*/ 449 if (smc->y[PB].wc_flag || !smc->y[PB].cf_join) { 450 smc->y[PA].scrub = TRUE ; 451 GO_STATE(SC9_C_WRAP_A) ; 452 break ; 453 } 454 /*SC42*/ 455 else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) { 456 smc->y[PB].scrub = TRUE ; 457 GO_STATE(SC10_C_WRAP_B) ; 458 break ; 459 } 460 /*SC45*/ 461 else if (smc->s.attach_s) { 462 smc->y[PB].scrub = TRUE ; 463 GO_STATE(SC5_THRU_B) ; 464 break ; 465 } 466 break ; 467 case ACTIONS(SC5_THRU_B) : 468 smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ; 469 smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ; 470 smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ; 471 smc->mib.p[PB].fddiPORTMACPlacement = 0 ; 472 smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ; 473 config_mux(smc,MUX_THRUB) ; /* configure PHY mux */ 474 smc->r.rm_loop = FALSE ; 475 smc->r.rm_join = TRUE ; 476 queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ 477 ACTIONS_DONE() ; 478 DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]); 479 break ; 480 case SC5_THRU_B : 481 /*SC51*/ 482 if (!smc->y[PB].cf_join || smc->y[PB].wc_flag) { 483 smc->y[PA].scrub = TRUE ; 484 GO_STATE(SC9_C_WRAP_A) ; 485 break ; 486 } 487 /*SC52*/ 488 else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) { 489 smc->y[PB].scrub = TRUE ; 490 GO_STATE(SC10_C_WRAP_B) ; 491 break ; 492 } 493 /*SC54*/ 494 else if (!smc->s.attach_s) { 495 smc->y[PA].scrub = TRUE ; 496 GO_STATE(SC4_THRU_A) ; 497 break ; 498 } 499 break ; 500 case ACTIONS(SC11_C_WRAP_S) : 501 smc->mib.p[PS].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ; 502 smc->mib.p[PS].fddiPORTMACPlacement = INDEX_MAC ; 503 smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ; 504 config_mux(smc,MUX_WRAPS) ; /* configure PHY mux */ 505 if (smc->y[PA].cf_loop || smc->y[PB].cf_loop) { 506 smc->r.rm_join = FALSE ; 507 smc->r.rm_loop = TRUE ; 508 queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */ 509 } 510 if (smc->y[PA].cf_join || smc->y[PB].cf_join) { 511 smc->r.rm_loop = FALSE ; 512 smc->r.rm_join = TRUE ; 513 queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ 514 } 515 ACTIONS_DONE() ; 516 DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]); 517 break ; 518 case SC11_C_WRAP_S : 519 /*SC70*/ 520 if ( !smc->y[PA].cf_join && !smc->y[PA].cf_loop && 521 !smc->y[PB].cf_join && !smc->y[PB].cf_loop) { 522 GO_STATE(SC0_ISOLATED) ; 523 break ; 524 } 525 break ; 526 default: 527 SMT_PANIC(smc,SMT_E0106, SMT_E0106_MSG) ; 528 break; 529 } 530 } 531 532 /* 533 * get MAC's input Port 534 * return : 535 * PA or PB 536 */ 537 int cfm_get_mac_input(struct s_smc *smc) 538 { 539 return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B || 540 smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA; 541 } 542 543 /* 544 * get MAC's output Port 545 * return : 546 * PA or PB 547 */ 548 int cfm_get_mac_output(struct s_smc *smc) 549 { 550 return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B || 551 smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA; 552 } 553 554 static char path_iso[] = { 555 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_ISO, 556 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_ISO, 557 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_ISO 558 } ; 559 560 static char path_wrap_a[] = { 561 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_PRIM, 562 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM, 563 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_ISO 564 } ; 565 566 static char path_wrap_b[] = { 567 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_PRIM, 568 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM, 569 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_ISO 570 } ; 571 572 static char path_thru[] = { 573 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_PRIM, 574 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM, 575 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_PRIM 576 } ; 577 578 static char path_wrap_s[] = { 579 0,0, 0,RES_PORT, 0,PS + INDEX_PORT, 0,PATH_PRIM, 580 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM, 581 } ; 582 583 static char path_iso_s[] = { 584 0,0, 0,RES_PORT, 0,PS + INDEX_PORT, 0,PATH_ISO, 585 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_ISO, 586 } ; 587 588 int cem_build_path(struct s_smc *smc, char *to, int path_index) 589 { 590 char *path ; 591 int len ; 592 593 switch (smc->mib.fddiSMTCF_State) { 594 default : 595 case SC0_ISOLATED : 596 path = smc->s.sas ? path_iso_s : path_iso ; 597 len = smc->s.sas ? sizeof(path_iso_s) : sizeof(path_iso) ; 598 break ; 599 case SC9_C_WRAP_A : 600 path = path_wrap_a ; 601 len = sizeof(path_wrap_a) ; 602 break ; 603 case SC10_C_WRAP_B : 604 path = path_wrap_b ; 605 len = sizeof(path_wrap_b) ; 606 break ; 607 case SC4_THRU_A : 608 path = path_thru ; 609 len = sizeof(path_thru) ; 610 break ; 611 case SC11_C_WRAP_S : 612 path = path_wrap_s ; 613 len = sizeof(path_wrap_s) ; 614 break ; 615 } 616 memcpy(to,path,len) ; 617 618 LINT_USE(path_index); 619 620 return len; 621 } 622