162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * (C)Copyright 1998,1999 SysKonnect, 562306a36Sopenharmony_ci * a business unit of Schneider & Koch & Co. Datensysteme GmbH. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * See the file "skfddi.c" for further information. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * The information in this file is provided "AS IS" without warranty. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci ******************************************************************************/ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include "h/types.h" 1462306a36Sopenharmony_ci#include "h/fddi.h" 1562306a36Sopenharmony_ci#include "h/smc.h" 1662306a36Sopenharmony_ci#include "h/smt_p.h" 1762306a36Sopenharmony_ci#include <linux/bitrev.h> 1862306a36Sopenharmony_ci#include <linux/kernel.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define KERNEL 2162306a36Sopenharmony_ci#include "h/smtstate.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* 2462306a36Sopenharmony_ci * FC in SMbuf 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci#define m_fc(mb) ((mb)->sm_data[0]) 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define SMT_TID_MAGIC 0x1f0a7b3c 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic const char *const smt_type_name[] = { 3162306a36Sopenharmony_ci "SMT_00??", "SMT_INFO", "SMT_02??", "SMT_03??", 3262306a36Sopenharmony_ci "SMT_04??", "SMT_05??", "SMT_06??", "SMT_07??", 3362306a36Sopenharmony_ci "SMT_08??", "SMT_09??", "SMT_0A??", "SMT_0B??", 3462306a36Sopenharmony_ci "SMT_0C??", "SMT_0D??", "SMT_0E??", "SMT_NSA" 3562306a36Sopenharmony_ci} ; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic const char *const smt_class_name[] = { 3862306a36Sopenharmony_ci "UNKNOWN","NIF","SIF_CONFIG","SIF_OPER","ECF","RAF","RDF", 3962306a36Sopenharmony_ci "SRF","PMF_GET","PMF_SET","ESF" 4062306a36Sopenharmony_ci} ; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define LAST_CLASS (SMT_PMF_SET) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic const struct fddi_addr SMT_Unknown = { 4562306a36Sopenharmony_ci { 0,0,0x1f,0,0,0 } 4662306a36Sopenharmony_ci} ; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* 4962306a36Sopenharmony_ci * function prototypes 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci#ifdef LITTLE_ENDIAN 5262306a36Sopenharmony_cistatic int smt_swap_short(u_short s); 5362306a36Sopenharmony_ci#endif 5462306a36Sopenharmony_cistatic int mac_index(struct s_smc *smc, int mac); 5562306a36Sopenharmony_cistatic int phy_index(struct s_smc *smc, int phy); 5662306a36Sopenharmony_cistatic int mac_con_resource_index(struct s_smc *smc, int mac); 5762306a36Sopenharmony_cistatic int phy_con_resource_index(struct s_smc *smc, int phy); 5862306a36Sopenharmony_cistatic void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason, 5962306a36Sopenharmony_ci int local); 6062306a36Sopenharmony_cistatic void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, 6162306a36Sopenharmony_ci int fc, u_long tid, int type, int local); 6262306a36Sopenharmony_cistatic void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc, 6362306a36Sopenharmony_ci u_long tid, int type, int len); 6462306a36Sopenharmony_cistatic void smt_echo_test(struct s_smc *smc, int dna); 6562306a36Sopenharmony_cistatic void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest, 6662306a36Sopenharmony_ci u_long tid, int local); 6762306a36Sopenharmony_cistatic void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest, 6862306a36Sopenharmony_ci u_long tid, int local); 6962306a36Sopenharmony_ci#ifdef LITTLE_ENDIAN 7062306a36Sopenharmony_cistatic void smt_string_swap(char *data, const char *format, int len); 7162306a36Sopenharmony_ci#endif 7262306a36Sopenharmony_cistatic void smt_add_frame_len(SMbuf *mb, int len); 7362306a36Sopenharmony_cistatic void smt_fill_una(struct s_smc *smc, struct smt_p_una *una); 7462306a36Sopenharmony_cistatic void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde); 7562306a36Sopenharmony_cistatic void smt_fill_state(struct s_smc *smc, struct smt_p_state *state); 7662306a36Sopenharmony_cistatic void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts); 7762306a36Sopenharmony_cistatic void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy); 7862306a36Sopenharmony_cistatic void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency); 7962306a36Sopenharmony_cistatic void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor); 8062306a36Sopenharmony_cistatic int smt_fill_path(struct s_smc *smc, struct smt_p_path *path); 8162306a36Sopenharmony_cistatic void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st); 8262306a36Sopenharmony_cistatic void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy); 8362306a36Sopenharmony_cistatic void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers); 8462306a36Sopenharmony_cistatic void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc); 8562306a36Sopenharmony_cistatic void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc); 8662306a36Sopenharmony_cistatic void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc); 8762306a36Sopenharmony_cistatic void smt_fill_manufacturer(struct s_smc *smc, 8862306a36Sopenharmony_ci struct smp_p_manufacturer *man); 8962306a36Sopenharmony_cistatic void smt_fill_user(struct s_smc *smc, struct smp_p_user *user); 9062306a36Sopenharmony_cistatic void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount); 9162306a36Sopenharmony_cistatic void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, 9262306a36Sopenharmony_ci int len); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic void smt_clear_una_dna(struct s_smc *smc); 9562306a36Sopenharmony_cistatic void smt_clear_old_una_dna(struct s_smc *smc); 9662306a36Sopenharmony_ci#ifdef CONCENTRATOR 9762306a36Sopenharmony_cistatic int entity_to_index(void); 9862306a36Sopenharmony_ci#endif 9962306a36Sopenharmony_cistatic void update_dac(struct s_smc *smc, int report); 10062306a36Sopenharmony_cistatic int div_ratio(u_long upper, u_long lower); 10162306a36Sopenharmony_ci#ifdef USE_CAN_ADDR 10262306a36Sopenharmony_cistatic void hwm_conv_can(struct s_smc *smc, char *data, int len); 10362306a36Sopenharmony_ci#else 10462306a36Sopenharmony_ci#define hwm_conv_can(smc,data,len) 10562306a36Sopenharmony_ci#endif 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic inline int is_my_addr(const struct s_smc *smc, 10962306a36Sopenharmony_ci const struct fddi_addr *addr) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci return(*(short *)(&addr->a[0]) == 11262306a36Sopenharmony_ci *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0]) 11362306a36Sopenharmony_ci && *(short *)(&addr->a[2]) == 11462306a36Sopenharmony_ci *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[2]) 11562306a36Sopenharmony_ci && *(short *)(&addr->a[4]) == 11662306a36Sopenharmony_ci *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ; 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic inline int is_broadcast(const struct fddi_addr *addr) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci return *(u_short *)(&addr->a[0]) == 0xffff && 12262306a36Sopenharmony_ci *(u_short *)(&addr->a[2]) == 0xffff && 12362306a36Sopenharmony_ci *(u_short *)(&addr->a[4]) == 0xffff; 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic inline int is_individual(const struct fddi_addr *addr) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci return !(addr->a[0] & GROUP_ADDR); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic inline int is_equal(const struct fddi_addr *addr1, 13262306a36Sopenharmony_ci const struct fddi_addr *addr2) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci return *(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) && 13562306a36Sopenharmony_ci *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) && 13662306a36Sopenharmony_ci *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]); 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci/* 14062306a36Sopenharmony_ci * list of mandatory paras in frames 14162306a36Sopenharmony_ci */ 14262306a36Sopenharmony_cistatic const u_short plist_nif[] = { SMT_P_UNA,SMT_P_SDE,SMT_P_STATE,0 } ; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci/* 14562306a36Sopenharmony_ci * init SMT agent 14662306a36Sopenharmony_ci */ 14762306a36Sopenharmony_civoid smt_agent_init(struct s_smc *smc) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci int i ; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* 15262306a36Sopenharmony_ci * get MAC address 15362306a36Sopenharmony_ci */ 15462306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACSMTAddress = smc->hw.fddi_home_addr ; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* 15762306a36Sopenharmony_ci * get OUI address from driver (bia == built-in-address) 15862306a36Sopenharmony_ci */ 15962306a36Sopenharmony_ci smc->mib.fddiSMTStationId.sid_oem[0] = 0 ; 16062306a36Sopenharmony_ci smc->mib.fddiSMTStationId.sid_oem[1] = 0 ; 16162306a36Sopenharmony_ci driver_get_bia(smc,&smc->mib.fddiSMTStationId.sid_node) ; 16262306a36Sopenharmony_ci for (i = 0 ; i < 6 ; i ++) { 16362306a36Sopenharmony_ci smc->mib.fddiSMTStationId.sid_node.a[i] = 16462306a36Sopenharmony_ci bitrev8(smc->mib.fddiSMTStationId.sid_node.a[i]); 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci smc->mib.fddiSMTManufacturerData[0] = 16762306a36Sopenharmony_ci smc->mib.fddiSMTStationId.sid_node.a[0] ; 16862306a36Sopenharmony_ci smc->mib.fddiSMTManufacturerData[1] = 16962306a36Sopenharmony_ci smc->mib.fddiSMTStationId.sid_node.a[1] ; 17062306a36Sopenharmony_ci smc->mib.fddiSMTManufacturerData[2] = 17162306a36Sopenharmony_ci smc->mib.fddiSMTStationId.sid_node.a[2] ; 17262306a36Sopenharmony_ci smc->sm.smt_tid = 0 ; 17362306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACDupAddressTest = DA_NONE ; 17462306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ; 17562306a36Sopenharmony_ci#ifndef SLIM_SMT 17662306a36Sopenharmony_ci smt_clear_una_dna(smc) ; 17762306a36Sopenharmony_ci smt_clear_old_una_dna(smc) ; 17862306a36Sopenharmony_ci#endif 17962306a36Sopenharmony_ci for (i = 0 ; i < SMT_MAX_TEST ; i++) 18062306a36Sopenharmony_ci smc->sm.pend[i] = 0 ; 18162306a36Sopenharmony_ci smc->sm.please_reconnect = 0 ; 18262306a36Sopenharmony_ci smc->sm.uniq_ticks = 0 ; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/* 18662306a36Sopenharmony_ci * SMT task 18762306a36Sopenharmony_ci * forever 18862306a36Sopenharmony_ci * delay 30 seconds 18962306a36Sopenharmony_ci * send NIF 19062306a36Sopenharmony_ci * check tvu & tvd 19162306a36Sopenharmony_ci * end 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_civoid smt_agent_task(struct s_smc *smc) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L, 19662306a36Sopenharmony_ci EV_TOKEN(EVENT_SMT,SM_TIMER)) ; 19762306a36Sopenharmony_ci DB_SMT("SMT agent task"); 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci#ifndef SMT_REAL_TOKEN_CT 20162306a36Sopenharmony_civoid smt_emulate_token_ct(struct s_smc *smc, int mac_index) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci u_long count; 20462306a36Sopenharmony_ci u_long time; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci time = smt_get_time(); 20862306a36Sopenharmony_ci count = ((time - smc->sm.last_tok_time[mac_index]) * 20962306a36Sopenharmony_ci 100)/TICKS_PER_SECOND; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci /* 21262306a36Sopenharmony_ci * Only when ring is up we will have a token count. The 21362306a36Sopenharmony_ci * flag is unfortunately a single instance value. This 21462306a36Sopenharmony_ci * doesn't matter now, because we currently have only 21562306a36Sopenharmony_ci * one MAC instance. 21662306a36Sopenharmony_ci */ 21762306a36Sopenharmony_ci if (smc->hw.mac_ring_is_up){ 21862306a36Sopenharmony_ci smc->mib.m[mac_index].fddiMACToken_Ct += count; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci /* Remember current time */ 22262306a36Sopenharmony_ci smc->sm.last_tok_time[mac_index] = time; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci#endif 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci/*ARGSUSED1*/ 22862306a36Sopenharmony_civoid smt_event(struct s_smc *smc, int event) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci u_long time ; 23162306a36Sopenharmony_ci#ifndef SMT_REAL_TOKEN_CT 23262306a36Sopenharmony_ci int i ; 23362306a36Sopenharmony_ci#endif 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci if (smc->sm.please_reconnect) { 23762306a36Sopenharmony_ci smc->sm.please_reconnect -- ; 23862306a36Sopenharmony_ci if (smc->sm.please_reconnect == 0) { 23962306a36Sopenharmony_ci /* Counted down */ 24062306a36Sopenharmony_ci queue_event(smc,EVENT_ECM,EC_CONNECT) ; 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (event == SM_FAST) 24562306a36Sopenharmony_ci return ; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* 24862306a36Sopenharmony_ci * timer for periodic cleanup in driver 24962306a36Sopenharmony_ci * reset and start the watchdog (FM2) 25062306a36Sopenharmony_ci * ESS timer 25162306a36Sopenharmony_ci * SBA timer 25262306a36Sopenharmony_ci */ 25362306a36Sopenharmony_ci smt_timer_poll(smc) ; 25462306a36Sopenharmony_ci smt_start_watchdog(smc) ; 25562306a36Sopenharmony_ci#ifndef SLIM_SMT 25662306a36Sopenharmony_ci#ifndef BOOT 25762306a36Sopenharmony_ci#ifdef ESS 25862306a36Sopenharmony_ci ess_timer_poll(smc) ; 25962306a36Sopenharmony_ci#endif 26062306a36Sopenharmony_ci#endif 26162306a36Sopenharmony_ci#ifdef SBA 26262306a36Sopenharmony_ci sba_timer_poll(smc) ; 26362306a36Sopenharmony_ci#endif 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci smt_srf_event(smc,0,0,0) ; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci#endif /* no SLIM_SMT */ 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci time = smt_get_time() ; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci if (time - smc->sm.smt_last_lem >= TICKS_PER_SECOND*8) { 27262306a36Sopenharmony_ci /* 27362306a36Sopenharmony_ci * Use 8 sec. for the time intervall, it simplifies the 27462306a36Sopenharmony_ci * LER estimation. 27562306a36Sopenharmony_ci */ 27662306a36Sopenharmony_ci struct fddi_mib_m *mib ; 27762306a36Sopenharmony_ci u_long upper ; 27862306a36Sopenharmony_ci u_long lower ; 27962306a36Sopenharmony_ci int cond ; 28062306a36Sopenharmony_ci int port; 28162306a36Sopenharmony_ci struct s_phy *phy ; 28262306a36Sopenharmony_ci /* 28362306a36Sopenharmony_ci * calculate LEM bit error rate 28462306a36Sopenharmony_ci */ 28562306a36Sopenharmony_ci sm_lem_evaluate(smc) ; 28662306a36Sopenharmony_ci smc->sm.smt_last_lem = time ; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* 28962306a36Sopenharmony_ci * check conditions 29062306a36Sopenharmony_ci */ 29162306a36Sopenharmony_ci#ifndef SLIM_SMT 29262306a36Sopenharmony_ci mac_update_counter(smc) ; 29362306a36Sopenharmony_ci mib = smc->mib.m ; 29462306a36Sopenharmony_ci upper = 29562306a36Sopenharmony_ci (mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) + 29662306a36Sopenharmony_ci (mib->fddiMACError_Ct - mib->fddiMACOld_Error_Ct) ; 29762306a36Sopenharmony_ci lower = 29862306a36Sopenharmony_ci (mib->fddiMACFrame_Ct - mib->fddiMACOld_Frame_Ct) + 29962306a36Sopenharmony_ci (mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) ; 30062306a36Sopenharmony_ci mib->fddiMACFrameErrorRatio = div_ratio(upper,lower) ; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci cond = 30362306a36Sopenharmony_ci ((!mib->fddiMACFrameErrorThreshold && 30462306a36Sopenharmony_ci mib->fddiMACError_Ct != mib->fddiMACOld_Error_Ct) || 30562306a36Sopenharmony_ci (mib->fddiMACFrameErrorRatio > 30662306a36Sopenharmony_ci mib->fddiMACFrameErrorThreshold)) ; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci if (cond != mib->fddiMACFrameErrorFlag) 30962306a36Sopenharmony_ci smt_srf_event(smc,SMT_COND_MAC_FRAME_ERROR, 31062306a36Sopenharmony_ci INDEX_MAC,cond) ; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci upper = 31362306a36Sopenharmony_ci (mib->fddiMACNotCopied_Ct - mib->fddiMACOld_NotCopied_Ct) ; 31462306a36Sopenharmony_ci lower = 31562306a36Sopenharmony_ci upper + 31662306a36Sopenharmony_ci (mib->fddiMACCopied_Ct - mib->fddiMACOld_Copied_Ct) ; 31762306a36Sopenharmony_ci mib->fddiMACNotCopiedRatio = div_ratio(upper,lower) ; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci cond = 32062306a36Sopenharmony_ci ((!mib->fddiMACNotCopiedThreshold && 32162306a36Sopenharmony_ci mib->fddiMACNotCopied_Ct != 32262306a36Sopenharmony_ci mib->fddiMACOld_NotCopied_Ct)|| 32362306a36Sopenharmony_ci (mib->fddiMACNotCopiedRatio > 32462306a36Sopenharmony_ci mib->fddiMACNotCopiedThreshold)) ; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (cond != mib->fddiMACNotCopiedFlag) 32762306a36Sopenharmony_ci smt_srf_event(smc,SMT_COND_MAC_NOT_COPIED, 32862306a36Sopenharmony_ci INDEX_MAC,cond) ; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci /* 33162306a36Sopenharmony_ci * set old values 33262306a36Sopenharmony_ci */ 33362306a36Sopenharmony_ci mib->fddiMACOld_Frame_Ct = mib->fddiMACFrame_Ct ; 33462306a36Sopenharmony_ci mib->fddiMACOld_Copied_Ct = mib->fddiMACCopied_Ct ; 33562306a36Sopenharmony_ci mib->fddiMACOld_Error_Ct = mib->fddiMACError_Ct ; 33662306a36Sopenharmony_ci mib->fddiMACOld_Lost_Ct = mib->fddiMACLost_Ct ; 33762306a36Sopenharmony_ci mib->fddiMACOld_NotCopied_Ct = mib->fddiMACNotCopied_Ct ; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci /* 34062306a36Sopenharmony_ci * Check port EBError Condition 34162306a36Sopenharmony_ci */ 34262306a36Sopenharmony_ci for (port = 0; port < NUMPHYS; port ++) { 34362306a36Sopenharmony_ci phy = &smc->y[port] ; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci if (!phy->mib->fddiPORTHardwarePresent) { 34662306a36Sopenharmony_ci continue; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci cond = (phy->mib->fddiPORTEBError_Ct - 35062306a36Sopenharmony_ci phy->mib->fddiPORTOldEBError_Ct > 5) ; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci /* If ratio is more than 5 in 8 seconds 35362306a36Sopenharmony_ci * Set the condition. 35462306a36Sopenharmony_ci */ 35562306a36Sopenharmony_ci smt_srf_event(smc,SMT_COND_PORT_EB_ERROR, 35662306a36Sopenharmony_ci (int) (INDEX_PORT+ phy->np) ,cond) ; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci /* 35962306a36Sopenharmony_ci * set old values 36062306a36Sopenharmony_ci */ 36162306a36Sopenharmony_ci phy->mib->fddiPORTOldEBError_Ct = 36262306a36Sopenharmony_ci phy->mib->fddiPORTEBError_Ct ; 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci#endif /* no SLIM_SMT */ 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci#ifndef SLIM_SMT 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci if (time - smc->sm.smt_last_notify >= (u_long) 37162306a36Sopenharmony_ci (smc->mib.fddiSMTTT_Notify * TICKS_PER_SECOND) ) { 37262306a36Sopenharmony_ci /* 37362306a36Sopenharmony_ci * we can either send an announcement or a request 37462306a36Sopenharmony_ci * a request will trigger a reply so that we can update 37562306a36Sopenharmony_ci * our dna 37662306a36Sopenharmony_ci * note: same tid must be used until reply is received 37762306a36Sopenharmony_ci */ 37862306a36Sopenharmony_ci if (!smc->sm.pend[SMT_TID_NIF]) 37962306a36Sopenharmony_ci smc->sm.pend[SMT_TID_NIF] = smt_get_tid(smc) ; 38062306a36Sopenharmony_ci smt_send_nif(smc,&fddi_broadcast, FC_SMT_NSA, 38162306a36Sopenharmony_ci smc->sm.pend[SMT_TID_NIF], SMT_REQUEST,0) ; 38262306a36Sopenharmony_ci smc->sm.smt_last_notify = time ; 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* 38662306a36Sopenharmony_ci * check timer 38762306a36Sopenharmony_ci */ 38862306a36Sopenharmony_ci if (smc->sm.smt_tvu && 38962306a36Sopenharmony_ci time - smc->sm.smt_tvu > 228*TICKS_PER_SECOND) { 39062306a36Sopenharmony_ci DB_SMT("SMT : UNA expired"); 39162306a36Sopenharmony_ci smc->sm.smt_tvu = 0 ; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci if (!is_equal(&smc->mib.m[MAC0].fddiMACUpstreamNbr, 39462306a36Sopenharmony_ci &SMT_Unknown)){ 39562306a36Sopenharmony_ci /* Do not update unknown address */ 39662306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACOldUpstreamNbr= 39762306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACUpstreamNbr ; 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ; 40062306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ; 40162306a36Sopenharmony_ci /* 40262306a36Sopenharmony_ci * Make sure the fddiMACUNDA_Flag = FALSE is 40362306a36Sopenharmony_ci * included in the SRF so we don't generate 40462306a36Sopenharmony_ci * a separate SRF for the deassertion of this 40562306a36Sopenharmony_ci * condition 40662306a36Sopenharmony_ci */ 40762306a36Sopenharmony_ci update_dac(smc,0) ; 40862306a36Sopenharmony_ci smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE, 40962306a36Sopenharmony_ci INDEX_MAC,0) ; 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci if (smc->sm.smt_tvd && 41262306a36Sopenharmony_ci time - smc->sm.smt_tvd > 228*TICKS_PER_SECOND) { 41362306a36Sopenharmony_ci DB_SMT("SMT : DNA expired"); 41462306a36Sopenharmony_ci smc->sm.smt_tvd = 0 ; 41562306a36Sopenharmony_ci if (!is_equal(&smc->mib.m[MAC0].fddiMACDownstreamNbr, 41662306a36Sopenharmony_ci &SMT_Unknown)){ 41762306a36Sopenharmony_ci /* Do not update unknown address */ 41862306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACOldDownstreamNbr= 41962306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACDownstreamNbr ; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ; 42262306a36Sopenharmony_ci smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE, 42362306a36Sopenharmony_ci INDEX_MAC,0) ; 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci#endif /* no SLIM_SMT */ 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci#ifndef SMT_REAL_TOKEN_CT 42962306a36Sopenharmony_ci /* 43062306a36Sopenharmony_ci * Token counter emulation section. If hardware supports the token 43162306a36Sopenharmony_ci * count, the token counter will be updated in mac_update_counter. 43262306a36Sopenharmony_ci */ 43362306a36Sopenharmony_ci for (i = MAC0; i < NUMMACS; i++ ){ 43462306a36Sopenharmony_ci if (time - smc->sm.last_tok_time[i] > 2*TICKS_PER_SECOND ){ 43562306a36Sopenharmony_ci smt_emulate_token_ct( smc, i ); 43662306a36Sopenharmony_ci } 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci#endif 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L, 44162306a36Sopenharmony_ci EV_TOKEN(EVENT_SMT,SM_TIMER)) ; 44262306a36Sopenharmony_ci} 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic int div_ratio(u_long upper, u_long lower) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci if ((upper<<16L) < upper) 44762306a36Sopenharmony_ci upper = 0xffff0000L ; 44862306a36Sopenharmony_ci else 44962306a36Sopenharmony_ci upper <<= 16L ; 45062306a36Sopenharmony_ci if (!lower) 45162306a36Sopenharmony_ci return 0; 45262306a36Sopenharmony_ci return (int)(upper/lower) ; 45362306a36Sopenharmony_ci} 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci#ifndef SLIM_SMT 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci/* 45862306a36Sopenharmony_ci * receive packet handler 45962306a36Sopenharmony_ci */ 46062306a36Sopenharmony_civoid smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs) 46162306a36Sopenharmony_ci/* int fs; frame status */ 46262306a36Sopenharmony_ci{ 46362306a36Sopenharmony_ci struct smt_header *sm ; 46462306a36Sopenharmony_ci int local ; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci int illegal = 0 ; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci switch (m_fc(mb)) { 46962306a36Sopenharmony_ci case FC_SMT_INFO : 47062306a36Sopenharmony_ci case FC_SMT_LAN_LOC : 47162306a36Sopenharmony_ci case FC_SMT_LOC : 47262306a36Sopenharmony_ci case FC_SMT_NSA : 47362306a36Sopenharmony_ci break ; 47462306a36Sopenharmony_ci default : 47562306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 47662306a36Sopenharmony_ci return ; 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACSMTCopied_Ct++ ; 48062306a36Sopenharmony_ci sm = smtod(mb,struct smt_header *) ; 48162306a36Sopenharmony_ci local = ((fs & L_INDICATOR) != 0) ; 48262306a36Sopenharmony_ci hwm_conv_can(smc,(char *)sm,12) ; 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci /* check destination address */ 48562306a36Sopenharmony_ci if (is_individual(&sm->smt_dest) && !is_my_addr(smc,&sm->smt_dest)) { 48662306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 48762306a36Sopenharmony_ci return ; 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci#if 0 /* for DUP recognition, do NOT filter them */ 49062306a36Sopenharmony_ci /* ignore loop back packets */ 49162306a36Sopenharmony_ci if (is_my_addr(smc,&sm->smt_source) && !local) { 49262306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 49362306a36Sopenharmony_ci return ; 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci#endif 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci smt_swap_para(sm,(int) mb->sm_len,1) ; 49862306a36Sopenharmony_ci DB_SMT("SMT : received packet [%s] at 0x%p", 49962306a36Sopenharmony_ci smt_type_name[m_fc(mb) & 0xf], sm); 50062306a36Sopenharmony_ci DB_SMT("SMT : version %d, class %s", 50162306a36Sopenharmony_ci sm->smt_version, 50262306a36Sopenharmony_ci smt_class_name[sm->smt_class > LAST_CLASS ? 0 : sm->smt_class]); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci#ifdef SBA 50562306a36Sopenharmony_ci /* 50662306a36Sopenharmony_ci * check if NSA frame 50762306a36Sopenharmony_ci */ 50862306a36Sopenharmony_ci if (m_fc(mb) == FC_SMT_NSA && sm->smt_class == SMT_NIF && 50962306a36Sopenharmony_ci (sm->smt_type == SMT_ANNOUNCE || sm->smt_type == SMT_REQUEST)) { 51062306a36Sopenharmony_ci smc->sba.sm = sm ; 51162306a36Sopenharmony_ci sba(smc,NIF) ; 51262306a36Sopenharmony_ci } 51362306a36Sopenharmony_ci#endif 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci /* 51662306a36Sopenharmony_ci * ignore any packet with NSA and A-indicator set 51762306a36Sopenharmony_ci */ 51862306a36Sopenharmony_ci if ( (fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) { 51962306a36Sopenharmony_ci DB_SMT("SMT : ignoring NSA with A-indicator set from %pM", 52062306a36Sopenharmony_ci &sm->smt_source); 52162306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 52262306a36Sopenharmony_ci return ; 52362306a36Sopenharmony_ci } 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci /* 52662306a36Sopenharmony_ci * ignore frames with illegal length 52762306a36Sopenharmony_ci */ 52862306a36Sopenharmony_ci if (((sm->smt_class == SMT_ECF) && (sm->smt_len > SMT_MAX_ECHO_LEN)) || 52962306a36Sopenharmony_ci ((sm->smt_class != SMT_ECF) && (sm->smt_len > SMT_MAX_INFO_LEN))) { 53062306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 53162306a36Sopenharmony_ci return ; 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci /* 53562306a36Sopenharmony_ci * check SMT version 53662306a36Sopenharmony_ci */ 53762306a36Sopenharmony_ci switch (sm->smt_class) { 53862306a36Sopenharmony_ci case SMT_NIF : 53962306a36Sopenharmony_ci case SMT_SIF_CONFIG : 54062306a36Sopenharmony_ci case SMT_SIF_OPER : 54162306a36Sopenharmony_ci case SMT_ECF : 54262306a36Sopenharmony_ci if (sm->smt_version != SMT_VID) 54362306a36Sopenharmony_ci illegal = 1; 54462306a36Sopenharmony_ci break ; 54562306a36Sopenharmony_ci default : 54662306a36Sopenharmony_ci if (sm->smt_version != SMT_VID_2) 54762306a36Sopenharmony_ci illegal = 1; 54862306a36Sopenharmony_ci break ; 54962306a36Sopenharmony_ci } 55062306a36Sopenharmony_ci if (illegal) { 55162306a36Sopenharmony_ci DB_SMT("SMT : version = %d, dest = %pM", 55262306a36Sopenharmony_ci sm->smt_version, &sm->smt_source); 55362306a36Sopenharmony_ci smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_VERSION,local) ; 55462306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 55562306a36Sopenharmony_ci return ; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci if ((sm->smt_len > mb->sm_len - sizeof(struct smt_header)) || 55862306a36Sopenharmony_ci ((sm->smt_len & 3) && (sm->smt_class != SMT_ECF))) { 55962306a36Sopenharmony_ci DB_SMT("SMT: info length error, len = %d", sm->smt_len); 56062306a36Sopenharmony_ci smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,local) ; 56162306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 56262306a36Sopenharmony_ci return ; 56362306a36Sopenharmony_ci } 56462306a36Sopenharmony_ci switch (sm->smt_class) { 56562306a36Sopenharmony_ci case SMT_NIF : 56662306a36Sopenharmony_ci if (smt_check_para(smc,sm,plist_nif)) { 56762306a36Sopenharmony_ci DB_SMT("SMT: NIF with para problem, ignoring"); 56862306a36Sopenharmony_ci break ; 56962306a36Sopenharmony_ci } 57062306a36Sopenharmony_ci switch (sm->smt_type) { 57162306a36Sopenharmony_ci case SMT_ANNOUNCE : 57262306a36Sopenharmony_ci case SMT_REQUEST : 57362306a36Sopenharmony_ci if (!(fs & C_INDICATOR) && m_fc(mb) == FC_SMT_NSA 57462306a36Sopenharmony_ci && is_broadcast(&sm->smt_dest)) { 57562306a36Sopenharmony_ci struct smt_p_state *st ; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci /* set my UNA */ 57862306a36Sopenharmony_ci if (!is_equal( 57962306a36Sopenharmony_ci &smc->mib.m[MAC0].fddiMACUpstreamNbr, 58062306a36Sopenharmony_ci &sm->smt_source)) { 58162306a36Sopenharmony_ci DB_SMT("SMT : updated my UNA = %pM", 58262306a36Sopenharmony_ci &sm->smt_source); 58362306a36Sopenharmony_ci if (!is_equal(&smc->mib.m[MAC0]. 58462306a36Sopenharmony_ci fddiMACUpstreamNbr,&SMT_Unknown)){ 58562306a36Sopenharmony_ci /* Do not update unknown address */ 58662306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACOldUpstreamNbr= 58762306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACUpstreamNbr ; 58862306a36Sopenharmony_ci } 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACUpstreamNbr = 59162306a36Sopenharmony_ci sm->smt_source ; 59262306a36Sopenharmony_ci smt_srf_event(smc, 59362306a36Sopenharmony_ci SMT_EVENT_MAC_NEIGHBOR_CHANGE, 59462306a36Sopenharmony_ci INDEX_MAC,0) ; 59562306a36Sopenharmony_ci smt_echo_test(smc,0) ; 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci smc->sm.smt_tvu = smt_get_time() ; 59862306a36Sopenharmony_ci st = (struct smt_p_state *) 59962306a36Sopenharmony_ci sm_to_para(smc,sm,SMT_P_STATE) ; 60062306a36Sopenharmony_ci if (st) { 60162306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACUNDA_Flag = 60262306a36Sopenharmony_ci (st->st_dupl_addr & SMT_ST_MY_DUPA) ? 60362306a36Sopenharmony_ci TRUE : FALSE ; 60462306a36Sopenharmony_ci update_dac(smc,1) ; 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci } 60762306a36Sopenharmony_ci if ((sm->smt_type == SMT_REQUEST) && 60862306a36Sopenharmony_ci is_individual(&sm->smt_source) && 60962306a36Sopenharmony_ci ((!(fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) || 61062306a36Sopenharmony_ci (m_fc(mb) != FC_SMT_NSA))) { 61162306a36Sopenharmony_ci DB_SMT("SMT : replying to NIF request %pM", 61262306a36Sopenharmony_ci &sm->smt_source); 61362306a36Sopenharmony_ci smt_send_nif(smc,&sm->smt_source, 61462306a36Sopenharmony_ci FC_SMT_INFO, 61562306a36Sopenharmony_ci sm->smt_tid, 61662306a36Sopenharmony_ci SMT_REPLY,local) ; 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci break ; 61962306a36Sopenharmony_ci case SMT_REPLY : 62062306a36Sopenharmony_ci DB_SMT("SMT : received NIF response from %pM", 62162306a36Sopenharmony_ci &sm->smt_source); 62262306a36Sopenharmony_ci if (fs & A_INDICATOR) { 62362306a36Sopenharmony_ci smc->sm.pend[SMT_TID_NIF] = 0 ; 62462306a36Sopenharmony_ci DB_SMT("SMT : duplicate address"); 62562306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACDupAddressTest = 62662306a36Sopenharmony_ci DA_FAILED ; 62762306a36Sopenharmony_ci smc->r.dup_addr_test = DA_FAILED ; 62862306a36Sopenharmony_ci queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ; 62962306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACDA_Flag = TRUE ; 63062306a36Sopenharmony_ci update_dac(smc,1) ; 63162306a36Sopenharmony_ci break ; 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci if (sm->smt_tid == smc->sm.pend[SMT_TID_NIF]) { 63462306a36Sopenharmony_ci smc->sm.pend[SMT_TID_NIF] = 0 ; 63562306a36Sopenharmony_ci /* set my DNA */ 63662306a36Sopenharmony_ci if (!is_equal( 63762306a36Sopenharmony_ci &smc->mib.m[MAC0].fddiMACDownstreamNbr, 63862306a36Sopenharmony_ci &sm->smt_source)) { 63962306a36Sopenharmony_ci DB_SMT("SMT : updated my DNA"); 64062306a36Sopenharmony_ci if (!is_equal(&smc->mib.m[MAC0]. 64162306a36Sopenharmony_ci fddiMACDownstreamNbr, &SMT_Unknown)){ 64262306a36Sopenharmony_ci /* Do not update unknown address */ 64362306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACOldDownstreamNbr = 64462306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACDownstreamNbr ; 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACDownstreamNbr = 64862306a36Sopenharmony_ci sm->smt_source ; 64962306a36Sopenharmony_ci smt_srf_event(smc, 65062306a36Sopenharmony_ci SMT_EVENT_MAC_NEIGHBOR_CHANGE, 65162306a36Sopenharmony_ci INDEX_MAC,0) ; 65262306a36Sopenharmony_ci smt_echo_test(smc,1) ; 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACDA_Flag = FALSE ; 65562306a36Sopenharmony_ci update_dac(smc,1) ; 65662306a36Sopenharmony_ci smc->sm.smt_tvd = smt_get_time() ; 65762306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACDupAddressTest = 65862306a36Sopenharmony_ci DA_PASSED ; 65962306a36Sopenharmony_ci if (smc->r.dup_addr_test != DA_PASSED) { 66062306a36Sopenharmony_ci smc->r.dup_addr_test = DA_PASSED ; 66162306a36Sopenharmony_ci queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ; 66262306a36Sopenharmony_ci } 66362306a36Sopenharmony_ci } 66462306a36Sopenharmony_ci else if (sm->smt_tid == 66562306a36Sopenharmony_ci smc->sm.pend[SMT_TID_NIF_TEST]) { 66662306a36Sopenharmony_ci DB_SMT("SMT : NIF test TID ok"); 66762306a36Sopenharmony_ci } 66862306a36Sopenharmony_ci else { 66962306a36Sopenharmony_ci DB_SMT("SMT : expected TID %lx, got %x", 67062306a36Sopenharmony_ci smc->sm.pend[SMT_TID_NIF], sm->smt_tid); 67162306a36Sopenharmony_ci } 67262306a36Sopenharmony_ci break ; 67362306a36Sopenharmony_ci default : 67462306a36Sopenharmony_ci illegal = 2 ; 67562306a36Sopenharmony_ci break ; 67662306a36Sopenharmony_ci } 67762306a36Sopenharmony_ci break ; 67862306a36Sopenharmony_ci case SMT_SIF_CONFIG : /* station information */ 67962306a36Sopenharmony_ci if (sm->smt_type != SMT_REQUEST) 68062306a36Sopenharmony_ci break ; 68162306a36Sopenharmony_ci DB_SMT("SMT : replying to SIF Config request from %pM", 68262306a36Sopenharmony_ci &sm->smt_source); 68362306a36Sopenharmony_ci smt_send_sif_config(smc,&sm->smt_source,sm->smt_tid,local) ; 68462306a36Sopenharmony_ci break ; 68562306a36Sopenharmony_ci case SMT_SIF_OPER : /* station information */ 68662306a36Sopenharmony_ci if (sm->smt_type != SMT_REQUEST) 68762306a36Sopenharmony_ci break ; 68862306a36Sopenharmony_ci DB_SMT("SMT : replying to SIF Operation request from %pM", 68962306a36Sopenharmony_ci &sm->smt_source); 69062306a36Sopenharmony_ci smt_send_sif_operation(smc,&sm->smt_source,sm->smt_tid,local) ; 69162306a36Sopenharmony_ci break ; 69262306a36Sopenharmony_ci case SMT_ECF : /* echo frame */ 69362306a36Sopenharmony_ci switch (sm->smt_type) { 69462306a36Sopenharmony_ci case SMT_REPLY : 69562306a36Sopenharmony_ci smc->mib.priv.fddiPRIVECF_Reply_Rx++ ; 69662306a36Sopenharmony_ci DB_SMT("SMT: received ECF reply from %pM", 69762306a36Sopenharmony_ci &sm->smt_source); 69862306a36Sopenharmony_ci if (sm_to_para(smc,sm,SMT_P_ECHODATA) == NULL) { 69962306a36Sopenharmony_ci DB_SMT("SMT: ECHODATA missing"); 70062306a36Sopenharmony_ci break ; 70162306a36Sopenharmony_ci } 70262306a36Sopenharmony_ci if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF]) { 70362306a36Sopenharmony_ci DB_SMT("SMT : ECF test TID ok"); 70462306a36Sopenharmony_ci } 70562306a36Sopenharmony_ci else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_UNA]) { 70662306a36Sopenharmony_ci DB_SMT("SMT : ECF test UNA ok"); 70762306a36Sopenharmony_ci } 70862306a36Sopenharmony_ci else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_DNA]) { 70962306a36Sopenharmony_ci DB_SMT("SMT : ECF test DNA ok"); 71062306a36Sopenharmony_ci } 71162306a36Sopenharmony_ci else { 71262306a36Sopenharmony_ci DB_SMT("SMT : expected TID %lx, got %x", 71362306a36Sopenharmony_ci smc->sm.pend[SMT_TID_ECF], 71462306a36Sopenharmony_ci sm->smt_tid); 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci break ; 71762306a36Sopenharmony_ci case SMT_REQUEST : 71862306a36Sopenharmony_ci smc->mib.priv.fddiPRIVECF_Req_Rx++ ; 71962306a36Sopenharmony_ci { 72062306a36Sopenharmony_ci if (sm->smt_len && !sm_to_para(smc,sm,SMT_P_ECHODATA)) { 72162306a36Sopenharmony_ci DB_SMT("SMT: ECF with para problem,sending RDF"); 72262306a36Sopenharmony_ci smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH, 72362306a36Sopenharmony_ci local) ; 72462306a36Sopenharmony_ci break ; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci DB_SMT("SMT - sending ECF reply to %pM", 72762306a36Sopenharmony_ci &sm->smt_source); 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* set destination addr. & reply */ 73062306a36Sopenharmony_ci sm->smt_dest = sm->smt_source ; 73162306a36Sopenharmony_ci sm->smt_type = SMT_REPLY ; 73262306a36Sopenharmony_ci dump_smt(smc,sm,"ECF REPLY") ; 73362306a36Sopenharmony_ci smc->mib.priv.fddiPRIVECF_Reply_Tx++ ; 73462306a36Sopenharmony_ci smt_send_frame(smc,mb,FC_SMT_INFO,local) ; 73562306a36Sopenharmony_ci return ; /* DON'T free mbuf */ 73662306a36Sopenharmony_ci } 73762306a36Sopenharmony_ci default : 73862306a36Sopenharmony_ci illegal = 1 ; 73962306a36Sopenharmony_ci break ; 74062306a36Sopenharmony_ci } 74162306a36Sopenharmony_ci break ; 74262306a36Sopenharmony_ci#ifndef BOOT 74362306a36Sopenharmony_ci case SMT_RAF : /* resource allocation */ 74462306a36Sopenharmony_ci#ifdef ESS 74562306a36Sopenharmony_ci DB_ESSN(2, "ESS: RAF frame received"); 74662306a36Sopenharmony_ci fs = ess_raf_received_pack(smc,mb,sm,fs) ; 74762306a36Sopenharmony_ci#endif 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci#ifdef SBA 75062306a36Sopenharmony_ci DB_SBAN(2, "SBA: RAF frame received") ; 75162306a36Sopenharmony_ci sba_raf_received_pack(smc,sm,fs) ; 75262306a36Sopenharmony_ci#endif 75362306a36Sopenharmony_ci break ; 75462306a36Sopenharmony_ci case SMT_RDF : /* request denied */ 75562306a36Sopenharmony_ci smc->mib.priv.fddiPRIVRDF_Rx++ ; 75662306a36Sopenharmony_ci break ; 75762306a36Sopenharmony_ci case SMT_ESF : /* extended service - not supported */ 75862306a36Sopenharmony_ci if (sm->smt_type == SMT_REQUEST) { 75962306a36Sopenharmony_ci DB_SMT("SMT - received ESF, sending RDF"); 76062306a36Sopenharmony_ci smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ; 76162306a36Sopenharmony_ci } 76262306a36Sopenharmony_ci break ; 76362306a36Sopenharmony_ci case SMT_PMF_GET : 76462306a36Sopenharmony_ci case SMT_PMF_SET : 76562306a36Sopenharmony_ci if (sm->smt_type != SMT_REQUEST) 76662306a36Sopenharmony_ci break ; 76762306a36Sopenharmony_ci /* update statistics */ 76862306a36Sopenharmony_ci if (sm->smt_class == SMT_PMF_GET) 76962306a36Sopenharmony_ci smc->mib.priv.fddiPRIVPMF_Get_Rx++ ; 77062306a36Sopenharmony_ci else 77162306a36Sopenharmony_ci smc->mib.priv.fddiPRIVPMF_Set_Rx++ ; 77262306a36Sopenharmony_ci /* 77362306a36Sopenharmony_ci * ignore PMF SET with I/G set 77462306a36Sopenharmony_ci */ 77562306a36Sopenharmony_ci if ((sm->smt_class == SMT_PMF_SET) && 77662306a36Sopenharmony_ci !is_individual(&sm->smt_dest)) { 77762306a36Sopenharmony_ci DB_SMT("SMT: ignoring PMF-SET with I/G set"); 77862306a36Sopenharmony_ci break ; 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci smt_pmf_received_pack(smc,mb, local) ; 78162306a36Sopenharmony_ci break ; 78262306a36Sopenharmony_ci case SMT_SRF : 78362306a36Sopenharmony_ci dump_smt(smc,sm,"SRF received") ; 78462306a36Sopenharmony_ci break ; 78562306a36Sopenharmony_ci default : 78662306a36Sopenharmony_ci if (sm->smt_type != SMT_REQUEST) 78762306a36Sopenharmony_ci break ; 78862306a36Sopenharmony_ci /* 78962306a36Sopenharmony_ci * For frames with unknown class: 79062306a36Sopenharmony_ci * we need to send a RDF frame according to 8.1.3.1.1, 79162306a36Sopenharmony_ci * only if it is a REQUEST. 79262306a36Sopenharmony_ci */ 79362306a36Sopenharmony_ci DB_SMT("SMT : class = %d, send RDF to %pM", 79462306a36Sopenharmony_ci sm->smt_class, &sm->smt_source); 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ; 79762306a36Sopenharmony_ci break ; 79862306a36Sopenharmony_ci#endif 79962306a36Sopenharmony_ci } 80062306a36Sopenharmony_ci if (illegal) { 80162306a36Sopenharmony_ci DB_SMT("SMT: discarding invalid frame, reason = %d", illegal); 80262306a36Sopenharmony_ci } 80362306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 80462306a36Sopenharmony_ci} 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_cistatic void update_dac(struct s_smc *smc, int report) 80762306a36Sopenharmony_ci{ 80862306a36Sopenharmony_ci int cond ; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci cond = ( smc->mib.m[MAC0].fddiMACUNDA_Flag | 81162306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACDA_Flag) != 0 ; 81262306a36Sopenharmony_ci if (report && (cond != smc->mib.m[MAC0].fddiMACDuplicateAddressCond)) 81362306a36Sopenharmony_ci smt_srf_event(smc, SMT_COND_MAC_DUP_ADDR,INDEX_MAC,cond) ; 81462306a36Sopenharmony_ci else 81562306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACDuplicateAddressCond = cond ; 81662306a36Sopenharmony_ci} 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci/* 81962306a36Sopenharmony_ci * send SMT frame 82062306a36Sopenharmony_ci * set source address 82162306a36Sopenharmony_ci * set station ID 82262306a36Sopenharmony_ci * send frame 82362306a36Sopenharmony_ci */ 82462306a36Sopenharmony_civoid smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local) 82562306a36Sopenharmony_ci/* SMbuf *mb; buffer to send */ 82662306a36Sopenharmony_ci/* int fc; FC value */ 82762306a36Sopenharmony_ci{ 82862306a36Sopenharmony_ci struct smt_header *sm ; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci if (!smc->r.sm_ma_avail && !local) { 83162306a36Sopenharmony_ci smt_free_mbuf(smc,mb) ; 83262306a36Sopenharmony_ci return ; 83362306a36Sopenharmony_ci } 83462306a36Sopenharmony_ci sm = smtod(mb,struct smt_header *) ; 83562306a36Sopenharmony_ci sm->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ; 83662306a36Sopenharmony_ci sm->smt_sid = smc->mib.fddiSMTStationId ; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci smt_swap_para(sm,(int) mb->sm_len,0) ; /* swap para & header */ 83962306a36Sopenharmony_ci hwm_conv_can(smc,(char *)sm,12) ; /* convert SA and DA */ 84062306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACSMTTransmit_Ct++ ; 84162306a36Sopenharmony_ci smt_send_mbuf(smc,mb,local ? FC_SMT_LOC : fc) ; 84262306a36Sopenharmony_ci} 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci/* 84562306a36Sopenharmony_ci * generate and send RDF 84662306a36Sopenharmony_ci */ 84762306a36Sopenharmony_cistatic void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason, 84862306a36Sopenharmony_ci int local) 84962306a36Sopenharmony_ci/* SMbuf *rej; mbuf of offending frame */ 85062306a36Sopenharmony_ci/* int fc; FC of denied frame */ 85162306a36Sopenharmony_ci/* int reason; reason code */ 85262306a36Sopenharmony_ci{ 85362306a36Sopenharmony_ci SMbuf *mb ; 85462306a36Sopenharmony_ci struct smt_header *sm ; /* header of offending frame */ 85562306a36Sopenharmony_ci struct smt_rdf *rdf ; 85662306a36Sopenharmony_ci int len ; 85762306a36Sopenharmony_ci int frame_len ; 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci sm = smtod(rej,struct smt_header *) ; 86062306a36Sopenharmony_ci if (sm->smt_type != SMT_REQUEST) 86162306a36Sopenharmony_ci return ; 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci DB_SMT("SMT: sending RDF to %pM,reason = 0x%x", 86462306a36Sopenharmony_ci &sm->smt_source, reason); 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci /* 86862306a36Sopenharmony_ci * note: get framelength from MAC length, NOT from SMT header 86962306a36Sopenharmony_ci * smt header length is included in sm_len 87062306a36Sopenharmony_ci */ 87162306a36Sopenharmony_ci frame_len = rej->sm_len ; 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci if (!(mb=smt_build_frame(smc,SMT_RDF,SMT_REPLY,sizeof(struct smt_rdf)))) 87462306a36Sopenharmony_ci return ; 87562306a36Sopenharmony_ci rdf = smtod(mb,struct smt_rdf *) ; 87662306a36Sopenharmony_ci rdf->smt.smt_tid = sm->smt_tid ; /* use TID from sm */ 87762306a36Sopenharmony_ci rdf->smt.smt_dest = sm->smt_source ; /* set dest = source */ 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci /* set P12 */ 88062306a36Sopenharmony_ci rdf->reason.para.p_type = SMT_P_REASON ; 88162306a36Sopenharmony_ci rdf->reason.para.p_len = sizeof(struct smt_p_reason) - PARA_LEN ; 88262306a36Sopenharmony_ci rdf->reason.rdf_reason = reason ; 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci /* set P14 */ 88562306a36Sopenharmony_ci rdf->version.para.p_type = SMT_P_VERSION ; 88662306a36Sopenharmony_ci rdf->version.para.p_len = sizeof(struct smt_p_version) - PARA_LEN ; 88762306a36Sopenharmony_ci rdf->version.v_pad = 0 ; 88862306a36Sopenharmony_ci rdf->version.v_n = 1 ; 88962306a36Sopenharmony_ci rdf->version.v_index = 1 ; 89062306a36Sopenharmony_ci rdf->version.v_version[0] = SMT_VID_2 ; 89162306a36Sopenharmony_ci rdf->version.v_pad2 = 0 ; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci /* set P13 */ 89462306a36Sopenharmony_ci if ((unsigned int) frame_len <= SMT_MAX_INFO_LEN - sizeof(*rdf) + 89562306a36Sopenharmony_ci 2*sizeof(struct smt_header)) 89662306a36Sopenharmony_ci len = frame_len ; 89762306a36Sopenharmony_ci else 89862306a36Sopenharmony_ci len = SMT_MAX_INFO_LEN - sizeof(*rdf) + 89962306a36Sopenharmony_ci 2*sizeof(struct smt_header) ; 90062306a36Sopenharmony_ci /* make length multiple of 4 */ 90162306a36Sopenharmony_ci len &= ~3 ; 90262306a36Sopenharmony_ci rdf->refused.para.p_type = SMT_P_REFUSED ; 90362306a36Sopenharmony_ci /* length of para is smt_frame + ref_fc */ 90462306a36Sopenharmony_ci rdf->refused.para.p_len = len + 4 ; 90562306a36Sopenharmony_ci rdf->refused.ref_fc = fc ; 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci /* swap it back */ 90862306a36Sopenharmony_ci smt_swap_para(sm,frame_len,0) ; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci memcpy((char *) &rdf->refused.ref_header,(char *) sm,len) ; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci len -= sizeof(struct smt_header) ; 91362306a36Sopenharmony_ci mb->sm_len += len ; 91462306a36Sopenharmony_ci rdf->smt.smt_len += len ; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci dump_smt(smc,(struct smt_header *)rdf,"RDF") ; 91762306a36Sopenharmony_ci smc->mib.priv.fddiPRIVRDF_Tx++ ; 91862306a36Sopenharmony_ci smt_send_frame(smc,mb,FC_SMT_INFO,local) ; 91962306a36Sopenharmony_ci} 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci/* 92262306a36Sopenharmony_ci * generate and send NIF 92362306a36Sopenharmony_ci */ 92462306a36Sopenharmony_cistatic void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, 92562306a36Sopenharmony_ci int fc, u_long tid, int type, int local) 92662306a36Sopenharmony_ci/* struct fddi_addr *dest; dest address */ 92762306a36Sopenharmony_ci/* int fc; frame control */ 92862306a36Sopenharmony_ci/* u_long tid; transaction id */ 92962306a36Sopenharmony_ci/* int type; frame type */ 93062306a36Sopenharmony_ci{ 93162306a36Sopenharmony_ci struct smt_nif *nif ; 93262306a36Sopenharmony_ci SMbuf *mb ; 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci if (!(mb = smt_build_frame(smc,SMT_NIF,type,sizeof(struct smt_nif)))) 93562306a36Sopenharmony_ci return ; 93662306a36Sopenharmony_ci nif = smtod(mb, struct smt_nif *) ; 93762306a36Sopenharmony_ci smt_fill_una(smc,&nif->una) ; /* set UNA */ 93862306a36Sopenharmony_ci smt_fill_sde(smc,&nif->sde) ; /* set station descriptor */ 93962306a36Sopenharmony_ci smt_fill_state(smc,&nif->state) ; /* set state information */ 94062306a36Sopenharmony_ci#ifdef SMT6_10 94162306a36Sopenharmony_ci smt_fill_fsc(smc,&nif->fsc) ; /* set frame status cap. */ 94262306a36Sopenharmony_ci#endif 94362306a36Sopenharmony_ci nif->smt.smt_dest = *dest ; /* destination address */ 94462306a36Sopenharmony_ci nif->smt.smt_tid = tid ; /* transaction ID */ 94562306a36Sopenharmony_ci dump_smt(smc,(struct smt_header *)nif,"NIF") ; 94662306a36Sopenharmony_ci smt_send_frame(smc,mb,fc,local) ; 94762306a36Sopenharmony_ci} 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci#ifdef DEBUG 95062306a36Sopenharmony_ci/* 95162306a36Sopenharmony_ci * send NIF request (test purpose) 95262306a36Sopenharmony_ci */ 95362306a36Sopenharmony_cistatic void smt_send_nif_request(struct s_smc *smc, struct fddi_addr *dest) 95462306a36Sopenharmony_ci{ 95562306a36Sopenharmony_ci smc->sm.pend[SMT_TID_NIF_TEST] = smt_get_tid(smc) ; 95662306a36Sopenharmony_ci smt_send_nif(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_NIF_TEST], 95762306a36Sopenharmony_ci SMT_REQUEST,0) ; 95862306a36Sopenharmony_ci} 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci/* 96162306a36Sopenharmony_ci * send ECF request (test purpose) 96262306a36Sopenharmony_ci */ 96362306a36Sopenharmony_cistatic void smt_send_ecf_request(struct s_smc *smc, struct fddi_addr *dest, 96462306a36Sopenharmony_ci int len) 96562306a36Sopenharmony_ci{ 96662306a36Sopenharmony_ci smc->sm.pend[SMT_TID_ECF] = smt_get_tid(smc) ; 96762306a36Sopenharmony_ci smt_send_ecf(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_ECF], 96862306a36Sopenharmony_ci SMT_REQUEST,len) ; 96962306a36Sopenharmony_ci} 97062306a36Sopenharmony_ci#endif 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci/* 97362306a36Sopenharmony_ci * echo test 97462306a36Sopenharmony_ci */ 97562306a36Sopenharmony_cistatic void smt_echo_test(struct s_smc *smc, int dna) 97662306a36Sopenharmony_ci{ 97762306a36Sopenharmony_ci u_long tid ; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci smc->sm.pend[dna ? SMT_TID_ECF_DNA : SMT_TID_ECF_UNA] = 98062306a36Sopenharmony_ci tid = smt_get_tid(smc) ; 98162306a36Sopenharmony_ci smt_send_ecf(smc, dna ? 98262306a36Sopenharmony_ci &smc->mib.m[MAC0].fddiMACDownstreamNbr : 98362306a36Sopenharmony_ci &smc->mib.m[MAC0].fddiMACUpstreamNbr, 98462306a36Sopenharmony_ci FC_SMT_INFO,tid, SMT_REQUEST, (SMT_TEST_ECHO_LEN & ~3)-8) ; 98562306a36Sopenharmony_ci} 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci/* 98862306a36Sopenharmony_ci * generate and send ECF 98962306a36Sopenharmony_ci */ 99062306a36Sopenharmony_cistatic void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc, 99162306a36Sopenharmony_ci u_long tid, int type, int len) 99262306a36Sopenharmony_ci/* struct fddi_addr *dest; dest address */ 99362306a36Sopenharmony_ci/* int fc; frame control */ 99462306a36Sopenharmony_ci/* u_long tid; transaction id */ 99562306a36Sopenharmony_ci/* int type; frame type */ 99662306a36Sopenharmony_ci/* int len; frame length */ 99762306a36Sopenharmony_ci{ 99862306a36Sopenharmony_ci struct smt_ecf *ecf ; 99962306a36Sopenharmony_ci SMbuf *mb ; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci if (!(mb = smt_build_frame(smc,SMT_ECF,type,SMT_ECF_LEN + len))) 100262306a36Sopenharmony_ci return ; 100362306a36Sopenharmony_ci ecf = smtod(mb, struct smt_ecf *) ; 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci smt_fill_echo(smc,&ecf->ec_echo,tid,len) ; /* set ECHO */ 100662306a36Sopenharmony_ci ecf->smt.smt_dest = *dest ; /* destination address */ 100762306a36Sopenharmony_ci ecf->smt.smt_tid = tid ; /* transaction ID */ 100862306a36Sopenharmony_ci smc->mib.priv.fddiPRIVECF_Req_Tx++ ; 100962306a36Sopenharmony_ci smt_send_frame(smc,mb,fc,0) ; 101062306a36Sopenharmony_ci} 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci/* 101362306a36Sopenharmony_ci * generate and send SIF config response 101462306a36Sopenharmony_ci */ 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_cistatic void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest, 101762306a36Sopenharmony_ci u_long tid, int local) 101862306a36Sopenharmony_ci/* struct fddi_addr *dest; dest address */ 101962306a36Sopenharmony_ci/* u_long tid; transaction id */ 102062306a36Sopenharmony_ci{ 102162306a36Sopenharmony_ci struct smt_sif_config *sif ; 102262306a36Sopenharmony_ci SMbuf *mb ; 102362306a36Sopenharmony_ci int len ; 102462306a36Sopenharmony_ci if (!(mb = smt_build_frame(smc,SMT_SIF_CONFIG,SMT_REPLY, 102562306a36Sopenharmony_ci SIZEOF_SMT_SIF_CONFIG))) 102662306a36Sopenharmony_ci return ; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci sif = smtod(mb, struct smt_sif_config *) ; 102962306a36Sopenharmony_ci smt_fill_timestamp(smc,&sif->ts) ; /* set time stamp */ 103062306a36Sopenharmony_ci smt_fill_sde(smc,&sif->sde) ; /* set station descriptor */ 103162306a36Sopenharmony_ci smt_fill_version(smc,&sif->version) ; /* set version information */ 103262306a36Sopenharmony_ci smt_fill_state(smc,&sif->state) ; /* set state information */ 103362306a36Sopenharmony_ci smt_fill_policy(smc,&sif->policy) ; /* set station policy */ 103462306a36Sopenharmony_ci smt_fill_latency(smc,&sif->latency); /* set station latency */ 103562306a36Sopenharmony_ci smt_fill_neighbor(smc,&sif->neighbor); /* set station neighbor */ 103662306a36Sopenharmony_ci smt_fill_setcount(smc,&sif->setcount) ; /* set count */ 103762306a36Sopenharmony_ci len = smt_fill_path(smc,&sif->path); /* set station path descriptor*/ 103862306a36Sopenharmony_ci sif->smt.smt_dest = *dest ; /* destination address */ 103962306a36Sopenharmony_ci sif->smt.smt_tid = tid ; /* transaction ID */ 104062306a36Sopenharmony_ci smt_add_frame_len(mb,len) ; /* adjust length fields */ 104162306a36Sopenharmony_ci dump_smt(smc,(struct smt_header *)sif,"SIF Configuration Reply") ; 104262306a36Sopenharmony_ci smt_send_frame(smc,mb,FC_SMT_INFO,local) ; 104362306a36Sopenharmony_ci} 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci/* 104662306a36Sopenharmony_ci * generate and send SIF operation response 104762306a36Sopenharmony_ci */ 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_cistatic void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest, 105062306a36Sopenharmony_ci u_long tid, int local) 105162306a36Sopenharmony_ci/* struct fddi_addr *dest; dest address */ 105262306a36Sopenharmony_ci/* u_long tid; transaction id */ 105362306a36Sopenharmony_ci{ 105462306a36Sopenharmony_ci struct smt_sif_operation *sif ; 105562306a36Sopenharmony_ci SMbuf *mb ; 105662306a36Sopenharmony_ci int ports ; 105762306a36Sopenharmony_ci int i ; 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci ports = NUMPHYS ; 106062306a36Sopenharmony_ci#ifndef CONCENTRATOR 106162306a36Sopenharmony_ci if (smc->s.sas == SMT_SAS) 106262306a36Sopenharmony_ci ports = 1 ; 106362306a36Sopenharmony_ci#endif 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci if (!(mb = smt_build_frame(smc,SMT_SIF_OPER,SMT_REPLY, 106662306a36Sopenharmony_ci struct_size(sif, lem, ports)))) 106762306a36Sopenharmony_ci return ; 106862306a36Sopenharmony_ci sif = smtod(mb, typeof(sif)); 106962306a36Sopenharmony_ci smt_fill_timestamp(smc,&sif->ts) ; /* set time stamp */ 107062306a36Sopenharmony_ci smt_fill_mac_status(smc,&sif->status) ; /* set mac status */ 107162306a36Sopenharmony_ci smt_fill_mac_counter(smc,&sif->mc) ; /* set mac counter field */ 107262306a36Sopenharmony_ci smt_fill_mac_fnc(smc,&sif->fnc) ; /* set frame not copied counter */ 107362306a36Sopenharmony_ci smt_fill_manufacturer(smc,&sif->man) ; /* set manufacturer field */ 107462306a36Sopenharmony_ci smt_fill_user(smc,&sif->user) ; /* set user field */ 107562306a36Sopenharmony_ci smt_fill_setcount(smc,&sif->setcount) ; /* set count */ 107662306a36Sopenharmony_ci /* 107762306a36Sopenharmony_ci * set link error mon information 107862306a36Sopenharmony_ci */ 107962306a36Sopenharmony_ci if (ports == 1) { 108062306a36Sopenharmony_ci smt_fill_lem(smc,sif->lem,PS) ; 108162306a36Sopenharmony_ci } 108262306a36Sopenharmony_ci else { 108362306a36Sopenharmony_ci for (i = 0 ; i < ports ; i++) { 108462306a36Sopenharmony_ci smt_fill_lem(smc,&sif->lem[i],i) ; 108562306a36Sopenharmony_ci } 108662306a36Sopenharmony_ci } 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci sif->smt.smt_dest = *dest ; /* destination address */ 108962306a36Sopenharmony_ci sif->smt.smt_tid = tid ; /* transaction ID */ 109062306a36Sopenharmony_ci dump_smt(smc,(struct smt_header *)sif,"SIF Operation Reply") ; 109162306a36Sopenharmony_ci smt_send_frame(smc,mb,FC_SMT_INFO,local) ; 109262306a36Sopenharmony_ci} 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci/* 109562306a36Sopenharmony_ci * get and initialize SMT frame 109662306a36Sopenharmony_ci */ 109762306a36Sopenharmony_ciSMbuf *smt_build_frame(struct s_smc *smc, int class, int type, 109862306a36Sopenharmony_ci int length) 109962306a36Sopenharmony_ci{ 110062306a36Sopenharmony_ci SMbuf *mb ; 110162306a36Sopenharmony_ci struct smt_header *smt ; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci#if 0 110462306a36Sopenharmony_ci if (!smc->r.sm_ma_avail) { 110562306a36Sopenharmony_ci return 0; 110662306a36Sopenharmony_ci } 110762306a36Sopenharmony_ci#endif 110862306a36Sopenharmony_ci if (!(mb = smt_get_mbuf(smc))) 110962306a36Sopenharmony_ci return mb; 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci mb->sm_len = length ; 111262306a36Sopenharmony_ci smt = smtod(mb, struct smt_header *) ; 111362306a36Sopenharmony_ci smt->smt_dest = fddi_broadcast ; /* set dest = broadcast */ 111462306a36Sopenharmony_ci smt->smt_class = class ; 111562306a36Sopenharmony_ci smt->smt_type = type ; 111662306a36Sopenharmony_ci switch (class) { 111762306a36Sopenharmony_ci case SMT_NIF : 111862306a36Sopenharmony_ci case SMT_SIF_CONFIG : 111962306a36Sopenharmony_ci case SMT_SIF_OPER : 112062306a36Sopenharmony_ci case SMT_ECF : 112162306a36Sopenharmony_ci smt->smt_version = SMT_VID ; 112262306a36Sopenharmony_ci break ; 112362306a36Sopenharmony_ci default : 112462306a36Sopenharmony_ci smt->smt_version = SMT_VID_2 ; 112562306a36Sopenharmony_ci break ; 112662306a36Sopenharmony_ci } 112762306a36Sopenharmony_ci smt->smt_tid = smt_get_tid(smc) ; /* set transaction ID */ 112862306a36Sopenharmony_ci smt->smt_pad = 0 ; 112962306a36Sopenharmony_ci smt->smt_len = length - sizeof(struct smt_header) ; 113062306a36Sopenharmony_ci return mb; 113162306a36Sopenharmony_ci} 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_cistatic void smt_add_frame_len(SMbuf *mb, int len) 113462306a36Sopenharmony_ci{ 113562306a36Sopenharmony_ci struct smt_header *smt ; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci smt = smtod(mb, struct smt_header *) ; 113862306a36Sopenharmony_ci smt->smt_len += len ; 113962306a36Sopenharmony_ci mb->sm_len += len ; 114062306a36Sopenharmony_ci} 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci/* 114562306a36Sopenharmony_ci * fill values in UNA parameter 114662306a36Sopenharmony_ci */ 114762306a36Sopenharmony_cistatic void smt_fill_una(struct s_smc *smc, struct smt_p_una *una) 114862306a36Sopenharmony_ci{ 114962306a36Sopenharmony_ci SMTSETPARA(una,SMT_P_UNA) ; 115062306a36Sopenharmony_ci una->una_pad = 0 ; 115162306a36Sopenharmony_ci una->una_node = smc->mib.m[MAC0].fddiMACUpstreamNbr ; 115262306a36Sopenharmony_ci} 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci/* 115562306a36Sopenharmony_ci * fill values in SDE parameter 115662306a36Sopenharmony_ci */ 115762306a36Sopenharmony_cistatic void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde) 115862306a36Sopenharmony_ci{ 115962306a36Sopenharmony_ci SMTSETPARA(sde,SMT_P_SDE) ; 116062306a36Sopenharmony_ci sde->sde_non_master = smc->mib.fddiSMTNonMaster_Ct ; 116162306a36Sopenharmony_ci sde->sde_master = smc->mib.fddiSMTMaster_Ct ; 116262306a36Sopenharmony_ci sde->sde_mac_count = NUMMACS ; /* only 1 MAC */ 116362306a36Sopenharmony_ci#ifdef CONCENTRATOR 116462306a36Sopenharmony_ci sde->sde_type = SMT_SDE_CONCENTRATOR ; 116562306a36Sopenharmony_ci#else 116662306a36Sopenharmony_ci sde->sde_type = SMT_SDE_STATION ; 116762306a36Sopenharmony_ci#endif 116862306a36Sopenharmony_ci} 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci/* 117162306a36Sopenharmony_ci * fill in values in station state parameter 117262306a36Sopenharmony_ci */ 117362306a36Sopenharmony_cistatic void smt_fill_state(struct s_smc *smc, struct smt_p_state *state) 117462306a36Sopenharmony_ci{ 117562306a36Sopenharmony_ci int top ; 117662306a36Sopenharmony_ci int twist ; 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci SMTSETPARA(state,SMT_P_STATE) ; 117962306a36Sopenharmony_ci state->st_pad = 0 ; 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci /* determine topology */ 118262306a36Sopenharmony_ci top = 0 ; 118362306a36Sopenharmony_ci if (smc->mib.fddiSMTPeerWrapFlag) { 118462306a36Sopenharmony_ci top |= SMT_ST_WRAPPED ; /* state wrapped */ 118562306a36Sopenharmony_ci } 118662306a36Sopenharmony_ci#ifdef CONCENTRATOR 118762306a36Sopenharmony_ci if (cfm_status_unattached(smc)) { 118862306a36Sopenharmony_ci top |= SMT_ST_UNATTACHED ; /* unattached concentrator */ 118962306a36Sopenharmony_ci } 119062306a36Sopenharmony_ci#endif 119162306a36Sopenharmony_ci if ((twist = pcm_status_twisted(smc)) & 1) { 119262306a36Sopenharmony_ci top |= SMT_ST_TWISTED_A ; /* twisted cable */ 119362306a36Sopenharmony_ci } 119462306a36Sopenharmony_ci if (twist & 2) { 119562306a36Sopenharmony_ci top |= SMT_ST_TWISTED_B ; /* twisted cable */ 119662306a36Sopenharmony_ci } 119762306a36Sopenharmony_ci#ifdef OPT_SRF 119862306a36Sopenharmony_ci top |= SMT_ST_SRF ; 119962306a36Sopenharmony_ci#endif 120062306a36Sopenharmony_ci if (pcm_rooted_station(smc)) 120162306a36Sopenharmony_ci top |= SMT_ST_ROOTED_S ; 120262306a36Sopenharmony_ci if (smc->mib.a[0].fddiPATHSbaPayload != 0) 120362306a36Sopenharmony_ci top |= SMT_ST_SYNC_SERVICE ; 120462306a36Sopenharmony_ci state->st_topology = top ; 120562306a36Sopenharmony_ci state->st_dupl_addr = 120662306a36Sopenharmony_ci ((smc->mib.m[MAC0].fddiMACDA_Flag ? SMT_ST_MY_DUPA : 0 ) | 120762306a36Sopenharmony_ci (smc->mib.m[MAC0].fddiMACUNDA_Flag ? SMT_ST_UNA_DUPA : 0)) ; 120862306a36Sopenharmony_ci} 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci/* 121162306a36Sopenharmony_ci * fill values in timestamp parameter 121262306a36Sopenharmony_ci */ 121362306a36Sopenharmony_cistatic void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts) 121462306a36Sopenharmony_ci{ 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci SMTSETPARA(ts,SMT_P_TIMESTAMP) ; 121762306a36Sopenharmony_ci smt_set_timestamp(smc,ts->ts_time) ; 121862306a36Sopenharmony_ci} 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_civoid smt_set_timestamp(struct s_smc *smc, u_char *p) 122162306a36Sopenharmony_ci{ 122262306a36Sopenharmony_ci u_long time ; 122362306a36Sopenharmony_ci u_long utime ; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci /* 122662306a36Sopenharmony_ci * timestamp is 64 bits long ; resolution is 80 nS 122762306a36Sopenharmony_ci * our clock resolution is 10mS 122862306a36Sopenharmony_ci * 10mS/80ns = 125000 ~ 2^17 = 131072 122962306a36Sopenharmony_ci */ 123062306a36Sopenharmony_ci utime = smt_get_time() ; 123162306a36Sopenharmony_ci time = utime * 100 ; 123262306a36Sopenharmony_ci time /= TICKS_PER_SECOND ; 123362306a36Sopenharmony_ci p[0] = 0 ; 123462306a36Sopenharmony_ci p[1] = (u_char)((time>>(8+8+8+8-1)) & 1) ; 123562306a36Sopenharmony_ci p[2] = (u_char)(time>>(8+8+8-1)) ; 123662306a36Sopenharmony_ci p[3] = (u_char)(time>>(8+8-1)) ; 123762306a36Sopenharmony_ci p[4] = (u_char)(time>>(8-1)) ; 123862306a36Sopenharmony_ci p[5] = (u_char)(time<<1) ; 123962306a36Sopenharmony_ci p[6] = (u_char)(smc->sm.uniq_ticks>>8) ; 124062306a36Sopenharmony_ci p[7] = (u_char)smc->sm.uniq_ticks ; 124162306a36Sopenharmony_ci /* 124262306a36Sopenharmony_ci * make sure we don't wrap: restart whenever the upper digits change 124362306a36Sopenharmony_ci */ 124462306a36Sopenharmony_ci if (utime != smc->sm.uniq_time) { 124562306a36Sopenharmony_ci smc->sm.uniq_ticks = 0 ; 124662306a36Sopenharmony_ci } 124762306a36Sopenharmony_ci smc->sm.uniq_ticks++ ; 124862306a36Sopenharmony_ci smc->sm.uniq_time = utime ; 124962306a36Sopenharmony_ci} 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci/* 125262306a36Sopenharmony_ci * fill values in station policy parameter 125362306a36Sopenharmony_ci */ 125462306a36Sopenharmony_cistatic void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy) 125562306a36Sopenharmony_ci{ 125662306a36Sopenharmony_ci int i ; 125762306a36Sopenharmony_ci const u_char *map ; 125862306a36Sopenharmony_ci u_short in ; 125962306a36Sopenharmony_ci u_short out ; 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci /* 126262306a36Sopenharmony_ci * MIB para 101b (fddiSMTConnectionPolicy) coding 126362306a36Sopenharmony_ci * is different from 0005 coding 126462306a36Sopenharmony_ci */ 126562306a36Sopenharmony_ci static const u_char ansi_weirdness[16] = { 126662306a36Sopenharmony_ci 0,7,5,3,8,1,6,4,9,10,2,11,12,13,14,15 126762306a36Sopenharmony_ci } ; 126862306a36Sopenharmony_ci SMTSETPARA(policy,SMT_P_POLICY) ; 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci out = 0 ; 127162306a36Sopenharmony_ci in = smc->mib.fddiSMTConnectionPolicy ; 127262306a36Sopenharmony_ci for (i = 0, map = ansi_weirdness ; i < 16 ; i++) { 127362306a36Sopenharmony_ci if (in & 1) 127462306a36Sopenharmony_ci out |= (1<<*map) ; 127562306a36Sopenharmony_ci in >>= 1 ; 127662306a36Sopenharmony_ci map++ ; 127762306a36Sopenharmony_ci } 127862306a36Sopenharmony_ci policy->pl_config = smc->mib.fddiSMTConfigPolicy ; 127962306a36Sopenharmony_ci policy->pl_connect = out ; 128062306a36Sopenharmony_ci} 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci/* 128362306a36Sopenharmony_ci * fill values in latency equivalent parameter 128462306a36Sopenharmony_ci */ 128562306a36Sopenharmony_cistatic void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency) 128662306a36Sopenharmony_ci{ 128762306a36Sopenharmony_ci SMTSETPARA(latency,SMT_P_LATENCY) ; 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci latency->lt_phyout_idx1 = phy_index(smc,0) ; 129062306a36Sopenharmony_ci latency->lt_latency1 = 10 ; /* in octets (byte clock) */ 129162306a36Sopenharmony_ci /* 129262306a36Sopenharmony_ci * note: latency has two phy entries by definition 129362306a36Sopenharmony_ci * for a SAS, the 2nd one is null 129462306a36Sopenharmony_ci */ 129562306a36Sopenharmony_ci if (smc->s.sas == SMT_DAS) { 129662306a36Sopenharmony_ci latency->lt_phyout_idx2 = phy_index(smc,1) ; 129762306a36Sopenharmony_ci latency->lt_latency2 = 10 ; /* in octets (byte clock) */ 129862306a36Sopenharmony_ci } 129962306a36Sopenharmony_ci else { 130062306a36Sopenharmony_ci latency->lt_phyout_idx2 = 0 ; 130162306a36Sopenharmony_ci latency->lt_latency2 = 0 ; 130262306a36Sopenharmony_ci } 130362306a36Sopenharmony_ci} 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci/* 130662306a36Sopenharmony_ci * fill values in MAC neighbors parameter 130762306a36Sopenharmony_ci */ 130862306a36Sopenharmony_cistatic void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor) 130962306a36Sopenharmony_ci{ 131062306a36Sopenharmony_ci SMTSETPARA(neighbor,SMT_P_NEIGHBORS) ; 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci neighbor->nb_mib_index = INDEX_MAC ; 131362306a36Sopenharmony_ci neighbor->nb_mac_index = mac_index(smc,1) ; 131462306a36Sopenharmony_ci neighbor->nb_una = smc->mib.m[MAC0].fddiMACUpstreamNbr ; 131562306a36Sopenharmony_ci neighbor->nb_dna = smc->mib.m[MAC0].fddiMACDownstreamNbr ; 131662306a36Sopenharmony_ci} 131762306a36Sopenharmony_ci 131862306a36Sopenharmony_ci/* 131962306a36Sopenharmony_ci * fill values in path descriptor 132062306a36Sopenharmony_ci */ 132162306a36Sopenharmony_ci#ifdef CONCENTRATOR 132262306a36Sopenharmony_ci#define ALLPHYS NUMPHYS 132362306a36Sopenharmony_ci#else 132462306a36Sopenharmony_ci#define ALLPHYS ((smc->s.sas == SMT_SAS) ? 1 : 2) 132562306a36Sopenharmony_ci#endif 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_cistatic int smt_fill_path(struct s_smc *smc, struct smt_p_path *path) 132862306a36Sopenharmony_ci{ 132962306a36Sopenharmony_ci SK_LOC_DECL(int,type) ; 133062306a36Sopenharmony_ci SK_LOC_DECL(int,state) ; 133162306a36Sopenharmony_ci SK_LOC_DECL(int,remote) ; 133262306a36Sopenharmony_ci SK_LOC_DECL(int,mac) ; 133362306a36Sopenharmony_ci int len ; 133462306a36Sopenharmony_ci int p ; 133562306a36Sopenharmony_ci int physp ; 133662306a36Sopenharmony_ci struct smt_phy_rec *phy ; 133762306a36Sopenharmony_ci struct smt_mac_rec *pd_mac ; 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci len = PARA_LEN + 134062306a36Sopenharmony_ci sizeof(struct smt_mac_rec) * NUMMACS + 134162306a36Sopenharmony_ci sizeof(struct smt_phy_rec) * ALLPHYS ; 134262306a36Sopenharmony_ci path->para.p_type = SMT_P_PATH ; 134362306a36Sopenharmony_ci path->para.p_len = len - PARA_LEN ; 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci /* PHYs */ 134662306a36Sopenharmony_ci for (p = 0,phy = path->pd_phy ; p < ALLPHYS ; p++, phy++) { 134762306a36Sopenharmony_ci physp = p ; 134862306a36Sopenharmony_ci#ifndef CONCENTRATOR 134962306a36Sopenharmony_ci if (smc->s.sas == SMT_SAS) 135062306a36Sopenharmony_ci physp = PS ; 135162306a36Sopenharmony_ci#endif 135262306a36Sopenharmony_ci pcm_status_state(smc,physp,&type,&state,&remote,&mac) ; 135362306a36Sopenharmony_ci#ifdef LITTLE_ENDIAN 135462306a36Sopenharmony_ci phy->phy_mib_index = smt_swap_short((u_short)p+INDEX_PORT) ; 135562306a36Sopenharmony_ci#else 135662306a36Sopenharmony_ci phy->phy_mib_index = p+INDEX_PORT ; 135762306a36Sopenharmony_ci#endif 135862306a36Sopenharmony_ci phy->phy_type = type ; 135962306a36Sopenharmony_ci phy->phy_connect_state = state ; 136062306a36Sopenharmony_ci phy->phy_remote_type = remote ; 136162306a36Sopenharmony_ci phy->phy_remote_mac = mac ; 136262306a36Sopenharmony_ci phy->phy_resource_idx = phy_con_resource_index(smc,p) ; 136362306a36Sopenharmony_ci } 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci /* MAC */ 136662306a36Sopenharmony_ci pd_mac = (struct smt_mac_rec *) phy ; 136762306a36Sopenharmony_ci pd_mac->mac_addr = smc->mib.m[MAC0].fddiMACSMTAddress ; 136862306a36Sopenharmony_ci pd_mac->mac_resource_idx = mac_con_resource_index(smc,1) ; 136962306a36Sopenharmony_ci return len; 137062306a36Sopenharmony_ci} 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci/* 137362306a36Sopenharmony_ci * fill values in mac status 137462306a36Sopenharmony_ci */ 137562306a36Sopenharmony_cistatic void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st) 137662306a36Sopenharmony_ci{ 137762306a36Sopenharmony_ci SMTSETPARA(st,SMT_P_MAC_STATUS) ; 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci st->st_mib_index = INDEX_MAC ; 138062306a36Sopenharmony_ci st->st_mac_index = mac_index(smc,1) ; 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci mac_update_counter(smc) ; 138362306a36Sopenharmony_ci /* 138462306a36Sopenharmony_ci * timer values are represented in SMT as 2's complement numbers 138562306a36Sopenharmony_ci * units : internal : 2's complement BCLK 138662306a36Sopenharmony_ci */ 138762306a36Sopenharmony_ci st->st_t_req = smc->mib.m[MAC0].fddiMACT_Req ; 138862306a36Sopenharmony_ci st->st_t_neg = smc->mib.m[MAC0].fddiMACT_Neg ; 138962306a36Sopenharmony_ci st->st_t_max = smc->mib.m[MAC0].fddiMACT_Max ; 139062306a36Sopenharmony_ci st->st_tvx_value = smc->mib.m[MAC0].fddiMACTvxValue ; 139162306a36Sopenharmony_ci st->st_t_min = smc->mib.m[MAC0].fddiMACT_Min ; 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci st->st_sba = smc->mib.a[PATH0].fddiPATHSbaPayload ; 139462306a36Sopenharmony_ci st->st_frame_ct = smc->mib.m[MAC0].fddiMACFrame_Ct ; 139562306a36Sopenharmony_ci st->st_error_ct = smc->mib.m[MAC0].fddiMACError_Ct ; 139662306a36Sopenharmony_ci st->st_lost_ct = smc->mib.m[MAC0].fddiMACLost_Ct ; 139762306a36Sopenharmony_ci} 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci/* 140062306a36Sopenharmony_ci * fill values in LEM status 140162306a36Sopenharmony_ci */ 140262306a36Sopenharmony_cistatic void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy) 140362306a36Sopenharmony_ci{ 140462306a36Sopenharmony_ci struct fddi_mib_p *mib ; 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci mib = smc->y[phy].mib ; 140762306a36Sopenharmony_ci 140862306a36Sopenharmony_ci SMTSETPARA(lem,SMT_P_LEM) ; 140962306a36Sopenharmony_ci lem->lem_mib_index = phy+INDEX_PORT ; 141062306a36Sopenharmony_ci lem->lem_phy_index = phy_index(smc,phy) ; 141162306a36Sopenharmony_ci lem->lem_pad2 = 0 ; 141262306a36Sopenharmony_ci lem->lem_cutoff = mib->fddiPORTLer_Cutoff ; 141362306a36Sopenharmony_ci lem->lem_alarm = mib->fddiPORTLer_Alarm ; 141462306a36Sopenharmony_ci /* long term bit error rate */ 141562306a36Sopenharmony_ci lem->lem_estimate = mib->fddiPORTLer_Estimate ; 141662306a36Sopenharmony_ci /* # of rejected connections */ 141762306a36Sopenharmony_ci lem->lem_reject_ct = mib->fddiPORTLem_Reject_Ct ; 141862306a36Sopenharmony_ci lem->lem_ct = mib->fddiPORTLem_Ct ; /* total number of errors */ 141962306a36Sopenharmony_ci} 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci/* 142262306a36Sopenharmony_ci * fill version parameter 142362306a36Sopenharmony_ci */ 142462306a36Sopenharmony_cistatic void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers) 142562306a36Sopenharmony_ci{ 142662306a36Sopenharmony_ci SK_UNUSED(smc) ; 142762306a36Sopenharmony_ci SMTSETPARA(vers,SMT_P_VERSION) ; 142862306a36Sopenharmony_ci vers->v_pad = 0 ; 142962306a36Sopenharmony_ci vers->v_n = 1 ; /* one version is enough .. */ 143062306a36Sopenharmony_ci vers->v_index = 1 ; 143162306a36Sopenharmony_ci vers->v_version[0] = SMT_VID_2 ; 143262306a36Sopenharmony_ci vers->v_pad2 = 0 ; 143362306a36Sopenharmony_ci} 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci#ifdef SMT6_10 143662306a36Sopenharmony_ci/* 143762306a36Sopenharmony_ci * fill frame status capabilities 143862306a36Sopenharmony_ci */ 143962306a36Sopenharmony_ci/* 144062306a36Sopenharmony_ci * note: this para 200B is NOT in swap table, because it's also set in 144162306a36Sopenharmony_ci * PMF add_para 144262306a36Sopenharmony_ci */ 144362306a36Sopenharmony_cistatic void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc) 144462306a36Sopenharmony_ci{ 144562306a36Sopenharmony_ci SK_UNUSED(smc) ; 144662306a36Sopenharmony_ci SMTSETPARA(fsc,SMT_P_FSC) ; 144762306a36Sopenharmony_ci fsc->fsc_pad0 = 0 ; 144862306a36Sopenharmony_ci fsc->fsc_mac_index = INDEX_MAC ; /* this is MIB ; MIB is NOT 144962306a36Sopenharmony_ci * mac_index ()i ! 145062306a36Sopenharmony_ci */ 145162306a36Sopenharmony_ci fsc->fsc_pad1 = 0 ; 145262306a36Sopenharmony_ci fsc->fsc_value = FSC_TYPE0 ; /* "normal" node */ 145362306a36Sopenharmony_ci#ifdef LITTLE_ENDIAN 145462306a36Sopenharmony_ci fsc->fsc_mac_index = smt_swap_short(INDEX_MAC) ; 145562306a36Sopenharmony_ci fsc->fsc_value = smt_swap_short(FSC_TYPE0) ; 145662306a36Sopenharmony_ci#endif 145762306a36Sopenharmony_ci} 145862306a36Sopenharmony_ci#endif 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci/* 146162306a36Sopenharmony_ci * fill mac counter field 146262306a36Sopenharmony_ci */ 146362306a36Sopenharmony_cistatic void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc) 146462306a36Sopenharmony_ci{ 146562306a36Sopenharmony_ci SMTSETPARA(mc,SMT_P_MAC_COUNTER) ; 146662306a36Sopenharmony_ci mc->mc_mib_index = INDEX_MAC ; 146762306a36Sopenharmony_ci mc->mc_index = mac_index(smc,1) ; 146862306a36Sopenharmony_ci mc->mc_receive_ct = smc->mib.m[MAC0].fddiMACCopied_Ct ; 146962306a36Sopenharmony_ci mc->mc_transmit_ct = smc->mib.m[MAC0].fddiMACTransmit_Ct ; 147062306a36Sopenharmony_ci} 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci/* 147362306a36Sopenharmony_ci * fill mac frame not copied counter 147462306a36Sopenharmony_ci */ 147562306a36Sopenharmony_cistatic void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc) 147662306a36Sopenharmony_ci{ 147762306a36Sopenharmony_ci SMTSETPARA(fnc,SMT_P_MAC_FNC) ; 147862306a36Sopenharmony_ci fnc->nc_mib_index = INDEX_MAC ; 147962306a36Sopenharmony_ci fnc->nc_index = mac_index(smc,1) ; 148062306a36Sopenharmony_ci fnc->nc_counter = smc->mib.m[MAC0].fddiMACNotCopied_Ct ; 148162306a36Sopenharmony_ci} 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci/* 148562306a36Sopenharmony_ci * fill manufacturer field 148662306a36Sopenharmony_ci */ 148762306a36Sopenharmony_cistatic void smt_fill_manufacturer(struct s_smc *smc, 148862306a36Sopenharmony_ci struct smp_p_manufacturer *man) 148962306a36Sopenharmony_ci{ 149062306a36Sopenharmony_ci SMTSETPARA(man,SMT_P_MANUFACTURER) ; 149162306a36Sopenharmony_ci memcpy((char *) man->mf_data, 149262306a36Sopenharmony_ci (char *) smc->mib.fddiSMTManufacturerData, 149362306a36Sopenharmony_ci sizeof(man->mf_data)) ; 149462306a36Sopenharmony_ci} 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci/* 149762306a36Sopenharmony_ci * fill user field 149862306a36Sopenharmony_ci */ 149962306a36Sopenharmony_cistatic void smt_fill_user(struct s_smc *smc, struct smp_p_user *user) 150062306a36Sopenharmony_ci{ 150162306a36Sopenharmony_ci SMTSETPARA(user,SMT_P_USER) ; 150262306a36Sopenharmony_ci memcpy((char *) user->us_data, 150362306a36Sopenharmony_ci (char *) smc->mib.fddiSMTUserData, 150462306a36Sopenharmony_ci sizeof(user->us_data)) ; 150562306a36Sopenharmony_ci} 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci/* 150862306a36Sopenharmony_ci * fill set count 150962306a36Sopenharmony_ci */ 151062306a36Sopenharmony_cistatic void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount) 151162306a36Sopenharmony_ci{ 151262306a36Sopenharmony_ci SK_UNUSED(smc) ; 151362306a36Sopenharmony_ci SMTSETPARA(setcount,SMT_P_SETCOUNT) ; 151462306a36Sopenharmony_ci setcount->count = smc->mib.fddiSMTSetCount.count ; 151562306a36Sopenharmony_ci memcpy((char *)setcount->timestamp, 151662306a36Sopenharmony_ci (char *)smc->mib.fddiSMTSetCount.timestamp,8) ; 151762306a36Sopenharmony_ci} 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci/* 152062306a36Sopenharmony_ci * fill echo data 152162306a36Sopenharmony_ci */ 152262306a36Sopenharmony_cistatic void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, 152362306a36Sopenharmony_ci int len) 152462306a36Sopenharmony_ci{ 152562306a36Sopenharmony_ci u_char *p ; 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci SK_UNUSED(smc) ; 152862306a36Sopenharmony_ci SMTSETPARA(echo,SMT_P_ECHODATA) ; 152962306a36Sopenharmony_ci echo->para.p_len = len ; 153062306a36Sopenharmony_ci for (p = echo->ec_data ; len ; len--) { 153162306a36Sopenharmony_ci *p++ = (u_char) seed ; 153262306a36Sopenharmony_ci seed += 13 ; 153362306a36Sopenharmony_ci } 153462306a36Sopenharmony_ci} 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_ci/* 153762306a36Sopenharmony_ci * clear DNA and UNA 153862306a36Sopenharmony_ci * called from CFM if configuration changes 153962306a36Sopenharmony_ci */ 154062306a36Sopenharmony_cistatic void smt_clear_una_dna(struct s_smc *smc) 154162306a36Sopenharmony_ci{ 154262306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ; 154362306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ; 154462306a36Sopenharmony_ci} 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_cistatic void smt_clear_old_una_dna(struct s_smc *smc) 154762306a36Sopenharmony_ci{ 154862306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACOldUpstreamNbr = SMT_Unknown ; 154962306a36Sopenharmony_ci smc->mib.m[MAC0].fddiMACOldDownstreamNbr = SMT_Unknown ; 155062306a36Sopenharmony_ci} 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ciu_long smt_get_tid(struct s_smc *smc) 155362306a36Sopenharmony_ci{ 155462306a36Sopenharmony_ci u_long tid ; 155562306a36Sopenharmony_ci while ((tid = ++(smc->sm.smt_tid) ^ SMT_TID_MAGIC) == 0) 155662306a36Sopenharmony_ci ; 155762306a36Sopenharmony_ci return tid & 0x3fffffffL; 155862306a36Sopenharmony_ci} 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci#ifdef LITTLE_ENDIAN 156162306a36Sopenharmony_ci/* 156262306a36Sopenharmony_ci * table of parameter lengths 156362306a36Sopenharmony_ci */ 156462306a36Sopenharmony_cistatic const struct smt_pdef { 156562306a36Sopenharmony_ci int ptype ; 156662306a36Sopenharmony_ci int plen ; 156762306a36Sopenharmony_ci const char *pswap ; 156862306a36Sopenharmony_ci} smt_pdef[] = { 156962306a36Sopenharmony_ci { SMT_P_UNA, sizeof(struct smt_p_una) , 157062306a36Sopenharmony_ci SWAP_SMT_P_UNA } , 157162306a36Sopenharmony_ci { SMT_P_SDE, sizeof(struct smt_p_sde) , 157262306a36Sopenharmony_ci SWAP_SMT_P_SDE } , 157362306a36Sopenharmony_ci { SMT_P_STATE, sizeof(struct smt_p_state) , 157462306a36Sopenharmony_ci SWAP_SMT_P_STATE } , 157562306a36Sopenharmony_ci { SMT_P_TIMESTAMP,sizeof(struct smt_p_timestamp) , 157662306a36Sopenharmony_ci SWAP_SMT_P_TIMESTAMP } , 157762306a36Sopenharmony_ci { SMT_P_POLICY, sizeof(struct smt_p_policy) , 157862306a36Sopenharmony_ci SWAP_SMT_P_POLICY } , 157962306a36Sopenharmony_ci { SMT_P_LATENCY, sizeof(struct smt_p_latency) , 158062306a36Sopenharmony_ci SWAP_SMT_P_LATENCY } , 158162306a36Sopenharmony_ci { SMT_P_NEIGHBORS,sizeof(struct smt_p_neighbor) , 158262306a36Sopenharmony_ci SWAP_SMT_P_NEIGHBORS } , 158362306a36Sopenharmony_ci { SMT_P_PATH, sizeof(struct smt_p_path) , 158462306a36Sopenharmony_ci SWAP_SMT_P_PATH } , 158562306a36Sopenharmony_ci { SMT_P_MAC_STATUS,sizeof(struct smt_p_mac_status) , 158662306a36Sopenharmony_ci SWAP_SMT_P_MAC_STATUS } , 158762306a36Sopenharmony_ci { SMT_P_LEM, sizeof(struct smt_p_lem) , 158862306a36Sopenharmony_ci SWAP_SMT_P_LEM } , 158962306a36Sopenharmony_ci { SMT_P_MAC_COUNTER,sizeof(struct smt_p_mac_counter) , 159062306a36Sopenharmony_ci SWAP_SMT_P_MAC_COUNTER } , 159162306a36Sopenharmony_ci { SMT_P_MAC_FNC,sizeof(struct smt_p_mac_fnc) , 159262306a36Sopenharmony_ci SWAP_SMT_P_MAC_FNC } , 159362306a36Sopenharmony_ci { SMT_P_PRIORITY,sizeof(struct smt_p_priority) , 159462306a36Sopenharmony_ci SWAP_SMT_P_PRIORITY } , 159562306a36Sopenharmony_ci { SMT_P_EB,sizeof(struct smt_p_eb) , 159662306a36Sopenharmony_ci SWAP_SMT_P_EB } , 159762306a36Sopenharmony_ci { SMT_P_MANUFACTURER,sizeof(struct smp_p_manufacturer) , 159862306a36Sopenharmony_ci SWAP_SMT_P_MANUFACTURER } , 159962306a36Sopenharmony_ci { SMT_P_REASON, sizeof(struct smt_p_reason) , 160062306a36Sopenharmony_ci SWAP_SMT_P_REASON } , 160162306a36Sopenharmony_ci { SMT_P_REFUSED, sizeof(struct smt_p_refused) , 160262306a36Sopenharmony_ci SWAP_SMT_P_REFUSED } , 160362306a36Sopenharmony_ci { SMT_P_VERSION, sizeof(struct smt_p_version) , 160462306a36Sopenharmony_ci SWAP_SMT_P_VERSION } , 160562306a36Sopenharmony_ci#ifdef ESS 160662306a36Sopenharmony_ci { SMT_P0015, sizeof(struct smt_p_0015) , SWAP_SMT_P0015 } , 160762306a36Sopenharmony_ci { SMT_P0016, sizeof(struct smt_p_0016) , SWAP_SMT_P0016 } , 160862306a36Sopenharmony_ci { SMT_P0017, sizeof(struct smt_p_0017) , SWAP_SMT_P0017 } , 160962306a36Sopenharmony_ci { SMT_P0018, sizeof(struct smt_p_0018) , SWAP_SMT_P0018 } , 161062306a36Sopenharmony_ci { SMT_P0019, sizeof(struct smt_p_0019) , SWAP_SMT_P0019 } , 161162306a36Sopenharmony_ci { SMT_P001A, sizeof(struct smt_p_001a) , SWAP_SMT_P001A } , 161262306a36Sopenharmony_ci { SMT_P001B, sizeof(struct smt_p_001b) , SWAP_SMT_P001B } , 161362306a36Sopenharmony_ci { SMT_P001C, sizeof(struct smt_p_001c) , SWAP_SMT_P001C } , 161462306a36Sopenharmony_ci { SMT_P001D, sizeof(struct smt_p_001d) , SWAP_SMT_P001D } , 161562306a36Sopenharmony_ci#endif 161662306a36Sopenharmony_ci#if 0 161762306a36Sopenharmony_ci { SMT_P_FSC, sizeof(struct smt_p_fsc) , 161862306a36Sopenharmony_ci SWAP_SMT_P_FSC } , 161962306a36Sopenharmony_ci#endif 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_ci { SMT_P_SETCOUNT,0, SWAP_SMT_P_SETCOUNT } , 162262306a36Sopenharmony_ci { SMT_P1048, 0, SWAP_SMT_P1048 } , 162362306a36Sopenharmony_ci { SMT_P208C, 0, SWAP_SMT_P208C } , 162462306a36Sopenharmony_ci { SMT_P208D, 0, SWAP_SMT_P208D } , 162562306a36Sopenharmony_ci { SMT_P208E, 0, SWAP_SMT_P208E } , 162662306a36Sopenharmony_ci { SMT_P208F, 0, SWAP_SMT_P208F } , 162762306a36Sopenharmony_ci { SMT_P2090, 0, SWAP_SMT_P2090 } , 162862306a36Sopenharmony_ci#ifdef ESS 162962306a36Sopenharmony_ci { SMT_P320B, sizeof(struct smt_p_320b) , SWAP_SMT_P320B } , 163062306a36Sopenharmony_ci { SMT_P320F, sizeof(struct smt_p_320f) , SWAP_SMT_P320F } , 163162306a36Sopenharmony_ci { SMT_P3210, sizeof(struct smt_p_3210) , SWAP_SMT_P3210 } , 163262306a36Sopenharmony_ci#endif 163362306a36Sopenharmony_ci { SMT_P4050, 0, SWAP_SMT_P4050 } , 163462306a36Sopenharmony_ci { SMT_P4051, 0, SWAP_SMT_P4051 } , 163562306a36Sopenharmony_ci { SMT_P4052, 0, SWAP_SMT_P4052 } , 163662306a36Sopenharmony_ci { SMT_P4053, 0, SWAP_SMT_P4053 } , 163762306a36Sopenharmony_ci} ; 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci#define N_SMT_PLEN ARRAY_SIZE(smt_pdef) 164062306a36Sopenharmony_ci#endif 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ciint smt_check_para(struct s_smc *smc, struct smt_header *sm, 164362306a36Sopenharmony_ci const u_short list[]) 164462306a36Sopenharmony_ci{ 164562306a36Sopenharmony_ci const u_short *p = list ; 164662306a36Sopenharmony_ci while (*p) { 164762306a36Sopenharmony_ci if (!sm_to_para(smc,sm,(int) *p)) { 164862306a36Sopenharmony_ci DB_SMT("SMT: smt_check_para - missing para %hx", *p); 164962306a36Sopenharmony_ci return -1; 165062306a36Sopenharmony_ci } 165162306a36Sopenharmony_ci p++ ; 165262306a36Sopenharmony_ci } 165362306a36Sopenharmony_ci return 0; 165462306a36Sopenharmony_ci} 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_civoid *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para) 165762306a36Sopenharmony_ci{ 165862306a36Sopenharmony_ci char *p ; 165962306a36Sopenharmony_ci int len ; 166062306a36Sopenharmony_ci int plen ; 166162306a36Sopenharmony_ci void *found = NULL; 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci SK_UNUSED(smc) ; 166462306a36Sopenharmony_ci 166562306a36Sopenharmony_ci len = sm->smt_len ; 166662306a36Sopenharmony_ci p = (char *)(sm+1) ; /* pointer to info */ 166762306a36Sopenharmony_ci while (len > 0 ) { 166862306a36Sopenharmony_ci if (((struct smt_para *)p)->p_type == para) 166962306a36Sopenharmony_ci found = (void *) p ; 167062306a36Sopenharmony_ci plen = ((struct smt_para *)p)->p_len + PARA_LEN ; 167162306a36Sopenharmony_ci p += plen ; 167262306a36Sopenharmony_ci len -= plen ; 167362306a36Sopenharmony_ci if (len < 0) { 167462306a36Sopenharmony_ci DB_SMT("SMT : sm_to_para - length error %d", plen); 167562306a36Sopenharmony_ci return NULL; 167662306a36Sopenharmony_ci } 167762306a36Sopenharmony_ci if ((plen & 3) && (para != SMT_P_ECHODATA)) { 167862306a36Sopenharmony_ci DB_SMT("SMT : sm_to_para - odd length %d", plen); 167962306a36Sopenharmony_ci return NULL; 168062306a36Sopenharmony_ci } 168162306a36Sopenharmony_ci if (found) 168262306a36Sopenharmony_ci return found; 168362306a36Sopenharmony_ci } 168462306a36Sopenharmony_ci return NULL; 168562306a36Sopenharmony_ci} 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci#if 0 168862306a36Sopenharmony_ci/* 168962306a36Sopenharmony_ci * send ANTC data test frame 169062306a36Sopenharmony_ci */ 169162306a36Sopenharmony_civoid fddi_send_antc(struct s_smc *smc, struct fddi_addr *dest) 169262306a36Sopenharmony_ci{ 169362306a36Sopenharmony_ci SK_UNUSED(smc) ; 169462306a36Sopenharmony_ci SK_UNUSED(dest) ; 169562306a36Sopenharmony_ci#if 0 169662306a36Sopenharmony_ci SMbuf *mb ; 169762306a36Sopenharmony_ci struct smt_header *smt ; 169862306a36Sopenharmony_ci int i ; 169962306a36Sopenharmony_ci char *p ; 170062306a36Sopenharmony_ci 170162306a36Sopenharmony_ci mb = smt_get_mbuf() ; 170262306a36Sopenharmony_ci mb->sm_len = 3000+12 ; 170362306a36Sopenharmony_ci p = smtod(mb, char *) + 12 ; 170462306a36Sopenharmony_ci for (i = 0 ; i < 3000 ; i++) 170562306a36Sopenharmony_ci *p++ = 1 << (i&7) ; 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_ci smt = smtod(mb, struct smt_header *) ; 170862306a36Sopenharmony_ci smt->smt_dest = *dest ; 170962306a36Sopenharmony_ci smt->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ; 171062306a36Sopenharmony_ci smt_send_mbuf(smc,mb,FC_ASYNC_LLC) ; 171162306a36Sopenharmony_ci#endif 171262306a36Sopenharmony_ci} 171362306a36Sopenharmony_ci#endif 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci/* 171662306a36Sopenharmony_ci * return static mac index 171762306a36Sopenharmony_ci */ 171862306a36Sopenharmony_cistatic int mac_index(struct s_smc *smc, int mac) 171962306a36Sopenharmony_ci{ 172062306a36Sopenharmony_ci SK_UNUSED(mac) ; 172162306a36Sopenharmony_ci#ifdef CONCENTRATOR 172262306a36Sopenharmony_ci SK_UNUSED(smc) ; 172362306a36Sopenharmony_ci return NUMPHYS + 1; 172462306a36Sopenharmony_ci#else 172562306a36Sopenharmony_ci return (smc->s.sas == SMT_SAS) ? 2 : 3; 172662306a36Sopenharmony_ci#endif 172762306a36Sopenharmony_ci} 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci/* 173062306a36Sopenharmony_ci * return static phy index 173162306a36Sopenharmony_ci */ 173262306a36Sopenharmony_cistatic int phy_index(struct s_smc *smc, int phy) 173362306a36Sopenharmony_ci{ 173462306a36Sopenharmony_ci SK_UNUSED(smc) ; 173562306a36Sopenharmony_ci return phy + 1; 173662306a36Sopenharmony_ci} 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ci/* 173962306a36Sopenharmony_ci * return dynamic mac connection resource index 174062306a36Sopenharmony_ci */ 174162306a36Sopenharmony_cistatic int mac_con_resource_index(struct s_smc *smc, int mac) 174262306a36Sopenharmony_ci{ 174362306a36Sopenharmony_ci#ifdef CONCENTRATOR 174462306a36Sopenharmony_ci SK_UNUSED(smc) ; 174562306a36Sopenharmony_ci SK_UNUSED(mac) ; 174662306a36Sopenharmony_ci return entity_to_index(smc, cem_get_downstream(smc, ENTITY_MAC)); 174762306a36Sopenharmony_ci#else 174862306a36Sopenharmony_ci SK_UNUSED(mac) ; 174962306a36Sopenharmony_ci switch (smc->mib.fddiSMTCF_State) { 175062306a36Sopenharmony_ci case SC9_C_WRAP_A : 175162306a36Sopenharmony_ci case SC5_THRU_B : 175262306a36Sopenharmony_ci case SC11_C_WRAP_S : 175362306a36Sopenharmony_ci return 1; 175462306a36Sopenharmony_ci case SC10_C_WRAP_B : 175562306a36Sopenharmony_ci case SC4_THRU_A : 175662306a36Sopenharmony_ci return 2; 175762306a36Sopenharmony_ci } 175862306a36Sopenharmony_ci return smc->s.sas == SMT_SAS ? 2 : 3; 175962306a36Sopenharmony_ci#endif 176062306a36Sopenharmony_ci} 176162306a36Sopenharmony_ci 176262306a36Sopenharmony_ci/* 176362306a36Sopenharmony_ci * return dynamic phy connection resource index 176462306a36Sopenharmony_ci */ 176562306a36Sopenharmony_cistatic int phy_con_resource_index(struct s_smc *smc, int phy) 176662306a36Sopenharmony_ci{ 176762306a36Sopenharmony_ci#ifdef CONCENTRATOR 176862306a36Sopenharmony_ci return entity_to_index(smc, cem_get_downstream(smc, ENTITY_PHY(phy))) ; 176962306a36Sopenharmony_ci#else 177062306a36Sopenharmony_ci switch (smc->mib.fddiSMTCF_State) { 177162306a36Sopenharmony_ci case SC9_C_WRAP_A : 177262306a36Sopenharmony_ci return phy == PA ? 3 : 2; 177362306a36Sopenharmony_ci case SC10_C_WRAP_B : 177462306a36Sopenharmony_ci return phy == PA ? 1 : 3; 177562306a36Sopenharmony_ci case SC4_THRU_A : 177662306a36Sopenharmony_ci return phy == PA ? 3 : 1; 177762306a36Sopenharmony_ci case SC5_THRU_B : 177862306a36Sopenharmony_ci return phy == PA ? 2 : 3; 177962306a36Sopenharmony_ci case SC11_C_WRAP_S : 178062306a36Sopenharmony_ci return 2; 178162306a36Sopenharmony_ci } 178262306a36Sopenharmony_ci return phy; 178362306a36Sopenharmony_ci#endif 178462306a36Sopenharmony_ci} 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci#ifdef CONCENTRATOR 178762306a36Sopenharmony_cistatic int entity_to_index(struct s_smc *smc, int e) 178862306a36Sopenharmony_ci{ 178962306a36Sopenharmony_ci if (e == ENTITY_MAC) 179062306a36Sopenharmony_ci return mac_index(smc, 1); 179162306a36Sopenharmony_ci else 179262306a36Sopenharmony_ci return phy_index(smc, e - ENTITY_PHY(0)); 179362306a36Sopenharmony_ci} 179462306a36Sopenharmony_ci#endif 179562306a36Sopenharmony_ci 179662306a36Sopenharmony_ci#ifdef LITTLE_ENDIAN 179762306a36Sopenharmony_cistatic int smt_swap_short(u_short s) 179862306a36Sopenharmony_ci{ 179962306a36Sopenharmony_ci return ((s>>8)&0xff) | ((s&0xff)<<8); 180062306a36Sopenharmony_ci} 180162306a36Sopenharmony_ci 180262306a36Sopenharmony_civoid smt_swap_para(struct smt_header *sm, int len, int direction) 180362306a36Sopenharmony_ci/* int direction; 0 encode 1 decode */ 180462306a36Sopenharmony_ci{ 180562306a36Sopenharmony_ci struct smt_para *pa ; 180662306a36Sopenharmony_ci const struct smt_pdef *pd ; 180762306a36Sopenharmony_ci char *p ; 180862306a36Sopenharmony_ci int plen ; 180962306a36Sopenharmony_ci int type ; 181062306a36Sopenharmony_ci int i ; 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci/* printf("smt_swap_para sm %x len %d dir %d\n", 181362306a36Sopenharmony_ci sm,len,direction) ; 181462306a36Sopenharmony_ci */ 181562306a36Sopenharmony_ci smt_string_swap((char *)sm,SWAP_SMTHEADER,len) ; 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci /* swap args */ 181862306a36Sopenharmony_ci len -= sizeof(struct smt_header) ; 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci p = (char *) (sm + 1) ; 182162306a36Sopenharmony_ci while (len > 0) { 182262306a36Sopenharmony_ci pa = (struct smt_para *) p ; 182362306a36Sopenharmony_ci plen = pa->p_len ; 182462306a36Sopenharmony_ci type = pa->p_type ; 182562306a36Sopenharmony_ci pa->p_type = smt_swap_short(pa->p_type) ; 182662306a36Sopenharmony_ci pa->p_len = smt_swap_short(pa->p_len) ; 182762306a36Sopenharmony_ci if (direction) { 182862306a36Sopenharmony_ci plen = pa->p_len ; 182962306a36Sopenharmony_ci type = pa->p_type ; 183062306a36Sopenharmony_ci } 183162306a36Sopenharmony_ci /* 183262306a36Sopenharmony_ci * note: paras can have 0 length ! 183362306a36Sopenharmony_ci */ 183462306a36Sopenharmony_ci if (plen < 0) 183562306a36Sopenharmony_ci break ; 183662306a36Sopenharmony_ci plen += PARA_LEN ; 183762306a36Sopenharmony_ci for (i = N_SMT_PLEN, pd = smt_pdef; i ; i--,pd++) { 183862306a36Sopenharmony_ci if (pd->ptype == type) 183962306a36Sopenharmony_ci break ; 184062306a36Sopenharmony_ci } 184162306a36Sopenharmony_ci if (i && pd->pswap) { 184262306a36Sopenharmony_ci smt_string_swap(p+PARA_LEN,pd->pswap,len) ; 184362306a36Sopenharmony_ci } 184462306a36Sopenharmony_ci len -= plen ; 184562306a36Sopenharmony_ci p += plen ; 184662306a36Sopenharmony_ci } 184762306a36Sopenharmony_ci} 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci 185062306a36Sopenharmony_cistatic void smt_string_swap(char *data, const char *format, int len) 185162306a36Sopenharmony_ci{ 185262306a36Sopenharmony_ci const char *open_paren = NULL ; 185362306a36Sopenharmony_ci 185462306a36Sopenharmony_ci while (len > 0 && *format) { 185562306a36Sopenharmony_ci switch (*format) { 185662306a36Sopenharmony_ci case '[' : 185762306a36Sopenharmony_ci open_paren = format ; 185862306a36Sopenharmony_ci break ; 185962306a36Sopenharmony_ci case ']' : 186062306a36Sopenharmony_ci format = open_paren ; 186162306a36Sopenharmony_ci break ; 186262306a36Sopenharmony_ci case '1' : 186362306a36Sopenharmony_ci case '2' : 186462306a36Sopenharmony_ci case '3' : 186562306a36Sopenharmony_ci case '4' : 186662306a36Sopenharmony_ci case '5' : 186762306a36Sopenharmony_ci case '6' : 186862306a36Sopenharmony_ci case '7' : 186962306a36Sopenharmony_ci case '8' : 187062306a36Sopenharmony_ci case '9' : 187162306a36Sopenharmony_ci data += *format - '0' ; 187262306a36Sopenharmony_ci len -= *format - '0' ; 187362306a36Sopenharmony_ci break ; 187462306a36Sopenharmony_ci case 'c': 187562306a36Sopenharmony_ci data++ ; 187662306a36Sopenharmony_ci len-- ; 187762306a36Sopenharmony_ci break ; 187862306a36Sopenharmony_ci case 's' : 187962306a36Sopenharmony_ci swap(data[0], data[1]) ; 188062306a36Sopenharmony_ci data += 2 ; 188162306a36Sopenharmony_ci len -= 2 ; 188262306a36Sopenharmony_ci break ; 188362306a36Sopenharmony_ci case 'l' : 188462306a36Sopenharmony_ci swap(data[0], data[3]) ; 188562306a36Sopenharmony_ci swap(data[1], data[2]) ; 188662306a36Sopenharmony_ci data += 4 ; 188762306a36Sopenharmony_ci len -= 4 ; 188862306a36Sopenharmony_ci break ; 188962306a36Sopenharmony_ci } 189062306a36Sopenharmony_ci format++ ; 189162306a36Sopenharmony_ci } 189262306a36Sopenharmony_ci} 189362306a36Sopenharmony_ci#else 189462306a36Sopenharmony_civoid smt_swap_para(struct smt_header *sm, int len, int direction) 189562306a36Sopenharmony_ci/* int direction; 0 encode 1 decode */ 189662306a36Sopenharmony_ci{ 189762306a36Sopenharmony_ci SK_UNUSED(sm) ; 189862306a36Sopenharmony_ci SK_UNUSED(len) ; 189962306a36Sopenharmony_ci SK_UNUSED(direction) ; 190062306a36Sopenharmony_ci} 190162306a36Sopenharmony_ci#endif 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_ci/* 190462306a36Sopenharmony_ci * PMF actions 190562306a36Sopenharmony_ci */ 190662306a36Sopenharmony_ciint smt_action(struct s_smc *smc, int class, int code, int index) 190762306a36Sopenharmony_ci{ 190862306a36Sopenharmony_ci int event ; 190962306a36Sopenharmony_ci int port ; 191062306a36Sopenharmony_ci DB_SMT("SMT: action %d code %d", class, code); 191162306a36Sopenharmony_ci switch(class) { 191262306a36Sopenharmony_ci case SMT_STATION_ACTION : 191362306a36Sopenharmony_ci switch(code) { 191462306a36Sopenharmony_ci case SMT_STATION_ACTION_CONNECT : 191562306a36Sopenharmony_ci smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ; 191662306a36Sopenharmony_ci queue_event(smc,EVENT_ECM,EC_CONNECT) ; 191762306a36Sopenharmony_ci break ; 191862306a36Sopenharmony_ci case SMT_STATION_ACTION_DISCONNECT : 191962306a36Sopenharmony_ci queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; 192062306a36Sopenharmony_ci smc->mib.fddiSMTRemoteDisconnectFlag = TRUE ; 192162306a36Sopenharmony_ci RS_SET(smc,RS_DISCONNECT) ; 192262306a36Sopenharmony_ci AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long) 192362306a36Sopenharmony_ci FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_DISCONNECT, 192462306a36Sopenharmony_ci smt_get_event_word(smc)); 192562306a36Sopenharmony_ci break ; 192662306a36Sopenharmony_ci case SMT_STATION_ACTION_PATHTEST : 192762306a36Sopenharmony_ci AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long) 192862306a36Sopenharmony_ci FDDI_SMT_EVENT, (u_long) FDDI_PATH_TEST, 192962306a36Sopenharmony_ci smt_get_event_word(smc)); 193062306a36Sopenharmony_ci break ; 193162306a36Sopenharmony_ci case SMT_STATION_ACTION_SELFTEST : 193262306a36Sopenharmony_ci AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long) 193362306a36Sopenharmony_ci FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_SELF_TEST, 193462306a36Sopenharmony_ci smt_get_event_word(smc)); 193562306a36Sopenharmony_ci break ; 193662306a36Sopenharmony_ci case SMT_STATION_ACTION_DISABLE_A : 193762306a36Sopenharmony_ci if (smc->y[PA].pc_mode == PM_PEER) { 193862306a36Sopenharmony_ci RS_SET(smc,RS_EVENT) ; 193962306a36Sopenharmony_ci queue_event(smc,EVENT_PCM+PA,PC_DISABLE) ; 194062306a36Sopenharmony_ci } 194162306a36Sopenharmony_ci break ; 194262306a36Sopenharmony_ci case SMT_STATION_ACTION_DISABLE_B : 194362306a36Sopenharmony_ci if (smc->y[PB].pc_mode == PM_PEER) { 194462306a36Sopenharmony_ci RS_SET(smc,RS_EVENT) ; 194562306a36Sopenharmony_ci queue_event(smc,EVENT_PCM+PB,PC_DISABLE) ; 194662306a36Sopenharmony_ci } 194762306a36Sopenharmony_ci break ; 194862306a36Sopenharmony_ci case SMT_STATION_ACTION_DISABLE_M : 194962306a36Sopenharmony_ci for (port = 0 ; port < NUMPHYS ; port++) { 195062306a36Sopenharmony_ci if (smc->mib.p[port].fddiPORTMy_Type != TM) 195162306a36Sopenharmony_ci continue ; 195262306a36Sopenharmony_ci RS_SET(smc,RS_EVENT) ; 195362306a36Sopenharmony_ci queue_event(smc,EVENT_PCM+port,PC_DISABLE) ; 195462306a36Sopenharmony_ci } 195562306a36Sopenharmony_ci break ; 195662306a36Sopenharmony_ci default : 195762306a36Sopenharmony_ci return 1; 195862306a36Sopenharmony_ci } 195962306a36Sopenharmony_ci break ; 196062306a36Sopenharmony_ci case SMT_PORT_ACTION : 196162306a36Sopenharmony_ci switch(code) { 196262306a36Sopenharmony_ci case SMT_PORT_ACTION_ENABLE : 196362306a36Sopenharmony_ci event = PC_ENABLE ; 196462306a36Sopenharmony_ci break ; 196562306a36Sopenharmony_ci case SMT_PORT_ACTION_DISABLE : 196662306a36Sopenharmony_ci event = PC_DISABLE ; 196762306a36Sopenharmony_ci break ; 196862306a36Sopenharmony_ci case SMT_PORT_ACTION_MAINT : 196962306a36Sopenharmony_ci event = PC_MAINT ; 197062306a36Sopenharmony_ci break ; 197162306a36Sopenharmony_ci case SMT_PORT_ACTION_START : 197262306a36Sopenharmony_ci event = PC_START ; 197362306a36Sopenharmony_ci break ; 197462306a36Sopenharmony_ci case SMT_PORT_ACTION_STOP : 197562306a36Sopenharmony_ci event = PC_STOP ; 197662306a36Sopenharmony_ci break ; 197762306a36Sopenharmony_ci default : 197862306a36Sopenharmony_ci return 1; 197962306a36Sopenharmony_ci } 198062306a36Sopenharmony_ci queue_event(smc,EVENT_PCM+index,event) ; 198162306a36Sopenharmony_ci break ; 198262306a36Sopenharmony_ci default : 198362306a36Sopenharmony_ci return 1; 198462306a36Sopenharmony_ci } 198562306a36Sopenharmony_ci return 0; 198662306a36Sopenharmony_ci} 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_ci/* 198962306a36Sopenharmony_ci * canonical conversion of <len> bytes beginning form *data 199062306a36Sopenharmony_ci */ 199162306a36Sopenharmony_ci#ifdef USE_CAN_ADDR 199262306a36Sopenharmony_cistatic void hwm_conv_can(struct s_smc *smc, char *data, int len) 199362306a36Sopenharmony_ci{ 199462306a36Sopenharmony_ci int i ; 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci SK_UNUSED(smc) ; 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_ci for (i = len; i ; i--, data++) 199962306a36Sopenharmony_ci *data = bitrev8(*data); 200062306a36Sopenharmony_ci} 200162306a36Sopenharmony_ci#endif 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci#endif /* no SLIM_SMT */ 200462306a36Sopenharmony_ci 2005