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