⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smt.c

📁 MIZI Research, Inc.发布的嵌入式Linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************** * *	(C)Copyright 1998,1999 SysKonnect, *	a business unit of Schneider & Koch & Co. Datensysteme GmbH. * *	See the file "skfddi.c" for further information. * *	This program is free software; you can redistribute it and/or modify *	it under the terms of the GNU General Public License as published by *	the Free Software Foundation; either version 2 of the License, or *	(at your option) any later version. * *	The information in this file is provided "AS IS" without warranty. * ******************************************************************************/#include "h/types.h"#include "h/fddi.h"#include "h/smc.h"#include "h/smt_p.h"#define KERNEL#include "h/smtstate.h"#ifndef	lintstatic const char ID_sccs[] = "@(#)smt.c	2.43 98/11/23 (C) SK " ;#endifextern const u_char canonical[256] ;/* * FC in SMbuf */#define m_fc(mb)	((mb)->sm_data[0])#define SMT_TID_MAGIC	0x1f0a7b3c#ifdef	DEBUGstatic const char *const smt_type_name[] = {	"SMT_00??", "SMT_INFO", "SMT_02??", "SMT_03??",	"SMT_04??", "SMT_05??", "SMT_06??", "SMT_07??",	"SMT_08??", "SMT_09??", "SMT_0A??", "SMT_0B??",	"SMT_0C??", "SMT_0D??", "SMT_0E??", "SMT_NSA"} ;static const char *const smt_class_name[] = {	"UNKNOWN","NIF","SIF_CONFIG","SIF_OPER","ECF","RAF","RDF",	"SRF","PMF_GET","PMF_SET","ESF"} ;#endif#define LAST_CLASS	(SMT_PMF_SET)static const struct fddi_addr SMT_Unknown = {	{ 0,0,0x1f,0,0,0 }} ;/* * external variables */extern const struct fddi_addr fddi_broadcast ;/* * external functions */int pcm_status_twisted() ;void pcm_status_state() ;int pcm_status_type() ;extern SMbuf *smt_get_mbuf() ;#define EXPORT_PMF/* * function prototypes */u_long smt_get_tid() ;EXPORT_PMF SMbuf *smt_build_frame() ;EXPORT_PMF void *sm_to_para() ;#ifdef	LITTLE_ENDIANstatic int smt_swap_short() ;#endifstatic int mac_index() ;static int phy_index() ;static int mac_con_resource_index() ;static int phy_con_resource_index() ;EXPORT_PMF void smt_send_frame() ;EXPORT_PMF void smt_set_timestamp() ;static void smt_send_rdf() ;static void smt_send_nif() ;static void smt_send_ecf() ;static void smt_echo_test() ;static void smt_send_sif_config() ;static void smt_send_sif_operation() ;EXPORT_PMF void smt_swap_para() ;#ifdef LITTLE_ENDIANstatic void smt_string_swap() ;#endifstatic void smt_add_frame_len() ;static void smt_fill_una() ;static void smt_fill_sde() ;static void smt_fill_state() ;static void smt_fill_timestamp() ;static void smt_fill_policy() ;static void smt_fill_latency() ;static void smt_fill_neighbor() ;static int  smt_fill_path() ;static void smt_fill_mac_status() ;static void smt_fill_lem() ;static void smt_fill_version() ;static void smt_fill_fsc() ;static void smt_fill_mac_counter() ;static void smt_fill_mac_fnc() ;static void smt_fill_manufacturer() ;static void smt_fill_user() ;static void smt_fill_setcount() ;static void smt_fill_echo() ;int smt_check_para() ;void smt_clear_una_dna() ;static void smt_clear_old_una_dna() ;#ifdef	CONCENTRATORstatic int entity_to_index() ;#endifstatic void update_dac() ;static int div_ratio() ;#ifdef  USE_CAN_ADDRvoid	hwm_conv_can() ;#else#define		hwm_conv_can(smc,data,len)#endif/* * list of mandatory paras in frames */static const u_short plist_nif[] = { SMT_P_UNA,SMT_P_SDE,SMT_P_STATE,0 } ;/* * init SMT agent */void smt_agent_init(smc)struct s_smc *smc ;{	int		i ;	/*	 * get MAC address	 */	smc->mib.m[MAC0].fddiMACSMTAddress = smc->hw.fddi_home_addr ;	/*	 * get OUI address from driver (bia == built-in-address)	 */	smc->mib.fddiSMTStationId.sid_oem[0] = 0 ;	smc->mib.fddiSMTStationId.sid_oem[1] = 0 ;	driver_get_bia(smc,&smc->mib.fddiSMTStationId.sid_node) ;	for (i = 0 ; i < 6 ; i ++) {		smc->mib.fddiSMTStationId.sid_node.a[i] =			canonical[smc->mib.fddiSMTStationId.sid_node.a[i]] ;	}	smc->mib.fddiSMTManufacturerData[0] =		smc->mib.fddiSMTStationId.sid_node.a[0] ;	smc->mib.fddiSMTManufacturerData[1] =		smc->mib.fddiSMTStationId.sid_node.a[1] ;	smc->mib.fddiSMTManufacturerData[2] =		smc->mib.fddiSMTStationId.sid_node.a[2] ;	smc->sm.smt_tid = 0 ;	smc->mib.m[MAC0].fddiMACDupAddressTest = DA_NONE ;	smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;#ifndef	SLIM_SMT	smt_clear_una_dna(smc) ;	smt_clear_old_una_dna(smc) ;#endif	for (i = 0 ; i < SMT_MAX_TEST ; i++)		smc->sm.pend[i] = 0 ;	smc->sm.please_reconnect = 0 ;	smc->sm.uniq_ticks = 0 ;}/* * SMT task * forever *	delay 30 seconds *	send NIF *	check tvu & tvd * end */void smt_agent_task(smc)struct s_smc *smc ;{	smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,		EV_TOKEN(EVENT_SMT,SM_TIMER)) ;	DB_SMT("SMT agent task\n",0,0) ;}void smt_please_reconnect(smc,reconn_time)struct s_smc	*smc ;		/* Pointer to SMT context */int		reconn_time ;	/* Wait for reconnect time in seconds */{	/*	 * The please reconnect variable is used as a timer.	 * It is decremented each time smt_event is called.	 * This happens every second or when smt_force_irq is called.	 * Note: smt_force_irq () is called on some packet receives and	 *       when a multicast address is changed. Since nothing	 *       is received during the disconnect and the multicast	 *       address changes can be viewed as not very often and	 *       the timer runs out close to its given value	 *       (reconn_time).	 */	smc->sm.please_reconnect = reconn_time ;}#ifndef SMT_REAL_TOKEN_CTvoid smt_emulate_token_ct(smc, mac_index)struct s_smc	*smc;int		mac_index;{	u_long	count;	u_long	time;	time = smt_get_time();	count =	((time - smc->sm.last_tok_time[mac_index]) *					100)/TICKS_PER_SECOND;	/*	 * Only when ring is up we will have a token count. The	 * flag is unfortunatly a single instance value. This	 * doesn't matter now, because we currently have only	 * one MAC instance.	 */	if (smc->hw.mac_ring_is_up){		smc->mib.m[mac_index].fddiMACToken_Ct += count;	}	/* Remember current time */	smc->sm.last_tok_time[mac_index] = time;}#endif/*ARGSUSED1*/void smt_event(smc,event)struct s_smc *smc ;int event ;{	u_long		time ;#ifndef SMT_REAL_TOKEN_CT	int		i ;#endif	if (smc->sm.please_reconnect) {		smc->sm.please_reconnect -- ;		if (smc->sm.please_reconnect == 0) {			/* Counted down */			queue_event(smc,EVENT_ECM,EC_CONNECT) ;		}	}	if (event == SM_FAST)		return ;	/*	 * timer for periodic cleanup in driver	 * reset and start the watchdog (FM2)	 * ESS timer	 * SBA timer	 */	smt_timer_poll(smc) ;	smt_start_watchdog(smc) ;#ifndef	SLIM_SMT#ifndef BOOT#ifdef	ESS	ess_timer_poll(smc) ;#endif#endif#ifdef	SBA	sba_timer_poll(smc) ;#endif	smt_srf_event(smc,0,0,0) ;#endif	/* no SLIM_SMT */	time = smt_get_time() ;	if (time - smc->sm.smt_last_lem >= TICKS_PER_SECOND*8) {		/*		 * Use 8 sec. for the time intervall, it simplifies the		 * LER estimation.		 */		struct fddi_mib_m	*mib ;		u_long			upper ;		u_long			lower ;		int			cond ;		int			port;		struct s_phy		*phy ;		/*		 * calculate LEM bit error rate		 */		sm_lem_evaluate(smc) ;		smc->sm.smt_last_lem = time ;		/*		 * check conditions		 */#ifndef	SLIM_SMT		mac_update_counter(smc) ;		mib = smc->mib.m ;		upper =		(mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) +		(mib->fddiMACError_Ct - mib->fddiMACOld_Error_Ct) ;		lower =		(mib->fddiMACFrame_Ct - mib->fddiMACOld_Frame_Ct) +		(mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) ;		mib->fddiMACFrameErrorRatio = div_ratio(upper,lower) ;		cond =			((!mib->fddiMACFrameErrorThreshold &&			mib->fddiMACError_Ct != mib->fddiMACOld_Error_Ct) ||			(mib->fddiMACFrameErrorRatio >			mib->fddiMACFrameErrorThreshold)) ;		if (cond != mib->fddiMACFrameErrorFlag)			smt_srf_event(smc,SMT_COND_MAC_FRAME_ERROR,				INDEX_MAC,cond) ;		upper =		(mib->fddiMACNotCopied_Ct - mib->fddiMACOld_NotCopied_Ct) ;		lower =		upper +		(mib->fddiMACCopied_Ct - mib->fddiMACOld_Copied_Ct) ;		mib->fddiMACNotCopiedRatio = div_ratio(upper,lower) ;		cond =			((!mib->fddiMACNotCopiedThreshold &&			mib->fddiMACNotCopied_Ct !=				mib->fddiMACOld_NotCopied_Ct)||			(mib->fddiMACNotCopiedRatio >			mib->fddiMACNotCopiedThreshold)) ;		if (cond != mib->fddiMACNotCopiedFlag)			smt_srf_event(smc,SMT_COND_MAC_NOT_COPIED,				INDEX_MAC,cond) ;		/*		 * set old values		 */		mib->fddiMACOld_Frame_Ct = mib->fddiMACFrame_Ct ;		mib->fddiMACOld_Copied_Ct = mib->fddiMACCopied_Ct ;		mib->fddiMACOld_Error_Ct = mib->fddiMACError_Ct ;		mib->fddiMACOld_Lost_Ct = mib->fddiMACLost_Ct ;		mib->fddiMACOld_NotCopied_Ct = mib->fddiMACNotCopied_Ct ;		/*		 * Check port EBError Condition		 */		for (port = 0; port < NUMPHYS; port ++) {			phy = &smc->y[port] ;			if (!phy->mib->fddiPORTHardwarePresent) {				continue;			}			cond = (phy->mib->fddiPORTEBError_Ct -				phy->mib->fddiPORTOldEBError_Ct > 5) ;			/* If ratio is more than 5 in 8 seconds			 * Set the condition.			 */			smt_srf_event(smc,SMT_COND_PORT_EB_ERROR,				(int) (INDEX_PORT+ phy->np) ,cond) ;			/*			 * set old values			 */			phy->mib->fddiPORTOldEBError_Ct =				phy->mib->fddiPORTEBError_Ct ;		}#endif	/* no SLIM_SMT */	}#ifndef	SLIM_SMT	if (time - smc->sm.smt_last_notify >= (u_long)		(smc->mib.fddiSMTTT_Notify * TICKS_PER_SECOND) ) {		/*		 * we can either send an announcement or a request		 * a request will trigger a reply so that we can update		 * our dna		 * note: same tid must be used until reply is received		 */		if (!smc->sm.pend[SMT_TID_NIF])			smc->sm.pend[SMT_TID_NIF] = smt_get_tid(smc) ;		smt_send_nif(smc,&fddi_broadcast,FC_SMT_NSA,			smc->sm.pend[SMT_TID_NIF], SMT_REQUEST,0) ;		smc->sm.smt_last_notify = time ;	}	/*	 * check timer	 */	if (smc->sm.smt_tvu &&	    time - smc->sm.smt_tvu > 228*TICKS_PER_SECOND) {		DB_SMT("SMT : UNA expired\n",0,0) ;		smc->sm.smt_tvu = 0 ;		if (!is_equal(&smc->mib.m[MAC0].fddiMACUpstreamNbr,			&SMT_Unknown)){			/* Do not update unknown address */			smc->mib.m[MAC0].fddiMACOldUpstreamNbr=				smc->mib.m[MAC0].fddiMACUpstreamNbr ;		}		smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;		smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;		/*		 * Make sure the fddiMACUNDA_Flag = FALSE is		 * included in the SRF so we don't generate		 * a seperate SRF for the deassertion of this		 * condition		 */		update_dac(smc,0) ;		smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,			INDEX_MAC,0) ;	}	if (smc->sm.smt_tvd &&	    time - smc->sm.smt_tvd > 228*TICKS_PER_SECOND) {		DB_SMT("SMT : DNA expired\n",0,0) ;		smc->sm.smt_tvd = 0 ;		if (!is_equal(&smc->mib.m[MAC0].fddiMACDownstreamNbr,			&SMT_Unknown)){			/* Do not update unknown address */			smc->mib.m[MAC0].fddiMACOldDownstreamNbr=				smc->mib.m[MAC0].fddiMACDownstreamNbr ;		}		smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;		smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,			INDEX_MAC,0) ;	}#endif	/* no SLIM_SMT */#ifndef SMT_REAL_TOKEN_CT	/*	 * Token counter emulation section. If hardware supports the token	 * count, the token counter will be updated in mac_update_counter.	 */	for (i = MAC0; i < NUMMACS; i++ ){		if (time - smc->sm.last_tok_time[i] > 2*TICKS_PER_SECOND ){			smt_emulate_token_ct( smc, i );		}	}#endif	smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,		EV_TOKEN(EVENT_SMT,SM_TIMER)) ;}static int div_ratio(upper,lower)u_long upper ;u_long lower ;{	if ((upper<<16L) < upper)		upper = 0xffff0000L ;	else		upper <<= 16L ;	if (!lower)		return(0) ;	return((int)(upper/lower)) ;}#ifndef	SLIM_SMT/* * receive packet handler */void smt_received_pack(smc,mb,fs)struct s_smc *smc ;SMbuf *mb ;int fs ;			/* frame status */{	struct smt_header	*sm ;	int			local ;	int			illegal = 0 ;	switch (m_fc(mb)) {	case FC_SMT_INFO :	case FC_SMT_LAN_LOC :	case FC_SMT_LOC :	case FC_SMT_NSA :		break ;	default :		smt_free_mbuf(smc,mb) ;		return ;	}	smc->mib.m[MAC0].fddiMACSMTCopied_Ct++ ;	sm = smtod(mb,struct smt_header *) ;	local = ((fs & L_INDICATOR) != 0) ;	hwm_conv_can(smc,(char *)sm,12) ;	/* check destination address */	if (is_individual(&sm->smt_dest) && !is_my_addr(smc,&sm->smt_dest)) {		smt_free_mbuf(smc,mb) ;		return ;	}#if	0		/* for DUP recognition, do NOT filter them */	/* ignore loop back packets */	if (is_my_addr(smc,&sm->smt_source) && !local) {		smt_free_mbuf(smc,mb) ;		return ;	}#endif	smt_swap_para(sm,(int) mb->sm_len,1) ;	DB_SMT("SMT : received packet [%s] at 0x%x\n",		smt_type_name[m_fc(mb) & 0xf],sm) ;	DB_SMT("SMT : version %d, class %s\n",sm->smt_version,		smt_class_name[(sm->smt_class>LAST_CLASS)?0 : sm->smt_class]) ;#ifdef	SBA	/*	 * check if NSA frame	 */	if (m_fc(mb) == FC_SMT_NSA && sm->smt_class == SMT_NIF &&		(sm->smt_type == SMT_ANNOUNCE || sm->smt_type == SMT_REQUEST)) {			smc->sba.sm = sm ;			sba(smc,NIF) ;	}#endif	/*	 * ignore any packet with NSA and A-indicator set	 */	if ( (fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) {		DB_SMT("SMT : ignoring NSA with A-indicator set from %s\n",			addr_to_string(&sm->smt_source),0) ;		smt_free_mbuf(smc,mb) ;		return ;	}	/*	 * ignore frames with illegal length	 */	if (((sm->smt_class == SMT_ECF) && (sm->smt_len > SMT_MAX_ECHO_LEN)) ||	    ((sm->smt_class != SMT_ECF) && (sm->smt_len > SMT_MAX_INFO_LEN))) {		smt_free_mbuf(smc,mb) ;		return ;	}	/*	 * check SMT version	 */	switch (sm->smt_class) {	case SMT_NIF :

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -