brintos

brintos / linux-shallow public Read only

0
0
Text · 50.1 KiB · dd15af4 Raw
2005 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/******************************************************************************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#include "h/types.h"14#include "h/fddi.h"15#include "h/smc.h"16#include "h/smt_p.h"17#include <linux/bitrev.h>18#include <linux/kernel.h>19 20#define KERNEL21#include "h/smtstate.h"22 23/*24 * FC in SMbuf25 */26#define m_fc(mb)	((mb)->sm_data[0])27 28#define SMT_TID_MAGIC	0x1f0a7b3c29 30static const char *const smt_type_name[] = {31	"SMT_00??", "SMT_INFO", "SMT_02??", "SMT_03??",32	"SMT_04??", "SMT_05??", "SMT_06??", "SMT_07??",33	"SMT_08??", "SMT_09??", "SMT_0A??", "SMT_0B??",34	"SMT_0C??", "SMT_0D??", "SMT_0E??", "SMT_NSA"35} ;36 37static const char *const smt_class_name[] = {38	"UNKNOWN","NIF","SIF_CONFIG","SIF_OPER","ECF","RAF","RDF",39	"SRF","PMF_GET","PMF_SET","ESF"40} ;41 42#define LAST_CLASS	(SMT_PMF_SET)43 44static const struct fddi_addr SMT_Unknown = {45	{ 0,0,0x1f,0,0,0 }46} ;47 48/*49 * function prototypes50 */51#ifdef	LITTLE_ENDIAN52static int smt_swap_short(u_short s);53#endif54static int mac_index(struct s_smc *smc, int mac);55static int phy_index(struct s_smc *smc, int phy);56static int mac_con_resource_index(struct s_smc *smc, int mac);57static int phy_con_resource_index(struct s_smc *smc, int phy);58static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason,59			 int local);60static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, 61			 int fc, u_long tid, int type, int local);62static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc,63                         u_long tid, int type, int len);64static void smt_echo_test(struct s_smc *smc, int dna);65static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest,66				u_long tid, int local);67static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest,68				   u_long tid, int local);69#ifdef LITTLE_ENDIAN70static void smt_string_swap(char *data, const char *format, int len);71#endif72static void smt_add_frame_len(SMbuf *mb, int len);73static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una);74static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde);75static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state);76static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts);77static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy);78static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency);79static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor);80static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path);81static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st);82static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy);83static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers);84static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc);85static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc);86static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc);87static void smt_fill_manufacturer(struct s_smc *smc, 88				  struct smp_p_manufacturer *man);89static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user);90static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount);91static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed,92			  int len);93 94static void smt_clear_una_dna(struct s_smc *smc);95static void smt_clear_old_una_dna(struct s_smc *smc);96#ifdef	CONCENTRATOR97static int entity_to_index(void);98#endif99static void update_dac(struct s_smc *smc, int report);100static int div_ratio(u_long upper, u_long lower);101#ifdef  USE_CAN_ADDR102static void	hwm_conv_can(struct s_smc *smc, char *data, int len);103#else104#define		hwm_conv_can(smc,data,len)105#endif106 107 108static inline int is_my_addr(const struct s_smc *smc, 109			     const struct fddi_addr *addr)110{111	return(*(short *)(&addr->a[0]) ==112		*(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0])113	  && *(short *)(&addr->a[2]) ==114		*(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[2])115	  && *(short *)(&addr->a[4]) ==116		*(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ;117}118 119static inline int is_broadcast(const struct fddi_addr *addr)120{121	return *(u_short *)(&addr->a[0]) == 0xffff &&122	       *(u_short *)(&addr->a[2]) == 0xffff &&123	       *(u_short *)(&addr->a[4]) == 0xffff;124}125 126static inline int is_individual(const struct fddi_addr *addr)127{128	return !(addr->a[0] & GROUP_ADDR);129}130 131static inline int is_equal(const struct fddi_addr *addr1, 132			   const struct fddi_addr *addr2)133{134	return *(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) &&135	       *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) &&136	       *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]);137}138 139/*140 * list of mandatory paras in frames141 */142static const u_short plist_nif[] = { SMT_P_UNA,SMT_P_SDE,SMT_P_STATE,0 } ;143 144/*145 * init SMT agent146 */147void smt_agent_init(struct s_smc *smc)148{149	int		i ;150 151	/*152	 * get MAC address153	 */154	smc->mib.m[MAC0].fddiMACSMTAddress = smc->hw.fddi_home_addr ;155 156	/*157	 * get OUI address from driver (bia == built-in-address)158	 */159	smc->mib.fddiSMTStationId.sid_oem[0] = 0 ;160	smc->mib.fddiSMTStationId.sid_oem[1] = 0 ;161	driver_get_bia(smc,&smc->mib.fddiSMTStationId.sid_node) ;162	for (i = 0 ; i < 6 ; i ++) {163		smc->mib.fddiSMTStationId.sid_node.a[i] =164			bitrev8(smc->mib.fddiSMTStationId.sid_node.a[i]);165	}166	smc->mib.fddiSMTManufacturerData[0] =167		smc->mib.fddiSMTStationId.sid_node.a[0] ;168	smc->mib.fddiSMTManufacturerData[1] =169		smc->mib.fddiSMTStationId.sid_node.a[1] ;170	smc->mib.fddiSMTManufacturerData[2] =171		smc->mib.fddiSMTStationId.sid_node.a[2] ;172	smc->sm.smt_tid = 0 ;173	smc->mib.m[MAC0].fddiMACDupAddressTest = DA_NONE ;174	smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;175#ifndef	SLIM_SMT176	smt_clear_una_dna(smc) ;177	smt_clear_old_una_dna(smc) ;178#endif179	for (i = 0 ; i < SMT_MAX_TEST ; i++)180		smc->sm.pend[i] = 0 ;181	smc->sm.please_reconnect = 0 ;182	smc->sm.uniq_ticks = 0 ;183}184 185/*186 * SMT task187 * forever188 *	delay 30 seconds189 *	send NIF190 *	check tvu & tvd191 * end192 */193void smt_agent_task(struct s_smc *smc)194{195	smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,196		EV_TOKEN(EVENT_SMT,SM_TIMER)) ;197	DB_SMT("SMT agent task");198}199 200#ifndef SMT_REAL_TOKEN_CT201void smt_emulate_token_ct(struct s_smc *smc, int mac_index)202{203	u_long	count;204	u_long	time;205 206 207	time = smt_get_time();208	count =	((time - smc->sm.last_tok_time[mac_index]) *209					100)/TICKS_PER_SECOND;210 211	/*212	 * Only when ring is up we will have a token count. The213	 * flag is unfortunately a single instance value. This214	 * doesn't matter now, because we currently have only215	 * one MAC instance.216	 */217	if (smc->hw.mac_ring_is_up){218		smc->mib.m[mac_index].fddiMACToken_Ct += count;219	}220 221	/* Remember current time */222	smc->sm.last_tok_time[mac_index] = time;223 224}225#endif226 227/*ARGSUSED1*/228void smt_event(struct s_smc *smc, int event)229{230	u_long		time ;231#ifndef SMT_REAL_TOKEN_CT232	int		i ;233#endif234 235 236	if (smc->sm.please_reconnect) {237		smc->sm.please_reconnect -- ;238		if (smc->sm.please_reconnect == 0) {239			/* Counted down */240			queue_event(smc,EVENT_ECM,EC_CONNECT) ;241		}242	}243 244	if (event == SM_FAST)245		return ;246 247	/*248	 * timer for periodic cleanup in driver249	 * reset and start the watchdog (FM2)250	 * ESS timer251	 * SBA timer252	 */253	smt_timer_poll(smc) ;254	smt_start_watchdog(smc) ;255#ifndef	SLIM_SMT256#ifndef BOOT257#ifdef	ESS258	ess_timer_poll(smc) ;259#endif260#endif261#ifdef	SBA262	sba_timer_poll(smc) ;263#endif264 265	smt_srf_event(smc,0,0,0) ;266 267#endif	/* no SLIM_SMT */268 269	time = smt_get_time() ;270 271	if (time - smc->sm.smt_last_lem >= TICKS_PER_SECOND*8) {272		/*273		 * Use 8 sec. for the time intervall, it simplifies the274		 * LER estimation.275		 */276		struct fddi_mib_m	*mib ;277		u_long			upper ;278		u_long			lower ;279		int			cond ;280		int			port;281		struct s_phy		*phy ;282		/*283		 * calculate LEM bit error rate284		 */285		sm_lem_evaluate(smc) ;286		smc->sm.smt_last_lem = time ;287 288		/*289		 * check conditions290		 */291#ifndef	SLIM_SMT292		mac_update_counter(smc) ;293		mib = smc->mib.m ;294		upper =295		(mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) +296		(mib->fddiMACError_Ct - mib->fddiMACOld_Error_Ct) ;297		lower =298		(mib->fddiMACFrame_Ct - mib->fddiMACOld_Frame_Ct) +299		(mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) ;300		mib->fddiMACFrameErrorRatio = div_ratio(upper,lower) ;301 302		cond =303			((!mib->fddiMACFrameErrorThreshold &&304			mib->fddiMACError_Ct != mib->fddiMACOld_Error_Ct) ||305			(mib->fddiMACFrameErrorRatio >306			mib->fddiMACFrameErrorThreshold)) ;307 308		if (cond != mib->fddiMACFrameErrorFlag)309			smt_srf_event(smc,SMT_COND_MAC_FRAME_ERROR,310				INDEX_MAC,cond) ;311 312		upper =313		(mib->fddiMACNotCopied_Ct - mib->fddiMACOld_NotCopied_Ct) ;314		lower =315		upper +316		(mib->fddiMACCopied_Ct - mib->fddiMACOld_Copied_Ct) ;317		mib->fddiMACNotCopiedRatio = div_ratio(upper,lower) ;318 319		cond =320			((!mib->fddiMACNotCopiedThreshold &&321			mib->fddiMACNotCopied_Ct !=322				mib->fddiMACOld_NotCopied_Ct)||323			(mib->fddiMACNotCopiedRatio >324			mib->fddiMACNotCopiedThreshold)) ;325 326		if (cond != mib->fddiMACNotCopiedFlag)327			smt_srf_event(smc,SMT_COND_MAC_NOT_COPIED,328				INDEX_MAC,cond) ;329 330		/*331		 * set old values332		 */333		mib->fddiMACOld_Frame_Ct = mib->fddiMACFrame_Ct ;334		mib->fddiMACOld_Copied_Ct = mib->fddiMACCopied_Ct ;335		mib->fddiMACOld_Error_Ct = mib->fddiMACError_Ct ;336		mib->fddiMACOld_Lost_Ct = mib->fddiMACLost_Ct ;337		mib->fddiMACOld_NotCopied_Ct = mib->fddiMACNotCopied_Ct ;338 339		/*340		 * Check port EBError Condition341		 */342		for (port = 0; port < NUMPHYS; port ++) {343			phy = &smc->y[port] ;344 345			if (!phy->mib->fddiPORTHardwarePresent) {346				continue;347			}348 349			cond = (phy->mib->fddiPORTEBError_Ct -350				phy->mib->fddiPORTOldEBError_Ct > 5) ;351 352			/* If ratio is more than 5 in 8 seconds353			 * Set the condition.354			 */355			smt_srf_event(smc,SMT_COND_PORT_EB_ERROR,356				(int) (INDEX_PORT+ phy->np) ,cond) ;357 358			/*359			 * set old values360			 */361			phy->mib->fddiPORTOldEBError_Ct =362				phy->mib->fddiPORTEBError_Ct ;363		}364 365#endif	/* no SLIM_SMT */366	}367 368#ifndef	SLIM_SMT369 370	if (time - smc->sm.smt_last_notify >= (u_long)371		(smc->mib.fddiSMTTT_Notify * TICKS_PER_SECOND) ) {372		/*373		 * we can either send an announcement or a request374		 * a request will trigger a reply so that we can update375		 * our dna376		 * note: same tid must be used until reply is received377		 */378		if (!smc->sm.pend[SMT_TID_NIF])379			smc->sm.pend[SMT_TID_NIF] = smt_get_tid(smc) ;380		smt_send_nif(smc,&fddi_broadcast, FC_SMT_NSA,381			smc->sm.pend[SMT_TID_NIF], SMT_REQUEST,0) ;382		smc->sm.smt_last_notify = time ;383	}384 385	/*386	 * check timer387	 */388	if (smc->sm.smt_tvu &&389	    time - smc->sm.smt_tvu > 228*TICKS_PER_SECOND) {390		DB_SMT("SMT : UNA expired");391		smc->sm.smt_tvu = 0 ;392 393		if (!is_equal(&smc->mib.m[MAC0].fddiMACUpstreamNbr,394			&SMT_Unknown)){395			/* Do not update unknown address */396			smc->mib.m[MAC0].fddiMACOldUpstreamNbr=397				smc->mib.m[MAC0].fddiMACUpstreamNbr ;398		}399		smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;400		smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;401		/*402		 * Make sure the fddiMACUNDA_Flag = FALSE is403		 * included in the SRF so we don't generate404		 * a separate SRF for the deassertion of this405		 * condition406		 */407		update_dac(smc,0) ;408		smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,409			INDEX_MAC,0) ;410	}411	if (smc->sm.smt_tvd &&412	    time - smc->sm.smt_tvd > 228*TICKS_PER_SECOND) {413		DB_SMT("SMT : DNA expired");414		smc->sm.smt_tvd = 0 ;415		if (!is_equal(&smc->mib.m[MAC0].fddiMACDownstreamNbr,416			&SMT_Unknown)){417			/* Do not update unknown address */418			smc->mib.m[MAC0].fddiMACOldDownstreamNbr=419				smc->mib.m[MAC0].fddiMACDownstreamNbr ;420		}421		smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;422		smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,423			INDEX_MAC,0) ;424	}425 426#endif	/* no SLIM_SMT */427 428#ifndef SMT_REAL_TOKEN_CT429	/*430	 * Token counter emulation section. If hardware supports the token431	 * count, the token counter will be updated in mac_update_counter.432	 */433	for (i = MAC0; i < NUMMACS; i++ ){434		if (time - smc->sm.last_tok_time[i] > 2*TICKS_PER_SECOND ){435			smt_emulate_token_ct( smc, i );436		}437	}438#endif439 440	smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,441		EV_TOKEN(EVENT_SMT,SM_TIMER)) ;442}443 444static int div_ratio(u_long upper, u_long lower)445{446	if ((upper<<16L) < upper)447		upper = 0xffff0000L ;448	else449		upper <<= 16L ;450	if (!lower)451		return 0;452	return (int)(upper/lower) ;453}454 455#ifndef	SLIM_SMT456 457/*458 * receive packet handler459 */460void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs)461/* int fs;  frame status */462{463	struct smt_header	*sm ;464	int			local ;465 466	int			illegal = 0 ;467 468	switch (m_fc(mb)) {469	case FC_SMT_INFO :470	case FC_SMT_LAN_LOC :471	case FC_SMT_LOC :472	case FC_SMT_NSA :473		break ;474	default :475		smt_free_mbuf(smc,mb) ;476		return ;477	}478 479	smc->mib.m[MAC0].fddiMACSMTCopied_Ct++ ;480	sm = smtod(mb,struct smt_header *) ;481	local = ((fs & L_INDICATOR) != 0) ;482	hwm_conv_can(smc,(char *)sm,12) ;483 484	/* check destination address */485	if (is_individual(&sm->smt_dest) && !is_my_addr(smc,&sm->smt_dest)) {486		smt_free_mbuf(smc,mb) ;487		return ;488	}489#if	0		/* for DUP recognition, do NOT filter them */490	/* ignore loop back packets */491	if (is_my_addr(smc,&sm->smt_source) && !local) {492		smt_free_mbuf(smc,mb) ;493		return ;494	}495#endif496 497	smt_swap_para(sm,(int) mb->sm_len,1) ;498	DB_SMT("SMT : received packet [%s] at 0x%p",499	       smt_type_name[m_fc(mb) & 0xf], sm);500	DB_SMT("SMT : version %d, class %s",501	       sm->smt_version,502	       smt_class_name[sm->smt_class > LAST_CLASS ? 0 : sm->smt_class]);503 504#ifdef	SBA505	/*506	 * check if NSA frame507	 */508	if (m_fc(mb) == FC_SMT_NSA && sm->smt_class == SMT_NIF &&509		(sm->smt_type == SMT_ANNOUNCE || sm->smt_type == SMT_REQUEST)) {510			smc->sba.sm = sm ;511			sba(smc,NIF) ;512	}513#endif514 515	/*516	 * ignore any packet with NSA and A-indicator set517	 */518	if ( (fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) {519		DB_SMT("SMT : ignoring NSA with A-indicator set from %pM",520		       &sm->smt_source);521		smt_free_mbuf(smc,mb) ;522		return ;523	}524 525	/*526	 * ignore frames with illegal length527	 */528	if (((sm->smt_class == SMT_ECF) && (sm->smt_len > SMT_MAX_ECHO_LEN)) ||529	    ((sm->smt_class != SMT_ECF) && (sm->smt_len > SMT_MAX_INFO_LEN))) {530		smt_free_mbuf(smc,mb) ;531		return ;532	}533 534	/*535	 * check SMT version536	 */537	switch (sm->smt_class) {538	case SMT_NIF :539	case SMT_SIF_CONFIG :540	case SMT_SIF_OPER :541	case SMT_ECF :542		if (sm->smt_version != SMT_VID)543			illegal = 1;544		break ;545	default :546		if (sm->smt_version != SMT_VID_2)547			illegal = 1;548		break ;549	}550	if (illegal) {551		DB_SMT("SMT : version = %d, dest = %pM",552		       sm->smt_version, &sm->smt_source);553		smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_VERSION,local) ;554		smt_free_mbuf(smc,mb) ;555		return ;556	}557	if ((sm->smt_len > mb->sm_len - sizeof(struct smt_header)) ||558	    ((sm->smt_len & 3) && (sm->smt_class != SMT_ECF))) {559		DB_SMT("SMT: info length error, len = %d", sm->smt_len);560		smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,local) ;561		smt_free_mbuf(smc,mb) ;562		return ;563	}564	switch (sm->smt_class) {565	case SMT_NIF :566		if (smt_check_para(smc,sm,plist_nif)) {567			DB_SMT("SMT: NIF with para problem, ignoring");568			break ;569		}570		switch (sm->smt_type) {571		case SMT_ANNOUNCE :572		case SMT_REQUEST :573			if (!(fs & C_INDICATOR) && m_fc(mb) == FC_SMT_NSA574				&& is_broadcast(&sm->smt_dest)) {575				struct smt_p_state	*st ;576 577				/* set my UNA */578				if (!is_equal(579					&smc->mib.m[MAC0].fddiMACUpstreamNbr,580					&sm->smt_source)) {581					DB_SMT("SMT : updated my UNA = %pM",582					       &sm->smt_source);583					if (!is_equal(&smc->mib.m[MAC0].584					    fddiMACUpstreamNbr,&SMT_Unknown)){585					 /* Do not update unknown address */586					 smc->mib.m[MAC0].fddiMACOldUpstreamNbr=587					 smc->mib.m[MAC0].fddiMACUpstreamNbr ;588					}589 590					smc->mib.m[MAC0].fddiMACUpstreamNbr =591						sm->smt_source ;592					smt_srf_event(smc,593						SMT_EVENT_MAC_NEIGHBOR_CHANGE,594						INDEX_MAC,0) ;595					smt_echo_test(smc,0) ;596				}597				smc->sm.smt_tvu = smt_get_time() ;598				st = (struct smt_p_state *)599					sm_to_para(smc,sm,SMT_P_STATE) ;600				if (st) {601					smc->mib.m[MAC0].fddiMACUNDA_Flag =602					(st->st_dupl_addr & SMT_ST_MY_DUPA) ?603					TRUE : FALSE ;604					update_dac(smc,1) ;605				}606			}607			if ((sm->smt_type == SMT_REQUEST) &&608			    is_individual(&sm->smt_source) &&609			    ((!(fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) ||610			     (m_fc(mb) != FC_SMT_NSA))) {611				DB_SMT("SMT : replying to NIF request %pM",612				       &sm->smt_source);613				smt_send_nif(smc,&sm->smt_source,614					FC_SMT_INFO,615					sm->smt_tid,616					SMT_REPLY,local) ;617			}618			break ;619		case SMT_REPLY :620			DB_SMT("SMT : received NIF response from %pM",621			       &sm->smt_source);622			if (fs & A_INDICATOR) {623				smc->sm.pend[SMT_TID_NIF] = 0 ;624				DB_SMT("SMT : duplicate address");625				smc->mib.m[MAC0].fddiMACDupAddressTest =626					DA_FAILED ;627				smc->r.dup_addr_test = DA_FAILED ;628				queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;629				smc->mib.m[MAC0].fddiMACDA_Flag = TRUE ;630				update_dac(smc,1) ;631				break ;632			}633			if (sm->smt_tid == smc->sm.pend[SMT_TID_NIF]) {634				smc->sm.pend[SMT_TID_NIF] = 0 ;635				/* set my DNA */636				if (!is_equal(637					&smc->mib.m[MAC0].fddiMACDownstreamNbr,638					&sm->smt_source)) {639					DB_SMT("SMT : updated my DNA");640					if (!is_equal(&smc->mib.m[MAC0].641					 fddiMACDownstreamNbr, &SMT_Unknown)){642					 /* Do not update unknown address */643				smc->mib.m[MAC0].fddiMACOldDownstreamNbr =644					 smc->mib.m[MAC0].fddiMACDownstreamNbr ;645					}646 647					smc->mib.m[MAC0].fddiMACDownstreamNbr =648						sm->smt_source ;649					smt_srf_event(smc,650						SMT_EVENT_MAC_NEIGHBOR_CHANGE,651						INDEX_MAC,0) ;652					smt_echo_test(smc,1) ;653				}654				smc->mib.m[MAC0].fddiMACDA_Flag = FALSE ;655				update_dac(smc,1) ;656				smc->sm.smt_tvd = smt_get_time() ;657				smc->mib.m[MAC0].fddiMACDupAddressTest =658					DA_PASSED ;659				if (smc->r.dup_addr_test != DA_PASSED) {660					smc->r.dup_addr_test = DA_PASSED ;661					queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;662				}663			}664			else if (sm->smt_tid ==665				smc->sm.pend[SMT_TID_NIF_TEST]) {666				DB_SMT("SMT : NIF test TID ok");667			}668			else {669				DB_SMT("SMT : expected TID %lx, got %x",670				       smc->sm.pend[SMT_TID_NIF], sm->smt_tid);671			}672			break ;673		default :674			illegal = 2 ;675			break ;676		}677		break ;678	case SMT_SIF_CONFIG :	/* station information */679		if (sm->smt_type != SMT_REQUEST)680			break ;681		DB_SMT("SMT : replying to SIF Config request from %pM",682		       &sm->smt_source);683		smt_send_sif_config(smc,&sm->smt_source,sm->smt_tid,local) ;684		break ;685	case SMT_SIF_OPER :	/* station information */686		if (sm->smt_type != SMT_REQUEST)687			break ;688		DB_SMT("SMT : replying to SIF Operation request from %pM",689		       &sm->smt_source);690		smt_send_sif_operation(smc,&sm->smt_source,sm->smt_tid,local) ;691		break ;692	case SMT_ECF :		/* echo frame */693		switch (sm->smt_type) {694		case SMT_REPLY :695			smc->mib.priv.fddiPRIVECF_Reply_Rx++ ;696			DB_SMT("SMT: received ECF reply from %pM",697			       &sm->smt_source);698			if (sm_to_para(smc,sm,SMT_P_ECHODATA) == NULL) {699				DB_SMT("SMT: ECHODATA missing");700				break ;701			}702			if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF]) {703				DB_SMT("SMT : ECF test TID ok");704			}705			else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_UNA]) {706				DB_SMT("SMT : ECF test UNA ok");707			}708			else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_DNA]) {709				DB_SMT("SMT : ECF test DNA ok");710			}711			else {712				DB_SMT("SMT : expected TID %lx, got %x",713				       smc->sm.pend[SMT_TID_ECF],714				       sm->smt_tid);715			}716			break ;717		case SMT_REQUEST :718			smc->mib.priv.fddiPRIVECF_Req_Rx++ ;719			{720			if (sm->smt_len && !sm_to_para(smc,sm,SMT_P_ECHODATA)) {721				DB_SMT("SMT: ECF with para problem,sending RDF");722				smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,723					local) ;724				break ;725			}726			DB_SMT("SMT - sending ECF reply to %pM",727			       &sm->smt_source);728 729			/* set destination addr.  & reply */730			sm->smt_dest = sm->smt_source ;731			sm->smt_type = SMT_REPLY ;732			dump_smt(smc,sm,"ECF REPLY") ;733			smc->mib.priv.fddiPRIVECF_Reply_Tx++ ;734			smt_send_frame(smc,mb,FC_SMT_INFO,local) ;735			return ;		/* DON'T free mbuf */736			}737		default :738			illegal = 1 ;739			break ;740		}741		break ;742#ifndef	BOOT743	case SMT_RAF :		/* resource allocation */744#ifdef	ESS745		DB_ESSN(2, "ESS: RAF frame received");746		fs = ess_raf_received_pack(smc,mb,sm,fs) ;747#endif748 749#ifdef	SBA750		DB_SBAN(2, "SBA: RAF frame received") ;751		sba_raf_received_pack(smc,sm,fs) ;752#endif753		break ;754	case SMT_RDF :		/* request denied */755		smc->mib.priv.fddiPRIVRDF_Rx++ ;756		break ;757	case SMT_ESF :		/* extended service - not supported */758		if (sm->smt_type == SMT_REQUEST) {759			DB_SMT("SMT - received ESF, sending RDF");760			smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;761		}762		break ;763	case SMT_PMF_GET :764	case SMT_PMF_SET :765		if (sm->smt_type != SMT_REQUEST)766			break ;767		/* update statistics */768		if (sm->smt_class == SMT_PMF_GET)769			smc->mib.priv.fddiPRIVPMF_Get_Rx++ ;770		else771			smc->mib.priv.fddiPRIVPMF_Set_Rx++ ;772		/*773		 * ignore PMF SET with I/G set774		 */775		if ((sm->smt_class == SMT_PMF_SET) &&776			!is_individual(&sm->smt_dest)) {777			DB_SMT("SMT: ignoring PMF-SET with I/G set");778			break ;779		}780		smt_pmf_received_pack(smc,mb, local) ;781		break ;782	case SMT_SRF :783		dump_smt(smc,sm,"SRF received") ;784		break ;785	default :786		if (sm->smt_type != SMT_REQUEST)787			break ;788		/*789		 * For frames with unknown class:790		 * we need to send a RDF frame according to 8.1.3.1.1,791		 * only if it is a REQUEST.792		 */793		DB_SMT("SMT : class = %d, send RDF to %pM",794		       sm->smt_class, &sm->smt_source);795 796		smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;797		break ;798#endif799	}800	if (illegal) {801		DB_SMT("SMT: discarding invalid frame, reason = %d", illegal);802	}803	smt_free_mbuf(smc,mb) ;804}805 806static void update_dac(struct s_smc *smc, int report)807{808	int	cond ;809 810	cond = ( smc->mib.m[MAC0].fddiMACUNDA_Flag |811		smc->mib.m[MAC0].fddiMACDA_Flag) != 0 ;812	if (report && (cond != smc->mib.m[MAC0].fddiMACDuplicateAddressCond))813		smt_srf_event(smc, SMT_COND_MAC_DUP_ADDR,INDEX_MAC,cond) ;814	else815		smc->mib.m[MAC0].fddiMACDuplicateAddressCond = cond ;816}817 818/*819 * send SMT frame820 *	set source address821 *	set station ID822 *	send frame823 */824void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local)825/* SMbuf *mb;	buffer to send */826/* int fc;	FC value */827{828	struct smt_header	*sm ;829 830	if (!smc->r.sm_ma_avail && !local) {831		smt_free_mbuf(smc,mb) ;832		return ;833	}834	sm = smtod(mb,struct smt_header *) ;835	sm->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ;836	sm->smt_sid = smc->mib.fddiSMTStationId ;837 838	smt_swap_para(sm,(int) mb->sm_len,0) ;		/* swap para & header */839	hwm_conv_can(smc,(char *)sm,12) ;		/* convert SA and DA */840	smc->mib.m[MAC0].fddiMACSMTTransmit_Ct++ ;841	smt_send_mbuf(smc,mb,local ? FC_SMT_LOC : fc) ;842}843 844/*845 * generate and send RDF846 */847static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason,848			 int local)849/* SMbuf *rej;	mbuf of offending frame */850/* int fc;	FC of denied frame */851/* int reason;	reason code */852{853	SMbuf	*mb ;854	struct smt_header	*sm ;	/* header of offending frame */855	struct smt_rdf	*rdf ;856	int		len ;857	int		frame_len ;858 859	sm = smtod(rej,struct smt_header *) ;860	if (sm->smt_type != SMT_REQUEST)861		return ;862 863	DB_SMT("SMT: sending RDF to %pM,reason = 0x%x",864	       &sm->smt_source, reason);865 866 867	/*868	 * note: get framelength from MAC length, NOT from SMT header869	 * smt header length is included in sm_len870	 */871	frame_len = rej->sm_len ;872 873	if (!(mb=smt_build_frame(smc,SMT_RDF,SMT_REPLY,sizeof(struct smt_rdf))))874		return ;875	rdf = smtod(mb,struct smt_rdf *) ;876	rdf->smt.smt_tid = sm->smt_tid ;		/* use TID from sm */877	rdf->smt.smt_dest = sm->smt_source ;		/* set dest = source */878 879	/* set P12 */880	rdf->reason.para.p_type = SMT_P_REASON ;881	rdf->reason.para.p_len = sizeof(struct smt_p_reason) - PARA_LEN ;882	rdf->reason.rdf_reason = reason ;883 884	/* set P14 */885	rdf->version.para.p_type = SMT_P_VERSION ;886	rdf->version.para.p_len = sizeof(struct smt_p_version) - PARA_LEN ;887	rdf->version.v_pad = 0 ;888	rdf->version.v_n = 1 ;889	rdf->version.v_index = 1 ;890	rdf->version.v_version[0] = SMT_VID_2 ;891	rdf->version.v_pad2 = 0 ;892 893	/* set P13 */894	if ((unsigned int) frame_len <= SMT_MAX_INFO_LEN - sizeof(*rdf) +895		2*sizeof(struct smt_header))896		len = frame_len ;897	else898		len = SMT_MAX_INFO_LEN - sizeof(*rdf) +899			2*sizeof(struct smt_header) ;900	/* make length multiple of 4 */901	len &= ~3 ;902	rdf->refused.para.p_type = SMT_P_REFUSED ;903	/* length of para is smt_frame + ref_fc */904	rdf->refused.para.p_len = len + 4 ;905	rdf->refused.ref_fc = fc ;906 907	/* swap it back */908	smt_swap_para(sm,frame_len,0) ;909 910	memcpy((char *) &rdf->refused.ref_header,(char *) sm,len) ;911 912	len -= sizeof(struct smt_header) ;913	mb->sm_len += len ;914	rdf->smt.smt_len += len ;915 916	dump_smt(smc,(struct smt_header *)rdf,"RDF") ;917	smc->mib.priv.fddiPRIVRDF_Tx++ ;918	smt_send_frame(smc,mb,FC_SMT_INFO,local) ;919}920 921/*922 * generate and send NIF923 */924static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, 925			 int fc, u_long tid, int type, int local)926/* struct fddi_addr *dest;	dest address */927/* int fc;			frame control */928/* u_long tid;			transaction id */929/* int type;			frame type */930{931	struct smt_nif	*nif ;932	SMbuf		*mb ;933 934	if (!(mb = smt_build_frame(smc,SMT_NIF,type,sizeof(struct smt_nif))))935		return ;936	nif = smtod(mb, struct smt_nif *) ;937	smt_fill_una(smc,&nif->una) ;	/* set UNA */938	smt_fill_sde(smc,&nif->sde) ;	/* set station descriptor */939	smt_fill_state(smc,&nif->state) ;	/* set state information */940#ifdef	SMT6_10941	smt_fill_fsc(smc,&nif->fsc) ;	/* set frame status cap. */942#endif943	nif->smt.smt_dest = *dest ;	/* destination address */944	nif->smt.smt_tid = tid ;	/* transaction ID */945	dump_smt(smc,(struct smt_header *)nif,"NIF") ;946	smt_send_frame(smc,mb,fc,local) ;947}948 949#ifdef	DEBUG950/*951 * send NIF request (test purpose)952 */953static void smt_send_nif_request(struct s_smc *smc, struct fddi_addr *dest)954{955	smc->sm.pend[SMT_TID_NIF_TEST] = smt_get_tid(smc) ;956	smt_send_nif(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_NIF_TEST],957		SMT_REQUEST,0) ;958}959 960/*961 * send ECF request (test purpose)962 */963static void smt_send_ecf_request(struct s_smc *smc, struct fddi_addr *dest,964				 int len)965{966	smc->sm.pend[SMT_TID_ECF] = smt_get_tid(smc) ;967	smt_send_ecf(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_ECF],968		SMT_REQUEST,len) ;969}970#endif971 972/*973 * echo test974 */975static void smt_echo_test(struct s_smc *smc, int dna)976{977	u_long	tid ;978 979	smc->sm.pend[dna ? SMT_TID_ECF_DNA : SMT_TID_ECF_UNA] =980		tid = smt_get_tid(smc) ;981	smt_send_ecf(smc, dna ?982		&smc->mib.m[MAC0].fddiMACDownstreamNbr :983		&smc->mib.m[MAC0].fddiMACUpstreamNbr,984		FC_SMT_INFO,tid, SMT_REQUEST, (SMT_TEST_ECHO_LEN & ~3)-8) ;985}986 987/*988 * generate and send ECF989 */990static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc,991			 u_long tid, int type, int len)992/* struct fddi_addr *dest;	dest address */993/* int fc;			frame control */994/* u_long tid;			transaction id */995/* int type;			frame type */996/* int len;			frame length */997{998	struct smt_ecf	*ecf ;999	SMbuf		*mb ;1000 1001	if (!(mb = smt_build_frame(smc,SMT_ECF,type,SMT_ECF_LEN + len)))1002		return ;1003	ecf = smtod(mb, struct smt_ecf *) ;1004 1005	smt_fill_echo(smc,&ecf->ec_echo,tid,len) ;	/* set ECHO */1006	ecf->smt.smt_dest = *dest ;	/* destination address */1007	ecf->smt.smt_tid = tid ;	/* transaction ID */1008	smc->mib.priv.fddiPRIVECF_Req_Tx++ ;1009	smt_send_frame(smc,mb,fc,0) ;1010}1011 1012/*1013 * generate and send SIF config response1014 */1015 1016static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest,1017				u_long tid, int local)1018/* struct fddi_addr *dest;	dest address */1019/* u_long tid;			transaction id */1020{1021	struct smt_sif_config	*sif ;1022	SMbuf			*mb ;1023	int			len ;1024	if (!(mb = smt_build_frame(smc,SMT_SIF_CONFIG,SMT_REPLY,1025		SIZEOF_SMT_SIF_CONFIG)))1026		return ;1027 1028	sif = smtod(mb, struct smt_sif_config *) ;1029	smt_fill_timestamp(smc,&sif->ts) ;	/* set time stamp */1030	smt_fill_sde(smc,&sif->sde) ;		/* set station descriptor */1031	smt_fill_version(smc,&sif->version) ;	/* set version information */1032	smt_fill_state(smc,&sif->state) ;	/* set state information */1033	smt_fill_policy(smc,&sif->policy) ;	/* set station policy */1034	smt_fill_latency(smc,&sif->latency);	/* set station latency */1035	smt_fill_neighbor(smc,&sif->neighbor);	/* set station neighbor */1036	smt_fill_setcount(smc,&sif->setcount) ;	/* set count */1037	len = smt_fill_path(smc,&sif->path);	/* set station path descriptor*/1038	sif->smt.smt_dest = *dest ;		/* destination address */1039	sif->smt.smt_tid = tid ;		/* transaction ID */1040	smt_add_frame_len(mb,len) ;		/* adjust length fields */1041	dump_smt(smc,(struct smt_header *)sif,"SIF Configuration Reply") ;1042	smt_send_frame(smc,mb,FC_SMT_INFO,local) ;1043}1044 1045/*1046 * generate and send SIF operation response1047 */1048 1049static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest,1050				   u_long tid, int local)1051/* struct fddi_addr *dest;	dest address */1052/* u_long tid;			transaction id */1053{1054	struct smt_sif_operation *sif ;1055	SMbuf			*mb ;1056	int			ports ;1057	int			i ;1058 1059	ports = NUMPHYS ;1060#ifndef	CONCENTRATOR1061	if (smc->s.sas == SMT_SAS)1062		ports = 1 ;1063#endif1064 1065	if (!(mb = smt_build_frame(smc,SMT_SIF_OPER,SMT_REPLY,1066				   struct_size(sif, lem, ports))))1067		return ;1068	sif = smtod(mb, typeof(sif));1069	smt_fill_timestamp(smc,&sif->ts) ;	/* set time stamp */1070	smt_fill_mac_status(smc,&sif->status) ; /* set mac status */1071	smt_fill_mac_counter(smc,&sif->mc) ; /* set mac counter field */1072	smt_fill_mac_fnc(smc,&sif->fnc) ; /* set frame not copied counter */1073	smt_fill_manufacturer(smc,&sif->man) ; /* set manufacturer field */1074	smt_fill_user(smc,&sif->user) ;		/* set user field */1075	smt_fill_setcount(smc,&sif->setcount) ;	/* set count */1076	/*1077	 * set link error mon information1078	 */1079	if (ports == 1) {1080		smt_fill_lem(smc,sif->lem,PS) ;1081	}1082	else {1083		for (i = 0 ; i < ports ; i++) {1084			smt_fill_lem(smc,&sif->lem[i],i) ;1085		}1086	}1087 1088	sif->smt.smt_dest = *dest ;	/* destination address */1089	sif->smt.smt_tid = tid ;	/* transaction ID */1090	dump_smt(smc,(struct smt_header *)sif,"SIF Operation Reply") ;1091	smt_send_frame(smc,mb,FC_SMT_INFO,local) ;1092}1093 1094/*1095 * get and initialize SMT frame1096 */1097SMbuf *smt_build_frame(struct s_smc *smc, int class, int type,1098				  int length)1099{1100	SMbuf			*mb ;1101	struct smt_header	*smt ;1102 1103#if	01104	if (!smc->r.sm_ma_avail) {1105		return 0;1106	}1107#endif1108	if (!(mb = smt_get_mbuf(smc)))1109		return mb;1110 1111	mb->sm_len = length ;1112	smt = smtod(mb, struct smt_header *) ;1113	smt->smt_dest = fddi_broadcast ; /* set dest = broadcast */1114	smt->smt_class = class ;1115	smt->smt_type = type ;1116	switch (class) {1117	case SMT_NIF :1118	case SMT_SIF_CONFIG :1119	case SMT_SIF_OPER :1120	case SMT_ECF :1121		smt->smt_version = SMT_VID ;1122		break ;1123	default :1124		smt->smt_version = SMT_VID_2 ;1125		break ;1126	}1127	smt->smt_tid = smt_get_tid(smc) ;	/* set transaction ID */1128	smt->smt_pad = 0 ;1129	smt->smt_len = length - sizeof(struct smt_header) ;1130	return mb;1131}1132 1133static void smt_add_frame_len(SMbuf *mb, int len)1134{1135	struct smt_header	*smt ;1136 1137	smt = smtod(mb, struct smt_header *) ;1138	smt->smt_len += len ;1139	mb->sm_len += len ;1140}1141 1142 1143 1144/*1145 * fill values in UNA parameter1146 */1147static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una)1148{1149	SMTSETPARA(una,SMT_P_UNA) ;1150	una->una_pad = 0 ;1151	una->una_node = smc->mib.m[MAC0].fddiMACUpstreamNbr ;1152}1153 1154/*1155 * fill values in SDE parameter1156 */1157static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde)1158{1159	SMTSETPARA(sde,SMT_P_SDE) ;1160	sde->sde_non_master = smc->mib.fddiSMTNonMaster_Ct ;1161	sde->sde_master = smc->mib.fddiSMTMaster_Ct ;1162	sde->sde_mac_count = NUMMACS ;		/* only 1 MAC */1163#ifdef	CONCENTRATOR1164	sde->sde_type = SMT_SDE_CONCENTRATOR ;1165#else1166	sde->sde_type = SMT_SDE_STATION ;1167#endif1168}1169 1170/*1171 * fill in values in station state parameter1172 */1173static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state)1174{1175	int	top ;1176	int	twist ;1177 1178	SMTSETPARA(state,SMT_P_STATE) ;1179	state->st_pad = 0 ;1180 1181	/* determine topology */1182	top = 0 ;1183	if (smc->mib.fddiSMTPeerWrapFlag) {1184		top |= SMT_ST_WRAPPED ;		/* state wrapped */1185	}1186#ifdef	CONCENTRATOR1187	if (cfm_status_unattached(smc)) {1188		top |= SMT_ST_UNATTACHED ;	/* unattached concentrator */1189	}1190#endif1191	if ((twist = pcm_status_twisted(smc)) & 1) {1192		top |= SMT_ST_TWISTED_A ;	/* twisted cable */1193	}1194	if (twist & 2) {1195		top |= SMT_ST_TWISTED_B ;	/* twisted cable */1196	}1197#ifdef	OPT_SRF1198	top |= SMT_ST_SRF ;1199#endif1200	if (pcm_rooted_station(smc))1201		top |= SMT_ST_ROOTED_S ;1202	if (smc->mib.a[0].fddiPATHSbaPayload != 0)1203		top |= SMT_ST_SYNC_SERVICE ;1204	state->st_topology = top ;1205	state->st_dupl_addr =1206		((smc->mib.m[MAC0].fddiMACDA_Flag ? SMT_ST_MY_DUPA : 0 ) |1207		 (smc->mib.m[MAC0].fddiMACUNDA_Flag ? SMT_ST_UNA_DUPA : 0)) ;1208}1209 1210/*1211 * fill values in timestamp parameter1212 */1213static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts)1214{1215 1216	SMTSETPARA(ts,SMT_P_TIMESTAMP) ;1217	smt_set_timestamp(smc,ts->ts_time) ;1218}1219 1220void smt_set_timestamp(struct s_smc *smc, u_char *p)1221{1222	u_long	time ;1223	u_long	utime ;1224 1225	/*1226	 * timestamp is 64 bits long ; resolution is 80 nS1227	 * our clock resolution is 10mS1228	 * 10mS/80ns = 125000 ~ 2^17 = 1310721229	 */1230	utime = smt_get_time() ;1231	time = utime * 100 ;1232	time /= TICKS_PER_SECOND ;1233	p[0] = 0 ;1234	p[1] = (u_char)((time>>(8+8+8+8-1)) & 1) ;1235	p[2] = (u_char)(time>>(8+8+8-1)) ;1236	p[3] = (u_char)(time>>(8+8-1)) ;1237	p[4] = (u_char)(time>>(8-1)) ;1238	p[5] = (u_char)(time<<1) ;1239	p[6] = (u_char)(smc->sm.uniq_ticks>>8) ;1240	p[7] = (u_char)smc->sm.uniq_ticks ;1241	/*1242	 * make sure we don't wrap: restart whenever the upper digits change1243	 */1244	if (utime != smc->sm.uniq_time) {1245		smc->sm.uniq_ticks = 0 ;1246	}1247	smc->sm.uniq_ticks++ ;1248	smc->sm.uniq_time = utime ;1249}1250 1251/*1252 * fill values in station policy parameter1253 */1254static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy)1255{1256	int	i ;1257	const u_char *map ;1258	u_short	in ;1259	u_short	out ;1260 1261	/*1262	 * MIB para 101b (fddiSMTConnectionPolicy) coding1263	 * is different from 0005 coding1264	 */1265	static const u_char ansi_weirdness[16] = {1266		0,7,5,3,8,1,6,4,9,10,2,11,12,13,14,151267	} ;1268	SMTSETPARA(policy,SMT_P_POLICY) ;1269 1270	out = 0 ;1271	in = smc->mib.fddiSMTConnectionPolicy ;1272	for (i = 0, map = ansi_weirdness ; i < 16 ; i++) {1273		if (in & 1)1274			out |= (1<<*map) ;1275		in >>= 1 ;1276		map++ ;1277	}1278	policy->pl_config = smc->mib.fddiSMTConfigPolicy ;1279	policy->pl_connect = out ;1280}1281 1282/*1283 * fill values in latency equivalent parameter1284 */1285static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency)1286{1287	SMTSETPARA(latency,SMT_P_LATENCY) ;1288 1289	latency->lt_phyout_idx1 = phy_index(smc,0) ;1290	latency->lt_latency1 = 10 ;	/* in octets (byte clock) */1291	/*1292	 * note: latency has two phy entries by definition1293	 * for a SAS, the 2nd one is null1294	 */1295	if (smc->s.sas == SMT_DAS) {1296		latency->lt_phyout_idx2 = phy_index(smc,1) ;1297		latency->lt_latency2 = 10 ;	/* in octets (byte clock) */1298	}1299	else {1300		latency->lt_phyout_idx2 = 0 ;1301		latency->lt_latency2 = 0 ;1302	}1303}1304 1305/*1306 * fill values in MAC neighbors parameter1307 */1308static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor)1309{1310	SMTSETPARA(neighbor,SMT_P_NEIGHBORS) ;1311 1312	neighbor->nb_mib_index = INDEX_MAC ;1313	neighbor->nb_mac_index = mac_index(smc,1) ;1314	neighbor->nb_una = smc->mib.m[MAC0].fddiMACUpstreamNbr ;1315	neighbor->nb_dna = smc->mib.m[MAC0].fddiMACDownstreamNbr ;1316}1317 1318/*1319 * fill values in path descriptor1320 */1321#ifdef	CONCENTRATOR1322#define ALLPHYS	NUMPHYS1323#else1324#define ALLPHYS	((smc->s.sas == SMT_SAS) ? 1 : 2)1325#endif1326 1327static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path)1328{1329	SK_LOC_DECL(int,type) ;1330	SK_LOC_DECL(int,state) ;1331	SK_LOC_DECL(int,remote) ;1332	SK_LOC_DECL(int,mac) ;1333	int	len ;1334	int	p ;1335	int	physp ;1336	struct smt_phy_rec	*phy ;1337	struct smt_mac_rec	*pd_mac ;1338 1339	len =	PARA_LEN +1340		sizeof(struct smt_mac_rec) * NUMMACS +1341		sizeof(struct smt_phy_rec) * ALLPHYS ;1342	path->para.p_type = SMT_P_PATH ;1343	path->para.p_len = len - PARA_LEN ;1344 1345	/* PHYs */1346	for (p = 0,phy = path->pd_phy ; p < ALLPHYS ; p++, phy++) {1347		physp = p ;1348#ifndef	CONCENTRATOR1349		if (smc->s.sas == SMT_SAS)1350			physp = PS ;1351#endif1352		pcm_status_state(smc,physp,&type,&state,&remote,&mac) ;1353#ifdef	LITTLE_ENDIAN1354		phy->phy_mib_index = smt_swap_short((u_short)p+INDEX_PORT) ;1355#else1356		phy->phy_mib_index = p+INDEX_PORT ;1357#endif1358		phy->phy_type = type ;1359		phy->phy_connect_state = state ;1360		phy->phy_remote_type = remote ;1361		phy->phy_remote_mac = mac ;1362		phy->phy_resource_idx = phy_con_resource_index(smc,p) ;1363	}1364 1365	/* MAC */1366	pd_mac = (struct smt_mac_rec *) phy ;1367	pd_mac->mac_addr = smc->mib.m[MAC0].fddiMACSMTAddress ;1368	pd_mac->mac_resource_idx = mac_con_resource_index(smc,1) ;1369	return len;1370}1371 1372/*1373 * fill values in mac status1374 */1375static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st)1376{1377	SMTSETPARA(st,SMT_P_MAC_STATUS) ;1378 1379	st->st_mib_index = INDEX_MAC ;1380	st->st_mac_index = mac_index(smc,1) ;1381 1382	mac_update_counter(smc) ;1383	/*1384	 * timer values are represented in SMT as 2's complement numbers1385	 * units :	internal :  2's complement BCLK1386	 */1387	st->st_t_req = smc->mib.m[MAC0].fddiMACT_Req ;1388	st->st_t_neg = smc->mib.m[MAC0].fddiMACT_Neg ;1389	st->st_t_max = smc->mib.m[MAC0].fddiMACT_Max ;1390	st->st_tvx_value = smc->mib.m[MAC0].fddiMACTvxValue ;1391	st->st_t_min = smc->mib.m[MAC0].fddiMACT_Min ;1392 1393	st->st_sba = smc->mib.a[PATH0].fddiPATHSbaPayload ;1394	st->st_frame_ct = smc->mib.m[MAC0].fddiMACFrame_Ct ;1395	st->st_error_ct = smc->mib.m[MAC0].fddiMACError_Ct ;1396	st->st_lost_ct = smc->mib.m[MAC0].fddiMACLost_Ct ;1397}1398 1399/*1400 * fill values in LEM status1401 */1402static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy)1403{1404	struct fddi_mib_p	*mib ;1405 1406	mib = smc->y[phy].mib ;1407 1408	SMTSETPARA(lem,SMT_P_LEM) ;1409	lem->lem_mib_index = phy+INDEX_PORT ;1410	lem->lem_phy_index = phy_index(smc,phy) ;1411	lem->lem_pad2 = 0 ;1412	lem->lem_cutoff = mib->fddiPORTLer_Cutoff ;1413	lem->lem_alarm = mib->fddiPORTLer_Alarm ;1414	/* long term bit error rate */1415	lem->lem_estimate = mib->fddiPORTLer_Estimate ;1416	/* # of rejected connections */1417	lem->lem_reject_ct = mib->fddiPORTLem_Reject_Ct ;1418	lem->lem_ct = mib->fddiPORTLem_Ct ;	/* total number of errors */1419}1420 1421/*1422 * fill version parameter1423 */1424static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers)1425{1426	SK_UNUSED(smc) ;1427	SMTSETPARA(vers,SMT_P_VERSION) ;1428	vers->v_pad = 0 ;1429	vers->v_n = 1 ;				/* one version is enough .. */1430	vers->v_index = 1 ;1431	vers->v_version[0] = SMT_VID_2 ;1432	vers->v_pad2 = 0 ;1433}1434 1435#ifdef	SMT6_101436/*1437 * fill frame status capabilities1438 */1439/*1440 * note: this para 200B is NOT in swap table, because it's also set in1441 * PMF add_para1442 */1443static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc)1444{1445	SK_UNUSED(smc) ;1446	SMTSETPARA(fsc,SMT_P_FSC) ;1447	fsc->fsc_pad0 = 0 ;1448	fsc->fsc_mac_index = INDEX_MAC ;	/* this is MIB ; MIB is NOT1449						 * mac_index ()i !1450						 */1451	fsc->fsc_pad1 = 0 ;1452	fsc->fsc_value = FSC_TYPE0 ;		/* "normal" node */1453#ifdef	LITTLE_ENDIAN1454	fsc->fsc_mac_index = smt_swap_short(INDEX_MAC) ;1455	fsc->fsc_value = smt_swap_short(FSC_TYPE0) ;1456#endif1457}1458#endif1459 1460/*1461 * fill mac counter field1462 */1463static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc)1464{1465	SMTSETPARA(mc,SMT_P_MAC_COUNTER) ;1466	mc->mc_mib_index = INDEX_MAC ;1467	mc->mc_index = mac_index(smc,1) ;1468	mc->mc_receive_ct = smc->mib.m[MAC0].fddiMACCopied_Ct ;1469	mc->mc_transmit_ct =  smc->mib.m[MAC0].fddiMACTransmit_Ct ;1470}1471 1472/*1473 * fill mac frame not copied counter1474 */1475static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc)1476{1477	SMTSETPARA(fnc,SMT_P_MAC_FNC) ;1478	fnc->nc_mib_index = INDEX_MAC ;1479	fnc->nc_index = mac_index(smc,1) ;1480	fnc->nc_counter = smc->mib.m[MAC0].fddiMACNotCopied_Ct ;1481}1482 1483 1484/*1485 * fill manufacturer field1486 */1487static void smt_fill_manufacturer(struct s_smc *smc, 1488				  struct smp_p_manufacturer *man)1489{1490	SMTSETPARA(man,SMT_P_MANUFACTURER) ;1491	memcpy((char *) man->mf_data,1492		(char *) smc->mib.fddiSMTManufacturerData,1493		sizeof(man->mf_data)) ;1494}1495 1496/*1497 * fill user field1498 */1499static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user)1500{1501	SMTSETPARA(user,SMT_P_USER) ;1502	memcpy((char *) user->us_data,1503		(char *) smc->mib.fddiSMTUserData,1504		sizeof(user->us_data)) ;1505}1506 1507/*1508 * fill set count1509 */1510static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount)1511{1512	SK_UNUSED(smc) ;1513	SMTSETPARA(setcount,SMT_P_SETCOUNT) ;1514	setcount->count = smc->mib.fddiSMTSetCount.count ;1515	memcpy((char *)setcount->timestamp,1516		(char *)smc->mib.fddiSMTSetCount.timestamp,8) ;1517}1518 1519/*1520 * fill echo data1521 */1522static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed,1523			  int len)1524{1525	u_char	*p ;1526 1527	SK_UNUSED(smc) ;1528	SMTSETPARA(echo,SMT_P_ECHODATA) ;1529	echo->para.p_len = len ;1530	for (p = echo->ec_data ; len ; len--) {1531		*p++ = (u_char) seed ;1532		seed += 13 ;1533	}1534}1535 1536/*1537 * clear DNA and UNA1538 * called from CFM if configuration changes1539 */1540static void smt_clear_una_dna(struct s_smc *smc)1541{1542	smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;1543	smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;1544}1545 1546static void smt_clear_old_una_dna(struct s_smc *smc)1547{1548	smc->mib.m[MAC0].fddiMACOldUpstreamNbr = SMT_Unknown ;1549	smc->mib.m[MAC0].fddiMACOldDownstreamNbr = SMT_Unknown ;1550}1551 1552u_long smt_get_tid(struct s_smc *smc)1553{1554	u_long	tid ;1555	while ((tid = ++(smc->sm.smt_tid) ^ SMT_TID_MAGIC) == 0)1556		;1557	return tid & 0x3fffffffL;1558}1559 1560#ifdef	LITTLE_ENDIAN1561/*1562 * table of parameter lengths1563 */1564static const struct smt_pdef {1565	int	ptype ;1566	int	plen ;1567	const char	*pswap ;1568} smt_pdef[] = {1569	{ SMT_P_UNA,	sizeof(struct smt_p_una) ,1570		SWAP_SMT_P_UNA					} ,1571	{ SMT_P_SDE,	sizeof(struct smt_p_sde) ,1572		SWAP_SMT_P_SDE					} ,1573	{ SMT_P_STATE,	sizeof(struct smt_p_state) ,1574		SWAP_SMT_P_STATE				} ,1575	{ SMT_P_TIMESTAMP,sizeof(struct smt_p_timestamp) ,1576		SWAP_SMT_P_TIMESTAMP				} ,1577	{ SMT_P_POLICY,	sizeof(struct smt_p_policy) ,1578		SWAP_SMT_P_POLICY				} ,1579	{ SMT_P_LATENCY,	sizeof(struct smt_p_latency) ,1580		SWAP_SMT_P_LATENCY				} ,1581	{ SMT_P_NEIGHBORS,sizeof(struct smt_p_neighbor) ,1582		SWAP_SMT_P_NEIGHBORS				} ,1583	{ SMT_P_PATH,	sizeof(struct smt_p_path) ,1584		SWAP_SMT_P_PATH					} ,1585	{ SMT_P_MAC_STATUS,sizeof(struct smt_p_mac_status) ,1586		SWAP_SMT_P_MAC_STATUS				} ,1587	{ SMT_P_LEM,	sizeof(struct smt_p_lem) ,1588		SWAP_SMT_P_LEM					} ,1589	{ SMT_P_MAC_COUNTER,sizeof(struct smt_p_mac_counter) ,1590		SWAP_SMT_P_MAC_COUNTER				} ,1591	{ SMT_P_MAC_FNC,sizeof(struct smt_p_mac_fnc) ,1592		SWAP_SMT_P_MAC_FNC				} ,1593	{ SMT_P_PRIORITY,sizeof(struct smt_p_priority) ,1594		SWAP_SMT_P_PRIORITY				} ,1595	{ SMT_P_EB,sizeof(struct smt_p_eb) ,1596		SWAP_SMT_P_EB					} ,1597	{ SMT_P_MANUFACTURER,sizeof(struct smp_p_manufacturer) ,1598		SWAP_SMT_P_MANUFACTURER				} ,1599	{ SMT_P_REASON,	sizeof(struct smt_p_reason) ,1600		SWAP_SMT_P_REASON				} ,1601	{ SMT_P_REFUSED, sizeof(struct smt_p_refused) ,1602		SWAP_SMT_P_REFUSED				} ,1603	{ SMT_P_VERSION, sizeof(struct smt_p_version) ,1604		SWAP_SMT_P_VERSION				} ,1605#ifdef ESS1606	{ SMT_P0015, sizeof(struct smt_p_0015) , SWAP_SMT_P0015 } ,1607	{ SMT_P0016, sizeof(struct smt_p_0016) , SWAP_SMT_P0016 } ,1608	{ SMT_P0017, sizeof(struct smt_p_0017) , SWAP_SMT_P0017 } ,1609	{ SMT_P0018, sizeof(struct smt_p_0018) , SWAP_SMT_P0018 } ,1610	{ SMT_P0019, sizeof(struct smt_p_0019) , SWAP_SMT_P0019 } ,1611	{ SMT_P001A, sizeof(struct smt_p_001a) , SWAP_SMT_P001A } ,1612	{ SMT_P001B, sizeof(struct smt_p_001b) , SWAP_SMT_P001B } ,1613	{ SMT_P001C, sizeof(struct smt_p_001c) , SWAP_SMT_P001C } ,1614	{ SMT_P001D, sizeof(struct smt_p_001d) , SWAP_SMT_P001D } ,1615#endif1616#if	01617	{ SMT_P_FSC,	sizeof(struct smt_p_fsc) ,1618		SWAP_SMT_P_FSC					} ,1619#endif1620 1621	{ SMT_P_SETCOUNT,0,	SWAP_SMT_P_SETCOUNT		} ,1622	{ SMT_P1048,	0,	SWAP_SMT_P1048			} ,1623	{ SMT_P208C,	0,	SWAP_SMT_P208C			} ,1624	{ SMT_P208D,	0,	SWAP_SMT_P208D			} ,1625	{ SMT_P208E,	0,	SWAP_SMT_P208E			} ,1626	{ SMT_P208F,	0,	SWAP_SMT_P208F			} ,1627	{ SMT_P2090,	0,	SWAP_SMT_P2090			} ,1628#ifdef	ESS1629	{ SMT_P320B, sizeof(struct smt_p_320b) , SWAP_SMT_P320B } ,1630	{ SMT_P320F, sizeof(struct smt_p_320f) , SWAP_SMT_P320F } ,1631	{ SMT_P3210, sizeof(struct smt_p_3210) , SWAP_SMT_P3210 } ,1632#endif1633	{ SMT_P4050,	0,	SWAP_SMT_P4050			} ,1634	{ SMT_P4051,	0,	SWAP_SMT_P4051			} ,1635	{ SMT_P4052,	0,	SWAP_SMT_P4052			} ,1636	{ SMT_P4053,	0,	SWAP_SMT_P4053			} ,1637} ;1638 1639#define N_SMT_PLEN	ARRAY_SIZE(smt_pdef)1640#endif1641 1642int smt_check_para(struct s_smc *smc, struct smt_header	*sm,1643		   const u_short list[])1644{1645	const u_short		*p = list ;1646	while (*p) {1647		if (!sm_to_para(smc,sm,(int) *p)) {1648			DB_SMT("SMT: smt_check_para - missing para %hx", *p);1649			return -1;1650		}1651		p++ ;1652	}1653	return 0;1654}1655 1656void *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para)1657{1658	char	*p ;1659	int	len ;1660	int	plen ;1661	void	*found = NULL;1662 1663	SK_UNUSED(smc) ;1664 1665	len = sm->smt_len ;1666	p = (char *)(sm+1) ;		/* pointer to info */1667	while (len > 0 ) {1668		if (((struct smt_para *)p)->p_type == para)1669			found = (void *) p ;1670		plen = ((struct smt_para *)p)->p_len + PARA_LEN ;1671		p += plen ;1672		len -= plen ;1673		if (len < 0) {1674			DB_SMT("SMT : sm_to_para - length error %d", plen);1675			return NULL;1676		}1677		if ((plen & 3) && (para != SMT_P_ECHODATA)) {1678			DB_SMT("SMT : sm_to_para - odd length %d", plen);1679			return NULL;1680		}1681		if (found)1682			return found;1683	}1684	return NULL;1685}1686 1687#if	01688/*1689 * send ANTC data test frame1690 */1691void fddi_send_antc(struct s_smc *smc, struct fddi_addr *dest)1692{1693	SK_UNUSED(smc) ;1694	SK_UNUSED(dest) ;1695#if	01696	SMbuf			*mb ;1697	struct smt_header	*smt ;1698	int			i ;1699	char			*p ;1700 1701	mb = smt_get_mbuf() ;1702	mb->sm_len = 3000+12 ;1703	p = smtod(mb, char *) + 12 ;1704	for (i = 0 ; i < 3000 ; i++)1705		*p++ = 1 << (i&7) ;1706 1707	smt = smtod(mb, struct smt_header *) ;1708	smt->smt_dest = *dest ;1709	smt->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ;1710	smt_send_mbuf(smc,mb,FC_ASYNC_LLC) ;1711#endif1712}1713#endif1714 1715/*1716 * return static mac index1717 */1718static int mac_index(struct s_smc *smc, int mac)1719{1720	SK_UNUSED(mac) ;1721#ifdef	CONCENTRATOR1722	SK_UNUSED(smc) ;1723	return NUMPHYS + 1;1724#else1725	return (smc->s.sas == SMT_SAS) ? 2 : 3;1726#endif1727}1728 1729/*1730 * return static phy index1731 */1732static int phy_index(struct s_smc *smc, int phy)1733{1734	SK_UNUSED(smc) ;1735	return phy + 1;1736}1737 1738/*1739 * return dynamic mac connection resource index1740 */1741static int mac_con_resource_index(struct s_smc *smc, int mac)1742{1743#ifdef	CONCENTRATOR1744	SK_UNUSED(smc) ;1745	SK_UNUSED(mac) ;1746	return entity_to_index(smc, cem_get_downstream(smc, ENTITY_MAC));1747#else1748	SK_UNUSED(mac) ;1749	switch (smc->mib.fddiSMTCF_State) {1750	case SC9_C_WRAP_A :1751	case SC5_THRU_B :1752	case SC11_C_WRAP_S :1753		return 1;1754	case SC10_C_WRAP_B :1755	case SC4_THRU_A :1756		return 2;1757	}1758	return smc->s.sas == SMT_SAS ? 2 : 3;1759#endif1760}1761 1762/*1763 * return dynamic phy connection resource index1764 */1765static int phy_con_resource_index(struct s_smc *smc, int phy)1766{1767#ifdef	CONCENTRATOR1768	return entity_to_index(smc, cem_get_downstream(smc, ENTITY_PHY(phy))) ;1769#else1770	switch (smc->mib.fddiSMTCF_State) {1771	case SC9_C_WRAP_A :1772		return phy == PA ? 3 : 2;1773	case SC10_C_WRAP_B :1774		return phy == PA ? 1 : 3;1775	case SC4_THRU_A :1776		return phy == PA ? 3 : 1;1777	case SC5_THRU_B :1778		return phy == PA ? 2 : 3;1779	case SC11_C_WRAP_S :1780		return 2;1781	}1782	return phy;1783#endif1784}1785 1786#ifdef	CONCENTRATOR1787static int entity_to_index(struct s_smc *smc, int e)1788{1789	if (e == ENTITY_MAC)1790		return mac_index(smc, 1);1791	else1792		return phy_index(smc, e - ENTITY_PHY(0));1793}1794#endif1795 1796#ifdef	LITTLE_ENDIAN1797static int smt_swap_short(u_short s)1798{1799	return ((s>>8)&0xff) | ((s&0xff)<<8);1800}1801 1802void smt_swap_para(struct smt_header *sm, int len, int direction)1803/* int direction;	0 encode 1 decode */1804{1805	struct smt_para	*pa ;1806	const  struct smt_pdef	*pd ;1807	char	*p ;1808	int	plen ;1809	int	type ;1810	int	i ;1811 1812/*	printf("smt_swap_para sm %x len %d dir %d\n",1813		sm,len,direction) ;1814 */1815	smt_string_swap((char *)sm,SWAP_SMTHEADER,len) ;1816 1817	/* swap args */1818	len -= sizeof(struct smt_header) ;1819 1820	p = (char *) (sm + 1) ;1821	while (len > 0) {1822		pa = (struct smt_para *) p ;1823		plen = pa->p_len ;1824		type = pa->p_type ;1825		pa->p_type = smt_swap_short(pa->p_type) ;1826		pa->p_len = smt_swap_short(pa->p_len) ;1827		if (direction) {1828			plen = pa->p_len ;1829			type = pa->p_type ;1830		}1831		/*1832		 * note: paras can have 0 length !1833		 */1834		if (plen < 0)1835			break ;1836		plen += PARA_LEN ;1837		for (i = N_SMT_PLEN, pd = smt_pdef; i ; i--,pd++) {1838			if (pd->ptype == type)1839				break ;1840		}1841		if (i && pd->pswap) {1842			smt_string_swap(p+PARA_LEN,pd->pswap,len) ;1843		}1844		len -= plen ;1845		p += plen ;1846	}1847}1848 1849 1850static void smt_string_swap(char *data, const char *format, int len)1851{1852	const char	*open_paren = NULL ;1853 1854	while (len > 0  && *format) {1855		switch (*format) {1856		case '[' :1857			open_paren = format ;1858			break ;1859		case ']' :1860			format = open_paren ;1861			break ;1862		case '1' :1863		case '2' :1864		case '3' :1865		case '4' :1866		case '5' :1867		case '6' :1868		case '7' :1869		case '8' :1870		case '9' :1871			data  += *format - '0' ;1872			len   -= *format - '0' ;1873			break ;1874		case 'c':1875			data++ ;1876			len-- ;1877			break ;1878		case 's' :1879			swap(data[0], data[1]) ;1880			data += 2 ;1881			len -= 2 ;1882			break ;1883		case 'l' :1884			swap(data[0], data[3]) ;1885			swap(data[1], data[2]) ;1886			data += 4 ;1887			len -= 4 ;1888			break ;1889		}1890		format++ ;1891	}1892}1893#else1894void smt_swap_para(struct smt_header *sm, int len, int direction)1895/* int direction;	0 encode 1 decode */1896{1897	SK_UNUSED(sm) ;1898	SK_UNUSED(len) ;1899	SK_UNUSED(direction) ;1900}1901#endif1902 1903/*1904 * PMF actions1905 */1906int smt_action(struct s_smc *smc, int class, int code, int index)1907{1908	int	event ;1909	int	port ;1910	DB_SMT("SMT: action %d code %d", class, code);1911	switch(class) {1912	case SMT_STATION_ACTION :1913		switch(code) {1914		case SMT_STATION_ACTION_CONNECT :1915			smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ;1916			queue_event(smc,EVENT_ECM,EC_CONNECT) ;1917			break ;1918		case SMT_STATION_ACTION_DISCONNECT :1919			queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;1920			smc->mib.fddiSMTRemoteDisconnectFlag = TRUE ;1921			RS_SET(smc,RS_DISCONNECT) ;1922			AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)1923				FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_DISCONNECT,1924				smt_get_event_word(smc));1925			break ;1926		case SMT_STATION_ACTION_PATHTEST :1927			AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)1928				FDDI_SMT_EVENT, (u_long) FDDI_PATH_TEST,1929				smt_get_event_word(smc));1930			break ;1931		case SMT_STATION_ACTION_SELFTEST :1932			AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)1933				FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_SELF_TEST,1934				smt_get_event_word(smc));1935			break ;1936		case SMT_STATION_ACTION_DISABLE_A :1937			if (smc->y[PA].pc_mode == PM_PEER) {1938				RS_SET(smc,RS_EVENT) ;1939				queue_event(smc,EVENT_PCM+PA,PC_DISABLE) ;1940			}1941			break ;1942		case SMT_STATION_ACTION_DISABLE_B :1943			if (smc->y[PB].pc_mode == PM_PEER) {1944				RS_SET(smc,RS_EVENT) ;1945				queue_event(smc,EVENT_PCM+PB,PC_DISABLE) ;1946			}1947			break ;1948		case SMT_STATION_ACTION_DISABLE_M :1949			for (port = 0 ; port <  NUMPHYS ; port++) {1950				if (smc->mib.p[port].fddiPORTMy_Type != TM)1951					continue ;1952				RS_SET(smc,RS_EVENT) ;1953				queue_event(smc,EVENT_PCM+port,PC_DISABLE) ;1954			}1955			break ;1956		default :1957			return 1;1958		}1959		break ;1960	case SMT_PORT_ACTION :1961		switch(code) {1962		case SMT_PORT_ACTION_ENABLE :1963			event = PC_ENABLE ;1964			break ;1965		case SMT_PORT_ACTION_DISABLE :1966			event = PC_DISABLE ;1967			break ;1968		case SMT_PORT_ACTION_MAINT :1969			event = PC_MAINT ;1970			break ;1971		case SMT_PORT_ACTION_START :1972			event = PC_START ;1973			break ;1974		case SMT_PORT_ACTION_STOP :1975			event = PC_STOP ;1976			break ;1977		default :1978			return 1;1979		}1980		queue_event(smc,EVENT_PCM+index,event) ;1981		break ;1982	default :1983		return 1;1984	}1985	return 0;1986}1987 1988/*1989 * canonical conversion of <len> bytes beginning form *data1990 */1991#ifdef  USE_CAN_ADDR1992static void hwm_conv_can(struct s_smc *smc, char *data, int len)1993{1994	int i ;1995 1996	SK_UNUSED(smc) ;1997 1998	for (i = len; i ; i--, data++)1999		*data = bitrev8(*data);2000}2001#endif2002 2003#endif	/* no SLIM_SMT */2004 2005