if_ed.c

来自「嵌入式系统开发中关于网络开发的的原代码及相关说明理。」· C语言 代码 · 共 892 行 · 第 1/2 页

C
892
字号
/* *  TOPPERS/JSP Kernel *      Toyohashi Open Platform for Embedded Real-Time Systems/ *      Just Standard Profile Kernel *  *  Copyright (C) 2000-2004 by Embedded and Real-Time Systems Laboratory *                              Toyohashi Univ. of Technology, JAPAN *  Copyright (C) 2001-2004 by Dep. of Computer Science and Engineering *                   Tomakomai National College of Technology, JAPAN * *  惧淡螟侯涪荚は·笆布の (1)×(4) の掘凤か·Free Software Foundation  *  によって给山されている GNU General Public License の Version 2 に淡 *  揭されている掘凤を塔たす眷圭に嘎り·塑ソフトウェア∈塑ソフトウェア *  を猖恃したものを崔むˉ笆布票じ∷を蝗脱ˇ剩澜ˇ猖恃ˇ浩芹邵∈笆布· *  网脱と钙ぶ∷することを痰浸で钓满するˉ *  (1) 塑ソフトウェアをソ〖スコ〖ドの妨で网脱する眷圭には·惧淡の螟侯 *      涪山绩·この网脱掘凤および布淡の痰瘦沮惮年が·そのままの妨でソ〖 *      スコ〖ド面に崔まれていることˉ *  (2) 塑ソフトウェアを·ライブラリ妨及など·戮のソフトウェア倡券に蝗 *      脱できる妨で浩芹邵する眷圭には·浩芹邵に燃うドキュメント∈网脱 *      荚マニュアルなど∷に·惧淡の螟侯涪山绩·この网脱掘凤および布淡 *      の痰瘦沮惮年を非很することˉ *  (3) 塑ソフトウェアを·怠达に寥み哈むなど·戮のソフトウェア倡券に蝗 *      脱できない妨で浩芹邵する眷圭には·肌のいずれかの掘凤を塔たすこ *      とˉ *    (a) 浩芹邵に燃うドキュメント∈网脱荚マニュアルなど∷に·惧淡の螟 *        侯涪山绩·この网脱掘凤および布淡の痰瘦沮惮年を非很することˉ *    (b) 浩芹邵の妨轮を·侍に年める数恕によって·TOPPERSプロジェクトに *        鼠桂することˉ *  (4) 塑ソフトウェアの网脱により木儡弄または粗儡弄に栏じるいかなる禄 *      巢からも·惧淡螟侯涪荚およびTOPPERSプロジェクトを倘勒することˉ * *  塑ソフトウェアは·痰瘦沮で捏丁されているものであるˉ惧淡螟侯涪荚お *  よびTOPPERSプロジェクトは·塑ソフトウェアに簇して·その努脱材墙拉も *  崔めて·いかなる瘦沮も乖わないˉまた·塑ソフトウェアの网脱により木 *  儡弄または粗儡弄に栏じたいかなる禄巢に簇しても·その勒扦を砷わないˉ *  *  @(#) $Id: if_ed.c,v 1.2 2004/09/07 00:51:20 abe Exp abe $ *//* * Copyright (c) 1995, David Greenman * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice unmodified, this list of conditions, and the following *    disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/isa/if_ed.c,v 1.148.2.4 1999/09/25 13:08:18 nyan Exp $ *//* * Device driver for National Semiconductor DS8390/WD83C690 based ethernet *   adapters. By David Greenman, 29-April-1993 * * Currently supports the Western Digital/SMC 8003 and 8013 series, *   the SMC Elite Ultra (8216), the 3Com 3c503, the NE1000 and NE2000, *   and a variety of similar clones. * */#include <s_services.h>#include <t_services.h>#include "kernel_id.h"#include <tinet_defs.h>#include <tinet_config.h>#include <net/if.h>#include <net/ethernet.h>#include <net/if_arp.h>#include <net/net.h>#include <net/net_timer.h>#include <net/net_count.h>#include <net/net_buf.h>#include "if_edreg.h"/* *  柒婶 RAM のペ〖ジ回年 */#define ED_INT_TXBUF_START	(ED_INT_RAM_BASE / ED_PAGE_SIZE)#define ED_INT_TXBUF_STOP	(ED_INT_RAM_BASE / ED_PAGE_SIZE + IF_ED_TXBUF_PAGE_SIZE)#define ED_INT_RXBUF_START	ED_INT_TXBUF_STOP#define ED_INT_RXBUF_STOP	((ED_INT_RAM_BASE + ED_INT_RAM_SIZE) / ED_PAGE_SIZE)/* *  ネットワ〖クインタフェ〖スに巴赂するソフトウェア攫鼠  */typedef struct t_ed_softc {	UW		nic_addr;			/* NIC のベ〖スアドレス	*/	UW		asic_addr;			/* ASIC のベ〖スアドレス*/	UH		txb_len[NUM_IF_ED_TXBUF];	/* 流慨バッファのオクテット眶*/	UB		txb_inuse;			/* 蝗脱面の流慨バッファ	*/	UB		txb_insend;			/* 流慨面の流慨バッファ	*/	UB		txb_write;			/* 今き哈む流慨バッファ	*/	UB		txb_send;			/* 流慨する流慨バッファ	*/	UB		rxb_read;			/* 粕み哈む减慨ペ〖ジ	*/	} T_ED_SOFTC;/* *  ネットワ〖クインタフェ〖スのソフトウェア攫鼠 *//* ネットワ〖クインタフェ〖スに巴赂するソフトウェア攫鼠 */static T_ED_SOFTC ed_softc = {	ED_BASE_ADDRESS + ED_NIC_OFFSET,	/* NIC のベ〖スアドレス		*/	ED_BASE_ADDRESS + ED_ASIC_OFFSET,	/* ASIC のベ〖スアドレス		*/	};/* ネットワ〖クインタフェ〖スに巴赂しないソフトウェア攫鼠 */T_IF_SOFTC if_softc = {	{},					/* ネットワ〖クインタフェ〖スのアドレス	*/	0,					/* 流慨タイムアウト			*/	&ed_softc,				/* ディバイス巴赂のソフトウェア攫鼠	*/	SEM_IF_ED_SBUF_READY,			/* 流慨セマフォ			*/	SEM_IF_ED_RBUF_READY,			/* 减慨セマフォ			*/#ifdef SUPPORT_INET6	IF_MADDR_INIT,				/* マルチキャストアドレスリスト	*/#endif	/* of #ifdef SUPPORT_INET6 */	};/* *  渡疥恃眶 */static void ed_pio_readmem (T_ED_SOFTC *sc, UW src, UB *dst, UH amount);static T_NET_BUF *ed_get_frame (T_ED_SOFTC *sc, UW ring, UH len);static void ed_xmit (T_IF_SOFTC *ic);static void ed_stop (T_ED_SOFTC *sc);static void ed_init_sub (T_IF_SOFTC *ic);static void ed_setrcr (T_IF_SOFTC *ic);#ifdef SUPPORT_INET6static UW ds_crc (UB *addr);static void ds_getmcaf (T_IF_SOFTC *ic, UW *mcaf);/* *  ds_crc -- イ〖サネットアドレスの CRC を纷换する。 */#define POLYNOMIAL	0x04c11db6static UWds_crc (UB *addr){	UW	crc = 0xffffffff;	int	carry, len, bit;	UB	byte;	for (len = ETHER_ADDR_LEN; len -- > 0; ) {		byte = *addr ++;		for (bit = 8; bit -- > 0; ) {			carry   = ((crc & 0x80000000) ? 1 : 0) ^ (byte & 0x01);			crc   <<= 1;			byte   >>= 1;			if (carry)				crc = (crc ^ POLYNOMIAL) | carry;			}		}	return crc;	}#undef POLYNOMIAL/* *  ds_getmcaf -- マルチキャストアドレスのリストからマルチキャストアドレス *                フィルタを纷换する。 */static voidds_getmcaf (T_IF_SOFTC *ic, UW *mcaf){	UW	count, index;	UB	*af = (UB*)mcaf;	mcaf[0] = mcaf[1] = 0;	for (count = MAX_IF_MADDR_CNT; count -- > 0; ) {		index = ds_crc(ic->maddrs[count].lladdr) >> 26;		af[index >> 3] |= 1 << (index & 7);		}	}/* * ed_setrcr -- 减慨菇喇レジスタ (RCR) を肋年する。 */static voided_setrcr (T_IF_SOFTC *ic){	T_ED_SOFTC	*sc = ic->sc;	int		ix;	UW		mcaf[2];	/* レジスタペ〖ジ 1 を联买する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_CR),	                 ED_CR_RD2 | ED_CR_PAGE1 | ED_CR_STP);	/* マルチキャストフィルタを肋年する。*/	ds_getmcaf(ic, mcaf);	/* マルチキャストの减慨肋年 */	for (ix = 0; ix < 8; ix ++)		sil_wrb_mem((VP)(sc->nic_addr + ED_P1_MAR(ix)), ((UB *)mcaf)[ix]);	/* レジスタペ〖ジ 0 を联买する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_CR),	            ED_CR_RD2 | ED_CR_PAGE0 | ED_CR_STP);	/* マルチキャストとユニキャストアドレスのみ减慨するように肋年する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_RCR), ED_RCR_AM);	/* NIC を弹瓢する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_CR),	            ED_CR_RD2 | ED_CR_PAGE0 | ED_CR_STA);	}/* * ed_addmulti -- マルチキャストアドレスを纳裁する。 */ERed_addmulti (T_IF_SOFTC *ic){	ed_setrcr(ic);	return E_OK;	}#endif	/* of #ifdef SUPPORT_INET6 *//* * ed_pio_readmem -- プログラム I/O を蝗って NIC のデ〖タを粕み哈む */static voided_pio_readmem (T_ED_SOFTC *sc, UW src, UB *dst, UH amount){	/* レジスタペ〖ジ 0 を联买し、DMA を匿贿する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_CR),	            ED_CR_RD2 | ED_CR_PAGE0 | ED_CR_STA);	/* DMA 啪流眶を肋年する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_RBCR0), amount);	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_RBCR1), amount >> 8);	/* NIC メモリの啪流傅アドレスを肋年する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_RSAR0), src);	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_RSAR1), src >> 8);	/* DMA 粕み哈みを联买する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_CR),	            ED_CR_RD0 | ED_CR_PAGE0 | ED_CR_STA);	/* NIC メモリから粕み哈む */	while (amount -- > 0)		*dst ++ = sil_reb_mem((VP)(sc->asic_addr + ED_DATA_OFFSET));	}/* * ed_pio_writemem -- プログラム I/O を蝗って NIC にデ〖タを今き哈む */static voided_pio_writemem (T_ED_SOFTC *sc, UB *src, UW dst, UH amount){	/* レジスタペ〖ジ 0 を联买し、DMA を匿贿する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_CR),	            ED_CR_RD2 | ED_CR_PAGE0 | ED_CR_STA);	/* DMA 啪流眶を肋年する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_RBCR0), amount);	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_RBCR1), amount >> 8);	/* NIC メモリの啪流黎アドレスを肋年する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_RSAR0), dst);	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_RSAR1), dst >> 8);	/* DMA 今哈みを联买する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_CR),	                 ED_CR_RD1 | ED_CR_PAGE0 | ED_CR_STA);	/* NIC メモリに今き哈む */	while (amount -- > 0)		sil_wrb_mem((VP)(sc->asic_addr + ED_DATA_OFFSET), *src ++);	}/* * ed_get_frame -- Ethernet フレ〖ムを掐蜗する。 */static T_NET_BUF *ed_get_frame (T_ED_SOFTC *sc, UW ring, UH len){	T_NET_BUF	*input = NULL;	UH		sublen, align;	UB		*dst;	ER		error;	/*	 *  +-----------+--------+---------+---------+	 *  | Ehter HDR | IP HDR | TCP HDR | TCP SDU |	 *  +-----------+--------+---------+---------+	 *        14        20        20        n	 *   <----------------- len ---------------->	 *              ^	 *              net_buf で 4 オクテット董肠にアラインされている。	 *	 *  tcp_input と udp_input では、导击ヘッダと SDU でチェックサムを	 *  纷换するが、n が 4 オクテット董肠になるように SDU の稿ろに 0 を	 *  パッディングする。その尸を雇胃して net_buf を惩评しなければならない。	 */	align = ((((len - sizeof(T_IF_HDR)) + 3) >> 2) << 2) + sizeof(T_IF_HDR);	if ((error = tget_net_buf(&input, align, TMO_IF_ED_GET_NET_BUF)) == E_OK && input != NULL) {		NET_COUNT_ETHER_NIC(net_count_ether_nic[NC_ETHER_NIC_IN_PACKETS], 1);		NET_COUNT_ETHER_NIC(net_count_ether_nic[NC_ETHER_NIC_IN_OCTETS],  len);		dst = input->buf;		if (ring + len > ED_INT_RAM_BASE + ED_INT_RAM_SIZE) {			sublen = (ED_INT_RAM_BASE + ED_INT_RAM_SIZE) - ring;			ed_pio_readmem(sc, ring, dst, sublen);			len -= sublen;			dst += sublen;			ring = ED_INT_RXBUF_START * ED_PAGE_SIZE;			}		ed_pio_readmem(sc, ring, dst, len);		}	else {		NET_COUNT_ETHER_NIC(net_count_ether_nic[NC_ETHER_NIC_IN_ERR_PACKETS], 1);		NET_COUNT_ETHER_NIC(net_count_ether_nic[NC_ETHER_NIC_NO_BUFS], 1);		}	return input;	}/* *  ed_xmit -- フレ〖ムを流慨する。 * *    庙罢: NIC 充り哈み敦贿觉轮で钙び叫すこと。 */static voided_xmit (T_IF_SOFTC *ic){	T_ED_SOFTC *sc = ic->sc;	/* レジスタペ〖ジ 0 を联买する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_CR),	            ED_CR_RD2 | ED_CR_PAGE0 | ED_CR_STA);	/* 流慨するペ〖ジを肋年する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_TPSR),	            ED_INT_TXBUF_START + sc->txb_send * NUM_IF_ED_TXBUF_PAGE);	/* 流慨するオクテット眶を肋年する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_TBCR0), sc->txb_len[sc->txb_send]);	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_TBCR1), sc->txb_len[sc->txb_send] >> 8);	/* 流慨する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_CR),	            ED_CR_RD2 | ED_CR_PAGE0 | ED_CR_TXP | ED_CR_STA);	/* 流慨バッファを磊り仑える。*/	sc->txb_send ++;	if (sc->txb_send == NUM_IF_ED_TXBUF)		sc->txb_send = 0;	sc->txb_insend ++;	/* 流慨タイムアウトを肋年する。*/	ic->timer = TMO_IF_ED_XMIT;	}/* *  ed_stop -- ed ネットワ〖クインタフェ〖スを匿贿する。 * *    庙罢: NIC 充り哈み敦贿觉轮で钙び叫すこと。 */static voided_stop (T_ED_SOFTC *sc){	int wait;	/* DMA を匿贿する。*/	sil_wrb_mem((VP)(sc->nic_addr + ED_P0_CR),	            ED_CR_RD2 | ED_CR_PAGE0 | ED_CR_STP);	/* NIC が匿贿觉轮になるまで略つ。ただし、5[ms]を惧嘎にしている。*/	for (wait = 5; ((sil_reb_mem((VP)(sc->nic_addr + ED_P0_ISR)) & ED_ISR_RST) == 0) && wait -- > 0; )		syscall(dly_tsk(1));	}/* *  ed_init_sub -- ed ネットワ〖クインタフェ〖スの介袋步 * *    庙罢: NIC 充り哈み敦贿觉轮で钙び叫すこと。 */static voided_init_sub (T_IF_SOFTC *ic){	T_ED_SOFTC	*sc = ic->sc;	int		ix;	/* 减慨ペ〖ジの肋年 */	sc->rxb_read = ED_INT_RXBUF_START + 1;	/* 流慨バッファの肋年 */	NET_COUNT_ETHER_NIC(net_count_ether_nic[NC_ETHER_NIC_OUT_ERR_PACKETS], sc->txb_inuse);	sc->txb_inuse  = 0;	sc->txb_insend = 0;	sc->txb_write  = 0;	sc->txb_send   = 0;		/* 流慨タイムアウトをリセットする。*/	ic->timer = 0;	/* インタフェ〖スを匿贿する。*/

⌨️ 快捷键说明

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