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