xref: /linux/drivers/net/fddi/skfp/smt.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
233f810b2SJeff Kirsher /******************************************************************************
333f810b2SJeff Kirsher  *
433f810b2SJeff Kirsher  *	(C)Copyright 1998,1999 SysKonnect,
533f810b2SJeff Kirsher  *	a business unit of Schneider & Koch & Co. Datensysteme GmbH.
633f810b2SJeff Kirsher  *
733f810b2SJeff Kirsher  *	See the file "skfddi.c" for further information.
833f810b2SJeff Kirsher  *
933f810b2SJeff Kirsher  *	The information in this file is provided "AS IS" without warranty.
1033f810b2SJeff Kirsher  *
1133f810b2SJeff Kirsher  ******************************************************************************/
1233f810b2SJeff Kirsher 
1333f810b2SJeff Kirsher #include "h/types.h"
1433f810b2SJeff Kirsher #include "h/fddi.h"
1533f810b2SJeff Kirsher #include "h/smc.h"
1633f810b2SJeff Kirsher #include "h/smt_p.h"
1733f810b2SJeff Kirsher #include <linux/bitrev.h>
1833f810b2SJeff Kirsher #include <linux/kernel.h>
1933f810b2SJeff Kirsher 
2033f810b2SJeff Kirsher #define KERNEL
2133f810b2SJeff Kirsher #include "h/smtstate.h"
2233f810b2SJeff Kirsher 
2333f810b2SJeff Kirsher /*
2433f810b2SJeff Kirsher  * FC in SMbuf
2533f810b2SJeff Kirsher  */
2633f810b2SJeff Kirsher #define m_fc(mb)	((mb)->sm_data[0])
2733f810b2SJeff Kirsher 
2833f810b2SJeff Kirsher #define SMT_TID_MAGIC	0x1f0a7b3c
2933f810b2SJeff Kirsher 
3033f810b2SJeff Kirsher static const char *const smt_type_name[] = {
3133f810b2SJeff Kirsher 	"SMT_00??", "SMT_INFO", "SMT_02??", "SMT_03??",
3233f810b2SJeff Kirsher 	"SMT_04??", "SMT_05??", "SMT_06??", "SMT_07??",
3333f810b2SJeff Kirsher 	"SMT_08??", "SMT_09??", "SMT_0A??", "SMT_0B??",
3433f810b2SJeff Kirsher 	"SMT_0C??", "SMT_0D??", "SMT_0E??", "SMT_NSA"
3533f810b2SJeff Kirsher } ;
3633f810b2SJeff Kirsher 
3733f810b2SJeff Kirsher static const char *const smt_class_name[] = {
3833f810b2SJeff Kirsher 	"UNKNOWN","NIF","SIF_CONFIG","SIF_OPER","ECF","RAF","RDF",
3933f810b2SJeff Kirsher 	"SRF","PMF_GET","PMF_SET","ESF"
4033f810b2SJeff Kirsher } ;
415671e8c1SJoe Perches 
4233f810b2SJeff Kirsher #define LAST_CLASS	(SMT_PMF_SET)
4333f810b2SJeff Kirsher 
4433f810b2SJeff Kirsher static const struct fddi_addr SMT_Unknown = {
4533f810b2SJeff Kirsher 	{ 0,0,0x1f,0,0,0 }
4633f810b2SJeff Kirsher } ;
4733f810b2SJeff Kirsher 
4833f810b2SJeff Kirsher /*
4933f810b2SJeff Kirsher  * function prototypes
5033f810b2SJeff Kirsher  */
5133f810b2SJeff Kirsher #ifdef	LITTLE_ENDIAN
5233f810b2SJeff Kirsher static int smt_swap_short(u_short s);
5333f810b2SJeff Kirsher #endif
5433f810b2SJeff Kirsher static int mac_index(struct s_smc *smc, int mac);
5533f810b2SJeff Kirsher static int phy_index(struct s_smc *smc, int phy);
5633f810b2SJeff Kirsher static int mac_con_resource_index(struct s_smc *smc, int mac);
5733f810b2SJeff Kirsher static int phy_con_resource_index(struct s_smc *smc, int phy);
5833f810b2SJeff Kirsher static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason,
5933f810b2SJeff Kirsher 			 int local);
6033f810b2SJeff Kirsher static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest,
6133f810b2SJeff Kirsher 			 int fc, u_long tid, int type, int local);
6233f810b2SJeff Kirsher static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc,
6333f810b2SJeff Kirsher                          u_long tid, int type, int len);
6433f810b2SJeff Kirsher static void smt_echo_test(struct s_smc *smc, int dna);
6533f810b2SJeff Kirsher static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest,
6633f810b2SJeff Kirsher 				u_long tid, int local);
6733f810b2SJeff Kirsher static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest,
6833f810b2SJeff Kirsher 				   u_long tid, int local);
6933f810b2SJeff Kirsher #ifdef LITTLE_ENDIAN
7033f810b2SJeff Kirsher static void smt_string_swap(char *data, const char *format, int len);
7133f810b2SJeff Kirsher #endif
7233f810b2SJeff Kirsher static void smt_add_frame_len(SMbuf *mb, int len);
7333f810b2SJeff Kirsher static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una);
7433f810b2SJeff Kirsher static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde);
7533f810b2SJeff Kirsher static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state);
7633f810b2SJeff Kirsher static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts);
7733f810b2SJeff Kirsher static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy);
7833f810b2SJeff Kirsher static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency);
7933f810b2SJeff Kirsher static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor);
8033f810b2SJeff Kirsher static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path);
8133f810b2SJeff Kirsher static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st);
8233f810b2SJeff Kirsher static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy);
8333f810b2SJeff Kirsher static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers);
8433f810b2SJeff Kirsher static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc);
8533f810b2SJeff Kirsher static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc);
8633f810b2SJeff Kirsher static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc);
8733f810b2SJeff Kirsher static void smt_fill_manufacturer(struct s_smc *smc,
8833f810b2SJeff Kirsher 				  struct smp_p_manufacturer *man);
8933f810b2SJeff Kirsher static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user);
9033f810b2SJeff Kirsher static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount);
9133f810b2SJeff Kirsher static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed,
9233f810b2SJeff Kirsher 			  int len);
9333f810b2SJeff Kirsher 
9433f810b2SJeff Kirsher static void smt_clear_una_dna(struct s_smc *smc);
9533f810b2SJeff Kirsher static void smt_clear_old_una_dna(struct s_smc *smc);
9633f810b2SJeff Kirsher #ifdef	CONCENTRATOR
9733f810b2SJeff Kirsher static int entity_to_index(void);
9833f810b2SJeff Kirsher #endif
9933f810b2SJeff Kirsher static void update_dac(struct s_smc *smc, int report);
10033f810b2SJeff Kirsher static int div_ratio(u_long upper, u_long lower);
10133f810b2SJeff Kirsher #ifdef  USE_CAN_ADDR
10233f810b2SJeff Kirsher static void	hwm_conv_can(struct s_smc *smc, char *data, int len);
10333f810b2SJeff Kirsher #else
10433f810b2SJeff Kirsher #define		hwm_conv_can(smc,data,len)
10533f810b2SJeff Kirsher #endif
10633f810b2SJeff Kirsher 
10733f810b2SJeff Kirsher 
is_my_addr(const struct s_smc * smc,const struct fddi_addr * addr)10833f810b2SJeff Kirsher static inline int is_my_addr(const struct s_smc *smc,
10933f810b2SJeff Kirsher 			     const struct fddi_addr *addr)
11033f810b2SJeff Kirsher {
11133f810b2SJeff Kirsher 	return(*(short *)(&addr->a[0]) ==
11233f810b2SJeff Kirsher 		*(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0])
11333f810b2SJeff Kirsher 	  && *(short *)(&addr->a[2]) ==
11433f810b2SJeff Kirsher 		*(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[2])
11533f810b2SJeff Kirsher 	  && *(short *)(&addr->a[4]) ==
11633f810b2SJeff Kirsher 		*(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ;
11733f810b2SJeff Kirsher }
11833f810b2SJeff Kirsher 
is_broadcast(const struct fddi_addr * addr)11933f810b2SJeff Kirsher static inline int is_broadcast(const struct fddi_addr *addr)
12033f810b2SJeff Kirsher {
12133f810b2SJeff Kirsher 	return *(u_short *)(&addr->a[0]) == 0xffff &&
12233f810b2SJeff Kirsher 	       *(u_short *)(&addr->a[2]) == 0xffff &&
12333f810b2SJeff Kirsher 	       *(u_short *)(&addr->a[4]) == 0xffff;
12433f810b2SJeff Kirsher }
12533f810b2SJeff Kirsher 
is_individual(const struct fddi_addr * addr)12633f810b2SJeff Kirsher static inline int is_individual(const struct fddi_addr *addr)
12733f810b2SJeff Kirsher {
12833f810b2SJeff Kirsher 	return !(addr->a[0] & GROUP_ADDR);
12933f810b2SJeff Kirsher }
13033f810b2SJeff Kirsher 
is_equal(const struct fddi_addr * addr1,const struct fddi_addr * addr2)13133f810b2SJeff Kirsher static inline int is_equal(const struct fddi_addr *addr1,
13233f810b2SJeff Kirsher 			   const struct fddi_addr *addr2)
13333f810b2SJeff Kirsher {
13433f810b2SJeff Kirsher 	return *(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) &&
13533f810b2SJeff Kirsher 	       *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) &&
13633f810b2SJeff Kirsher 	       *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]);
13733f810b2SJeff Kirsher }
13833f810b2SJeff Kirsher 
13933f810b2SJeff Kirsher /*
14033f810b2SJeff Kirsher  * list of mandatory paras in frames
14133f810b2SJeff Kirsher  */
14233f810b2SJeff Kirsher static const u_short plist_nif[] = { SMT_P_UNA,SMT_P_SDE,SMT_P_STATE,0 } ;
14333f810b2SJeff Kirsher 
14433f810b2SJeff Kirsher /*
14533f810b2SJeff Kirsher  * init SMT agent
14633f810b2SJeff Kirsher  */
smt_agent_init(struct s_smc * smc)14733f810b2SJeff Kirsher void smt_agent_init(struct s_smc *smc)
14833f810b2SJeff Kirsher {
14933f810b2SJeff Kirsher 	int		i ;
15033f810b2SJeff Kirsher 
15133f810b2SJeff Kirsher 	/*
15233f810b2SJeff Kirsher 	 * get MAC address
15333f810b2SJeff Kirsher 	 */
15433f810b2SJeff Kirsher 	smc->mib.m[MAC0].fddiMACSMTAddress = smc->hw.fddi_home_addr ;
15533f810b2SJeff Kirsher 
15633f810b2SJeff Kirsher 	/*
15733f810b2SJeff Kirsher 	 * get OUI address from driver (bia == built-in-address)
15833f810b2SJeff Kirsher 	 */
15933f810b2SJeff Kirsher 	smc->mib.fddiSMTStationId.sid_oem[0] = 0 ;
16033f810b2SJeff Kirsher 	smc->mib.fddiSMTStationId.sid_oem[1] = 0 ;
16133f810b2SJeff Kirsher 	driver_get_bia(smc,&smc->mib.fddiSMTStationId.sid_node) ;
16233f810b2SJeff Kirsher 	for (i = 0 ; i < 6 ; i ++) {
16333f810b2SJeff Kirsher 		smc->mib.fddiSMTStationId.sid_node.a[i] =
16433f810b2SJeff Kirsher 			bitrev8(smc->mib.fddiSMTStationId.sid_node.a[i]);
16533f810b2SJeff Kirsher 	}
16633f810b2SJeff Kirsher 	smc->mib.fddiSMTManufacturerData[0] =
16733f810b2SJeff Kirsher 		smc->mib.fddiSMTStationId.sid_node.a[0] ;
16833f810b2SJeff Kirsher 	smc->mib.fddiSMTManufacturerData[1] =
16933f810b2SJeff Kirsher 		smc->mib.fddiSMTStationId.sid_node.a[1] ;
17033f810b2SJeff Kirsher 	smc->mib.fddiSMTManufacturerData[2] =
17133f810b2SJeff Kirsher 		smc->mib.fddiSMTStationId.sid_node.a[2] ;
17233f810b2SJeff Kirsher 	smc->sm.smt_tid = 0 ;
17333f810b2SJeff Kirsher 	smc->mib.m[MAC0].fddiMACDupAddressTest = DA_NONE ;
17433f810b2SJeff Kirsher 	smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;
17533f810b2SJeff Kirsher #ifndef	SLIM_SMT
17633f810b2SJeff Kirsher 	smt_clear_una_dna(smc) ;
17733f810b2SJeff Kirsher 	smt_clear_old_una_dna(smc) ;
17833f810b2SJeff Kirsher #endif
17933f810b2SJeff Kirsher 	for (i = 0 ; i < SMT_MAX_TEST ; i++)
18033f810b2SJeff Kirsher 		smc->sm.pend[i] = 0 ;
18133f810b2SJeff Kirsher 	smc->sm.please_reconnect = 0 ;
18233f810b2SJeff Kirsher 	smc->sm.uniq_ticks = 0 ;
18333f810b2SJeff Kirsher }
18433f810b2SJeff Kirsher 
18533f810b2SJeff Kirsher /*
18633f810b2SJeff Kirsher  * SMT task
18733f810b2SJeff Kirsher  * forever
18833f810b2SJeff Kirsher  *	delay 30 seconds
18933f810b2SJeff Kirsher  *	send NIF
19033f810b2SJeff Kirsher  *	check tvu & tvd
19133f810b2SJeff Kirsher  * end
19233f810b2SJeff Kirsher  */
smt_agent_task(struct s_smc * smc)19333f810b2SJeff Kirsher void smt_agent_task(struct s_smc *smc)
19433f810b2SJeff Kirsher {
19533f810b2SJeff Kirsher 	smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,
19633f810b2SJeff Kirsher 		EV_TOKEN(EVENT_SMT,SM_TIMER)) ;
1975671e8c1SJoe Perches 	DB_SMT("SMT agent task");
19833f810b2SJeff Kirsher }
19933f810b2SJeff Kirsher 
20033f810b2SJeff Kirsher #ifndef SMT_REAL_TOKEN_CT
smt_emulate_token_ct(struct s_smc * smc,int mac_index)20133f810b2SJeff Kirsher void smt_emulate_token_ct(struct s_smc *smc, int mac_index)
20233f810b2SJeff Kirsher {
20333f810b2SJeff Kirsher 	u_long	count;
20433f810b2SJeff Kirsher 	u_long	time;
20533f810b2SJeff Kirsher 
20633f810b2SJeff Kirsher 
20733f810b2SJeff Kirsher 	time = smt_get_time();
20833f810b2SJeff Kirsher 	count =	((time - smc->sm.last_tok_time[mac_index]) *
20933f810b2SJeff Kirsher 					100)/TICKS_PER_SECOND;
21033f810b2SJeff Kirsher 
21133f810b2SJeff Kirsher 	/*
21233f810b2SJeff Kirsher 	 * Only when ring is up we will have a token count. The
21333f810b2SJeff Kirsher 	 * flag is unfortunately a single instance value. This
21433f810b2SJeff Kirsher 	 * doesn't matter now, because we currently have only
21533f810b2SJeff Kirsher 	 * one MAC instance.
21633f810b2SJeff Kirsher 	 */
21733f810b2SJeff Kirsher 	if (smc->hw.mac_ring_is_up){
21833f810b2SJeff Kirsher 		smc->mib.m[mac_index].fddiMACToken_Ct += count;
21933f810b2SJeff Kirsher 	}
22033f810b2SJeff Kirsher 
22133f810b2SJeff Kirsher 	/* Remember current time */
22233f810b2SJeff Kirsher 	smc->sm.last_tok_time[mac_index] = time;
22333f810b2SJeff Kirsher 
22433f810b2SJeff Kirsher }
22533f810b2SJeff Kirsher #endif
22633f810b2SJeff Kirsher 
22733f810b2SJeff Kirsher /*ARGSUSED1*/
smt_event(struct s_smc * smc,int event)22833f810b2SJeff Kirsher void smt_event(struct s_smc *smc, int event)
22933f810b2SJeff Kirsher {
23033f810b2SJeff Kirsher 	u_long		time ;
23133f810b2SJeff Kirsher #ifndef SMT_REAL_TOKEN_CT
23233f810b2SJeff Kirsher 	int		i ;
23333f810b2SJeff Kirsher #endif
23433f810b2SJeff Kirsher 
23533f810b2SJeff Kirsher 
23633f810b2SJeff Kirsher 	if (smc->sm.please_reconnect) {
23733f810b2SJeff Kirsher 		smc->sm.please_reconnect -- ;
23833f810b2SJeff Kirsher 		if (smc->sm.please_reconnect == 0) {
23933f810b2SJeff Kirsher 			/* Counted down */
24033f810b2SJeff Kirsher 			queue_event(smc,EVENT_ECM,EC_CONNECT) ;
24133f810b2SJeff Kirsher 		}
24233f810b2SJeff Kirsher 	}
24333f810b2SJeff Kirsher 
24433f810b2SJeff Kirsher 	if (event == SM_FAST)
24533f810b2SJeff Kirsher 		return ;
24633f810b2SJeff Kirsher 
24733f810b2SJeff Kirsher 	/*
24833f810b2SJeff Kirsher 	 * timer for periodic cleanup in driver
24933f810b2SJeff Kirsher 	 * reset and start the watchdog (FM2)
25033f810b2SJeff Kirsher 	 * ESS timer
25133f810b2SJeff Kirsher 	 * SBA timer
25233f810b2SJeff Kirsher 	 */
25333f810b2SJeff Kirsher 	smt_timer_poll(smc) ;
25433f810b2SJeff Kirsher 	smt_start_watchdog(smc) ;
25533f810b2SJeff Kirsher #ifndef	SLIM_SMT
25633f810b2SJeff Kirsher #ifndef BOOT
25733f810b2SJeff Kirsher #ifdef	ESS
25833f810b2SJeff Kirsher 	ess_timer_poll(smc) ;
25933f810b2SJeff Kirsher #endif
26033f810b2SJeff Kirsher #endif
26133f810b2SJeff Kirsher #ifdef	SBA
26233f810b2SJeff Kirsher 	sba_timer_poll(smc) ;
26333f810b2SJeff Kirsher #endif
26433f810b2SJeff Kirsher 
26533f810b2SJeff Kirsher 	smt_srf_event(smc,0,0,0) ;
26633f810b2SJeff Kirsher 
26733f810b2SJeff Kirsher #endif	/* no SLIM_SMT */
26833f810b2SJeff Kirsher 
26933f810b2SJeff Kirsher 	time = smt_get_time() ;
27033f810b2SJeff Kirsher 
27133f810b2SJeff Kirsher 	if (time - smc->sm.smt_last_lem >= TICKS_PER_SECOND*8) {
27233f810b2SJeff Kirsher 		/*
27333f810b2SJeff Kirsher 		 * Use 8 sec. for the time intervall, it simplifies the
27433f810b2SJeff Kirsher 		 * LER estimation.
27533f810b2SJeff Kirsher 		 */
27633f810b2SJeff Kirsher 		struct fddi_mib_m	*mib ;
27733f810b2SJeff Kirsher 		u_long			upper ;
27833f810b2SJeff Kirsher 		u_long			lower ;
27933f810b2SJeff Kirsher 		int			cond ;
28033f810b2SJeff Kirsher 		int			port;
28133f810b2SJeff Kirsher 		struct s_phy		*phy ;
28233f810b2SJeff Kirsher 		/*
28333f810b2SJeff Kirsher 		 * calculate LEM bit error rate
28433f810b2SJeff Kirsher 		 */
28533f810b2SJeff Kirsher 		sm_lem_evaluate(smc) ;
28633f810b2SJeff Kirsher 		smc->sm.smt_last_lem = time ;
28733f810b2SJeff Kirsher 
28833f810b2SJeff Kirsher 		/*
28933f810b2SJeff Kirsher 		 * check conditions
29033f810b2SJeff Kirsher 		 */
29133f810b2SJeff Kirsher #ifndef	SLIM_SMT
29233f810b2SJeff Kirsher 		mac_update_counter(smc) ;
29333f810b2SJeff Kirsher 		mib = smc->mib.m ;
29433f810b2SJeff Kirsher 		upper =
29533f810b2SJeff Kirsher 		(mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) +
29633f810b2SJeff Kirsher 		(mib->fddiMACError_Ct - mib->fddiMACOld_Error_Ct) ;
29733f810b2SJeff Kirsher 		lower =
29833f810b2SJeff Kirsher 		(mib->fddiMACFrame_Ct - mib->fddiMACOld_Frame_Ct) +
29933f810b2SJeff Kirsher 		(mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) ;
30033f810b2SJeff Kirsher 		mib->fddiMACFrameErrorRatio = div_ratio(upper,lower) ;
30133f810b2SJeff Kirsher 
30233f810b2SJeff Kirsher 		cond =
30333f810b2SJeff Kirsher 			((!mib->fddiMACFrameErrorThreshold &&
30433f810b2SJeff Kirsher 			mib->fddiMACError_Ct != mib->fddiMACOld_Error_Ct) ||
30533f810b2SJeff Kirsher 			(mib->fddiMACFrameErrorRatio >
30633f810b2SJeff Kirsher 			mib->fddiMACFrameErrorThreshold)) ;
30733f810b2SJeff Kirsher 
30833f810b2SJeff Kirsher 		if (cond != mib->fddiMACFrameErrorFlag)
30933f810b2SJeff Kirsher 			smt_srf_event(smc,SMT_COND_MAC_FRAME_ERROR,
31033f810b2SJeff Kirsher 				INDEX_MAC,cond) ;
31133f810b2SJeff Kirsher 
31233f810b2SJeff Kirsher 		upper =
31333f810b2SJeff Kirsher 		(mib->fddiMACNotCopied_Ct - mib->fddiMACOld_NotCopied_Ct) ;
31433f810b2SJeff Kirsher 		lower =
31533f810b2SJeff Kirsher 		upper +
31633f810b2SJeff Kirsher 		(mib->fddiMACCopied_Ct - mib->fddiMACOld_Copied_Ct) ;
31733f810b2SJeff Kirsher 		mib->fddiMACNotCopiedRatio = div_ratio(upper,lower) ;
31833f810b2SJeff Kirsher 
31933f810b2SJeff Kirsher 		cond =
32033f810b2SJeff Kirsher 			((!mib->fddiMACNotCopiedThreshold &&
32133f810b2SJeff Kirsher 			mib->fddiMACNotCopied_Ct !=
32233f810b2SJeff Kirsher 				mib->fddiMACOld_NotCopied_Ct)||
32333f810b2SJeff Kirsher 			(mib->fddiMACNotCopiedRatio >
32433f810b2SJeff Kirsher 			mib->fddiMACNotCopiedThreshold)) ;
32533f810b2SJeff Kirsher 
32633f810b2SJeff Kirsher 		if (cond != mib->fddiMACNotCopiedFlag)
32733f810b2SJeff Kirsher 			smt_srf_event(smc,SMT_COND_MAC_NOT_COPIED,
32833f810b2SJeff Kirsher 				INDEX_MAC,cond) ;
32933f810b2SJeff Kirsher 
33033f810b2SJeff Kirsher 		/*
33133f810b2SJeff Kirsher 		 * set old values
33233f810b2SJeff Kirsher 		 */
33333f810b2SJeff Kirsher 		mib->fddiMACOld_Frame_Ct = mib->fddiMACFrame_Ct ;
33433f810b2SJeff Kirsher 		mib->fddiMACOld_Copied_Ct = mib->fddiMACCopied_Ct ;
33533f810b2SJeff Kirsher 		mib->fddiMACOld_Error_Ct = mib->fddiMACError_Ct ;
33633f810b2SJeff Kirsher 		mib->fddiMACOld_Lost_Ct = mib->fddiMACLost_Ct ;
33733f810b2SJeff Kirsher 		mib->fddiMACOld_NotCopied_Ct = mib->fddiMACNotCopied_Ct ;
33833f810b2SJeff Kirsher 
33933f810b2SJeff Kirsher 		/*
34033f810b2SJeff Kirsher 		 * Check port EBError Condition
34133f810b2SJeff Kirsher 		 */
34233f810b2SJeff Kirsher 		for (port = 0; port < NUMPHYS; port ++) {
34333f810b2SJeff Kirsher 			phy = &smc->y[port] ;
34433f810b2SJeff Kirsher 
34533f810b2SJeff Kirsher 			if (!phy->mib->fddiPORTHardwarePresent) {
34633f810b2SJeff Kirsher 				continue;
34733f810b2SJeff Kirsher 			}
34833f810b2SJeff Kirsher 
34933f810b2SJeff Kirsher 			cond = (phy->mib->fddiPORTEBError_Ct -
35033f810b2SJeff Kirsher 				phy->mib->fddiPORTOldEBError_Ct > 5) ;
35133f810b2SJeff Kirsher 
35233f810b2SJeff Kirsher 			/* If ratio is more than 5 in 8 seconds
35333f810b2SJeff Kirsher 			 * Set the condition.
35433f810b2SJeff Kirsher 			 */
35533f810b2SJeff Kirsher 			smt_srf_event(smc,SMT_COND_PORT_EB_ERROR,
35633f810b2SJeff Kirsher 				(int) (INDEX_PORT+ phy->np) ,cond) ;
35733f810b2SJeff Kirsher 
35833f810b2SJeff Kirsher 			/*
35933f810b2SJeff Kirsher 			 * set old values
36033f810b2SJeff Kirsher 			 */
36133f810b2SJeff Kirsher 			phy->mib->fddiPORTOldEBError_Ct =
36233f810b2SJeff Kirsher 				phy->mib->fddiPORTEBError_Ct ;
36333f810b2SJeff Kirsher 		}
36433f810b2SJeff Kirsher 
36533f810b2SJeff Kirsher #endif	/* no SLIM_SMT */
36633f810b2SJeff Kirsher 	}
36733f810b2SJeff Kirsher 
36833f810b2SJeff Kirsher #ifndef	SLIM_SMT
36933f810b2SJeff Kirsher 
37033f810b2SJeff Kirsher 	if (time - smc->sm.smt_last_notify >= (u_long)
37133f810b2SJeff Kirsher 		(smc->mib.fddiSMTTT_Notify * TICKS_PER_SECOND) ) {
37233f810b2SJeff Kirsher 		/*
37333f810b2SJeff Kirsher 		 * we can either send an announcement or a request
37433f810b2SJeff Kirsher 		 * a request will trigger a reply so that we can update
37533f810b2SJeff Kirsher 		 * our dna
37633f810b2SJeff Kirsher 		 * note: same tid must be used until reply is received
37733f810b2SJeff Kirsher 		 */
37833f810b2SJeff Kirsher 		if (!smc->sm.pend[SMT_TID_NIF])
37933f810b2SJeff Kirsher 			smc->sm.pend[SMT_TID_NIF] = smt_get_tid(smc) ;
38033f810b2SJeff Kirsher 		smt_send_nif(smc,&fddi_broadcast, FC_SMT_NSA,
38133f810b2SJeff Kirsher 			smc->sm.pend[SMT_TID_NIF], SMT_REQUEST,0) ;
38233f810b2SJeff Kirsher 		smc->sm.smt_last_notify = time ;
38333f810b2SJeff Kirsher 	}
38433f810b2SJeff Kirsher 
38533f810b2SJeff Kirsher 	/*
38633f810b2SJeff Kirsher 	 * check timer
38733f810b2SJeff Kirsher 	 */
38833f810b2SJeff Kirsher 	if (smc->sm.smt_tvu &&
38933f810b2SJeff Kirsher 	    time - smc->sm.smt_tvu > 228*TICKS_PER_SECOND) {
3905671e8c1SJoe Perches 		DB_SMT("SMT : UNA expired");
39133f810b2SJeff Kirsher 		smc->sm.smt_tvu = 0 ;
39233f810b2SJeff Kirsher 
39333f810b2SJeff Kirsher 		if (!is_equal(&smc->mib.m[MAC0].fddiMACUpstreamNbr,
39433f810b2SJeff Kirsher 			&SMT_Unknown)){
39533f810b2SJeff Kirsher 			/* Do not update unknown address */
39633f810b2SJeff Kirsher 			smc->mib.m[MAC0].fddiMACOldUpstreamNbr=
39733f810b2SJeff Kirsher 				smc->mib.m[MAC0].fddiMACUpstreamNbr ;
39833f810b2SJeff Kirsher 		}
39933f810b2SJeff Kirsher 		smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;
40033f810b2SJeff Kirsher 		smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;
40133f810b2SJeff Kirsher 		/*
40233f810b2SJeff Kirsher 		 * Make sure the fddiMACUNDA_Flag = FALSE is
40333f810b2SJeff Kirsher 		 * included in the SRF so we don't generate
40433f810b2SJeff Kirsher 		 * a separate SRF for the deassertion of this
40533f810b2SJeff Kirsher 		 * condition
40633f810b2SJeff Kirsher 		 */
40733f810b2SJeff Kirsher 		update_dac(smc,0) ;
40833f810b2SJeff Kirsher 		smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,
40933f810b2SJeff Kirsher 			INDEX_MAC,0) ;
41033f810b2SJeff Kirsher 	}
41133f810b2SJeff Kirsher 	if (smc->sm.smt_tvd &&
41233f810b2SJeff Kirsher 	    time - smc->sm.smt_tvd > 228*TICKS_PER_SECOND) {
4135671e8c1SJoe Perches 		DB_SMT("SMT : DNA expired");
41433f810b2SJeff Kirsher 		smc->sm.smt_tvd = 0 ;
41533f810b2SJeff Kirsher 		if (!is_equal(&smc->mib.m[MAC0].fddiMACDownstreamNbr,
41633f810b2SJeff Kirsher 			&SMT_Unknown)){
41733f810b2SJeff Kirsher 			/* Do not update unknown address */
41833f810b2SJeff Kirsher 			smc->mib.m[MAC0].fddiMACOldDownstreamNbr=
41933f810b2SJeff Kirsher 				smc->mib.m[MAC0].fddiMACDownstreamNbr ;
42033f810b2SJeff Kirsher 		}
42133f810b2SJeff Kirsher 		smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;
42233f810b2SJeff Kirsher 		smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,
42333f810b2SJeff Kirsher 			INDEX_MAC,0) ;
42433f810b2SJeff Kirsher 	}
42533f810b2SJeff Kirsher 
42633f810b2SJeff Kirsher #endif	/* no SLIM_SMT */
42733f810b2SJeff Kirsher 
42833f810b2SJeff Kirsher #ifndef SMT_REAL_TOKEN_CT
42933f810b2SJeff Kirsher 	/*
43033f810b2SJeff Kirsher 	 * Token counter emulation section. If hardware supports the token
43133f810b2SJeff Kirsher 	 * count, the token counter will be updated in mac_update_counter.
43233f810b2SJeff Kirsher 	 */
43333f810b2SJeff Kirsher 	for (i = MAC0; i < NUMMACS; i++ ){
43433f810b2SJeff Kirsher 		if (time - smc->sm.last_tok_time[i] > 2*TICKS_PER_SECOND ){
43533f810b2SJeff Kirsher 			smt_emulate_token_ct( smc, i );
43633f810b2SJeff Kirsher 		}
43733f810b2SJeff Kirsher 	}
43833f810b2SJeff Kirsher #endif
43933f810b2SJeff Kirsher 
44033f810b2SJeff Kirsher 	smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,
44133f810b2SJeff Kirsher 		EV_TOKEN(EVENT_SMT,SM_TIMER)) ;
44233f810b2SJeff Kirsher }
44333f810b2SJeff Kirsher 
div_ratio(u_long upper,u_long lower)44433f810b2SJeff Kirsher static int div_ratio(u_long upper, u_long lower)
44533f810b2SJeff Kirsher {
44633f810b2SJeff Kirsher 	if ((upper<<16L) < upper)
44733f810b2SJeff Kirsher 		upper = 0xffff0000L ;
44833f810b2SJeff Kirsher 	else
44933f810b2SJeff Kirsher 		upper <<= 16L ;
45033f810b2SJeff Kirsher 	if (!lower)
45133f810b2SJeff Kirsher 		return 0;
45233f810b2SJeff Kirsher 	return (int)(upper/lower) ;
45333f810b2SJeff Kirsher }
45433f810b2SJeff Kirsher 
45533f810b2SJeff Kirsher #ifndef	SLIM_SMT
45633f810b2SJeff Kirsher 
45733f810b2SJeff Kirsher /*
45833f810b2SJeff Kirsher  * receive packet handler
45933f810b2SJeff Kirsher  */
smt_received_pack(struct s_smc * smc,SMbuf * mb,int fs)46033f810b2SJeff Kirsher void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs)
46133f810b2SJeff Kirsher /* int fs;  frame status */
46233f810b2SJeff Kirsher {
46333f810b2SJeff Kirsher 	struct smt_header	*sm ;
46433f810b2SJeff Kirsher 	int			local ;
46533f810b2SJeff Kirsher 
46633f810b2SJeff Kirsher 	int			illegal = 0 ;
46733f810b2SJeff Kirsher 
46833f810b2SJeff Kirsher 	switch (m_fc(mb)) {
46933f810b2SJeff Kirsher 	case FC_SMT_INFO :
47033f810b2SJeff Kirsher 	case FC_SMT_LAN_LOC :
47133f810b2SJeff Kirsher 	case FC_SMT_LOC :
47233f810b2SJeff Kirsher 	case FC_SMT_NSA :
47333f810b2SJeff Kirsher 		break ;
47433f810b2SJeff Kirsher 	default :
47533f810b2SJeff Kirsher 		smt_free_mbuf(smc,mb) ;
47633f810b2SJeff Kirsher 		return ;
47733f810b2SJeff Kirsher 	}
47833f810b2SJeff Kirsher 
47933f810b2SJeff Kirsher 	smc->mib.m[MAC0].fddiMACSMTCopied_Ct++ ;
48033f810b2SJeff Kirsher 	sm = smtod(mb,struct smt_header *) ;
48133f810b2SJeff Kirsher 	local = ((fs & L_INDICATOR) != 0) ;
48233f810b2SJeff Kirsher 	hwm_conv_can(smc,(char *)sm,12) ;
48333f810b2SJeff Kirsher 
48433f810b2SJeff Kirsher 	/* check destination address */
48533f810b2SJeff Kirsher 	if (is_individual(&sm->smt_dest) && !is_my_addr(smc,&sm->smt_dest)) {
48633f810b2SJeff Kirsher 		smt_free_mbuf(smc,mb) ;
48733f810b2SJeff Kirsher 		return ;
48833f810b2SJeff Kirsher 	}
48933f810b2SJeff Kirsher #if	0		/* for DUP recognition, do NOT filter them */
49033f810b2SJeff Kirsher 	/* ignore loop back packets */
49133f810b2SJeff Kirsher 	if (is_my_addr(smc,&sm->smt_source) && !local) {
49233f810b2SJeff Kirsher 		smt_free_mbuf(smc,mb) ;
49333f810b2SJeff Kirsher 		return ;
49433f810b2SJeff Kirsher 	}
49533f810b2SJeff Kirsher #endif
49633f810b2SJeff Kirsher 
49733f810b2SJeff Kirsher 	smt_swap_para(sm,(int) mb->sm_len,1) ;
4985671e8c1SJoe Perches 	DB_SMT("SMT : received packet [%s] at 0x%p",
49933f810b2SJeff Kirsher 	       smt_type_name[m_fc(mb) & 0xf], sm);
5005671e8c1SJoe Perches 	DB_SMT("SMT : version %d, class %s",
5015671e8c1SJoe Perches 	       sm->smt_version,
5025671e8c1SJoe Perches 	       smt_class_name[sm->smt_class > LAST_CLASS ? 0 : sm->smt_class]);
50333f810b2SJeff Kirsher 
50433f810b2SJeff Kirsher #ifdef	SBA
50533f810b2SJeff Kirsher 	/*
50633f810b2SJeff Kirsher 	 * check if NSA frame
50733f810b2SJeff Kirsher 	 */
50833f810b2SJeff Kirsher 	if (m_fc(mb) == FC_SMT_NSA && sm->smt_class == SMT_NIF &&
50933f810b2SJeff Kirsher 		(sm->smt_type == SMT_ANNOUNCE || sm->smt_type == SMT_REQUEST)) {
51033f810b2SJeff Kirsher 			smc->sba.sm = sm ;
51133f810b2SJeff Kirsher 			sba(smc,NIF) ;
51233f810b2SJeff Kirsher 	}
51333f810b2SJeff Kirsher #endif
51433f810b2SJeff Kirsher 
51533f810b2SJeff Kirsher 	/*
51633f810b2SJeff Kirsher 	 * ignore any packet with NSA and A-indicator set
51733f810b2SJeff Kirsher 	 */
51833f810b2SJeff Kirsher 	if ( (fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) {
519c19b05b8STetsuo Handa 		DB_SMT("SMT : ignoring NSA with A-indicator set from %pM",
520c19b05b8STetsuo Handa 		       &sm->smt_source);
52133f810b2SJeff Kirsher 		smt_free_mbuf(smc,mb) ;
52233f810b2SJeff Kirsher 		return ;
52333f810b2SJeff Kirsher 	}
52433f810b2SJeff Kirsher 
52533f810b2SJeff Kirsher 	/*
52633f810b2SJeff Kirsher 	 * ignore frames with illegal length
52733f810b2SJeff Kirsher 	 */
52833f810b2SJeff Kirsher 	if (((sm->smt_class == SMT_ECF) && (sm->smt_len > SMT_MAX_ECHO_LEN)) ||
52933f810b2SJeff Kirsher 	    ((sm->smt_class != SMT_ECF) && (sm->smt_len > SMT_MAX_INFO_LEN))) {
53033f810b2SJeff Kirsher 		smt_free_mbuf(smc,mb) ;
53133f810b2SJeff Kirsher 		return ;
53233f810b2SJeff Kirsher 	}
53333f810b2SJeff Kirsher 
53433f810b2SJeff Kirsher 	/*
53533f810b2SJeff Kirsher 	 * check SMT version
53633f810b2SJeff Kirsher 	 */
53733f810b2SJeff Kirsher 	switch (sm->smt_class) {
53833f810b2SJeff Kirsher 	case SMT_NIF :
53933f810b2SJeff Kirsher 	case SMT_SIF_CONFIG :
54033f810b2SJeff Kirsher 	case SMT_SIF_OPER :
54133f810b2SJeff Kirsher 	case SMT_ECF :
54233f810b2SJeff Kirsher 		if (sm->smt_version != SMT_VID)
54333f810b2SJeff Kirsher 			illegal = 1;
54433f810b2SJeff Kirsher 		break ;
54533f810b2SJeff Kirsher 	default :
54633f810b2SJeff Kirsher 		if (sm->smt_version != SMT_VID_2)
54733f810b2SJeff Kirsher 			illegal = 1;
54833f810b2SJeff Kirsher 		break ;
54933f810b2SJeff Kirsher 	}
55033f810b2SJeff Kirsher 	if (illegal) {
551c19b05b8STetsuo Handa 		DB_SMT("SMT : version = %d, dest = %pM",
552c19b05b8STetsuo Handa 		       sm->smt_version, &sm->smt_source);
55333f810b2SJeff Kirsher 		smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_VERSION,local) ;
55433f810b2SJeff Kirsher 		smt_free_mbuf(smc,mb) ;
55533f810b2SJeff Kirsher 		return ;
55633f810b2SJeff Kirsher 	}
55733f810b2SJeff Kirsher 	if ((sm->smt_len > mb->sm_len - sizeof(struct smt_header)) ||
55833f810b2SJeff Kirsher 	    ((sm->smt_len & 3) && (sm->smt_class != SMT_ECF))) {
5595671e8c1SJoe Perches 		DB_SMT("SMT: info length error, len = %d", sm->smt_len);
56033f810b2SJeff Kirsher 		smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,local) ;
56133f810b2SJeff Kirsher 		smt_free_mbuf(smc,mb) ;
56233f810b2SJeff Kirsher 		return ;
56333f810b2SJeff Kirsher 	}
56433f810b2SJeff Kirsher 	switch (sm->smt_class) {
56533f810b2SJeff Kirsher 	case SMT_NIF :
56633f810b2SJeff Kirsher 		if (smt_check_para(smc,sm,plist_nif)) {
5675671e8c1SJoe Perches 			DB_SMT("SMT: NIF with para problem, ignoring");
56833f810b2SJeff Kirsher 			break ;
56933f810b2SJeff Kirsher 		}
57033f810b2SJeff Kirsher 		switch (sm->smt_type) {
57133f810b2SJeff Kirsher 		case SMT_ANNOUNCE :
57233f810b2SJeff Kirsher 		case SMT_REQUEST :
57333f810b2SJeff Kirsher 			if (!(fs & C_INDICATOR) && m_fc(mb) == FC_SMT_NSA
57433f810b2SJeff Kirsher 				&& is_broadcast(&sm->smt_dest)) {
57533f810b2SJeff Kirsher 				struct smt_p_state	*st ;
57633f810b2SJeff Kirsher 
57733f810b2SJeff Kirsher 				/* set my UNA */
57833f810b2SJeff Kirsher 				if (!is_equal(
57933f810b2SJeff Kirsher 					&smc->mib.m[MAC0].fddiMACUpstreamNbr,
58033f810b2SJeff Kirsher 					&sm->smt_source)) {
581c19b05b8STetsuo Handa 					DB_SMT("SMT : updated my UNA = %pM",
582c19b05b8STetsuo Handa 					       &sm->smt_source);
58333f810b2SJeff Kirsher 					if (!is_equal(&smc->mib.m[MAC0].
58433f810b2SJeff Kirsher 					    fddiMACUpstreamNbr,&SMT_Unknown)){
58533f810b2SJeff Kirsher 					 /* Do not update unknown address */
58633f810b2SJeff Kirsher 					 smc->mib.m[MAC0].fddiMACOldUpstreamNbr=
58733f810b2SJeff Kirsher 					 smc->mib.m[MAC0].fddiMACUpstreamNbr ;
58833f810b2SJeff Kirsher 					}
58933f810b2SJeff Kirsher 
59033f810b2SJeff Kirsher 					smc->mib.m[MAC0].fddiMACUpstreamNbr =
59133f810b2SJeff Kirsher 						sm->smt_source ;
59233f810b2SJeff Kirsher 					smt_srf_event(smc,
59333f810b2SJeff Kirsher 						SMT_EVENT_MAC_NEIGHBOR_CHANGE,
59433f810b2SJeff Kirsher 						INDEX_MAC,0) ;
59533f810b2SJeff Kirsher 					smt_echo_test(smc,0) ;
59633f810b2SJeff Kirsher 				}
59733f810b2SJeff Kirsher 				smc->sm.smt_tvu = smt_get_time() ;
59833f810b2SJeff Kirsher 				st = (struct smt_p_state *)
59933f810b2SJeff Kirsher 					sm_to_para(smc,sm,SMT_P_STATE) ;
60033f810b2SJeff Kirsher 				if (st) {
60133f810b2SJeff Kirsher 					smc->mib.m[MAC0].fddiMACUNDA_Flag =
60233f810b2SJeff Kirsher 					(st->st_dupl_addr & SMT_ST_MY_DUPA) ?
60333f810b2SJeff Kirsher 					TRUE : FALSE ;
60433f810b2SJeff Kirsher 					update_dac(smc,1) ;
60533f810b2SJeff Kirsher 				}
60633f810b2SJeff Kirsher 			}
60733f810b2SJeff Kirsher 			if ((sm->smt_type == SMT_REQUEST) &&
60833f810b2SJeff Kirsher 			    is_individual(&sm->smt_source) &&
60933f810b2SJeff Kirsher 			    ((!(fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) ||
61033f810b2SJeff Kirsher 			     (m_fc(mb) != FC_SMT_NSA))) {
611c19b05b8STetsuo Handa 				DB_SMT("SMT : replying to NIF request %pM",
612c19b05b8STetsuo Handa 				       &sm->smt_source);
61333f810b2SJeff Kirsher 				smt_send_nif(smc,&sm->smt_source,
61433f810b2SJeff Kirsher 					FC_SMT_INFO,
61533f810b2SJeff Kirsher 					sm->smt_tid,
61633f810b2SJeff Kirsher 					SMT_REPLY,local) ;
61733f810b2SJeff Kirsher 			}
61833f810b2SJeff Kirsher 			break ;
61933f810b2SJeff Kirsher 		case SMT_REPLY :
620c19b05b8STetsuo Handa 			DB_SMT("SMT : received NIF response from %pM",
621c19b05b8STetsuo Handa 			       &sm->smt_source);
62233f810b2SJeff Kirsher 			if (fs & A_INDICATOR) {
62333f810b2SJeff Kirsher 				smc->sm.pend[SMT_TID_NIF] = 0 ;
6245671e8c1SJoe Perches 				DB_SMT("SMT : duplicate address");
62533f810b2SJeff Kirsher 				smc->mib.m[MAC0].fddiMACDupAddressTest =
62633f810b2SJeff Kirsher 					DA_FAILED ;
62733f810b2SJeff Kirsher 				smc->r.dup_addr_test = DA_FAILED ;
62833f810b2SJeff Kirsher 				queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
62933f810b2SJeff Kirsher 				smc->mib.m[MAC0].fddiMACDA_Flag = TRUE ;
63033f810b2SJeff Kirsher 				update_dac(smc,1) ;
63133f810b2SJeff Kirsher 				break ;
63233f810b2SJeff Kirsher 			}
63333f810b2SJeff Kirsher 			if (sm->smt_tid == smc->sm.pend[SMT_TID_NIF]) {
63433f810b2SJeff Kirsher 				smc->sm.pend[SMT_TID_NIF] = 0 ;
63533f810b2SJeff Kirsher 				/* set my DNA */
63633f810b2SJeff Kirsher 				if (!is_equal(
63733f810b2SJeff Kirsher 					&smc->mib.m[MAC0].fddiMACDownstreamNbr,
63833f810b2SJeff Kirsher 					&sm->smt_source)) {
6395671e8c1SJoe Perches 					DB_SMT("SMT : updated my DNA");
64033f810b2SJeff Kirsher 					if (!is_equal(&smc->mib.m[MAC0].
64133f810b2SJeff Kirsher 					 fddiMACDownstreamNbr, &SMT_Unknown)){
64233f810b2SJeff Kirsher 					 /* Do not update unknown address */
64333f810b2SJeff Kirsher 				smc->mib.m[MAC0].fddiMACOldDownstreamNbr =
64433f810b2SJeff Kirsher 					 smc->mib.m[MAC0].fddiMACDownstreamNbr ;
64533f810b2SJeff Kirsher 					}
64633f810b2SJeff Kirsher 
64733f810b2SJeff Kirsher 					smc->mib.m[MAC0].fddiMACDownstreamNbr =
64833f810b2SJeff Kirsher 						sm->smt_source ;
64933f810b2SJeff Kirsher 					smt_srf_event(smc,
65033f810b2SJeff Kirsher 						SMT_EVENT_MAC_NEIGHBOR_CHANGE,
65133f810b2SJeff Kirsher 						INDEX_MAC,0) ;
65233f810b2SJeff Kirsher 					smt_echo_test(smc,1) ;
65333f810b2SJeff Kirsher 				}
65433f810b2SJeff Kirsher 				smc->mib.m[MAC0].fddiMACDA_Flag = FALSE ;
65533f810b2SJeff Kirsher 				update_dac(smc,1) ;
65633f810b2SJeff Kirsher 				smc->sm.smt_tvd = smt_get_time() ;
65733f810b2SJeff Kirsher 				smc->mib.m[MAC0].fddiMACDupAddressTest =
65833f810b2SJeff Kirsher 					DA_PASSED ;
65933f810b2SJeff Kirsher 				if (smc->r.dup_addr_test != DA_PASSED) {
66033f810b2SJeff Kirsher 					smc->r.dup_addr_test = DA_PASSED ;
66133f810b2SJeff Kirsher 					queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
66233f810b2SJeff Kirsher 				}
66333f810b2SJeff Kirsher 			}
66433f810b2SJeff Kirsher 			else if (sm->smt_tid ==
66533f810b2SJeff Kirsher 				smc->sm.pend[SMT_TID_NIF_TEST]) {
6665671e8c1SJoe Perches 				DB_SMT("SMT : NIF test TID ok");
66733f810b2SJeff Kirsher 			}
66833f810b2SJeff Kirsher 			else {
6695671e8c1SJoe Perches 				DB_SMT("SMT : expected TID %lx, got %x",
67033f810b2SJeff Kirsher 				       smc->sm.pend[SMT_TID_NIF], sm->smt_tid);
67133f810b2SJeff Kirsher 			}
67233f810b2SJeff Kirsher 			break ;
67333f810b2SJeff Kirsher 		default :
67433f810b2SJeff Kirsher 			illegal = 2 ;
67533f810b2SJeff Kirsher 			break ;
67633f810b2SJeff Kirsher 		}
67733f810b2SJeff Kirsher 		break ;
67833f810b2SJeff Kirsher 	case SMT_SIF_CONFIG :	/* station information */
67933f810b2SJeff Kirsher 		if (sm->smt_type != SMT_REQUEST)
68033f810b2SJeff Kirsher 			break ;
681c19b05b8STetsuo Handa 		DB_SMT("SMT : replying to SIF Config request from %pM",
682c19b05b8STetsuo Handa 		       &sm->smt_source);
68333f810b2SJeff Kirsher 		smt_send_sif_config(smc,&sm->smt_source,sm->smt_tid,local) ;
68433f810b2SJeff Kirsher 		break ;
68533f810b2SJeff Kirsher 	case SMT_SIF_OPER :	/* station information */
68633f810b2SJeff Kirsher 		if (sm->smt_type != SMT_REQUEST)
68733f810b2SJeff Kirsher 			break ;
688c19b05b8STetsuo Handa 		DB_SMT("SMT : replying to SIF Operation request from %pM",
689c19b05b8STetsuo Handa 		       &sm->smt_source);
69033f810b2SJeff Kirsher 		smt_send_sif_operation(smc,&sm->smt_source,sm->smt_tid,local) ;
69133f810b2SJeff Kirsher 		break ;
69233f810b2SJeff Kirsher 	case SMT_ECF :		/* echo frame */
69333f810b2SJeff Kirsher 		switch (sm->smt_type) {
69433f810b2SJeff Kirsher 		case SMT_REPLY :
69533f810b2SJeff Kirsher 			smc->mib.priv.fddiPRIVECF_Reply_Rx++ ;
696c19b05b8STetsuo Handa 			DB_SMT("SMT: received ECF reply from %pM",
697c19b05b8STetsuo Handa 			       &sm->smt_source);
69833f810b2SJeff Kirsher 			if (sm_to_para(smc,sm,SMT_P_ECHODATA) == NULL) {
6995671e8c1SJoe Perches 				DB_SMT("SMT: ECHODATA missing");
70033f810b2SJeff Kirsher 				break ;
70133f810b2SJeff Kirsher 			}
70233f810b2SJeff Kirsher 			if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF]) {
7035671e8c1SJoe Perches 				DB_SMT("SMT : ECF test TID ok");
70433f810b2SJeff Kirsher 			}
70533f810b2SJeff Kirsher 			else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_UNA]) {
7065671e8c1SJoe Perches 				DB_SMT("SMT : ECF test UNA ok");
70733f810b2SJeff Kirsher 			}
70833f810b2SJeff Kirsher 			else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_DNA]) {
7095671e8c1SJoe Perches 				DB_SMT("SMT : ECF test DNA ok");
71033f810b2SJeff Kirsher 			}
71133f810b2SJeff Kirsher 			else {
7125671e8c1SJoe Perches 				DB_SMT("SMT : expected TID %lx, got %x",
71333f810b2SJeff Kirsher 				       smc->sm.pend[SMT_TID_ECF],
71433f810b2SJeff Kirsher 				       sm->smt_tid);
71533f810b2SJeff Kirsher 			}
71633f810b2SJeff Kirsher 			break ;
71733f810b2SJeff Kirsher 		case SMT_REQUEST :
71833f810b2SJeff Kirsher 			smc->mib.priv.fddiPRIVECF_Req_Rx++ ;
71933f810b2SJeff Kirsher 			{
72033f810b2SJeff Kirsher 			if (sm->smt_len && !sm_to_para(smc,sm,SMT_P_ECHODATA)) {
7215671e8c1SJoe Perches 				DB_SMT("SMT: ECF with para problem,sending RDF");
72233f810b2SJeff Kirsher 				smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,
72333f810b2SJeff Kirsher 					local) ;
72433f810b2SJeff Kirsher 				break ;
72533f810b2SJeff Kirsher 			}
726c19b05b8STetsuo Handa 			DB_SMT("SMT - sending ECF reply to %pM",
727c19b05b8STetsuo Handa 			       &sm->smt_source);
72833f810b2SJeff Kirsher 
72933f810b2SJeff Kirsher 			/* set destination addr.  & reply */
73033f810b2SJeff Kirsher 			sm->smt_dest = sm->smt_source ;
73133f810b2SJeff Kirsher 			sm->smt_type = SMT_REPLY ;
73233f810b2SJeff Kirsher 			dump_smt(smc,sm,"ECF REPLY") ;
73333f810b2SJeff Kirsher 			smc->mib.priv.fddiPRIVECF_Reply_Tx++ ;
73433f810b2SJeff Kirsher 			smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
73533f810b2SJeff Kirsher 			return ;		/* DON'T free mbuf */
73633f810b2SJeff Kirsher 			}
73733f810b2SJeff Kirsher 		default :
73833f810b2SJeff Kirsher 			illegal = 1 ;
73933f810b2SJeff Kirsher 			break ;
74033f810b2SJeff Kirsher 		}
74133f810b2SJeff Kirsher 		break ;
74233f810b2SJeff Kirsher #ifndef	BOOT
74333f810b2SJeff Kirsher 	case SMT_RAF :		/* resource allocation */
74433f810b2SJeff Kirsher #ifdef	ESS
7455671e8c1SJoe Perches 		DB_ESSN(2, "ESS: RAF frame received");
74633f810b2SJeff Kirsher 		fs = ess_raf_received_pack(smc,mb,sm,fs) ;
74733f810b2SJeff Kirsher #endif
74833f810b2SJeff Kirsher 
74933f810b2SJeff Kirsher #ifdef	SBA
750*2a11fb1dSTom Rix 		DB_SBAN(2, "SBA: RAF frame received") ;
75133f810b2SJeff Kirsher 		sba_raf_received_pack(smc,sm,fs) ;
75233f810b2SJeff Kirsher #endif
75333f810b2SJeff Kirsher 		break ;
75433f810b2SJeff Kirsher 	case SMT_RDF :		/* request denied */
75533f810b2SJeff Kirsher 		smc->mib.priv.fddiPRIVRDF_Rx++ ;
75633f810b2SJeff Kirsher 		break ;
75733f810b2SJeff Kirsher 	case SMT_ESF :		/* extended service - not supported */
75833f810b2SJeff Kirsher 		if (sm->smt_type == SMT_REQUEST) {
7595671e8c1SJoe Perches 			DB_SMT("SMT - received ESF, sending RDF");
76033f810b2SJeff Kirsher 			smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;
76133f810b2SJeff Kirsher 		}
76233f810b2SJeff Kirsher 		break ;
76333f810b2SJeff Kirsher 	case SMT_PMF_GET :
76433f810b2SJeff Kirsher 	case SMT_PMF_SET :
76533f810b2SJeff Kirsher 		if (sm->smt_type != SMT_REQUEST)
76633f810b2SJeff Kirsher 			break ;
76733f810b2SJeff Kirsher 		/* update statistics */
76833f810b2SJeff Kirsher 		if (sm->smt_class == SMT_PMF_GET)
76933f810b2SJeff Kirsher 			smc->mib.priv.fddiPRIVPMF_Get_Rx++ ;
77033f810b2SJeff Kirsher 		else
77133f810b2SJeff Kirsher 			smc->mib.priv.fddiPRIVPMF_Set_Rx++ ;
77233f810b2SJeff Kirsher 		/*
77333f810b2SJeff Kirsher 		 * ignore PMF SET with I/G set
77433f810b2SJeff Kirsher 		 */
77533f810b2SJeff Kirsher 		if ((sm->smt_class == SMT_PMF_SET) &&
77633f810b2SJeff Kirsher 			!is_individual(&sm->smt_dest)) {
7775671e8c1SJoe Perches 			DB_SMT("SMT: ignoring PMF-SET with I/G set");
77833f810b2SJeff Kirsher 			break ;
77933f810b2SJeff Kirsher 		}
78033f810b2SJeff Kirsher 		smt_pmf_received_pack(smc,mb, local) ;
78133f810b2SJeff Kirsher 		break ;
78233f810b2SJeff Kirsher 	case SMT_SRF :
78333f810b2SJeff Kirsher 		dump_smt(smc,sm,"SRF received") ;
78433f810b2SJeff Kirsher 		break ;
78533f810b2SJeff Kirsher 	default :
78633f810b2SJeff Kirsher 		if (sm->smt_type != SMT_REQUEST)
78733f810b2SJeff Kirsher 			break ;
78833f810b2SJeff Kirsher 		/*
78933f810b2SJeff Kirsher 		 * For frames with unknown class:
79033f810b2SJeff Kirsher 		 * we need to send a RDF frame according to 8.1.3.1.1,
79133f810b2SJeff Kirsher 		 * only if it is a REQUEST.
79233f810b2SJeff Kirsher 		 */
793c19b05b8STetsuo Handa 		DB_SMT("SMT : class = %d, send RDF to %pM",
794c19b05b8STetsuo Handa 		       sm->smt_class, &sm->smt_source);
79533f810b2SJeff Kirsher 
79633f810b2SJeff Kirsher 		smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;
79733f810b2SJeff Kirsher 		break ;
79833f810b2SJeff Kirsher #endif
79933f810b2SJeff Kirsher 	}
80033f810b2SJeff Kirsher 	if (illegal) {
8015671e8c1SJoe Perches 		DB_SMT("SMT: discarding invalid frame, reason = %d", illegal);
80233f810b2SJeff Kirsher 	}
80333f810b2SJeff Kirsher 	smt_free_mbuf(smc,mb) ;
80433f810b2SJeff Kirsher }
80533f810b2SJeff Kirsher 
update_dac(struct s_smc * smc,int report)80633f810b2SJeff Kirsher static void update_dac(struct s_smc *smc, int report)
80733f810b2SJeff Kirsher {
80833f810b2SJeff Kirsher 	int	cond ;
80933f810b2SJeff Kirsher 
81033f810b2SJeff Kirsher 	cond = ( smc->mib.m[MAC0].fddiMACUNDA_Flag |
81133f810b2SJeff Kirsher 		smc->mib.m[MAC0].fddiMACDA_Flag) != 0 ;
81233f810b2SJeff Kirsher 	if (report && (cond != smc->mib.m[MAC0].fddiMACDuplicateAddressCond))
81333f810b2SJeff Kirsher 		smt_srf_event(smc, SMT_COND_MAC_DUP_ADDR,INDEX_MAC,cond) ;
81433f810b2SJeff Kirsher 	else
81533f810b2SJeff Kirsher 		smc->mib.m[MAC0].fddiMACDuplicateAddressCond = cond ;
81633f810b2SJeff Kirsher }
81733f810b2SJeff Kirsher 
81833f810b2SJeff Kirsher /*
81933f810b2SJeff Kirsher  * send SMT frame
82033f810b2SJeff Kirsher  *	set source address
82133f810b2SJeff Kirsher  *	set station ID
82233f810b2SJeff Kirsher  *	send frame
82333f810b2SJeff Kirsher  */
smt_send_frame(struct s_smc * smc,SMbuf * mb,int fc,int local)82433f810b2SJeff Kirsher void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local)
82533f810b2SJeff Kirsher /* SMbuf *mb;	buffer to send */
82633f810b2SJeff Kirsher /* int fc;	FC value */
82733f810b2SJeff Kirsher {
82833f810b2SJeff Kirsher 	struct smt_header	*sm ;
82933f810b2SJeff Kirsher 
83033f810b2SJeff Kirsher 	if (!smc->r.sm_ma_avail && !local) {
83133f810b2SJeff Kirsher 		smt_free_mbuf(smc,mb) ;
83233f810b2SJeff Kirsher 		return ;
83333f810b2SJeff Kirsher 	}
83433f810b2SJeff Kirsher 	sm = smtod(mb,struct smt_header *) ;
83533f810b2SJeff Kirsher 	sm->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ;
83633f810b2SJeff Kirsher 	sm->smt_sid = smc->mib.fddiSMTStationId ;
83733f810b2SJeff Kirsher 
83833f810b2SJeff Kirsher 	smt_swap_para(sm,(int) mb->sm_len,0) ;		/* swap para & header */
83933f810b2SJeff Kirsher 	hwm_conv_can(smc,(char *)sm,12) ;		/* convert SA and DA */
84033f810b2SJeff Kirsher 	smc->mib.m[MAC0].fddiMACSMTTransmit_Ct++ ;
84133f810b2SJeff Kirsher 	smt_send_mbuf(smc,mb,local ? FC_SMT_LOC : fc) ;
84233f810b2SJeff Kirsher }
84333f810b2SJeff Kirsher 
84433f810b2SJeff Kirsher /*
84533f810b2SJeff Kirsher  * generate and send RDF
84633f810b2SJeff Kirsher  */
smt_send_rdf(struct s_smc * smc,SMbuf * rej,int fc,int reason,int local)84733f810b2SJeff Kirsher static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason,
84833f810b2SJeff Kirsher 			 int local)
84933f810b2SJeff Kirsher /* SMbuf *rej;	mbuf of offending frame */
85033f810b2SJeff Kirsher /* int fc;	FC of denied frame */
85133f810b2SJeff Kirsher /* int reason;	reason code */
85233f810b2SJeff Kirsher {
85333f810b2SJeff Kirsher 	SMbuf	*mb ;
85433f810b2SJeff Kirsher 	struct smt_header	*sm ;	/* header of offending frame */
85533f810b2SJeff Kirsher 	struct smt_rdf	*rdf ;
85633f810b2SJeff Kirsher 	int		len ;
85733f810b2SJeff Kirsher 	int		frame_len ;
85833f810b2SJeff Kirsher 
85933f810b2SJeff Kirsher 	sm = smtod(rej,struct smt_header *) ;
86033f810b2SJeff Kirsher 	if (sm->smt_type != SMT_REQUEST)
86133f810b2SJeff Kirsher 		return ;
86233f810b2SJeff Kirsher 
863c19b05b8STetsuo Handa 	DB_SMT("SMT: sending RDF to %pM,reason = 0x%x",
864c19b05b8STetsuo Handa 	       &sm->smt_source, reason);
86533f810b2SJeff Kirsher 
86633f810b2SJeff Kirsher 
86733f810b2SJeff Kirsher 	/*
86833f810b2SJeff Kirsher 	 * note: get framelength from MAC length, NOT from SMT header
86933f810b2SJeff Kirsher 	 * smt header length is included in sm_len
87033f810b2SJeff Kirsher 	 */
87133f810b2SJeff Kirsher 	frame_len = rej->sm_len ;
87233f810b2SJeff Kirsher 
87333f810b2SJeff Kirsher 	if (!(mb=smt_build_frame(smc,SMT_RDF,SMT_REPLY,sizeof(struct smt_rdf))))
87433f810b2SJeff Kirsher 		return ;
87533f810b2SJeff Kirsher 	rdf = smtod(mb,struct smt_rdf *) ;
87633f810b2SJeff Kirsher 	rdf->smt.smt_tid = sm->smt_tid ;		/* use TID from sm */
87733f810b2SJeff Kirsher 	rdf->smt.smt_dest = sm->smt_source ;		/* set dest = source */
87833f810b2SJeff Kirsher 
87933f810b2SJeff Kirsher 	/* set P12 */
88033f810b2SJeff Kirsher 	rdf->reason.para.p_type = SMT_P_REASON ;
88133f810b2SJeff Kirsher 	rdf->reason.para.p_len = sizeof(struct smt_p_reason) - PARA_LEN ;
88233f810b2SJeff Kirsher 	rdf->reason.rdf_reason = reason ;
88333f810b2SJeff Kirsher 
88433f810b2SJeff Kirsher 	/* set P14 */
88533f810b2SJeff Kirsher 	rdf->version.para.p_type = SMT_P_VERSION ;
88633f810b2SJeff Kirsher 	rdf->version.para.p_len = sizeof(struct smt_p_version) - PARA_LEN ;
88733f810b2SJeff Kirsher 	rdf->version.v_pad = 0 ;
88833f810b2SJeff Kirsher 	rdf->version.v_n = 1 ;
88933f810b2SJeff Kirsher 	rdf->version.v_index = 1 ;
89033f810b2SJeff Kirsher 	rdf->version.v_version[0] = SMT_VID_2 ;
89133f810b2SJeff Kirsher 	rdf->version.v_pad2 = 0 ;
89233f810b2SJeff Kirsher 
89333f810b2SJeff Kirsher 	/* set P13 */
89489e47d3bStanxiaojun 	if ((unsigned int) frame_len <= SMT_MAX_INFO_LEN - sizeof(*rdf) +
89533f810b2SJeff Kirsher 		2*sizeof(struct smt_header))
89633f810b2SJeff Kirsher 		len = frame_len ;
89733f810b2SJeff Kirsher 	else
89833f810b2SJeff Kirsher 		len = SMT_MAX_INFO_LEN - sizeof(*rdf) +
89933f810b2SJeff Kirsher 			2*sizeof(struct smt_header) ;
90033f810b2SJeff Kirsher 	/* make length multiple of 4 */
90133f810b2SJeff Kirsher 	len &= ~3 ;
90233f810b2SJeff Kirsher 	rdf->refused.para.p_type = SMT_P_REFUSED ;
90333f810b2SJeff Kirsher 	/* length of para is smt_frame + ref_fc */
90433f810b2SJeff Kirsher 	rdf->refused.para.p_len = len + 4 ;
90533f810b2SJeff Kirsher 	rdf->refused.ref_fc = fc ;
90633f810b2SJeff Kirsher 
90733f810b2SJeff Kirsher 	/* swap it back */
90833f810b2SJeff Kirsher 	smt_swap_para(sm,frame_len,0) ;
90933f810b2SJeff Kirsher 
91033f810b2SJeff Kirsher 	memcpy((char *) &rdf->refused.ref_header,(char *) sm,len) ;
91133f810b2SJeff Kirsher 
91233f810b2SJeff Kirsher 	len -= sizeof(struct smt_header) ;
91333f810b2SJeff Kirsher 	mb->sm_len += len ;
91433f810b2SJeff Kirsher 	rdf->smt.smt_len += len ;
91533f810b2SJeff Kirsher 
91633f810b2SJeff Kirsher 	dump_smt(smc,(struct smt_header *)rdf,"RDF") ;
91733f810b2SJeff Kirsher 	smc->mib.priv.fddiPRIVRDF_Tx++ ;
91833f810b2SJeff Kirsher 	smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
91933f810b2SJeff Kirsher }
92033f810b2SJeff Kirsher 
92133f810b2SJeff Kirsher /*
92233f810b2SJeff Kirsher  * generate and send NIF
92333f810b2SJeff Kirsher  */
smt_send_nif(struct s_smc * smc,const struct fddi_addr * dest,int fc,u_long tid,int type,int local)92433f810b2SJeff Kirsher static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest,
92533f810b2SJeff Kirsher 			 int fc, u_long tid, int type, int local)
92633f810b2SJeff Kirsher /* struct fddi_addr *dest;	dest address */
92733f810b2SJeff Kirsher /* int fc;			frame control */
92833f810b2SJeff Kirsher /* u_long tid;			transaction id */
92933f810b2SJeff Kirsher /* int type;			frame type */
93033f810b2SJeff Kirsher {
93133f810b2SJeff Kirsher 	struct smt_nif	*nif ;
93233f810b2SJeff Kirsher 	SMbuf		*mb ;
93333f810b2SJeff Kirsher 
93433f810b2SJeff Kirsher 	if (!(mb = smt_build_frame(smc,SMT_NIF,type,sizeof(struct smt_nif))))
93533f810b2SJeff Kirsher 		return ;
93633f810b2SJeff Kirsher 	nif = smtod(mb, struct smt_nif *) ;
93733f810b2SJeff Kirsher 	smt_fill_una(smc,&nif->una) ;	/* set UNA */
93833f810b2SJeff Kirsher 	smt_fill_sde(smc,&nif->sde) ;	/* set station descriptor */
93933f810b2SJeff Kirsher 	smt_fill_state(smc,&nif->state) ;	/* set state information */
94033f810b2SJeff Kirsher #ifdef	SMT6_10
94133f810b2SJeff Kirsher 	smt_fill_fsc(smc,&nif->fsc) ;	/* set frame status cap. */
94233f810b2SJeff Kirsher #endif
94333f810b2SJeff Kirsher 	nif->smt.smt_dest = *dest ;	/* destination address */
94433f810b2SJeff Kirsher 	nif->smt.smt_tid = tid ;	/* transaction ID */
94533f810b2SJeff Kirsher 	dump_smt(smc,(struct smt_header *)nif,"NIF") ;
94633f810b2SJeff Kirsher 	smt_send_frame(smc,mb,fc,local) ;
94733f810b2SJeff Kirsher }
94833f810b2SJeff Kirsher 
94933f810b2SJeff Kirsher #ifdef	DEBUG
95033f810b2SJeff Kirsher /*
95133f810b2SJeff Kirsher  * send NIF request (test purpose)
95233f810b2SJeff Kirsher  */
smt_send_nif_request(struct s_smc * smc,struct fddi_addr * dest)95333f810b2SJeff Kirsher static void smt_send_nif_request(struct s_smc *smc, struct fddi_addr *dest)
95433f810b2SJeff Kirsher {
95533f810b2SJeff Kirsher 	smc->sm.pend[SMT_TID_NIF_TEST] = smt_get_tid(smc) ;
95633f810b2SJeff Kirsher 	smt_send_nif(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_NIF_TEST],
95733f810b2SJeff Kirsher 		SMT_REQUEST,0) ;
95833f810b2SJeff Kirsher }
95933f810b2SJeff Kirsher 
96033f810b2SJeff Kirsher /*
96133f810b2SJeff Kirsher  * send ECF request (test purpose)
96233f810b2SJeff Kirsher  */
smt_send_ecf_request(struct s_smc * smc,struct fddi_addr * dest,int len)96333f810b2SJeff Kirsher static void smt_send_ecf_request(struct s_smc *smc, struct fddi_addr *dest,
96433f810b2SJeff Kirsher 				 int len)
96533f810b2SJeff Kirsher {
96633f810b2SJeff Kirsher 	smc->sm.pend[SMT_TID_ECF] = smt_get_tid(smc) ;
96733f810b2SJeff Kirsher 	smt_send_ecf(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_ECF],
96833f810b2SJeff Kirsher 		SMT_REQUEST,len) ;
96933f810b2SJeff Kirsher }
97033f810b2SJeff Kirsher #endif
97133f810b2SJeff Kirsher 
97233f810b2SJeff Kirsher /*
97333f810b2SJeff Kirsher  * echo test
97433f810b2SJeff Kirsher  */
smt_echo_test(struct s_smc * smc,int dna)97533f810b2SJeff Kirsher static void smt_echo_test(struct s_smc *smc, int dna)
97633f810b2SJeff Kirsher {
97733f810b2SJeff Kirsher 	u_long	tid ;
97833f810b2SJeff Kirsher 
97933f810b2SJeff Kirsher 	smc->sm.pend[dna ? SMT_TID_ECF_DNA : SMT_TID_ECF_UNA] =
98033f810b2SJeff Kirsher 		tid = smt_get_tid(smc) ;
98133f810b2SJeff Kirsher 	smt_send_ecf(smc, dna ?
98233f810b2SJeff Kirsher 		&smc->mib.m[MAC0].fddiMACDownstreamNbr :
98333f810b2SJeff Kirsher 		&smc->mib.m[MAC0].fddiMACUpstreamNbr,
98433f810b2SJeff Kirsher 		FC_SMT_INFO,tid, SMT_REQUEST, (SMT_TEST_ECHO_LEN & ~3)-8) ;
98533f810b2SJeff Kirsher }
98633f810b2SJeff Kirsher 
98733f810b2SJeff Kirsher /*
98833f810b2SJeff Kirsher  * generate and send ECF
98933f810b2SJeff Kirsher  */
smt_send_ecf(struct s_smc * smc,struct fddi_addr * dest,int fc,u_long tid,int type,int len)99033f810b2SJeff Kirsher static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc,
99133f810b2SJeff Kirsher 			 u_long tid, int type, int len)
99233f810b2SJeff Kirsher /* struct fddi_addr *dest;	dest address */
99333f810b2SJeff Kirsher /* int fc;			frame control */
99433f810b2SJeff Kirsher /* u_long tid;			transaction id */
99533f810b2SJeff Kirsher /* int type;			frame type */
99633f810b2SJeff Kirsher /* int len;			frame length */
99733f810b2SJeff Kirsher {
99833f810b2SJeff Kirsher 	struct smt_ecf	*ecf ;
99933f810b2SJeff Kirsher 	SMbuf		*mb ;
100033f810b2SJeff Kirsher 
100133f810b2SJeff Kirsher 	if (!(mb = smt_build_frame(smc,SMT_ECF,type,SMT_ECF_LEN + len)))
100233f810b2SJeff Kirsher 		return ;
100333f810b2SJeff Kirsher 	ecf = smtod(mb, struct smt_ecf *) ;
100433f810b2SJeff Kirsher 
100533f810b2SJeff Kirsher 	smt_fill_echo(smc,&ecf->ec_echo,tid,len) ;	/* set ECHO */
100633f810b2SJeff Kirsher 	ecf->smt.smt_dest = *dest ;	/* destination address */
100733f810b2SJeff Kirsher 	ecf->smt.smt_tid = tid ;	/* transaction ID */
100833f810b2SJeff Kirsher 	smc->mib.priv.fddiPRIVECF_Req_Tx++ ;
100933f810b2SJeff Kirsher 	smt_send_frame(smc,mb,fc,0) ;
101033f810b2SJeff Kirsher }
101133f810b2SJeff Kirsher 
101233f810b2SJeff Kirsher /*
101333f810b2SJeff Kirsher  * generate and send SIF config response
101433f810b2SJeff Kirsher  */
101533f810b2SJeff Kirsher 
smt_send_sif_config(struct s_smc * smc,struct fddi_addr * dest,u_long tid,int local)101633f810b2SJeff Kirsher static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest,
101733f810b2SJeff Kirsher 				u_long tid, int local)
101833f810b2SJeff Kirsher /* struct fddi_addr *dest;	dest address */
101933f810b2SJeff Kirsher /* u_long tid;			transaction id */
102033f810b2SJeff Kirsher {
102133f810b2SJeff Kirsher 	struct smt_sif_config	*sif ;
102233f810b2SJeff Kirsher 	SMbuf			*mb ;
102333f810b2SJeff Kirsher 	int			len ;
102433f810b2SJeff Kirsher 	if (!(mb = smt_build_frame(smc,SMT_SIF_CONFIG,SMT_REPLY,
102533f810b2SJeff Kirsher 		SIZEOF_SMT_SIF_CONFIG)))
102633f810b2SJeff Kirsher 		return ;
102733f810b2SJeff Kirsher 
102833f810b2SJeff Kirsher 	sif = smtod(mb, struct smt_sif_config *) ;
102933f810b2SJeff Kirsher 	smt_fill_timestamp(smc,&sif->ts) ;	/* set time stamp */
103033f810b2SJeff Kirsher 	smt_fill_sde(smc,&sif->sde) ;		/* set station descriptor */
103133f810b2SJeff Kirsher 	smt_fill_version(smc,&sif->version) ;	/* set version information */
103233f810b2SJeff Kirsher 	smt_fill_state(smc,&sif->state) ;	/* set state information */
103333f810b2SJeff Kirsher 	smt_fill_policy(smc,&sif->policy) ;	/* set station policy */
103433f810b2SJeff Kirsher 	smt_fill_latency(smc,&sif->latency);	/* set station latency */
103533f810b2SJeff Kirsher 	smt_fill_neighbor(smc,&sif->neighbor);	/* set station neighbor */
103633f810b2SJeff Kirsher 	smt_fill_setcount(smc,&sif->setcount) ;	/* set count */
103733f810b2SJeff Kirsher 	len = smt_fill_path(smc,&sif->path);	/* set station path descriptor*/
103833f810b2SJeff Kirsher 	sif->smt.smt_dest = *dest ;		/* destination address */
103933f810b2SJeff Kirsher 	sif->smt.smt_tid = tid ;		/* transaction ID */
104033f810b2SJeff Kirsher 	smt_add_frame_len(mb,len) ;		/* adjust length fields */
104133f810b2SJeff Kirsher 	dump_smt(smc,(struct smt_header *)sif,"SIF Configuration Reply") ;
104233f810b2SJeff Kirsher 	smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
104333f810b2SJeff Kirsher }
104433f810b2SJeff Kirsher 
104533f810b2SJeff Kirsher /*
104633f810b2SJeff Kirsher  * generate and send SIF operation response
104733f810b2SJeff Kirsher  */
104833f810b2SJeff Kirsher 
smt_send_sif_operation(struct s_smc * smc,struct fddi_addr * dest,u_long tid,int local)104933f810b2SJeff Kirsher static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest,
105033f810b2SJeff Kirsher 				   u_long tid, int local)
105133f810b2SJeff Kirsher /* struct fddi_addr *dest;	dest address */
105233f810b2SJeff Kirsher /* u_long tid;			transaction id */
105333f810b2SJeff Kirsher {
105433f810b2SJeff Kirsher 	struct smt_sif_operation *sif ;
105533f810b2SJeff Kirsher 	SMbuf			*mb ;
105633f810b2SJeff Kirsher 	int			ports ;
105733f810b2SJeff Kirsher 	int			i ;
105833f810b2SJeff Kirsher 
105933f810b2SJeff Kirsher 	ports = NUMPHYS ;
106033f810b2SJeff Kirsher #ifndef	CONCENTRATOR
106133f810b2SJeff Kirsher 	if (smc->s.sas == SMT_SAS)
106233f810b2SJeff Kirsher 		ports = 1 ;
106333f810b2SJeff Kirsher #endif
106433f810b2SJeff Kirsher 
106533f810b2SJeff Kirsher 	if (!(mb = smt_build_frame(smc,SMT_SIF_OPER,SMT_REPLY,
1066537a0c5cSGustavo A. R. Silva 				   struct_size(sif, lem, ports))))
106733f810b2SJeff Kirsher 		return ;
1068537a0c5cSGustavo A. R. Silva 	sif = smtod(mb, typeof(sif));
106933f810b2SJeff Kirsher 	smt_fill_timestamp(smc,&sif->ts) ;	/* set time stamp */
107033f810b2SJeff Kirsher 	smt_fill_mac_status(smc,&sif->status) ; /* set mac status */
107133f810b2SJeff Kirsher 	smt_fill_mac_counter(smc,&sif->mc) ; /* set mac counter field */
107233f810b2SJeff Kirsher 	smt_fill_mac_fnc(smc,&sif->fnc) ; /* set frame not copied counter */
107333f810b2SJeff Kirsher 	smt_fill_manufacturer(smc,&sif->man) ; /* set manufacturer field */
107433f810b2SJeff Kirsher 	smt_fill_user(smc,&sif->user) ;		/* set user field */
107533f810b2SJeff Kirsher 	smt_fill_setcount(smc,&sif->setcount) ;	/* set count */
107633f810b2SJeff Kirsher 	/*
107733f810b2SJeff Kirsher 	 * set link error mon information
107833f810b2SJeff Kirsher 	 */
107933f810b2SJeff Kirsher 	if (ports == 1) {
108033f810b2SJeff Kirsher 		smt_fill_lem(smc,sif->lem,PS) ;
108133f810b2SJeff Kirsher 	}
108233f810b2SJeff Kirsher 	else {
108333f810b2SJeff Kirsher 		for (i = 0 ; i < ports ; i++) {
108433f810b2SJeff Kirsher 			smt_fill_lem(smc,&sif->lem[i],i) ;
108533f810b2SJeff Kirsher 		}
108633f810b2SJeff Kirsher 	}
108733f810b2SJeff Kirsher 
108833f810b2SJeff Kirsher 	sif->smt.smt_dest = *dest ;	/* destination address */
108933f810b2SJeff Kirsher 	sif->smt.smt_tid = tid ;	/* transaction ID */
109033f810b2SJeff Kirsher 	dump_smt(smc,(struct smt_header *)sif,"SIF Operation Reply") ;
109133f810b2SJeff Kirsher 	smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
109233f810b2SJeff Kirsher }
109333f810b2SJeff Kirsher 
109433f810b2SJeff Kirsher /*
109533f810b2SJeff Kirsher  * get and initialize SMT frame
109633f810b2SJeff Kirsher  */
smt_build_frame(struct s_smc * smc,int class,int type,int length)109733f810b2SJeff Kirsher SMbuf *smt_build_frame(struct s_smc *smc, int class, int type,
109833f810b2SJeff Kirsher 				  int length)
109933f810b2SJeff Kirsher {
110033f810b2SJeff Kirsher 	SMbuf			*mb ;
110133f810b2SJeff Kirsher 	struct smt_header	*smt ;
110233f810b2SJeff Kirsher 
110333f810b2SJeff Kirsher #if	0
110433f810b2SJeff Kirsher 	if (!smc->r.sm_ma_avail) {
110533f810b2SJeff Kirsher 		return 0;
110633f810b2SJeff Kirsher 	}
110733f810b2SJeff Kirsher #endif
110833f810b2SJeff Kirsher 	if (!(mb = smt_get_mbuf(smc)))
110933f810b2SJeff Kirsher 		return mb;
111033f810b2SJeff Kirsher 
111133f810b2SJeff Kirsher 	mb->sm_len = length ;
111233f810b2SJeff Kirsher 	smt = smtod(mb, struct smt_header *) ;
111333f810b2SJeff Kirsher 	smt->smt_dest = fddi_broadcast ; /* set dest = broadcast */
111433f810b2SJeff Kirsher 	smt->smt_class = class ;
111533f810b2SJeff Kirsher 	smt->smt_type = type ;
111633f810b2SJeff Kirsher 	switch (class) {
111733f810b2SJeff Kirsher 	case SMT_NIF :
111833f810b2SJeff Kirsher 	case SMT_SIF_CONFIG :
111933f810b2SJeff Kirsher 	case SMT_SIF_OPER :
112033f810b2SJeff Kirsher 	case SMT_ECF :
112133f810b2SJeff Kirsher 		smt->smt_version = SMT_VID ;
112233f810b2SJeff Kirsher 		break ;
112333f810b2SJeff Kirsher 	default :
112433f810b2SJeff Kirsher 		smt->smt_version = SMT_VID_2 ;
112533f810b2SJeff Kirsher 		break ;
112633f810b2SJeff Kirsher 	}
112733f810b2SJeff Kirsher 	smt->smt_tid = smt_get_tid(smc) ;	/* set transaction ID */
112833f810b2SJeff Kirsher 	smt->smt_pad = 0 ;
112933f810b2SJeff Kirsher 	smt->smt_len = length - sizeof(struct smt_header) ;
113033f810b2SJeff Kirsher 	return mb;
113133f810b2SJeff Kirsher }
113233f810b2SJeff Kirsher 
smt_add_frame_len(SMbuf * mb,int len)113333f810b2SJeff Kirsher static void smt_add_frame_len(SMbuf *mb, int len)
113433f810b2SJeff Kirsher {
113533f810b2SJeff Kirsher 	struct smt_header	*smt ;
113633f810b2SJeff Kirsher 
113733f810b2SJeff Kirsher 	smt = smtod(mb, struct smt_header *) ;
113833f810b2SJeff Kirsher 	smt->smt_len += len ;
113933f810b2SJeff Kirsher 	mb->sm_len += len ;
114033f810b2SJeff Kirsher }
114133f810b2SJeff Kirsher 
114233f810b2SJeff Kirsher 
114333f810b2SJeff Kirsher 
114433f810b2SJeff Kirsher /*
114533f810b2SJeff Kirsher  * fill values in UNA parameter
114633f810b2SJeff Kirsher  */
smt_fill_una(struct s_smc * smc,struct smt_p_una * una)114733f810b2SJeff Kirsher static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una)
114833f810b2SJeff Kirsher {
114933f810b2SJeff Kirsher 	SMTSETPARA(una,SMT_P_UNA) ;
115033f810b2SJeff Kirsher 	una->una_pad = 0 ;
115133f810b2SJeff Kirsher 	una->una_node = smc->mib.m[MAC0].fddiMACUpstreamNbr ;
115233f810b2SJeff Kirsher }
115333f810b2SJeff Kirsher 
115433f810b2SJeff Kirsher /*
115533f810b2SJeff Kirsher  * fill values in SDE parameter
115633f810b2SJeff Kirsher  */
smt_fill_sde(struct s_smc * smc,struct smt_p_sde * sde)115733f810b2SJeff Kirsher static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde)
115833f810b2SJeff Kirsher {
115933f810b2SJeff Kirsher 	SMTSETPARA(sde,SMT_P_SDE) ;
116033f810b2SJeff Kirsher 	sde->sde_non_master = smc->mib.fddiSMTNonMaster_Ct ;
116133f810b2SJeff Kirsher 	sde->sde_master = smc->mib.fddiSMTMaster_Ct ;
116233f810b2SJeff Kirsher 	sde->sde_mac_count = NUMMACS ;		/* only 1 MAC */
116333f810b2SJeff Kirsher #ifdef	CONCENTRATOR
116433f810b2SJeff Kirsher 	sde->sde_type = SMT_SDE_CONCENTRATOR ;
116533f810b2SJeff Kirsher #else
116633f810b2SJeff Kirsher 	sde->sde_type = SMT_SDE_STATION ;
116733f810b2SJeff Kirsher #endif
116833f810b2SJeff Kirsher }
116933f810b2SJeff Kirsher 
117033f810b2SJeff Kirsher /*
117133f810b2SJeff Kirsher  * fill in values in station state parameter
117233f810b2SJeff Kirsher  */
smt_fill_state(struct s_smc * smc,struct smt_p_state * state)117333f810b2SJeff Kirsher static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state)
117433f810b2SJeff Kirsher {
117533f810b2SJeff Kirsher 	int	top ;
117633f810b2SJeff Kirsher 	int	twist ;
117733f810b2SJeff Kirsher 
117833f810b2SJeff Kirsher 	SMTSETPARA(state,SMT_P_STATE) ;
117933f810b2SJeff Kirsher 	state->st_pad = 0 ;
118033f810b2SJeff Kirsher 
118133f810b2SJeff Kirsher 	/* determine topology */
118233f810b2SJeff Kirsher 	top = 0 ;
118333f810b2SJeff Kirsher 	if (smc->mib.fddiSMTPeerWrapFlag) {
118433f810b2SJeff Kirsher 		top |= SMT_ST_WRAPPED ;		/* state wrapped */
118533f810b2SJeff Kirsher 	}
118633f810b2SJeff Kirsher #ifdef	CONCENTRATOR
118733f810b2SJeff Kirsher 	if (cfm_status_unattached(smc)) {
118833f810b2SJeff Kirsher 		top |= SMT_ST_UNATTACHED ;	/* unattached concentrator */
118933f810b2SJeff Kirsher 	}
119033f810b2SJeff Kirsher #endif
119133f810b2SJeff Kirsher 	if ((twist = pcm_status_twisted(smc)) & 1) {
119233f810b2SJeff Kirsher 		top |= SMT_ST_TWISTED_A ;	/* twisted cable */
119333f810b2SJeff Kirsher 	}
119433f810b2SJeff Kirsher 	if (twist & 2) {
119533f810b2SJeff Kirsher 		top |= SMT_ST_TWISTED_B ;	/* twisted cable */
119633f810b2SJeff Kirsher 	}
119733f810b2SJeff Kirsher #ifdef	OPT_SRF
119833f810b2SJeff Kirsher 	top |= SMT_ST_SRF ;
119933f810b2SJeff Kirsher #endif
120033f810b2SJeff Kirsher 	if (pcm_rooted_station(smc))
120133f810b2SJeff Kirsher 		top |= SMT_ST_ROOTED_S ;
120233f810b2SJeff Kirsher 	if (smc->mib.a[0].fddiPATHSbaPayload != 0)
120333f810b2SJeff Kirsher 		top |= SMT_ST_SYNC_SERVICE ;
120433f810b2SJeff Kirsher 	state->st_topology = top ;
120533f810b2SJeff Kirsher 	state->st_dupl_addr =
120633f810b2SJeff Kirsher 		((smc->mib.m[MAC0].fddiMACDA_Flag ? SMT_ST_MY_DUPA : 0 ) |
120733f810b2SJeff Kirsher 		 (smc->mib.m[MAC0].fddiMACUNDA_Flag ? SMT_ST_UNA_DUPA : 0)) ;
120833f810b2SJeff Kirsher }
120933f810b2SJeff Kirsher 
121033f810b2SJeff Kirsher /*
121133f810b2SJeff Kirsher  * fill values in timestamp parameter
121233f810b2SJeff Kirsher  */
smt_fill_timestamp(struct s_smc * smc,struct smt_p_timestamp * ts)121333f810b2SJeff Kirsher static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts)
121433f810b2SJeff Kirsher {
121533f810b2SJeff Kirsher 
121633f810b2SJeff Kirsher 	SMTSETPARA(ts,SMT_P_TIMESTAMP) ;
121733f810b2SJeff Kirsher 	smt_set_timestamp(smc,ts->ts_time) ;
121833f810b2SJeff Kirsher }
121933f810b2SJeff Kirsher 
smt_set_timestamp(struct s_smc * smc,u_char * p)122033f810b2SJeff Kirsher void smt_set_timestamp(struct s_smc *smc, u_char *p)
122133f810b2SJeff Kirsher {
122233f810b2SJeff Kirsher 	u_long	time ;
122333f810b2SJeff Kirsher 	u_long	utime ;
122433f810b2SJeff Kirsher 
122533f810b2SJeff Kirsher 	/*
122633f810b2SJeff Kirsher 	 * timestamp is 64 bits long ; resolution is 80 nS
122733f810b2SJeff Kirsher 	 * our clock resolution is 10mS
122833f810b2SJeff Kirsher 	 * 10mS/80ns = 125000 ~ 2^17 = 131072
122933f810b2SJeff Kirsher 	 */
123033f810b2SJeff Kirsher 	utime = smt_get_time() ;
123133f810b2SJeff Kirsher 	time = utime * 100 ;
123233f810b2SJeff Kirsher 	time /= TICKS_PER_SECOND ;
123333f810b2SJeff Kirsher 	p[0] = 0 ;
123433f810b2SJeff Kirsher 	p[1] = (u_char)((time>>(8+8+8+8-1)) & 1) ;
123533f810b2SJeff Kirsher 	p[2] = (u_char)(time>>(8+8+8-1)) ;
123633f810b2SJeff Kirsher 	p[3] = (u_char)(time>>(8+8-1)) ;
123733f810b2SJeff Kirsher 	p[4] = (u_char)(time>>(8-1)) ;
123833f810b2SJeff Kirsher 	p[5] = (u_char)(time<<1) ;
123933f810b2SJeff Kirsher 	p[6] = (u_char)(smc->sm.uniq_ticks>>8) ;
124033f810b2SJeff Kirsher 	p[7] = (u_char)smc->sm.uniq_ticks ;
124133f810b2SJeff Kirsher 	/*
124233f810b2SJeff Kirsher 	 * make sure we don't wrap: restart whenever the upper digits change
124333f810b2SJeff Kirsher 	 */
124433f810b2SJeff Kirsher 	if (utime != smc->sm.uniq_time) {
124533f810b2SJeff Kirsher 		smc->sm.uniq_ticks = 0 ;
124633f810b2SJeff Kirsher 	}
124733f810b2SJeff Kirsher 	smc->sm.uniq_ticks++ ;
124833f810b2SJeff Kirsher 	smc->sm.uniq_time = utime ;
124933f810b2SJeff Kirsher }
125033f810b2SJeff Kirsher 
125133f810b2SJeff Kirsher /*
125233f810b2SJeff Kirsher  * fill values in station policy parameter
125333f810b2SJeff Kirsher  */
smt_fill_policy(struct s_smc * smc,struct smt_p_policy * policy)125433f810b2SJeff Kirsher static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy)
125533f810b2SJeff Kirsher {
125633f810b2SJeff Kirsher 	int	i ;
125733f810b2SJeff Kirsher 	const u_char *map ;
125833f810b2SJeff Kirsher 	u_short	in ;
125933f810b2SJeff Kirsher 	u_short	out ;
126033f810b2SJeff Kirsher 
126133f810b2SJeff Kirsher 	/*
126233f810b2SJeff Kirsher 	 * MIB para 101b (fddiSMTConnectionPolicy) coding
126333f810b2SJeff Kirsher 	 * is different from 0005 coding
126433f810b2SJeff Kirsher 	 */
126533f810b2SJeff Kirsher 	static const u_char ansi_weirdness[16] = {
126633f810b2SJeff Kirsher 		0,7,5,3,8,1,6,4,9,10,2,11,12,13,14,15
126733f810b2SJeff Kirsher 	} ;
126833f810b2SJeff Kirsher 	SMTSETPARA(policy,SMT_P_POLICY) ;
126933f810b2SJeff Kirsher 
127033f810b2SJeff Kirsher 	out = 0 ;
127133f810b2SJeff Kirsher 	in = smc->mib.fddiSMTConnectionPolicy ;
127233f810b2SJeff Kirsher 	for (i = 0, map = ansi_weirdness ; i < 16 ; i++) {
127333f810b2SJeff Kirsher 		if (in & 1)
127433f810b2SJeff Kirsher 			out |= (1<<*map) ;
127533f810b2SJeff Kirsher 		in >>= 1 ;
127633f810b2SJeff Kirsher 		map++ ;
127733f810b2SJeff Kirsher 	}
127833f810b2SJeff Kirsher 	policy->pl_config = smc->mib.fddiSMTConfigPolicy ;
127933f810b2SJeff Kirsher 	policy->pl_connect = out ;
128033f810b2SJeff Kirsher }
128133f810b2SJeff Kirsher 
128233f810b2SJeff Kirsher /*
128333f810b2SJeff Kirsher  * fill values in latency equivalent parameter
128433f810b2SJeff Kirsher  */
smt_fill_latency(struct s_smc * smc,struct smt_p_latency * latency)128533f810b2SJeff Kirsher static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency)
128633f810b2SJeff Kirsher {
128733f810b2SJeff Kirsher 	SMTSETPARA(latency,SMT_P_LATENCY) ;
128833f810b2SJeff Kirsher 
128933f810b2SJeff Kirsher 	latency->lt_phyout_idx1 = phy_index(smc,0) ;
129033f810b2SJeff Kirsher 	latency->lt_latency1 = 10 ;	/* in octets (byte clock) */
129133f810b2SJeff Kirsher 	/*
129233f810b2SJeff Kirsher 	 * note: latency has two phy entries by definition
129333f810b2SJeff Kirsher 	 * for a SAS, the 2nd one is null
129433f810b2SJeff Kirsher 	 */
129533f810b2SJeff Kirsher 	if (smc->s.sas == SMT_DAS) {
129633f810b2SJeff Kirsher 		latency->lt_phyout_idx2 = phy_index(smc,1) ;
129733f810b2SJeff Kirsher 		latency->lt_latency2 = 10 ;	/* in octets (byte clock) */
129833f810b2SJeff Kirsher 	}
129933f810b2SJeff Kirsher 	else {
130033f810b2SJeff Kirsher 		latency->lt_phyout_idx2 = 0 ;
130133f810b2SJeff Kirsher 		latency->lt_latency2 = 0 ;
130233f810b2SJeff Kirsher 	}
130333f810b2SJeff Kirsher }
130433f810b2SJeff Kirsher 
130533f810b2SJeff Kirsher /*
130633f810b2SJeff Kirsher  * fill values in MAC neighbors parameter
130733f810b2SJeff Kirsher  */
smt_fill_neighbor(struct s_smc * smc,struct smt_p_neighbor * neighbor)130833f810b2SJeff Kirsher static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor)
130933f810b2SJeff Kirsher {
131033f810b2SJeff Kirsher 	SMTSETPARA(neighbor,SMT_P_NEIGHBORS) ;
131133f810b2SJeff Kirsher 
131233f810b2SJeff Kirsher 	neighbor->nb_mib_index = INDEX_MAC ;
131333f810b2SJeff Kirsher 	neighbor->nb_mac_index = mac_index(smc,1) ;
131433f810b2SJeff Kirsher 	neighbor->nb_una = smc->mib.m[MAC0].fddiMACUpstreamNbr ;
131533f810b2SJeff Kirsher 	neighbor->nb_dna = smc->mib.m[MAC0].fddiMACDownstreamNbr ;
131633f810b2SJeff Kirsher }
131733f810b2SJeff Kirsher 
131833f810b2SJeff Kirsher /*
131933f810b2SJeff Kirsher  * fill values in path descriptor
132033f810b2SJeff Kirsher  */
132133f810b2SJeff Kirsher #ifdef	CONCENTRATOR
132233f810b2SJeff Kirsher #define ALLPHYS	NUMPHYS
132333f810b2SJeff Kirsher #else
132433f810b2SJeff Kirsher #define ALLPHYS	((smc->s.sas == SMT_SAS) ? 1 : 2)
132533f810b2SJeff Kirsher #endif
132633f810b2SJeff Kirsher 
smt_fill_path(struct s_smc * smc,struct smt_p_path * path)132733f810b2SJeff Kirsher static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path)
132833f810b2SJeff Kirsher {
132933f810b2SJeff Kirsher 	SK_LOC_DECL(int,type) ;
133033f810b2SJeff Kirsher 	SK_LOC_DECL(int,state) ;
133133f810b2SJeff Kirsher 	SK_LOC_DECL(int,remote) ;
133233f810b2SJeff Kirsher 	SK_LOC_DECL(int,mac) ;
133333f810b2SJeff Kirsher 	int	len ;
133433f810b2SJeff Kirsher 	int	p ;
133533f810b2SJeff Kirsher 	int	physp ;
133633f810b2SJeff Kirsher 	struct smt_phy_rec	*phy ;
133733f810b2SJeff Kirsher 	struct smt_mac_rec	*pd_mac ;
133833f810b2SJeff Kirsher 
133933f810b2SJeff Kirsher 	len =	PARA_LEN +
134033f810b2SJeff Kirsher 		sizeof(struct smt_mac_rec) * NUMMACS +
134133f810b2SJeff Kirsher 		sizeof(struct smt_phy_rec) * ALLPHYS ;
134233f810b2SJeff Kirsher 	path->para.p_type = SMT_P_PATH ;
134333f810b2SJeff Kirsher 	path->para.p_len = len - PARA_LEN ;
134433f810b2SJeff Kirsher 
134533f810b2SJeff Kirsher 	/* PHYs */
134633f810b2SJeff Kirsher 	for (p = 0,phy = path->pd_phy ; p < ALLPHYS ; p++, phy++) {
134733f810b2SJeff Kirsher 		physp = p ;
134833f810b2SJeff Kirsher #ifndef	CONCENTRATOR
134933f810b2SJeff Kirsher 		if (smc->s.sas == SMT_SAS)
135033f810b2SJeff Kirsher 			physp = PS ;
135133f810b2SJeff Kirsher #endif
135233f810b2SJeff Kirsher 		pcm_status_state(smc,physp,&type,&state,&remote,&mac) ;
135333f810b2SJeff Kirsher #ifdef	LITTLE_ENDIAN
135433f810b2SJeff Kirsher 		phy->phy_mib_index = smt_swap_short((u_short)p+INDEX_PORT) ;
135533f810b2SJeff Kirsher #else
135633f810b2SJeff Kirsher 		phy->phy_mib_index = p+INDEX_PORT ;
135733f810b2SJeff Kirsher #endif
135833f810b2SJeff Kirsher 		phy->phy_type = type ;
135933f810b2SJeff Kirsher 		phy->phy_connect_state = state ;
136033f810b2SJeff Kirsher 		phy->phy_remote_type = remote ;
136133f810b2SJeff Kirsher 		phy->phy_remote_mac = mac ;
136233f810b2SJeff Kirsher 		phy->phy_resource_idx = phy_con_resource_index(smc,p) ;
136333f810b2SJeff Kirsher 	}
136433f810b2SJeff Kirsher 
136533f810b2SJeff Kirsher 	/* MAC */
136633f810b2SJeff Kirsher 	pd_mac = (struct smt_mac_rec *) phy ;
136733f810b2SJeff Kirsher 	pd_mac->mac_addr = smc->mib.m[MAC0].fddiMACSMTAddress ;
136833f810b2SJeff Kirsher 	pd_mac->mac_resource_idx = mac_con_resource_index(smc,1) ;
136933f810b2SJeff Kirsher 	return len;
137033f810b2SJeff Kirsher }
137133f810b2SJeff Kirsher 
137233f810b2SJeff Kirsher /*
137333f810b2SJeff Kirsher  * fill values in mac status
137433f810b2SJeff Kirsher  */
smt_fill_mac_status(struct s_smc * smc,struct smt_p_mac_status * st)137533f810b2SJeff Kirsher static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st)
137633f810b2SJeff Kirsher {
137733f810b2SJeff Kirsher 	SMTSETPARA(st,SMT_P_MAC_STATUS) ;
137833f810b2SJeff Kirsher 
137933f810b2SJeff Kirsher 	st->st_mib_index = INDEX_MAC ;
138033f810b2SJeff Kirsher 	st->st_mac_index = mac_index(smc,1) ;
138133f810b2SJeff Kirsher 
138233f810b2SJeff Kirsher 	mac_update_counter(smc) ;
138333f810b2SJeff Kirsher 	/*
138433f810b2SJeff Kirsher 	 * timer values are represented in SMT as 2's complement numbers
138533f810b2SJeff Kirsher 	 * units :	internal :  2's complement BCLK
138633f810b2SJeff Kirsher 	 */
138733f810b2SJeff Kirsher 	st->st_t_req = smc->mib.m[MAC0].fddiMACT_Req ;
138833f810b2SJeff Kirsher 	st->st_t_neg = smc->mib.m[MAC0].fddiMACT_Neg ;
138933f810b2SJeff Kirsher 	st->st_t_max = smc->mib.m[MAC0].fddiMACT_Max ;
139033f810b2SJeff Kirsher 	st->st_tvx_value = smc->mib.m[MAC0].fddiMACTvxValue ;
139133f810b2SJeff Kirsher 	st->st_t_min = smc->mib.m[MAC0].fddiMACT_Min ;
139233f810b2SJeff Kirsher 
139333f810b2SJeff Kirsher 	st->st_sba = smc->mib.a[PATH0].fddiPATHSbaPayload ;
139433f810b2SJeff Kirsher 	st->st_frame_ct = smc->mib.m[MAC0].fddiMACFrame_Ct ;
139533f810b2SJeff Kirsher 	st->st_error_ct = smc->mib.m[MAC0].fddiMACError_Ct ;
139633f810b2SJeff Kirsher 	st->st_lost_ct = smc->mib.m[MAC0].fddiMACLost_Ct ;
139733f810b2SJeff Kirsher }
139833f810b2SJeff Kirsher 
139933f810b2SJeff Kirsher /*
140033f810b2SJeff Kirsher  * fill values in LEM status
140133f810b2SJeff Kirsher  */
smt_fill_lem(struct s_smc * smc,struct smt_p_lem * lem,int phy)140233f810b2SJeff Kirsher static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy)
140333f810b2SJeff Kirsher {
140433f810b2SJeff Kirsher 	struct fddi_mib_p	*mib ;
140533f810b2SJeff Kirsher 
140633f810b2SJeff Kirsher 	mib = smc->y[phy].mib ;
140733f810b2SJeff Kirsher 
140833f810b2SJeff Kirsher 	SMTSETPARA(lem,SMT_P_LEM) ;
140933f810b2SJeff Kirsher 	lem->lem_mib_index = phy+INDEX_PORT ;
141033f810b2SJeff Kirsher 	lem->lem_phy_index = phy_index(smc,phy) ;
141133f810b2SJeff Kirsher 	lem->lem_pad2 = 0 ;
141233f810b2SJeff Kirsher 	lem->lem_cutoff = mib->fddiPORTLer_Cutoff ;
141333f810b2SJeff Kirsher 	lem->lem_alarm = mib->fddiPORTLer_Alarm ;
141433f810b2SJeff Kirsher 	/* long term bit error rate */
141533f810b2SJeff Kirsher 	lem->lem_estimate = mib->fddiPORTLer_Estimate ;
141633f810b2SJeff Kirsher 	/* # of rejected connections */
141733f810b2SJeff Kirsher 	lem->lem_reject_ct = mib->fddiPORTLem_Reject_Ct ;
141833f810b2SJeff Kirsher 	lem->lem_ct = mib->fddiPORTLem_Ct ;	/* total number of errors */
141933f810b2SJeff Kirsher }
142033f810b2SJeff Kirsher 
142133f810b2SJeff Kirsher /*
142233f810b2SJeff Kirsher  * fill version parameter
142333f810b2SJeff Kirsher  */
smt_fill_version(struct s_smc * smc,struct smt_p_version * vers)142433f810b2SJeff Kirsher static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers)
142533f810b2SJeff Kirsher {
142633f810b2SJeff Kirsher 	SK_UNUSED(smc) ;
142733f810b2SJeff Kirsher 	SMTSETPARA(vers,SMT_P_VERSION) ;
142833f810b2SJeff Kirsher 	vers->v_pad = 0 ;
142933f810b2SJeff Kirsher 	vers->v_n = 1 ;				/* one version is enough .. */
143033f810b2SJeff Kirsher 	vers->v_index = 1 ;
143133f810b2SJeff Kirsher 	vers->v_version[0] = SMT_VID_2 ;
143233f810b2SJeff Kirsher 	vers->v_pad2 = 0 ;
143333f810b2SJeff Kirsher }
143433f810b2SJeff Kirsher 
143533f810b2SJeff Kirsher #ifdef	SMT6_10
143633f810b2SJeff Kirsher /*
143733f810b2SJeff Kirsher  * fill frame status capabilities
143833f810b2SJeff Kirsher  */
143933f810b2SJeff Kirsher /*
144033f810b2SJeff Kirsher  * note: this para 200B is NOT in swap table, because it's also set in
144133f810b2SJeff Kirsher  * PMF add_para
144233f810b2SJeff Kirsher  */
smt_fill_fsc(struct s_smc * smc,struct smt_p_fsc * fsc)144333f810b2SJeff Kirsher static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc)
144433f810b2SJeff Kirsher {
144533f810b2SJeff Kirsher 	SK_UNUSED(smc) ;
144633f810b2SJeff Kirsher 	SMTSETPARA(fsc,SMT_P_FSC) ;
144733f810b2SJeff Kirsher 	fsc->fsc_pad0 = 0 ;
144833f810b2SJeff Kirsher 	fsc->fsc_mac_index = INDEX_MAC ;	/* this is MIB ; MIB is NOT
144933f810b2SJeff Kirsher 						 * mac_index ()i !
145033f810b2SJeff Kirsher 						 */
145133f810b2SJeff Kirsher 	fsc->fsc_pad1 = 0 ;
145233f810b2SJeff Kirsher 	fsc->fsc_value = FSC_TYPE0 ;		/* "normal" node */
145333f810b2SJeff Kirsher #ifdef	LITTLE_ENDIAN
145433f810b2SJeff Kirsher 	fsc->fsc_mac_index = smt_swap_short(INDEX_MAC) ;
145533f810b2SJeff Kirsher 	fsc->fsc_value = smt_swap_short(FSC_TYPE0) ;
145633f810b2SJeff Kirsher #endif
145733f810b2SJeff Kirsher }
145833f810b2SJeff Kirsher #endif
145933f810b2SJeff Kirsher 
146033f810b2SJeff Kirsher /*
146133f810b2SJeff Kirsher  * fill mac counter field
146233f810b2SJeff Kirsher  */
smt_fill_mac_counter(struct s_smc * smc,struct smt_p_mac_counter * mc)146333f810b2SJeff Kirsher static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc)
146433f810b2SJeff Kirsher {
146533f810b2SJeff Kirsher 	SMTSETPARA(mc,SMT_P_MAC_COUNTER) ;
146633f810b2SJeff Kirsher 	mc->mc_mib_index = INDEX_MAC ;
146733f810b2SJeff Kirsher 	mc->mc_index = mac_index(smc,1) ;
146833f810b2SJeff Kirsher 	mc->mc_receive_ct = smc->mib.m[MAC0].fddiMACCopied_Ct ;
146933f810b2SJeff Kirsher 	mc->mc_transmit_ct =  smc->mib.m[MAC0].fddiMACTransmit_Ct ;
147033f810b2SJeff Kirsher }
147133f810b2SJeff Kirsher 
147233f810b2SJeff Kirsher /*
147333f810b2SJeff Kirsher  * fill mac frame not copied counter
147433f810b2SJeff Kirsher  */
smt_fill_mac_fnc(struct s_smc * smc,struct smt_p_mac_fnc * fnc)147533f810b2SJeff Kirsher static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc)
147633f810b2SJeff Kirsher {
147733f810b2SJeff Kirsher 	SMTSETPARA(fnc,SMT_P_MAC_FNC) ;
147833f810b2SJeff Kirsher 	fnc->nc_mib_index = INDEX_MAC ;
147933f810b2SJeff Kirsher 	fnc->nc_index = mac_index(smc,1) ;
148033f810b2SJeff Kirsher 	fnc->nc_counter = smc->mib.m[MAC0].fddiMACNotCopied_Ct ;
148133f810b2SJeff Kirsher }
148233f810b2SJeff Kirsher 
148333f810b2SJeff Kirsher 
148433f810b2SJeff Kirsher /*
148533f810b2SJeff Kirsher  * fill manufacturer field
148633f810b2SJeff Kirsher  */
smt_fill_manufacturer(struct s_smc * smc,struct smp_p_manufacturer * man)148733f810b2SJeff Kirsher static void smt_fill_manufacturer(struct s_smc *smc,
148833f810b2SJeff Kirsher 				  struct smp_p_manufacturer *man)
148933f810b2SJeff Kirsher {
149033f810b2SJeff Kirsher 	SMTSETPARA(man,SMT_P_MANUFACTURER) ;
149133f810b2SJeff Kirsher 	memcpy((char *) man->mf_data,
149233f810b2SJeff Kirsher 		(char *) smc->mib.fddiSMTManufacturerData,
149333f810b2SJeff Kirsher 		sizeof(man->mf_data)) ;
149433f810b2SJeff Kirsher }
149533f810b2SJeff Kirsher 
149633f810b2SJeff Kirsher /*
149733f810b2SJeff Kirsher  * fill user field
149833f810b2SJeff Kirsher  */
smt_fill_user(struct s_smc * smc,struct smp_p_user * user)149933f810b2SJeff Kirsher static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user)
150033f810b2SJeff Kirsher {
150133f810b2SJeff Kirsher 	SMTSETPARA(user,SMT_P_USER) ;
150233f810b2SJeff Kirsher 	memcpy((char *) user->us_data,
150333f810b2SJeff Kirsher 		(char *) smc->mib.fddiSMTUserData,
150433f810b2SJeff Kirsher 		sizeof(user->us_data)) ;
150533f810b2SJeff Kirsher }
150633f810b2SJeff Kirsher 
150733f810b2SJeff Kirsher /*
150833f810b2SJeff Kirsher  * fill set count
150933f810b2SJeff Kirsher  */
smt_fill_setcount(struct s_smc * smc,struct smt_p_setcount * setcount)151033f810b2SJeff Kirsher static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount)
151133f810b2SJeff Kirsher {
151233f810b2SJeff Kirsher 	SK_UNUSED(smc) ;
151333f810b2SJeff Kirsher 	SMTSETPARA(setcount,SMT_P_SETCOUNT) ;
151433f810b2SJeff Kirsher 	setcount->count = smc->mib.fddiSMTSetCount.count ;
151533f810b2SJeff Kirsher 	memcpy((char *)setcount->timestamp,
151633f810b2SJeff Kirsher 		(char *)smc->mib.fddiSMTSetCount.timestamp,8) ;
151733f810b2SJeff Kirsher }
151833f810b2SJeff Kirsher 
151933f810b2SJeff Kirsher /*
152033f810b2SJeff Kirsher  * fill echo data
152133f810b2SJeff Kirsher  */
smt_fill_echo(struct s_smc * smc,struct smt_p_echo * echo,u_long seed,int len)152233f810b2SJeff Kirsher static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed,
152333f810b2SJeff Kirsher 			  int len)
152433f810b2SJeff Kirsher {
152533f810b2SJeff Kirsher 	u_char	*p ;
152633f810b2SJeff Kirsher 
152733f810b2SJeff Kirsher 	SK_UNUSED(smc) ;
152833f810b2SJeff Kirsher 	SMTSETPARA(echo,SMT_P_ECHODATA) ;
152933f810b2SJeff Kirsher 	echo->para.p_len = len ;
153033f810b2SJeff Kirsher 	for (p = echo->ec_data ; len ; len--) {
153133f810b2SJeff Kirsher 		*p++ = (u_char) seed ;
153233f810b2SJeff Kirsher 		seed += 13 ;
153333f810b2SJeff Kirsher 	}
153433f810b2SJeff Kirsher }
153533f810b2SJeff Kirsher 
153633f810b2SJeff Kirsher /*
153733f810b2SJeff Kirsher  * clear DNA and UNA
153833f810b2SJeff Kirsher  * called from CFM if configuration changes
153933f810b2SJeff Kirsher  */
smt_clear_una_dna(struct s_smc * smc)154033f810b2SJeff Kirsher static void smt_clear_una_dna(struct s_smc *smc)
154133f810b2SJeff Kirsher {
154233f810b2SJeff Kirsher 	smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;
154333f810b2SJeff Kirsher 	smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;
154433f810b2SJeff Kirsher }
154533f810b2SJeff Kirsher 
smt_clear_old_una_dna(struct s_smc * smc)154633f810b2SJeff Kirsher static void smt_clear_old_una_dna(struct s_smc *smc)
154733f810b2SJeff Kirsher {
154833f810b2SJeff Kirsher 	smc->mib.m[MAC0].fddiMACOldUpstreamNbr = SMT_Unknown ;
154933f810b2SJeff Kirsher 	smc->mib.m[MAC0].fddiMACOldDownstreamNbr = SMT_Unknown ;
155033f810b2SJeff Kirsher }
155133f810b2SJeff Kirsher 
smt_get_tid(struct s_smc * smc)155233f810b2SJeff Kirsher u_long smt_get_tid(struct s_smc *smc)
155333f810b2SJeff Kirsher {
155433f810b2SJeff Kirsher 	u_long	tid ;
155533f810b2SJeff Kirsher 	while ((tid = ++(smc->sm.smt_tid) ^ SMT_TID_MAGIC) == 0)
155633f810b2SJeff Kirsher 		;
155733f810b2SJeff Kirsher 	return tid & 0x3fffffffL;
155833f810b2SJeff Kirsher }
155933f810b2SJeff Kirsher 
1560327afdd7SLee Jones #ifdef	LITTLE_ENDIAN
156133f810b2SJeff Kirsher /*
156233f810b2SJeff Kirsher  * table of parameter lengths
156333f810b2SJeff Kirsher  */
156433f810b2SJeff Kirsher static const struct smt_pdef {
156533f810b2SJeff Kirsher 	int	ptype ;
156633f810b2SJeff Kirsher 	int	plen ;
156733f810b2SJeff Kirsher 	const char	*pswap ;
156833f810b2SJeff Kirsher } smt_pdef[] = {
156933f810b2SJeff Kirsher 	{ SMT_P_UNA,	sizeof(struct smt_p_una) ,
157033f810b2SJeff Kirsher 		SWAP_SMT_P_UNA					} ,
157133f810b2SJeff Kirsher 	{ SMT_P_SDE,	sizeof(struct smt_p_sde) ,
157233f810b2SJeff Kirsher 		SWAP_SMT_P_SDE					} ,
157333f810b2SJeff Kirsher 	{ SMT_P_STATE,	sizeof(struct smt_p_state) ,
157433f810b2SJeff Kirsher 		SWAP_SMT_P_STATE				} ,
157533f810b2SJeff Kirsher 	{ SMT_P_TIMESTAMP,sizeof(struct smt_p_timestamp) ,
157633f810b2SJeff Kirsher 		SWAP_SMT_P_TIMESTAMP				} ,
157733f810b2SJeff Kirsher 	{ SMT_P_POLICY,	sizeof(struct smt_p_policy) ,
157833f810b2SJeff Kirsher 		SWAP_SMT_P_POLICY				} ,
157933f810b2SJeff Kirsher 	{ SMT_P_LATENCY,	sizeof(struct smt_p_latency) ,
158033f810b2SJeff Kirsher 		SWAP_SMT_P_LATENCY				} ,
158133f810b2SJeff Kirsher 	{ SMT_P_NEIGHBORS,sizeof(struct smt_p_neighbor) ,
158233f810b2SJeff Kirsher 		SWAP_SMT_P_NEIGHBORS				} ,
158333f810b2SJeff Kirsher 	{ SMT_P_PATH,	sizeof(struct smt_p_path) ,
158433f810b2SJeff Kirsher 		SWAP_SMT_P_PATH					} ,
158533f810b2SJeff Kirsher 	{ SMT_P_MAC_STATUS,sizeof(struct smt_p_mac_status) ,
158633f810b2SJeff Kirsher 		SWAP_SMT_P_MAC_STATUS				} ,
158733f810b2SJeff Kirsher 	{ SMT_P_LEM,	sizeof(struct smt_p_lem) ,
158833f810b2SJeff Kirsher 		SWAP_SMT_P_LEM					} ,
158933f810b2SJeff Kirsher 	{ SMT_P_MAC_COUNTER,sizeof(struct smt_p_mac_counter) ,
159033f810b2SJeff Kirsher 		SWAP_SMT_P_MAC_COUNTER				} ,
159133f810b2SJeff Kirsher 	{ SMT_P_MAC_FNC,sizeof(struct smt_p_mac_fnc) ,
159233f810b2SJeff Kirsher 		SWAP_SMT_P_MAC_FNC				} ,
159333f810b2SJeff Kirsher 	{ SMT_P_PRIORITY,sizeof(struct smt_p_priority) ,
159433f810b2SJeff Kirsher 		SWAP_SMT_P_PRIORITY				} ,
159533f810b2SJeff Kirsher 	{ SMT_P_EB,sizeof(struct smt_p_eb) ,
159633f810b2SJeff Kirsher 		SWAP_SMT_P_EB					} ,
159733f810b2SJeff Kirsher 	{ SMT_P_MANUFACTURER,sizeof(struct smp_p_manufacturer) ,
159833f810b2SJeff Kirsher 		SWAP_SMT_P_MANUFACTURER				} ,
159933f810b2SJeff Kirsher 	{ SMT_P_REASON,	sizeof(struct smt_p_reason) ,
160033f810b2SJeff Kirsher 		SWAP_SMT_P_REASON				} ,
160133f810b2SJeff Kirsher 	{ SMT_P_REFUSED, sizeof(struct smt_p_refused) ,
160233f810b2SJeff Kirsher 		SWAP_SMT_P_REFUSED				} ,
160333f810b2SJeff Kirsher 	{ SMT_P_VERSION, sizeof(struct smt_p_version) ,
160433f810b2SJeff Kirsher 		SWAP_SMT_P_VERSION				} ,
160533f810b2SJeff Kirsher #ifdef ESS
160633f810b2SJeff Kirsher 	{ SMT_P0015, sizeof(struct smt_p_0015) , SWAP_SMT_P0015 } ,
160733f810b2SJeff Kirsher 	{ SMT_P0016, sizeof(struct smt_p_0016) , SWAP_SMT_P0016 } ,
160833f810b2SJeff Kirsher 	{ SMT_P0017, sizeof(struct smt_p_0017) , SWAP_SMT_P0017 } ,
160933f810b2SJeff Kirsher 	{ SMT_P0018, sizeof(struct smt_p_0018) , SWAP_SMT_P0018 } ,
161033f810b2SJeff Kirsher 	{ SMT_P0019, sizeof(struct smt_p_0019) , SWAP_SMT_P0019 } ,
161133f810b2SJeff Kirsher 	{ SMT_P001A, sizeof(struct smt_p_001a) , SWAP_SMT_P001A } ,
161233f810b2SJeff Kirsher 	{ SMT_P001B, sizeof(struct smt_p_001b) , SWAP_SMT_P001B } ,
161333f810b2SJeff Kirsher 	{ SMT_P001C, sizeof(struct smt_p_001c) , SWAP_SMT_P001C } ,
161433f810b2SJeff Kirsher 	{ SMT_P001D, sizeof(struct smt_p_001d) , SWAP_SMT_P001D } ,
161533f810b2SJeff Kirsher #endif
161633f810b2SJeff Kirsher #if	0
161733f810b2SJeff Kirsher 	{ SMT_P_FSC,	sizeof(struct smt_p_fsc) ,
161833f810b2SJeff Kirsher 		SWAP_SMT_P_FSC					} ,
161933f810b2SJeff Kirsher #endif
162033f810b2SJeff Kirsher 
162133f810b2SJeff Kirsher 	{ SMT_P_SETCOUNT,0,	SWAP_SMT_P_SETCOUNT		} ,
162233f810b2SJeff Kirsher 	{ SMT_P1048,	0,	SWAP_SMT_P1048			} ,
162333f810b2SJeff Kirsher 	{ SMT_P208C,	0,	SWAP_SMT_P208C			} ,
162433f810b2SJeff Kirsher 	{ SMT_P208D,	0,	SWAP_SMT_P208D			} ,
162533f810b2SJeff Kirsher 	{ SMT_P208E,	0,	SWAP_SMT_P208E			} ,
162633f810b2SJeff Kirsher 	{ SMT_P208F,	0,	SWAP_SMT_P208F			} ,
162733f810b2SJeff Kirsher 	{ SMT_P2090,	0,	SWAP_SMT_P2090			} ,
162833f810b2SJeff Kirsher #ifdef	ESS
162933f810b2SJeff Kirsher 	{ SMT_P320B, sizeof(struct smt_p_320b) , SWAP_SMT_P320B } ,
163033f810b2SJeff Kirsher 	{ SMT_P320F, sizeof(struct smt_p_320f) , SWAP_SMT_P320F } ,
163133f810b2SJeff Kirsher 	{ SMT_P3210, sizeof(struct smt_p_3210) , SWAP_SMT_P3210 } ,
163233f810b2SJeff Kirsher #endif
163333f810b2SJeff Kirsher 	{ SMT_P4050,	0,	SWAP_SMT_P4050			} ,
163433f810b2SJeff Kirsher 	{ SMT_P4051,	0,	SWAP_SMT_P4051			} ,
163533f810b2SJeff Kirsher 	{ SMT_P4052,	0,	SWAP_SMT_P4052			} ,
163633f810b2SJeff Kirsher 	{ SMT_P4053,	0,	SWAP_SMT_P4053			} ,
163733f810b2SJeff Kirsher } ;
163833f810b2SJeff Kirsher 
163933f810b2SJeff Kirsher #define N_SMT_PLEN	ARRAY_SIZE(smt_pdef)
1640327afdd7SLee Jones #endif
164133f810b2SJeff Kirsher 
smt_check_para(struct s_smc * smc,struct smt_header * sm,const u_short list[])164233f810b2SJeff Kirsher int smt_check_para(struct s_smc *smc, struct smt_header	*sm,
164333f810b2SJeff Kirsher 		   const u_short list[])
164433f810b2SJeff Kirsher {
164533f810b2SJeff Kirsher 	const u_short		*p = list ;
164633f810b2SJeff Kirsher 	while (*p) {
164733f810b2SJeff Kirsher 		if (!sm_to_para(smc,sm,(int) *p)) {
16485671e8c1SJoe Perches 			DB_SMT("SMT: smt_check_para - missing para %hx", *p);
164933f810b2SJeff Kirsher 			return -1;
165033f810b2SJeff Kirsher 		}
165133f810b2SJeff Kirsher 		p++ ;
165233f810b2SJeff Kirsher 	}
165333f810b2SJeff Kirsher 	return 0;
165433f810b2SJeff Kirsher }
165533f810b2SJeff Kirsher 
sm_to_para(struct s_smc * smc,struct smt_header * sm,int para)165633f810b2SJeff Kirsher void *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para)
165733f810b2SJeff Kirsher {
165833f810b2SJeff Kirsher 	char	*p ;
165933f810b2SJeff Kirsher 	int	len ;
166033f810b2SJeff Kirsher 	int	plen ;
166133f810b2SJeff Kirsher 	void	*found = NULL;
166233f810b2SJeff Kirsher 
166333f810b2SJeff Kirsher 	SK_UNUSED(smc) ;
166433f810b2SJeff Kirsher 
166533f810b2SJeff Kirsher 	len = sm->smt_len ;
166633f810b2SJeff Kirsher 	p = (char *)(sm+1) ;		/* pointer to info */
166733f810b2SJeff Kirsher 	while (len > 0 ) {
166833f810b2SJeff Kirsher 		if (((struct smt_para *)p)->p_type == para)
166933f810b2SJeff Kirsher 			found = (void *) p ;
167033f810b2SJeff Kirsher 		plen = ((struct smt_para *)p)->p_len + PARA_LEN ;
167133f810b2SJeff Kirsher 		p += plen ;
167233f810b2SJeff Kirsher 		len -= plen ;
167333f810b2SJeff Kirsher 		if (len < 0) {
16745671e8c1SJoe Perches 			DB_SMT("SMT : sm_to_para - length error %d", plen);
167533f810b2SJeff Kirsher 			return NULL;
167633f810b2SJeff Kirsher 		}
167733f810b2SJeff Kirsher 		if ((plen & 3) && (para != SMT_P_ECHODATA)) {
16785671e8c1SJoe Perches 			DB_SMT("SMT : sm_to_para - odd length %d", plen);
167933f810b2SJeff Kirsher 			return NULL;
168033f810b2SJeff Kirsher 		}
168133f810b2SJeff Kirsher 		if (found)
168233f810b2SJeff Kirsher 			return found;
168333f810b2SJeff Kirsher 	}
168433f810b2SJeff Kirsher 	return NULL;
168533f810b2SJeff Kirsher }
168633f810b2SJeff Kirsher 
168733f810b2SJeff Kirsher #if	0
168833f810b2SJeff Kirsher /*
168933f810b2SJeff Kirsher  * send ANTC data test frame
169033f810b2SJeff Kirsher  */
169133f810b2SJeff Kirsher void fddi_send_antc(struct s_smc *smc, struct fddi_addr *dest)
169233f810b2SJeff Kirsher {
169333f810b2SJeff Kirsher 	SK_UNUSED(smc) ;
169433f810b2SJeff Kirsher 	SK_UNUSED(dest) ;
169533f810b2SJeff Kirsher #if	0
169633f810b2SJeff Kirsher 	SMbuf			*mb ;
169733f810b2SJeff Kirsher 	struct smt_header	*smt ;
169833f810b2SJeff Kirsher 	int			i ;
169933f810b2SJeff Kirsher 	char			*p ;
170033f810b2SJeff Kirsher 
170133f810b2SJeff Kirsher 	mb = smt_get_mbuf() ;
170233f810b2SJeff Kirsher 	mb->sm_len = 3000+12 ;
170333f810b2SJeff Kirsher 	p = smtod(mb, char *) + 12 ;
170433f810b2SJeff Kirsher 	for (i = 0 ; i < 3000 ; i++)
170533f810b2SJeff Kirsher 		*p++ = 1 << (i&7) ;
170633f810b2SJeff Kirsher 
170733f810b2SJeff Kirsher 	smt = smtod(mb, struct smt_header *) ;
170833f810b2SJeff Kirsher 	smt->smt_dest = *dest ;
170933f810b2SJeff Kirsher 	smt->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ;
171033f810b2SJeff Kirsher 	smt_send_mbuf(smc,mb,FC_ASYNC_LLC) ;
171133f810b2SJeff Kirsher #endif
171233f810b2SJeff Kirsher }
171333f810b2SJeff Kirsher #endif
171433f810b2SJeff Kirsher 
171533f810b2SJeff Kirsher /*
171633f810b2SJeff Kirsher  * return static mac index
171733f810b2SJeff Kirsher  */
mac_index(struct s_smc * smc,int mac)171833f810b2SJeff Kirsher static int mac_index(struct s_smc *smc, int mac)
171933f810b2SJeff Kirsher {
172033f810b2SJeff Kirsher 	SK_UNUSED(mac) ;
172133f810b2SJeff Kirsher #ifdef	CONCENTRATOR
172233f810b2SJeff Kirsher 	SK_UNUSED(smc) ;
172333f810b2SJeff Kirsher 	return NUMPHYS + 1;
172433f810b2SJeff Kirsher #else
172533f810b2SJeff Kirsher 	return (smc->s.sas == SMT_SAS) ? 2 : 3;
172633f810b2SJeff Kirsher #endif
172733f810b2SJeff Kirsher }
172833f810b2SJeff Kirsher 
172933f810b2SJeff Kirsher /*
173033f810b2SJeff Kirsher  * return static phy index
173133f810b2SJeff Kirsher  */
phy_index(struct s_smc * smc,int phy)173233f810b2SJeff Kirsher static int phy_index(struct s_smc *smc, int phy)
173333f810b2SJeff Kirsher {
173433f810b2SJeff Kirsher 	SK_UNUSED(smc) ;
173533f810b2SJeff Kirsher 	return phy + 1;
173633f810b2SJeff Kirsher }
173733f810b2SJeff Kirsher 
173833f810b2SJeff Kirsher /*
173933f810b2SJeff Kirsher  * return dynamic mac connection resource index
174033f810b2SJeff Kirsher  */
mac_con_resource_index(struct s_smc * smc,int mac)174133f810b2SJeff Kirsher static int mac_con_resource_index(struct s_smc *smc, int mac)
174233f810b2SJeff Kirsher {
174333f810b2SJeff Kirsher #ifdef	CONCENTRATOR
174433f810b2SJeff Kirsher 	SK_UNUSED(smc) ;
174533f810b2SJeff Kirsher 	SK_UNUSED(mac) ;
174633f810b2SJeff Kirsher 	return entity_to_index(smc, cem_get_downstream(smc, ENTITY_MAC));
174733f810b2SJeff Kirsher #else
174833f810b2SJeff Kirsher 	SK_UNUSED(mac) ;
174933f810b2SJeff Kirsher 	switch (smc->mib.fddiSMTCF_State) {
175033f810b2SJeff Kirsher 	case SC9_C_WRAP_A :
175133f810b2SJeff Kirsher 	case SC5_THRU_B :
175233f810b2SJeff Kirsher 	case SC11_C_WRAP_S :
175333f810b2SJeff Kirsher 		return 1;
175433f810b2SJeff Kirsher 	case SC10_C_WRAP_B :
175533f810b2SJeff Kirsher 	case SC4_THRU_A :
175633f810b2SJeff Kirsher 		return 2;
175733f810b2SJeff Kirsher 	}
175833f810b2SJeff Kirsher 	return smc->s.sas == SMT_SAS ? 2 : 3;
175933f810b2SJeff Kirsher #endif
176033f810b2SJeff Kirsher }
176133f810b2SJeff Kirsher 
176233f810b2SJeff Kirsher /*
176333f810b2SJeff Kirsher  * return dynamic phy connection resource index
176433f810b2SJeff Kirsher  */
phy_con_resource_index(struct s_smc * smc,int phy)176533f810b2SJeff Kirsher static int phy_con_resource_index(struct s_smc *smc, int phy)
176633f810b2SJeff Kirsher {
176733f810b2SJeff Kirsher #ifdef	CONCENTRATOR
176833f810b2SJeff Kirsher 	return entity_to_index(smc, cem_get_downstream(smc, ENTITY_PHY(phy))) ;
176933f810b2SJeff Kirsher #else
177033f810b2SJeff Kirsher 	switch (smc->mib.fddiSMTCF_State) {
177133f810b2SJeff Kirsher 	case SC9_C_WRAP_A :
177233f810b2SJeff Kirsher 		return phy == PA ? 3 : 2;
177333f810b2SJeff Kirsher 	case SC10_C_WRAP_B :
177433f810b2SJeff Kirsher 		return phy == PA ? 1 : 3;
177533f810b2SJeff Kirsher 	case SC4_THRU_A :
177633f810b2SJeff Kirsher 		return phy == PA ? 3 : 1;
177733f810b2SJeff Kirsher 	case SC5_THRU_B :
177833f810b2SJeff Kirsher 		return phy == PA ? 2 : 3;
177933f810b2SJeff Kirsher 	case SC11_C_WRAP_S :
178033f810b2SJeff Kirsher 		return 2;
178133f810b2SJeff Kirsher 	}
178233f810b2SJeff Kirsher 	return phy;
178333f810b2SJeff Kirsher #endif
178433f810b2SJeff Kirsher }
178533f810b2SJeff Kirsher 
178633f810b2SJeff Kirsher #ifdef	CONCENTRATOR
entity_to_index(struct s_smc * smc,int e)178733f810b2SJeff Kirsher static int entity_to_index(struct s_smc *smc, int e)
178833f810b2SJeff Kirsher {
178933f810b2SJeff Kirsher 	if (e == ENTITY_MAC)
179033f810b2SJeff Kirsher 		return mac_index(smc, 1);
179133f810b2SJeff Kirsher 	else
179233f810b2SJeff Kirsher 		return phy_index(smc, e - ENTITY_PHY(0));
179333f810b2SJeff Kirsher }
179433f810b2SJeff Kirsher #endif
179533f810b2SJeff Kirsher 
179633f810b2SJeff Kirsher #ifdef	LITTLE_ENDIAN
smt_swap_short(u_short s)179733f810b2SJeff Kirsher static int smt_swap_short(u_short s)
179833f810b2SJeff Kirsher {
179933f810b2SJeff Kirsher 	return ((s>>8)&0xff) | ((s&0xff)<<8);
180033f810b2SJeff Kirsher }
180133f810b2SJeff Kirsher 
smt_swap_para(struct smt_header * sm,int len,int direction)180233f810b2SJeff Kirsher void smt_swap_para(struct smt_header *sm, int len, int direction)
180333f810b2SJeff Kirsher /* int direction;	0 encode 1 decode */
180433f810b2SJeff Kirsher {
180533f810b2SJeff Kirsher 	struct smt_para	*pa ;
180633f810b2SJeff Kirsher 	const  struct smt_pdef	*pd ;
180733f810b2SJeff Kirsher 	char	*p ;
180833f810b2SJeff Kirsher 	int	plen ;
180933f810b2SJeff Kirsher 	int	type ;
181033f810b2SJeff Kirsher 	int	i ;
181133f810b2SJeff Kirsher 
181233f810b2SJeff Kirsher /*	printf("smt_swap_para sm %x len %d dir %d\n",
181333f810b2SJeff Kirsher 		sm,len,direction) ;
181433f810b2SJeff Kirsher  */
181533f810b2SJeff Kirsher 	smt_string_swap((char *)sm,SWAP_SMTHEADER,len) ;
181633f810b2SJeff Kirsher 
181733f810b2SJeff Kirsher 	/* swap args */
181833f810b2SJeff Kirsher 	len -= sizeof(struct smt_header) ;
181933f810b2SJeff Kirsher 
182033f810b2SJeff Kirsher 	p = (char *) (sm + 1) ;
182133f810b2SJeff Kirsher 	while (len > 0) {
182233f810b2SJeff Kirsher 		pa = (struct smt_para *) p ;
182333f810b2SJeff Kirsher 		plen = pa->p_len ;
182433f810b2SJeff Kirsher 		type = pa->p_type ;
182533f810b2SJeff Kirsher 		pa->p_type = smt_swap_short(pa->p_type) ;
182633f810b2SJeff Kirsher 		pa->p_len = smt_swap_short(pa->p_len) ;
182733f810b2SJeff Kirsher 		if (direction) {
182833f810b2SJeff Kirsher 			plen = pa->p_len ;
182933f810b2SJeff Kirsher 			type = pa->p_type ;
183033f810b2SJeff Kirsher 		}
183133f810b2SJeff Kirsher 		/*
183233f810b2SJeff Kirsher 		 * note: paras can have 0 length !
183333f810b2SJeff Kirsher 		 */
183433f810b2SJeff Kirsher 		if (plen < 0)
183533f810b2SJeff Kirsher 			break ;
183633f810b2SJeff Kirsher 		plen += PARA_LEN ;
183733f810b2SJeff Kirsher 		for (i = N_SMT_PLEN, pd = smt_pdef; i ; i--,pd++) {
183833f810b2SJeff Kirsher 			if (pd->ptype == type)
183933f810b2SJeff Kirsher 				break ;
184033f810b2SJeff Kirsher 		}
184133f810b2SJeff Kirsher 		if (i && pd->pswap) {
184233f810b2SJeff Kirsher 			smt_string_swap(p+PARA_LEN,pd->pswap,len) ;
184333f810b2SJeff Kirsher 		}
184433f810b2SJeff Kirsher 		len -= plen ;
184533f810b2SJeff Kirsher 		p += plen ;
184633f810b2SJeff Kirsher 	}
184733f810b2SJeff Kirsher }
184833f810b2SJeff Kirsher 
1849311107bdSYihao Han 
smt_string_swap(char * data,const char * format,int len)185033f810b2SJeff Kirsher static void smt_string_swap(char *data, const char *format, int len)
185133f810b2SJeff Kirsher {
185233f810b2SJeff Kirsher 	const char	*open_paren = NULL ;
185333f810b2SJeff Kirsher 
185433f810b2SJeff Kirsher 	while (len > 0  && *format) {
185533f810b2SJeff Kirsher 		switch (*format) {
185633f810b2SJeff Kirsher 		case '[' :
185733f810b2SJeff Kirsher 			open_paren = format ;
185833f810b2SJeff Kirsher 			break ;
185933f810b2SJeff Kirsher 		case ']' :
186033f810b2SJeff Kirsher 			format = open_paren ;
186133f810b2SJeff Kirsher 			break ;
186233f810b2SJeff Kirsher 		case '1' :
186333f810b2SJeff Kirsher 		case '2' :
186433f810b2SJeff Kirsher 		case '3' :
186533f810b2SJeff Kirsher 		case '4' :
186633f810b2SJeff Kirsher 		case '5' :
186733f810b2SJeff Kirsher 		case '6' :
186833f810b2SJeff Kirsher 		case '7' :
186933f810b2SJeff Kirsher 		case '8' :
187033f810b2SJeff Kirsher 		case '9' :
187133f810b2SJeff Kirsher 			data  += *format - '0' ;
187233f810b2SJeff Kirsher 			len   -= *format - '0' ;
187333f810b2SJeff Kirsher 			break ;
187433f810b2SJeff Kirsher 		case 'c':
187533f810b2SJeff Kirsher 			data++ ;
187633f810b2SJeff Kirsher 			len-- ;
187733f810b2SJeff Kirsher 			break ;
187833f810b2SJeff Kirsher 		case 's' :
1879311107bdSYihao Han 			swap(data[0], data[1]) ;
188033f810b2SJeff Kirsher 			data += 2 ;
188133f810b2SJeff Kirsher 			len -= 2 ;
188233f810b2SJeff Kirsher 			break ;
188333f810b2SJeff Kirsher 		case 'l' :
1884311107bdSYihao Han 			swap(data[0], data[3]) ;
1885311107bdSYihao Han 			swap(data[1], data[2]) ;
188633f810b2SJeff Kirsher 			data += 4 ;
188733f810b2SJeff Kirsher 			len -= 4 ;
188833f810b2SJeff Kirsher 			break ;
188933f810b2SJeff Kirsher 		}
189033f810b2SJeff Kirsher 		format++ ;
189133f810b2SJeff Kirsher 	}
189233f810b2SJeff Kirsher }
189333f810b2SJeff Kirsher #else
smt_swap_para(struct smt_header * sm,int len,int direction)189433f810b2SJeff Kirsher void smt_swap_para(struct smt_header *sm, int len, int direction)
189533f810b2SJeff Kirsher /* int direction;	0 encode 1 decode */
189633f810b2SJeff Kirsher {
189733f810b2SJeff Kirsher 	SK_UNUSED(sm) ;
189833f810b2SJeff Kirsher 	SK_UNUSED(len) ;
189933f810b2SJeff Kirsher 	SK_UNUSED(direction) ;
190033f810b2SJeff Kirsher }
190133f810b2SJeff Kirsher #endif
190233f810b2SJeff Kirsher 
190333f810b2SJeff Kirsher /*
190433f810b2SJeff Kirsher  * PMF actions
190533f810b2SJeff Kirsher  */
smt_action(struct s_smc * smc,int class,int code,int index)190633f810b2SJeff Kirsher int smt_action(struct s_smc *smc, int class, int code, int index)
190733f810b2SJeff Kirsher {
190833f810b2SJeff Kirsher 	int	event ;
190933f810b2SJeff Kirsher 	int	port ;
19105671e8c1SJoe Perches 	DB_SMT("SMT: action %d code %d", class, code);
191133f810b2SJeff Kirsher 	switch(class) {
191233f810b2SJeff Kirsher 	case SMT_STATION_ACTION :
191333f810b2SJeff Kirsher 		switch(code) {
191433f810b2SJeff Kirsher 		case SMT_STATION_ACTION_CONNECT :
191533f810b2SJeff Kirsher 			smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ;
191633f810b2SJeff Kirsher 			queue_event(smc,EVENT_ECM,EC_CONNECT) ;
191733f810b2SJeff Kirsher 			break ;
191833f810b2SJeff Kirsher 		case SMT_STATION_ACTION_DISCONNECT :
191933f810b2SJeff Kirsher 			queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
192033f810b2SJeff Kirsher 			smc->mib.fddiSMTRemoteDisconnectFlag = TRUE ;
192133f810b2SJeff Kirsher 			RS_SET(smc,RS_DISCONNECT) ;
192233f810b2SJeff Kirsher 			AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
192333f810b2SJeff Kirsher 				FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_DISCONNECT,
192433f810b2SJeff Kirsher 				smt_get_event_word(smc));
192533f810b2SJeff Kirsher 			break ;
192633f810b2SJeff Kirsher 		case SMT_STATION_ACTION_PATHTEST :
192733f810b2SJeff Kirsher 			AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
192833f810b2SJeff Kirsher 				FDDI_SMT_EVENT, (u_long) FDDI_PATH_TEST,
192933f810b2SJeff Kirsher 				smt_get_event_word(smc));
193033f810b2SJeff Kirsher 			break ;
193133f810b2SJeff Kirsher 		case SMT_STATION_ACTION_SELFTEST :
193233f810b2SJeff Kirsher 			AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
193333f810b2SJeff Kirsher 				FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_SELF_TEST,
193433f810b2SJeff Kirsher 				smt_get_event_word(smc));
193533f810b2SJeff Kirsher 			break ;
193633f810b2SJeff Kirsher 		case SMT_STATION_ACTION_DISABLE_A :
193733f810b2SJeff Kirsher 			if (smc->y[PA].pc_mode == PM_PEER) {
193833f810b2SJeff Kirsher 				RS_SET(smc,RS_EVENT) ;
193933f810b2SJeff Kirsher 				queue_event(smc,EVENT_PCM+PA,PC_DISABLE) ;
194033f810b2SJeff Kirsher 			}
194133f810b2SJeff Kirsher 			break ;
194233f810b2SJeff Kirsher 		case SMT_STATION_ACTION_DISABLE_B :
194333f810b2SJeff Kirsher 			if (smc->y[PB].pc_mode == PM_PEER) {
194433f810b2SJeff Kirsher 				RS_SET(smc,RS_EVENT) ;
194533f810b2SJeff Kirsher 				queue_event(smc,EVENT_PCM+PB,PC_DISABLE) ;
194633f810b2SJeff Kirsher 			}
194733f810b2SJeff Kirsher 			break ;
194833f810b2SJeff Kirsher 		case SMT_STATION_ACTION_DISABLE_M :
194933f810b2SJeff Kirsher 			for (port = 0 ; port <  NUMPHYS ; port++) {
195033f810b2SJeff Kirsher 				if (smc->mib.p[port].fddiPORTMy_Type != TM)
195133f810b2SJeff Kirsher 					continue ;
195233f810b2SJeff Kirsher 				RS_SET(smc,RS_EVENT) ;
195333f810b2SJeff Kirsher 				queue_event(smc,EVENT_PCM+port,PC_DISABLE) ;
195433f810b2SJeff Kirsher 			}
195533f810b2SJeff Kirsher 			break ;
195633f810b2SJeff Kirsher 		default :
195733f810b2SJeff Kirsher 			return 1;
195833f810b2SJeff Kirsher 		}
195933f810b2SJeff Kirsher 		break ;
196033f810b2SJeff Kirsher 	case SMT_PORT_ACTION :
196133f810b2SJeff Kirsher 		switch(code) {
196233f810b2SJeff Kirsher 		case SMT_PORT_ACTION_ENABLE :
196333f810b2SJeff Kirsher 			event = PC_ENABLE ;
196433f810b2SJeff Kirsher 			break ;
196533f810b2SJeff Kirsher 		case SMT_PORT_ACTION_DISABLE :
196633f810b2SJeff Kirsher 			event = PC_DISABLE ;
196733f810b2SJeff Kirsher 			break ;
196833f810b2SJeff Kirsher 		case SMT_PORT_ACTION_MAINT :
196933f810b2SJeff Kirsher 			event = PC_MAINT ;
197033f810b2SJeff Kirsher 			break ;
197133f810b2SJeff Kirsher 		case SMT_PORT_ACTION_START :
197233f810b2SJeff Kirsher 			event = PC_START ;
197333f810b2SJeff Kirsher 			break ;
197433f810b2SJeff Kirsher 		case SMT_PORT_ACTION_STOP :
197533f810b2SJeff Kirsher 			event = PC_STOP ;
197633f810b2SJeff Kirsher 			break ;
197733f810b2SJeff Kirsher 		default :
197833f810b2SJeff Kirsher 			return 1;
197933f810b2SJeff Kirsher 		}
198033f810b2SJeff Kirsher 		queue_event(smc,EVENT_PCM+index,event) ;
198133f810b2SJeff Kirsher 		break ;
198233f810b2SJeff Kirsher 	default :
198333f810b2SJeff Kirsher 		return 1;
198433f810b2SJeff Kirsher 	}
198533f810b2SJeff Kirsher 	return 0;
198633f810b2SJeff Kirsher }
198733f810b2SJeff Kirsher 
198833f810b2SJeff Kirsher /*
198933f810b2SJeff Kirsher  * canonical conversion of <len> bytes beginning form *data
199033f810b2SJeff Kirsher  */
199133f810b2SJeff Kirsher #ifdef  USE_CAN_ADDR
hwm_conv_can(struct s_smc * smc,char * data,int len)199233f810b2SJeff Kirsher static void hwm_conv_can(struct s_smc *smc, char *data, int len)
199333f810b2SJeff Kirsher {
199433f810b2SJeff Kirsher 	int i ;
199533f810b2SJeff Kirsher 
199633f810b2SJeff Kirsher 	SK_UNUSED(smc) ;
199733f810b2SJeff Kirsher 
199833f810b2SJeff Kirsher 	for (i = len; i ; i--, data++)
199933f810b2SJeff Kirsher 		*data = bitrev8(*data);
200033f810b2SJeff Kirsher }
200133f810b2SJeff Kirsher #endif
200233f810b2SJeff Kirsher 
200333f810b2SJeff Kirsher #endif	/* no SLIM_SMT */
200433f810b2SJeff Kirsher 
2005