| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | 
|  | 44 | static 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 | */ | 
|  | 59 | static 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 | */ | 
|  | 68 | static 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 | */ | 
| Alan | b882add | 2007-02-20 18:08:57 +0000 | [diff] [blame] | 76 | static const unsigned char cf_to_ptype[] = { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | */ | 
|  | 99 | static void cfm_fsm(struct s_smc *smc, int cmd); | 
|  | 100 |  | 
|  | 101 | /* | 
|  | 102 | init CFM state machine | 
|  | 103 | clear all CFM vars and flags | 
|  | 104 | */ | 
|  | 105 | void 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 */ | 
|  | 120 | static 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 |  | 
|  | 146 | void 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 |  | 
|  | 157 | static 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 | */ | 
|  | 213 | void 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 | #if	0 | 
|  | 260 | /* | 
|  | 261 | * Don't send ever MAC_PATH_CHANGE events. Our MAC is hard-wired | 
|  | 262 | * to the primary path. | 
|  | 263 | */ | 
|  | 264 | /* | 
|  | 265 | * path change | 
|  | 266 | */ | 
|  | 267 | if (smc->mib.fddiSMTCF_State != oldstate) { | 
|  | 268 | smt_srf_event(smc,SMT_EVENT_MAC_PATH_CHANGE,INDEX_MAC,0) ; | 
|  | 269 | } | 
|  | 270 | #endif | 
|  | 271 | #endif	/* no SLIM_SMT */ | 
|  | 272 |  | 
|  | 273 | /* | 
|  | 274 | * set MAC port type | 
|  | 275 | */ | 
|  | 276 | smc->mib.m[MAC0].fddiMACDownstreamPORTType = | 
|  | 277 | cf_to_ptype[smc->mib.fddiSMTCF_State] ; | 
|  | 278 | cfm_state_change(smc,(int)smc->mib.fddiSMTCF_State) ; | 
|  | 279 | } | 
|  | 280 |  | 
|  | 281 | /* | 
|  | 282 | process CFM event | 
|  | 283 | */ | 
|  | 284 | /*ARGSUSED1*/ | 
|  | 285 | static void cfm_fsm(struct s_smc *smc, int cmd) | 
|  | 286 | { | 
|  | 287 | switch(smc->mib.fddiSMTCF_State) { | 
|  | 288 | case ACTIONS(SC0_ISOLATED) : | 
|  | 289 | smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ; | 
|  | 290 | smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ; | 
|  | 291 | smc->mib.p[PA].fddiPORTMACPlacement = 0 ; | 
|  | 292 | smc->mib.p[PB].fddiPORTMACPlacement = 0 ; | 
|  | 293 | smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_SEPA ; | 
|  | 294 | config_mux(smc,MUX_ISOLATE) ;	/* configure PHY Mux */ | 
|  | 295 | smc->r.rm_loop = FALSE ; | 
|  | 296 | smc->r.rm_join = FALSE ; | 
|  | 297 | queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ | 
|  | 298 | /* Don't do the WC-Flag changing here */ | 
|  | 299 | ACTIONS_DONE() ; | 
|  | 300 | DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ; | 
|  | 301 | break; | 
|  | 302 | case SC0_ISOLATED : | 
|  | 303 | /*SC07*/ | 
|  | 304 | /*SAS port can be PA or PB ! */ | 
|  | 305 | if (smc->s.sas && (smc->y[PA].cf_join || smc->y[PA].cf_loop || | 
|  | 306 | smc->y[PB].cf_join || smc->y[PB].cf_loop)) { | 
|  | 307 | GO_STATE(SC11_C_WRAP_S) ; | 
|  | 308 | break ; | 
|  | 309 | } | 
|  | 310 | /*SC01*/ | 
|  | 311 | if ((smc->y[PA].cem_pst == CEM_PST_UP && smc->y[PA].cf_join && | 
|  | 312 | !smc->y[PA].wc_flag) || smc->y[PA].cf_loop) { | 
|  | 313 | GO_STATE(SC9_C_WRAP_A) ; | 
|  | 314 | break ; | 
|  | 315 | } | 
|  | 316 | /*SC02*/ | 
|  | 317 | if ((smc->y[PB].cem_pst == CEM_PST_UP && smc->y[PB].cf_join && | 
|  | 318 | !smc->y[PB].wc_flag) || smc->y[PB].cf_loop) { | 
|  | 319 | GO_STATE(SC10_C_WRAP_B) ; | 
|  | 320 | break ; | 
|  | 321 | } | 
|  | 322 | break ; | 
|  | 323 | case ACTIONS(SC9_C_WRAP_A) : | 
|  | 324 | smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ; | 
|  | 325 | smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ; | 
|  | 326 | smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ; | 
|  | 327 | smc->mib.p[PB].fddiPORTMACPlacement = 0 ; | 
|  | 328 | smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ; | 
|  | 329 | config_mux(smc,MUX_WRAPA) ;		/* configure PHY mux */ | 
|  | 330 | if (smc->y[PA].cf_loop) { | 
|  | 331 | smc->r.rm_join = FALSE ; | 
|  | 332 | smc->r.rm_loop = TRUE ; | 
|  | 333 | queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */ | 
|  | 334 | } | 
|  | 335 | if (smc->y[PA].cf_join) { | 
|  | 336 | smc->r.rm_loop = FALSE ; | 
|  | 337 | smc->r.rm_join = TRUE ; | 
|  | 338 | queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ | 
|  | 339 | } | 
|  | 340 | ACTIONS_DONE() ; | 
|  | 341 | DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ; | 
|  | 342 | break ; | 
|  | 343 | case SC9_C_WRAP_A : | 
|  | 344 | /*SC10*/ | 
|  | 345 | if ( (smc->y[PA].wc_flag || !smc->y[PA].cf_join) && | 
|  | 346 | !smc->y[PA].cf_loop ) { | 
|  | 347 | GO_STATE(SC0_ISOLATED) ; | 
|  | 348 | break ; | 
|  | 349 | } | 
|  | 350 | /*SC12*/ | 
|  | 351 | else if ( (smc->y[PB].cf_loop && smc->y[PA].cf_join && | 
|  | 352 | smc->y[PA].cem_pst == CEM_PST_UP) || | 
|  | 353 | ((smc->y[PB].cf_loop || | 
|  | 354 | (smc->y[PB].cf_join && | 
|  | 355 | smc->y[PB].cem_pst == CEM_PST_UP)) && | 
|  | 356 | (smc->y[PA].pc_mode == PM_TREE || | 
|  | 357 | smc->y[PB].pc_mode == PM_TREE))) { | 
|  | 358 | smc->y[PA].scrub = TRUE ; | 
|  | 359 | GO_STATE(SC10_C_WRAP_B) ; | 
|  | 360 | break ; | 
|  | 361 | } | 
|  | 362 | /*SC14*/ | 
|  | 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 && smc->y[PB].cf_join && | 
|  | 367 | smc->y[PB].cem_pst == CEM_PST_UP && | 
|  | 368 | smc->y[PB].pc_mode == PM_PEER) { | 
|  | 369 | smc->y[PA].scrub = TRUE ; | 
|  | 370 | smc->y[PB].scrub = TRUE ; | 
|  | 371 | GO_STATE(SC4_THRU_A) ; | 
|  | 372 | break ; | 
|  | 373 | } | 
|  | 374 | /*SC15*/ | 
|  | 375 | else if ( smc->s.attach_s && | 
|  | 376 | smc->y[PA].cf_join && | 
|  | 377 | smc->y[PA].cem_pst == CEM_PST_UP && | 
|  | 378 | smc->y[PA].pc_mode == PM_PEER && | 
|  | 379 | smc->y[PB].cf_join && | 
|  | 380 | smc->y[PB].cem_pst == CEM_PST_UP && | 
|  | 381 | smc->y[PB].pc_mode == PM_PEER) { | 
|  | 382 | smc->y[PA].scrub = TRUE ; | 
|  | 383 | smc->y[PB].scrub = TRUE ; | 
|  | 384 | GO_STATE(SC5_THRU_B) ; | 
|  | 385 | break ; | 
|  | 386 | } | 
|  | 387 | break ; | 
|  | 388 | case ACTIONS(SC10_C_WRAP_B) : | 
|  | 389 | smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ; | 
|  | 390 | smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ; | 
|  | 391 | smc->mib.p[PA].fddiPORTMACPlacement = 0 ; | 
|  | 392 | smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ; | 
|  | 393 | smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ; | 
|  | 394 | config_mux(smc,MUX_WRAPB) ;		/* configure PHY mux */ | 
|  | 395 | if (smc->y[PB].cf_loop) { | 
|  | 396 | smc->r.rm_join = FALSE ; | 
|  | 397 | smc->r.rm_loop = TRUE ; | 
|  | 398 | queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */ | 
|  | 399 | } | 
|  | 400 | if (smc->y[PB].cf_join) { | 
|  | 401 | smc->r.rm_loop = FALSE ; | 
|  | 402 | smc->r.rm_join = TRUE ; | 
|  | 403 | queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ | 
|  | 404 | } | 
|  | 405 | ACTIONS_DONE() ; | 
|  | 406 | DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ; | 
|  | 407 | break ; | 
|  | 408 | case SC10_C_WRAP_B : | 
|  | 409 | /*SC20*/ | 
|  | 410 | if ( !smc->y[PB].cf_join && !smc->y[PB].cf_loop ) { | 
|  | 411 | GO_STATE(SC0_ISOLATED) ; | 
|  | 412 | break ; | 
|  | 413 | } | 
|  | 414 | /*SC21*/ | 
|  | 415 | else if ( smc->y[PA].cf_loop && smc->y[PA].pc_mode == PM_PEER && | 
|  | 416 | smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) { | 
|  | 417 | smc->y[PB].scrub = TRUE ; | 
|  | 418 | GO_STATE(SC9_C_WRAP_A) ; | 
|  | 419 | break ; | 
|  | 420 | } | 
|  | 421 | /*SC24*/ | 
|  | 422 | else if (!smc->s.attach_s && | 
|  | 423 | smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER && | 
|  | 424 | smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) { | 
|  | 425 | smc->y[PA].scrub = TRUE ; | 
|  | 426 | smc->y[PB].scrub = TRUE ; | 
|  | 427 | GO_STATE(SC4_THRU_A) ; | 
|  | 428 | break ; | 
|  | 429 | } | 
|  | 430 | /*SC25*/ | 
|  | 431 | else if ( smc->s.attach_s && | 
|  | 432 | smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER && | 
|  | 433 | smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) { | 
|  | 434 | smc->y[PA].scrub = TRUE ; | 
|  | 435 | smc->y[PB].scrub = TRUE ; | 
|  | 436 | GO_STATE(SC5_THRU_B) ; | 
|  | 437 | break ; | 
|  | 438 | } | 
|  | 439 | break ; | 
|  | 440 | case ACTIONS(SC4_THRU_A) : | 
|  | 441 | smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ; | 
|  | 442 | smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ; | 
|  | 443 | smc->mib.p[PA].fddiPORTMACPlacement = 0 ; | 
|  | 444 | smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ; | 
|  | 445 | smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ; | 
|  | 446 | config_mux(smc,MUX_THRUA) ;		/* configure PHY mux */ | 
|  | 447 | smc->r.rm_loop = FALSE ; | 
|  | 448 | smc->r.rm_join = TRUE ; | 
|  | 449 | queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ | 
|  | 450 | ACTIONS_DONE() ; | 
|  | 451 | DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ; | 
|  | 452 | break ; | 
|  | 453 | case SC4_THRU_A : | 
|  | 454 | /*SC41*/ | 
|  | 455 | if (smc->y[PB].wc_flag || !smc->y[PB].cf_join) { | 
|  | 456 | smc->y[PA].scrub = TRUE ; | 
|  | 457 | GO_STATE(SC9_C_WRAP_A) ; | 
|  | 458 | break ; | 
|  | 459 | } | 
|  | 460 | /*SC42*/ | 
|  | 461 | else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) { | 
|  | 462 | smc->y[PB].scrub = TRUE ; | 
|  | 463 | GO_STATE(SC10_C_WRAP_B) ; | 
|  | 464 | break ; | 
|  | 465 | } | 
|  | 466 | /*SC45*/ | 
|  | 467 | else if (smc->s.attach_s) { | 
|  | 468 | smc->y[PB].scrub = TRUE ; | 
|  | 469 | GO_STATE(SC5_THRU_B) ; | 
|  | 470 | break ; | 
|  | 471 | } | 
|  | 472 | break ; | 
|  | 473 | case ACTIONS(SC5_THRU_B) : | 
|  | 474 | smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ; | 
|  | 475 | smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ; | 
|  | 476 | smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ; | 
|  | 477 | smc->mib.p[PB].fddiPORTMACPlacement = 0 ; | 
|  | 478 | smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ; | 
|  | 479 | config_mux(smc,MUX_THRUB) ;		/* configure PHY mux */ | 
|  | 480 | smc->r.rm_loop = FALSE ; | 
|  | 481 | smc->r.rm_join = TRUE ; | 
|  | 482 | queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ | 
|  | 483 | ACTIONS_DONE() ; | 
|  | 484 | DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ; | 
|  | 485 | break ; | 
|  | 486 | case SC5_THRU_B : | 
|  | 487 | /*SC51*/ | 
|  | 488 | if (!smc->y[PB].cf_join || smc->y[PB].wc_flag) { | 
|  | 489 | smc->y[PA].scrub = TRUE ; | 
|  | 490 | GO_STATE(SC9_C_WRAP_A) ; | 
|  | 491 | break ; | 
|  | 492 | } | 
|  | 493 | /*SC52*/ | 
|  | 494 | else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) { | 
|  | 495 | smc->y[PB].scrub = TRUE ; | 
|  | 496 | GO_STATE(SC10_C_WRAP_B) ; | 
|  | 497 | break ; | 
|  | 498 | } | 
|  | 499 | /*SC54*/ | 
|  | 500 | else if (!smc->s.attach_s) { | 
|  | 501 | smc->y[PA].scrub = TRUE ; | 
|  | 502 | GO_STATE(SC4_THRU_A) ; | 
|  | 503 | break ; | 
|  | 504 | } | 
|  | 505 | break ; | 
|  | 506 | case ACTIONS(SC11_C_WRAP_S) : | 
|  | 507 | smc->mib.p[PS].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ; | 
|  | 508 | smc->mib.p[PS].fddiPORTMACPlacement = INDEX_MAC ; | 
|  | 509 | smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ; | 
|  | 510 | config_mux(smc,MUX_WRAPS) ;		/* configure PHY mux */ | 
|  | 511 | if (smc->y[PA].cf_loop || smc->y[PB].cf_loop) { | 
|  | 512 | smc->r.rm_join = FALSE ; | 
|  | 513 | smc->r.rm_loop = TRUE ; | 
|  | 514 | queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */ | 
|  | 515 | } | 
|  | 516 | if (smc->y[PA].cf_join || smc->y[PB].cf_join) { | 
|  | 517 | smc->r.rm_loop = FALSE ; | 
|  | 518 | smc->r.rm_join = TRUE ; | 
|  | 519 | queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ | 
|  | 520 | } | 
|  | 521 | ACTIONS_DONE() ; | 
|  | 522 | DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ; | 
|  | 523 | break ; | 
|  | 524 | case SC11_C_WRAP_S : | 
|  | 525 | /*SC70*/ | 
|  | 526 | if ( !smc->y[PA].cf_join && !smc->y[PA].cf_loop && | 
|  | 527 | !smc->y[PB].cf_join && !smc->y[PB].cf_loop) { | 
|  | 528 | GO_STATE(SC0_ISOLATED) ; | 
|  | 529 | break ; | 
|  | 530 | } | 
|  | 531 | break ; | 
|  | 532 | default: | 
|  | 533 | SMT_PANIC(smc,SMT_E0106, SMT_E0106_MSG) ; | 
|  | 534 | break; | 
|  | 535 | } | 
|  | 536 | } | 
|  | 537 |  | 
|  | 538 | /* | 
|  | 539 | * get MAC's input Port | 
|  | 540 | *	return : | 
|  | 541 | *		PA or PB | 
|  | 542 | */ | 
|  | 543 | int cfm_get_mac_input(struct s_smc *smc) | 
|  | 544 | { | 
|  | 545 | return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B || | 
|  | 546 | smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA) ; | 
|  | 547 | } | 
|  | 548 |  | 
|  | 549 | /* | 
|  | 550 | * get MAC's output Port | 
|  | 551 | *	return : | 
|  | 552 | *		PA or PB | 
|  | 553 | */ | 
|  | 554 | int cfm_get_mac_output(struct s_smc *smc) | 
|  | 555 | { | 
|  | 556 | return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B || | 
|  | 557 | smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA) ; | 
|  | 558 | } | 
|  | 559 |  | 
|  | 560 | static char path_iso[] = { | 
|  | 561 | 0,0,	0,RES_PORT,	0,PA + INDEX_PORT,	0,PATH_ISO, | 
|  | 562 | 0,0,	0,RES_MAC,	0,INDEX_MAC,		0,PATH_ISO, | 
|  | 563 | 0,0,	0,RES_PORT,	0,PB + INDEX_PORT,	0,PATH_ISO | 
|  | 564 | } ; | 
|  | 565 |  | 
|  | 566 | static char path_wrap_a[] = { | 
|  | 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_ISO | 
|  | 570 | } ; | 
|  | 571 |  | 
|  | 572 | static char path_wrap_b[] = { | 
|  | 573 | 0,0,	0,RES_PORT,	0,PB + INDEX_PORT,	0,PATH_PRIM, | 
|  | 574 | 0,0,	0,RES_MAC,	0,INDEX_MAC,		0,PATH_PRIM, | 
|  | 575 | 0,0,	0,RES_PORT,	0,PA + INDEX_PORT,	0,PATH_ISO | 
|  | 576 | } ; | 
|  | 577 |  | 
|  | 578 | static char path_thru[] = { | 
|  | 579 | 0,0,	0,RES_PORT,	0,PA + INDEX_PORT,	0,PATH_PRIM, | 
|  | 580 | 0,0,	0,RES_MAC,	0,INDEX_MAC,		0,PATH_PRIM, | 
|  | 581 | 0,0,	0,RES_PORT,	0,PB + INDEX_PORT,	0,PATH_PRIM | 
|  | 582 | } ; | 
|  | 583 |  | 
|  | 584 | static char path_wrap_s[] = { | 
|  | 585 | 0,0,	0,RES_PORT,	0,PS + INDEX_PORT,	0,PATH_PRIM, | 
|  | 586 | 0,0,	0,RES_MAC,	0,INDEX_MAC,		0,PATH_PRIM, | 
|  | 587 | } ; | 
|  | 588 |  | 
|  | 589 | static char path_iso_s[] = { | 
|  | 590 | 0,0,	0,RES_PORT,	0,PS + INDEX_PORT,	0,PATH_ISO, | 
|  | 591 | 0,0,	0,RES_MAC,	0,INDEX_MAC,		0,PATH_ISO, | 
|  | 592 | } ; | 
|  | 593 |  | 
|  | 594 | int cem_build_path(struct s_smc *smc, char *to, int path_index) | 
|  | 595 | { | 
|  | 596 | char	*path ; | 
|  | 597 | int	len ; | 
|  | 598 |  | 
|  | 599 | switch (smc->mib.fddiSMTCF_State) { | 
|  | 600 | default : | 
|  | 601 | case SC0_ISOLATED : | 
|  | 602 | path = smc->s.sas ? path_iso_s : path_iso ; | 
|  | 603 | len = smc->s.sas ? sizeof(path_iso_s) :  sizeof(path_iso) ; | 
|  | 604 | break ; | 
|  | 605 | case SC9_C_WRAP_A : | 
|  | 606 | path = path_wrap_a ; | 
|  | 607 | len = sizeof(path_wrap_a) ; | 
|  | 608 | break ; | 
|  | 609 | case SC10_C_WRAP_B : | 
|  | 610 | path = path_wrap_b ; | 
|  | 611 | len = sizeof(path_wrap_b) ; | 
|  | 612 | break ; | 
|  | 613 | case SC4_THRU_A : | 
|  | 614 | path = path_thru ; | 
|  | 615 | len = sizeof(path_thru) ; | 
|  | 616 | break ; | 
|  | 617 | case SC11_C_WRAP_S : | 
|  | 618 | path = path_wrap_s ; | 
|  | 619 | len = sizeof(path_wrap_s) ; | 
|  | 620 | break ; | 
|  | 621 | } | 
|  | 622 | memcpy(to,path,len) ; | 
|  | 623 |  | 
|  | 624 | LINT_USE(path_index); | 
|  | 625 |  | 
|  | 626 | return(len) ; | 
|  | 627 | } |