diff options
Diffstat (limited to 'drivers/net/fddi/skfp/cfm.c')
| -rw-r--r-- | drivers/net/fddi/skfp/cfm.c | 627 | 
1 files changed, 627 insertions, 0 deletions
diff --git a/drivers/net/fddi/skfp/cfm.c b/drivers/net/fddi/skfp/cfm.c new file mode 100644 index 00000000000..e395ace3120 --- /dev/null +++ b/drivers/net/fddi/skfp/cfm.c @@ -0,0 +1,627 @@ +/****************************************************************************** + * + *	(C)Copyright 1998,1999 SysKonnect, + *	a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * + *	See the file "skfddi.c" for further information. + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 2 of the License, or + *	(at your option) any later version. + * + *	The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/* +	SMT CFM +	Configuration Management +	DAS with single MAC +*/ + +/* + *	Hardware independent state machine implemantation + *	The following external SMT functions are referenced : + * + *		queue_event() + * + *	The following external HW dependent functions are referenced : + *		config_mux() + * + *	The following HW dependent events are required : + *		NONE  + */ + +#include "h/types.h" +#include "h/fddi.h" +#include "h/smc.h" + +#define KERNEL +#include "h/smtstate.h" + +#ifndef	lint +static const char ID_sccs[] = "@(#)cfm.c	2.18 98/10/06 (C) SK " ; +#endif + +/* + * FSM Macros + */ +#define AFLAG	0x10 +#define GO_STATE(x)	(smc->mib.fddiSMTCF_State = (x)|AFLAG) +#define ACTIONS_DONE()	(smc->mib.fddiSMTCF_State &= ~AFLAG) +#define ACTIONS(x)	(x|AFLAG) + +#ifdef	DEBUG +/* + * symbolic state names + */ +static const char * const cfm_states[] = { +	"SC0_ISOLATED","CF1","CF2","CF3","CF4", +	"SC1_WRAP_A","SC2_WRAP_B","SC5_TRHU_B","SC7_WRAP_S", +	"SC9_C_WRAP_A","SC10_C_WRAP_B","SC11_C_WRAP_S","SC4_THRU_A" +} ; + +/* + * symbolic event names + */ +static const char * const cfm_events[] = { +	"NONE","CF_LOOP_A","CF_LOOP_B","CF_JOIN_A","CF_JOIN_B" +} ; +#endif + +/* + * map from state to downstream port type + */ +static const unsigned char cf_to_ptype[] = { +	TNONE,TNONE,TNONE,TNONE,TNONE, +	TNONE,TB,TB,TS, +	TA,TB,TS,TB +} ; + +/* + * CEM port states + */ +#define	CEM_PST_DOWN	0 +#define	CEM_PST_UP	1 +#define	CEM_PST_HOLD	2 +/* define portstate array only for A and B port */ +/* Do this within the smc structure (use in multiple cards) */ + +/* + * all Globals  are defined in smc.h + * struct s_cfm + */ + +/* + * function declarations + */ +static void cfm_fsm(struct s_smc *smc, int cmd); + +/* +	init CFM state machine +	clear all CFM vars and flags +*/ +void cfm_init(struct s_smc *smc) +{ +	smc->mib.fddiSMTCF_State = ACTIONS(SC0_ISOLATED) ; +	smc->r.rm_join = 0 ; +	smc->r.rm_loop = 0 ; +	smc->y[PA].scrub = 0 ; +	smc->y[PB].scrub = 0 ; +	smc->y[PA].cem_pst = CEM_PST_DOWN ; +	smc->y[PB].cem_pst = CEM_PST_DOWN ; +} + +/* Some terms conditions used by the selection criteria */ +#define THRU_ENABLED(smc)	(smc->y[PA].pc_mode != PM_TREE && \ +				 smc->y[PB].pc_mode != PM_TREE) +/* Selection criteria for the ports */ +static void selection_criteria (struct s_smc *smc, struct s_phy *phy) +{ + +	switch (phy->mib->fddiPORTMy_Type) { +	case TA: +		if ( !THRU_ENABLED(smc) && smc->y[PB].cf_join ) { +			phy->wc_flag = TRUE ; +		} else { +			phy->wc_flag = FALSE ; +		} + +		break; +	case TB: +		/* take precedence over PA */ +		phy->wc_flag = FALSE ; +		break; +	case TS: +		phy->wc_flag = FALSE ; +		break; +	case TM: +		phy->wc_flag = FALSE ; +		break; +	} + +} + +void all_selection_criteria(struct s_smc *smc) +{ +	struct s_phy	*phy ; +	int		p ; + +	for ( p = 0,phy = smc->y ; p < NUMPHYS; p++, phy++ ) { +		/* Do the selection criteria */ +		selection_criteria (smc,phy); +	} +} + +static void cem_priv_state(struct s_smc *smc, int event) +/* State machine for private PORT states: used to optimize dual homing */ +{ +	int	np;	/* Number of the port */ +	int	i; + +	/* Do this only in a DAS */ +	if (smc->s.sas != SMT_DAS ) +		return ; + +	np = event - CF_JOIN; + +	if (np != PA && np != PB) { +		return ; +	} +	/* Change the port state according to the event (portnumber) */ +	if (smc->y[np].cf_join) { +		smc->y[np].cem_pst = CEM_PST_UP ; +	} else if (!smc->y[np].wc_flag) { +		/* set the port to done only if it is not withheld */ +		smc->y[np].cem_pst = CEM_PST_DOWN ; +	} + +	/* Don't set an hold port to down */ + +	/* Check all ports of restart conditions */ +	for (i = 0 ; i < 2 ; i ++ ) { +		/* Check all port for PORT is on hold and no withhold is done */ +		if ( smc->y[i].cem_pst == CEM_PST_HOLD && !smc->y[i].wc_flag ) { +			smc->y[i].cem_pst = CEM_PST_DOWN; +			queue_event(smc,(int)(EVENT_PCM+i),PC_START) ; +		} +		if ( smc->y[i].cem_pst == CEM_PST_UP && smc->y[i].wc_flag ) { +			smc->y[i].cem_pst = CEM_PST_HOLD; +			queue_event(smc,(int)(EVENT_PCM+i),PC_START) ; +		} +		if ( smc->y[i].cem_pst == CEM_PST_DOWN && smc->y[i].wc_flag ) { +			/* +			 * The port must be restarted when the wc_flag +			 * will be reset. So set the port on hold. +			 */ +			smc->y[i].cem_pst = CEM_PST_HOLD; +		} +	} +	return ; +} + +/* +	CFM state machine +	called by dispatcher + +	do +		display state change +		process event +	until SM is stable +*/ +void cfm(struct s_smc *smc, int event) +{ +	int	state ;		/* remember last state */ +	int	cond ; +	int	oldstate ; + +	/* We will do the following: */ +	/*  - compute the variable WC_Flag for every port (This is where */ +	/*    we can extend the requested path checking !!) */ +	/*  - do the old (SMT 6.2 like) state machine */ +	/*  - do the resulting station states */ + +	all_selection_criteria (smc); + +	/* We will check now whether a state transition is allowed or not */ +	/*  - change the portstates */ +	cem_priv_state (smc, event); + +	oldstate = smc->mib.fddiSMTCF_State ; +	do { +		DB_CFM("CFM : state %s%s", +			(smc->mib.fddiSMTCF_State & AFLAG) ? "ACTIONS " : "", +			cfm_states[smc->mib.fddiSMTCF_State & ~AFLAG]) ; +		DB_CFM(" event %s\n",cfm_events[event],0) ; +		state = smc->mib.fddiSMTCF_State ; +		cfm_fsm(smc,event) ; +		event = 0 ; +	} while (state != smc->mib.fddiSMTCF_State) ; + +#ifndef	SLIM_SMT +	/* +	 * check peer wrap condition +	 */ +	cond = FALSE ; +	if (	(smc->mib.fddiSMTCF_State == SC9_C_WRAP_A && +		smc->y[PA].pc_mode == PM_PEER) 	|| +		(smc->mib.fddiSMTCF_State == SC10_C_WRAP_B && +		smc->y[PB].pc_mode == PM_PEER) 	|| +		(smc->mib.fddiSMTCF_State == SC11_C_WRAP_S && +		smc->y[PS].pc_mode == PM_PEER && +		smc->y[PS].mib->fddiPORTNeighborType != TS ) ) { +			cond = TRUE ; +	} +	if (cond != smc->mib.fddiSMTPeerWrapFlag) +		smt_srf_event(smc,SMT_COND_SMT_PEER_WRAP,0,cond) ; + +#if	0 +	/* +	 * Don't send ever MAC_PATH_CHANGE events. Our MAC is hard-wired +	 * to the primary path. +	 */ +	/* +	 * path change +	 */ +	if (smc->mib.fddiSMTCF_State != oldstate) { +		smt_srf_event(smc,SMT_EVENT_MAC_PATH_CHANGE,INDEX_MAC,0) ; +	} +#endif +#endif	/* no SLIM_SMT */ + +	/* +	 * set MAC port type +	 */ +	smc->mib.m[MAC0].fddiMACDownstreamPORTType = +		cf_to_ptype[smc->mib.fddiSMTCF_State] ; +	cfm_state_change(smc,(int)smc->mib.fddiSMTCF_State) ; +} + +/* +	process CFM event +*/ +/*ARGSUSED1*/ +static void cfm_fsm(struct s_smc *smc, int cmd) +{ +	switch(smc->mib.fddiSMTCF_State) { +	case ACTIONS(SC0_ISOLATED) : +		smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ; +		smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ; +		smc->mib.p[PA].fddiPORTMACPlacement = 0 ; +		smc->mib.p[PB].fddiPORTMACPlacement = 0 ; +		smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_SEPA ; +		config_mux(smc,MUX_ISOLATE) ;	/* configure PHY Mux */ +		smc->r.rm_loop = FALSE ; +		smc->r.rm_join = FALSE ; +		queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ +		/* Don't do the WC-Flag changing here */ +		ACTIONS_DONE() ; +		DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ; +		break; +	case SC0_ISOLATED : +		/*SC07*/ +		/*SAS port can be PA or PB ! */ +		if (smc->s.sas && (smc->y[PA].cf_join || smc->y[PA].cf_loop || +				smc->y[PB].cf_join || smc->y[PB].cf_loop)) { +			GO_STATE(SC11_C_WRAP_S) ; +			break ; +		} +		/*SC01*/ +		if ((smc->y[PA].cem_pst == CEM_PST_UP && smc->y[PA].cf_join && +		     !smc->y[PA].wc_flag) || smc->y[PA].cf_loop) { +			GO_STATE(SC9_C_WRAP_A) ; +			break ; +		} +		/*SC02*/ +		if ((smc->y[PB].cem_pst == CEM_PST_UP && smc->y[PB].cf_join && +		     !smc->y[PB].wc_flag) || smc->y[PB].cf_loop) { +			GO_STATE(SC10_C_WRAP_B) ; +			break ; +		} +		break ; +	case ACTIONS(SC9_C_WRAP_A) : +		smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ; +		smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ; +		smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ; +		smc->mib.p[PB].fddiPORTMACPlacement = 0 ; +		smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ; +		config_mux(smc,MUX_WRAPA) ;		/* configure PHY mux */ +		if (smc->y[PA].cf_loop) { +			smc->r.rm_join = FALSE ; +			smc->r.rm_loop = TRUE ; +			queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */ +		} +		if (smc->y[PA].cf_join) { +			smc->r.rm_loop = FALSE ; +			smc->r.rm_join = TRUE ; +			queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ +		} +		ACTIONS_DONE() ; +		DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ; +		break ; +	case SC9_C_WRAP_A : +		/*SC10*/ +		if ( (smc->y[PA].wc_flag || !smc->y[PA].cf_join) && +		      !smc->y[PA].cf_loop ) { +			GO_STATE(SC0_ISOLATED) ; +			break ; +		} +		/*SC12*/ +		else if ( (smc->y[PB].cf_loop && smc->y[PA].cf_join && +			   smc->y[PA].cem_pst == CEM_PST_UP) || +			  ((smc->y[PB].cf_loop || +			   (smc->y[PB].cf_join && +			    smc->y[PB].cem_pst == CEM_PST_UP)) && +			    (smc->y[PA].pc_mode == PM_TREE || +			     smc->y[PB].pc_mode == PM_TREE))) { +			smc->y[PA].scrub = TRUE ; +			GO_STATE(SC10_C_WRAP_B) ; +			break ; +		} +		/*SC14*/ +		else if (!smc->s.attach_s && +			  smc->y[PA].cf_join && +			  smc->y[PA].cem_pst == CEM_PST_UP && +			  smc->y[PA].pc_mode == PM_PEER && smc->y[PB].cf_join && +			  smc->y[PB].cem_pst == CEM_PST_UP && +			  smc->y[PB].pc_mode == PM_PEER) { +			smc->y[PA].scrub = TRUE ; +			smc->y[PB].scrub = TRUE ; +			GO_STATE(SC4_THRU_A) ; +			break ; +		} +		/*SC15*/ +		else if ( smc->s.attach_s && +			  smc->y[PA].cf_join && +			  smc->y[PA].cem_pst == CEM_PST_UP && +			  smc->y[PA].pc_mode == PM_PEER && +			  smc->y[PB].cf_join && +			  smc->y[PB].cem_pst == CEM_PST_UP && +			  smc->y[PB].pc_mode == PM_PEER) { +			smc->y[PA].scrub = TRUE ; +			smc->y[PB].scrub = TRUE ; +			GO_STATE(SC5_THRU_B) ; +			break ; +		} +		break ; +	case ACTIONS(SC10_C_WRAP_B) : +		smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ; +		smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ; +		smc->mib.p[PA].fddiPORTMACPlacement = 0 ; +		smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ; +		smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ; +		config_mux(smc,MUX_WRAPB) ;		/* configure PHY mux */ +		if (smc->y[PB].cf_loop) { +			smc->r.rm_join = FALSE ; +			smc->r.rm_loop = TRUE ; +			queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */ +		} +		if (smc->y[PB].cf_join) { +			smc->r.rm_loop = FALSE ; +			smc->r.rm_join = TRUE ; +			queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ +		} +		ACTIONS_DONE() ; +		DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ; +		break ; +	case SC10_C_WRAP_B : +		/*SC20*/ +		if ( !smc->y[PB].cf_join && !smc->y[PB].cf_loop ) { +			GO_STATE(SC0_ISOLATED) ; +			break ; +		} +		/*SC21*/ +		else if ( smc->y[PA].cf_loop && smc->y[PA].pc_mode == PM_PEER && +			  smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) { +			smc->y[PB].scrub = TRUE ; +			GO_STATE(SC9_C_WRAP_A) ; +			break ; +		} +		/*SC24*/ +		else if (!smc->s.attach_s && +			 smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER && +			 smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) { +			smc->y[PA].scrub = TRUE ; +			smc->y[PB].scrub = TRUE ; +			GO_STATE(SC4_THRU_A) ; +			break ; +		} +		/*SC25*/ +		else if ( smc->s.attach_s && +			 smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER && +			 smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) { +			smc->y[PA].scrub = TRUE ; +			smc->y[PB].scrub = TRUE ; +			GO_STATE(SC5_THRU_B) ; +			break ; +		} +		break ; +	case ACTIONS(SC4_THRU_A) : +		smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ; +		smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ; +		smc->mib.p[PA].fddiPORTMACPlacement = 0 ; +		smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ; +		smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ; +		config_mux(smc,MUX_THRUA) ;		/* configure PHY mux */ +		smc->r.rm_loop = FALSE ; +		smc->r.rm_join = TRUE ; +		queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ +		ACTIONS_DONE() ; +		DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ; +		break ; +	case SC4_THRU_A : +		/*SC41*/ +		if (smc->y[PB].wc_flag || !smc->y[PB].cf_join) { +			smc->y[PA].scrub = TRUE ; +			GO_STATE(SC9_C_WRAP_A) ; +			break ; +		} +		/*SC42*/ +		else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) { +			smc->y[PB].scrub = TRUE ; +			GO_STATE(SC10_C_WRAP_B) ; +			break ; +		} +		/*SC45*/ +		else if (smc->s.attach_s) { +			smc->y[PB].scrub = TRUE ; +			GO_STATE(SC5_THRU_B) ; +			break ; +		} +		break ; +	case ACTIONS(SC5_THRU_B) : +		smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ; +		smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ; +		smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ; +		smc->mib.p[PB].fddiPORTMACPlacement = 0 ; +		smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ; +		config_mux(smc,MUX_THRUB) ;		/* configure PHY mux */ +		smc->r.rm_loop = FALSE ; +		smc->r.rm_join = TRUE ; +		queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ +		ACTIONS_DONE() ; +		DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ; +		break ; +	case SC5_THRU_B : +		/*SC51*/ +		if (!smc->y[PB].cf_join || smc->y[PB].wc_flag) { +			smc->y[PA].scrub = TRUE ; +			GO_STATE(SC9_C_WRAP_A) ; +			break ; +		} +		/*SC52*/ +		else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) { +			smc->y[PB].scrub = TRUE ; +			GO_STATE(SC10_C_WRAP_B) ; +			break ; +		} +		/*SC54*/ +		else if (!smc->s.attach_s) { +			smc->y[PA].scrub = TRUE ; +			GO_STATE(SC4_THRU_A) ; +			break ; +		} +		break ; +	case ACTIONS(SC11_C_WRAP_S) : +		smc->mib.p[PS].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ; +		smc->mib.p[PS].fddiPORTMACPlacement = INDEX_MAC ; +		smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ; +		config_mux(smc,MUX_WRAPS) ;		/* configure PHY mux */ +		if (smc->y[PA].cf_loop || smc->y[PB].cf_loop) { +			smc->r.rm_join = FALSE ; +			smc->r.rm_loop = TRUE ; +			queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */ +		} +		if (smc->y[PA].cf_join || smc->y[PB].cf_join) { +			smc->r.rm_loop = FALSE ; +			smc->r.rm_join = TRUE ; +			queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */ +		} +		ACTIONS_DONE() ; +		DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ; +		break ; +	case SC11_C_WRAP_S : +		/*SC70*/ +		if ( !smc->y[PA].cf_join && !smc->y[PA].cf_loop && +		     !smc->y[PB].cf_join && !smc->y[PB].cf_loop) { +			GO_STATE(SC0_ISOLATED) ; +			break ; +		} +		break ; +	default: +		SMT_PANIC(smc,SMT_E0106, SMT_E0106_MSG) ; +		break; +	} +} + +/* + * get MAC's input Port + *	return : + *		PA or PB + */ +int cfm_get_mac_input(struct s_smc *smc) +{ +	return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B || +		smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA; +} + +/* + * get MAC's output Port + *	return : + *		PA or PB + */ +int cfm_get_mac_output(struct s_smc *smc) +{ +	return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B || +		smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA; +} + +static char path_iso[] = { +	0,0,	0,RES_PORT,	0,PA + INDEX_PORT,	0,PATH_ISO, +	0,0,	0,RES_MAC,	0,INDEX_MAC,		0,PATH_ISO, +	0,0,	0,RES_PORT,	0,PB + INDEX_PORT,	0,PATH_ISO +} ; + +static char path_wrap_a[] = { +	0,0,	0,RES_PORT,	0,PA + INDEX_PORT,	0,PATH_PRIM, +	0,0,	0,RES_MAC,	0,INDEX_MAC,		0,PATH_PRIM, +	0,0,	0,RES_PORT,	0,PB + INDEX_PORT,	0,PATH_ISO +} ; + +static char path_wrap_b[] = { +	0,0,	0,RES_PORT,	0,PB + INDEX_PORT,	0,PATH_PRIM, +	0,0,	0,RES_MAC,	0,INDEX_MAC,		0,PATH_PRIM, +	0,0,	0,RES_PORT,	0,PA + INDEX_PORT,	0,PATH_ISO +} ; + +static char path_thru[] = { +	0,0,	0,RES_PORT,	0,PA + INDEX_PORT,	0,PATH_PRIM, +	0,0,	0,RES_MAC,	0,INDEX_MAC,		0,PATH_PRIM, +	0,0,	0,RES_PORT,	0,PB + INDEX_PORT,	0,PATH_PRIM +} ; + +static char path_wrap_s[] = { +	0,0,	0,RES_PORT,	0,PS + INDEX_PORT,	0,PATH_PRIM, +	0,0,	0,RES_MAC,	0,INDEX_MAC,		0,PATH_PRIM, +} ; + +static char path_iso_s[] = { +	0,0,	0,RES_PORT,	0,PS + INDEX_PORT,	0,PATH_ISO, +	0,0,	0,RES_MAC,	0,INDEX_MAC,		0,PATH_ISO, +} ; + +int cem_build_path(struct s_smc *smc, char *to, int path_index) +{ +	char	*path ; +	int	len ; + +	switch (smc->mib.fddiSMTCF_State) { +	default : +	case SC0_ISOLATED : +		path = smc->s.sas ? path_iso_s : path_iso ; +		len = smc->s.sas ? sizeof(path_iso_s) :  sizeof(path_iso) ; +		break ; +	case SC9_C_WRAP_A : +		path = path_wrap_a ; +		len = sizeof(path_wrap_a) ; +		break ; +	case SC10_C_WRAP_B : +		path = path_wrap_b ; +		len = sizeof(path_wrap_b) ; +		break ; +	case SC4_THRU_A : +		path = path_thru ; +		len = sizeof(path_thru) ; +		break ; +	case SC11_C_WRAP_S : +		path = path_wrap_s ; +		len = sizeof(path_wrap_s) ; +		break ; +	} +	memcpy(to,path,len) ; + +	LINT_USE(path_index); + +	return len; +}  | 
