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

📄 fplustm.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************** * *	(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. * ******************************************************************************//* * FORMAC+ Driver for tag mode */#include "h/types.h"#include "h/fddi.h"#include "h/smc.h"#include "h/supern_2.h"#include "can.c"#ifndef	lintstatic const char ID_sccs[] = "@(#)fplustm.c	1.32 99/02/23 (C) SK " ;#endif#ifndef UNUSED#ifdef  lint#define UNUSED(x)	(x) = (x)#else#define UNUSED(x)#endif#endif#define FM_ADDRX	 (FM_ADDET|FM_EXGPA0|FM_EXGPA1)#define MS2BCLK(x)	((x)*12500L)#define US2BCLK(x)	((x)*1250L)/* * prototypes for static function */static void build_claim_beacon(struct s_smc *smc, u_long t_request);static int init_mac(struct s_smc *smc, int all);static void rtm_init(struct s_smc *smc);static void smt_split_up_fifo(struct s_smc *smc);#if (!defined(NO_SMT_PANIC) || defined(DEBUG))static	char write_mdr_warning [] = "E350 write_mdr() FM_SNPPND is set\n";static	char cam_warning [] = "E_SMT_004: CAM still busy\n";#endif#define	DUMMY_READ()	smc->hw.mc_dummy = (u_short) inp(ADDR(B0_RAP))#define	CHECK_NPP() {	unsigned k = 10000 ;\			while ((inpw(FM_A(FM_STMCHN)) & FM_SNPPND) && k) k--;\			if (!k) { \				SMT_PANIC(smc,SMT_E0130, SMT_E0130_MSG) ; \			}	\		}#define	CHECK_CAM() {	unsigned k = 10 ;\			while (!(inpw(FM_A(FM_AFSTAT)) & FM_DONE) && k) k--;\			if (!k) { \				SMT_PANIC(smc,SMT_E0131, SMT_E0131_MSG) ; \			}	\		}const struct fddi_addr fddi_broadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};static const struct fddi_addr null_addr = {{0,0,0,0,0,0}};static const struct fddi_addr dbeacon_multi = {{0x01,0x80,0xc2,0x00,0x01,0x00}};static const u_short my_said = 0xffff ;	/* short address (n.u.) */static const u_short my_sagp = 0xffff ;	/* short group address (n.u.) *//* * define my address */#ifdef	USE_CAN_ADDR#define MA	smc->hw.fddi_canon_addr#else#define MA	smc->hw.fddi_home_addr#endif/* * useful interrupt bits */static int mac_imsk1u = FM_STXABRS | FM_STXABRA0 | FM_SXMTABT ;static int mac_imsk1l = FM_SQLCKS | FM_SQLCKA0 | FM_SPCEPDS | FM_SPCEPDA0|			FM_STBURS | FM_STBURA0 ;	/* delete FM_SRBFL after tests */static int mac_imsk2u = FM_SERRSF | FM_SNFSLD | FM_SRCVOVR | FM_SRBFL |			FM_SMYCLM ;static int mac_imsk2l = FM_STRTEXR | FM_SDUPCLM | FM_SFRMCTR |			FM_SERRCTR | FM_SLSTCTR |			FM_STRTEXP | FM_SMULTDA | FM_SRNGOP ;static int mac_imsk3u = FM_SRCVOVR2 | FM_SRBFL2 ;static int mac_imsk3l = FM_SRPERRQ2 | FM_SRPERRQ1 ;static int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC |			FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ;static u_long mac_get_tneg(struct s_smc *smc){	u_long	tneg ;	tneg = (u_long)((long)inpw(FM_A(FM_TNEG))<<5) ;	return((u_long)((tneg + ((inpw(FM_A(FM_TMRS))>>10)&0x1f)) |		0xffe00000L)) ;}void mac_update_counter(struct s_smc *smc){	smc->mib.m[MAC0].fddiMACFrame_Ct =		(smc->mib.m[MAC0].fddiMACFrame_Ct & 0xffff0000L)		+ (u_short) inpw(FM_A(FM_FCNTR)) ;	smc->mib.m[MAC0].fddiMACLost_Ct =		(smc->mib.m[MAC0].fddiMACLost_Ct & 0xffff0000L)		+ (u_short) inpw(FM_A(FM_LCNTR)) ;	smc->mib.m[MAC0].fddiMACError_Ct =		(smc->mib.m[MAC0].fddiMACError_Ct & 0xffff0000L)		+ (u_short) inpw(FM_A(FM_ECNTR)) ;	smc->mib.m[MAC0].fddiMACT_Neg = mac_get_tneg(smc) ;#ifdef SMT_REAL_TOKEN_CT	/*	 * If the token counter is emulated it is updated in smt_event.	 */	TBD#else	smt_emulate_token_ct( smc, MAC0 );#endif}/* * write long value into buffer memory over memory data register (MDR), */static void write_mdr(struct s_smc *smc, u_long val){	CHECK_NPP() ;	MDRW(val) ;}#if 0/* * read long value from buffer memory over memory data register (MDR), */static u_long read_mdr(struct s_smc *smc, unsigned int addr){	long p ;	CHECK_NPP() ;	MARR(addr) ;	outpw(FM_A(FM_CMDREG1),FM_IRMEMWO) ;	CHECK_NPP() ;	/* needed for PCI to prevent from timeing violations *//*	p = MDRR() ; */	/* bad read values if the workaround */			/* smc->hw.mc_dummy = *((short volatile far *)(addr)))*/			/* is used */	p = (u_long)inpw(FM_A(FM_MDRU))<<16 ;	p += (u_long)inpw(FM_A(FM_MDRL)) ;	return(p) ;}#endif/* * clear buffer memory */static void init_ram(struct s_smc *smc){	u_short i ;	smc->hw.fp.fifo.rbc_ram_start = 0 ;	smc->hw.fp.fifo.rbc_ram_end =		smc->hw.fp.fifo.rbc_ram_start + RBC_MEM_SIZE ;	CHECK_NPP() ;	MARW(smc->hw.fp.fifo.rbc_ram_start) ;	for (i = smc->hw.fp.fifo.rbc_ram_start;		i < (u_short) (smc->hw.fp.fifo.rbc_ram_end-1); i++)		write_mdr(smc,0L) ;	/* Erase the last byte too */	write_mdr(smc,0L) ;}/* * set receive FIFO pointer */static void set_recvptr(struct s_smc *smc){	/*	 * initialize the pointer for receive queue 1	 */	outpw(FM_A(FM_RPR1),smc->hw.fp.fifo.rx1_fifo_start) ;	/* RPR1 */	outpw(FM_A(FM_SWPR1),smc->hw.fp.fifo.rx1_fifo_start) ;	/* SWPR1 */	outpw(FM_A(FM_WPR1),smc->hw.fp.fifo.rx1_fifo_start) ;	/* WPR1 */	outpw(FM_A(FM_EARV1),smc->hw.fp.fifo.tx_s_start-1) ;	/* EARV1 */	/*	 * initialize the pointer for receive queue 2	 */	if (smc->hw.fp.fifo.rx2_fifo_size) {		outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rx2_fifo_start) ;		outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rx2_fifo_start) ;		outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rx2_fifo_start) ;		outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;	}	else {		outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;		outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;		outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;		outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;	}}/* * set transmit FIFO pointer */static void set_txptr(struct s_smc *smc){	outpw(FM_A(FM_CMDREG2),FM_IRSTQ) ;	/* reset transmit queues */	/*	 * initialize the pointer for asynchronous transmit queue	 */	outpw(FM_A(FM_RPXA0),smc->hw.fp.fifo.tx_a0_start) ;	/* RPXA0 */	outpw(FM_A(FM_SWPXA0),smc->hw.fp.fifo.tx_a0_start) ;	/* SWPXA0 */	outpw(FM_A(FM_WPXA0),smc->hw.fp.fifo.tx_a0_start) ;	/* WPXA0 */	outpw(FM_A(FM_EAA0),smc->hw.fp.fifo.rx2_fifo_start-1) ;	/* EAA0 */	/*	 * initialize the pointer for synchronous transmit queue	 */	if (smc->hw.fp.fifo.tx_s_size) {		outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_s_start) ;		outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_s_start) ;		outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_s_start) ;		outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;	}	else {		outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_a0_start-1) ;		outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_a0_start-1) ;		outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_a0_start-1) ;		outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;	}}/* * init memory buffer management registers */static void init_rbc(struct s_smc *smc){	u_short	rbc_ram_addr ;	/*	 * set unused pointers or permanent pointers	 */	rbc_ram_addr = smc->hw.fp.fifo.rx2_fifo_start - 1 ;	outpw(FM_A(FM_RPXA1),rbc_ram_addr) ;	/* a1-send pointer */	outpw(FM_A(FM_WPXA1),rbc_ram_addr) ;	outpw(FM_A(FM_SWPXA1),rbc_ram_addr) ;	outpw(FM_A(FM_EAA1),rbc_ram_addr) ;	set_recvptr(smc) ;	set_txptr(smc) ;}/* * init rx pointer */static void init_rx(struct s_smc *smc){	struct s_smt_rx_queue	*queue ;	/*	 * init all tx data structures for receive queue 1	 */	smc->hw.fp.rx[QUEUE_R1] = queue = &smc->hw.fp.rx_q[QUEUE_R1] ;	queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R1_CSR) ;	queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R1_DA) ;	/*	 * init all tx data structures for receive queue 2	 */	smc->hw.fp.rx[QUEUE_R2] = queue = &smc->hw.fp.rx_q[QUEUE_R2] ;	queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R2_CSR) ;	queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R2_DA) ;}/* * set the TSYNC register of the FORMAC to regulate synchronous transmission */void set_formac_tsync(struct s_smc *smc, long sync_bw){	outpw(FM_A(FM_TSYNC),(unsigned int) (((-sync_bw) >> 5) & 0xffff) ) ;}/* * init all tx data structures */static void init_tx(struct s_smc *smc){	struct s_smt_tx_queue	*queue ;	/*	 * init all tx data structures for the synchronous queue	 */	smc->hw.fp.tx[QUEUE_S] = queue = &smc->hw.fp.tx_q[QUEUE_S] ;	queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XS_CSR) ;	queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XS_DA) ;#ifdef ESS	set_formac_tsync(smc,smc->ess.sync_bw) ;#endif	/*	 * init all tx data structures for the asynchronous queue 0	 */	smc->hw.fp.tx[QUEUE_A0] = queue = &smc->hw.fp.tx_q[QUEUE_A0] ;	queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XA_CSR) ;	queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XA_DA) ;	llc_recover_tx(smc) ;}static void mac_counter_init(struct s_smc *smc){	int i ;	u_long *ec ;	/*	 * clear FORMAC+ frame-, lost- and error counter	 */	outpw(FM_A(FM_FCNTR),0) ;	outpw(FM_A(FM_LCNTR),0) ;	outpw(FM_A(FM_ECNTR),0) ;	/*	 * clear internal error counter stucture	 */	ec = (u_long *)&smc->hw.fp.err_stats ;	for (i = (sizeof(struct err_st)/sizeof(long)) ; i ; i--)		*ec++ = 0L ;	smc->mib.m[MAC0].fddiMACRingOp_Ct = 0 ;}/* * set FORMAC address, and t_request */static	void set_formac_addr(struct s_smc *smc){	long	t_requ = smc->mib.m[MAC0].fddiMACT_Req ;	outpw(FM_A(FM_SAID),my_said) ;	/* set short address */	outpw(FM_A(FM_LAIL),(unsigned)((smc->hw.fddi_home_addr.a[4]<<8) +					smc->hw.fddi_home_addr.a[5])) ;	outpw(FM_A(FM_LAIC),(unsigned)((smc->hw.fddi_home_addr.a[2]<<8) +					smc->hw.fddi_home_addr.a[3])) ;	outpw(FM_A(FM_LAIM),(unsigned)((smc->hw.fddi_home_addr.a[0]<<8) +					smc->hw.fddi_home_addr.a[1])) ;	outpw(FM_A(FM_SAGP),my_sagp) ;	/* set short group address */	outpw(FM_A(FM_LAGL),(unsigned)((smc->hw.fp.group_addr.a[4]<<8) +					smc->hw.fp.group_addr.a[5])) ;	outpw(FM_A(FM_LAGC),(unsigned)((smc->hw.fp.group_addr.a[2]<<8) +					smc->hw.fp.group_addr.a[3])) ;	outpw(FM_A(FM_LAGM),(unsigned)((smc->hw.fp.group_addr.a[0]<<8) +					smc->hw.fp.group_addr.a[1])) ;	/* set r_request regs. (MSW & LSW of TRT ) */	outpw(FM_A(FM_TREQ1),(unsigned)(t_requ>>16)) ;	outpw(FM_A(FM_TREQ0),(unsigned)t_requ) ;}static void set_int(char *p, int l){	p[0] = (char)(l >> 24) ;	p[1] = (char)(l >> 16) ;	p[2] = (char)(l >> 8) ;	p[3] = (char)(l >> 0) ;}/* * copy TX descriptor to buffer mem * append FC field and MAC frame * if more bit is set in descr *	append pointer to descriptor (endless loop) * else *	append 'end of chain' pointer */static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac,			unsigned off, int len)/* u_long td;		 transmit descriptor *//* struct fddi_mac *mac; mac frame pointer *//* unsigned off;	 start address within buffer memory *//* int len ;		 lenght of the frame including the FC */{	int	i ;	u_int	*p ;	CHECK_NPP() ;	MARW(off) ;		/* set memory address reg for writes */	p = (u_int *) mac ;	for (i = (len + 3)/4 ; i ; i--) {		if (i == 1) {			/* last word, set the tag bit */			outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;		}		write_mdr(smc,MDR_REVERSE(*p)) ;		p++ ;	}	outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;	/* set the tag bit */	write_mdr(smc,td) ;	/* write over memory data reg to buffer */}/*	BEGIN_MANUAL_ENTRY(module;tests;3)	How to test directed beacon frames	----------------------------------------------------------------	o Insert a break point in the function build_claim_beacon()	  before calling copy_tx_mac() for building the claim frame.	o Modify the RM3_DETECT case so that the RM6_DETECT state	  will always entered from the RM3_DETECT state (function rmt_fsm(),	  rmt.c)	o Compile the driver.	o Set the parameter TREQ in the protocol.ini or net.cfg to a	  small value to make sure your station will win the claim	  process.	o Start the driver.	o When you reach the break point, modify the SA and DA address	  of the claim frame (e.g. SA = DA = 10005affffff).	o When you see RM3_DETECT and RM6_DETECT, observe the direct	  beacon frames on the UPPSLANA.	END_MANUAL_ENTRY */static void directed_beacon(struct s_smc *smc){	SK_LOC_DECL(u_int,a[2]) ;	/*	 * set UNA in frame	 * enable FORMAC to send endless queue of directed beacon	 * important: the UNA starts at byte 1 (not at byte 0)	 */	* (char *) a = (char) ((long)DBEACON_INFO<<24L) ;	a[1] = 0 ;	memcpy((char *)a+1,(char *) &smc->mib.m[MAC0].fddiMACUpstreamNbr,6) ;	CHECK_NPP() ;	 /* set memory address reg for writes */	MARW(smc->hw.fp.fifo.rbc_ram_start+DBEACON_FRAME_OFF+4) ;	write_mdr(smc,MDR_REVERSE(a[0])) ;	outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;	/* set the tag bit */	write_mdr(smc,MDR_REVERSE(a[1])) ;	outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF) ;}/*	setup claim & beacon pointer	NOTE :		special frame packets end with a pointer to their own		descriptor, and the MORE bit is set in the descriptor*/static void build_claim_beacon(struct s_smc *smc, u_long t_request){	u_int	td ;	int	len ;	struct fddi_mac_sf *mac ;	/*	 * build claim packet	 */	len = 17 ;	td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;	mac = &smc->hw.fp.mac_sfb ;	mac->mac_fc = FC_CLAIM ;	/* DA == SA in claim frame */	mac->mac_source = mac->mac_dest = MA ;	/* 2's complement */	set_int((char *)mac->mac_info,(int)t_request) ;	copy_tx_mac(smc,td,(struct fddi_mac *)mac,		smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF,len) ;	/* set CLAIM start pointer */	outpw(FM_A(FM_SACL),smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF) ;	/*	 * build beacon packet	 */	len = 17 ;	td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;	mac->mac_fc = FC_BEACON ;	mac->mac_source = MA ;	mac->mac_dest = null_addr ;		/* DA == 0 in beacon frame */	set_int((char *) mac->mac_info,((int)BEACON_INFO<<24) + 0 ) ;	copy_tx_mac(smc,td,(struct fddi_mac *)mac,		smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF,len) ;	/* set beacon start pointer */	outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF) ;	/*	 * build directed beacon packet	 * contains optional UNA	 */	len = 23 ;	td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;	mac->mac_fc = FC_BEACON ;	mac->mac_source = MA ;	mac->mac_dest = dbeacon_multi ;		/* multicast */	set_int((char *) mac->mac_info,((int)DBEACON_INFO<<24) + 0 ) ;

⌨️ 快捷键说明

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