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

📄 if_lance.c

📁 早期freebsd实现
💻 C
字号:
/* * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. * * 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, 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. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * from: $Hdr: if_lance.c,v 4.300 91/06/09 06:25:58 root Rel41 $ SONY * *	@(#)if_lance.c	8.1 (Berkeley) 6/11/93 *//* * if_lance: Am7990 LANCE driver * * This driver is available only for single CPU machine. */#define	LANCE_LED#include "en.h"#if NEN > 0#include <machine/adrsmap.h>#include <sys/param.h>#include <news3400/if/lancereg.h>#include <news3400/if/if_lance.h>#ifdef mips#define	VOLATILE	volatile#else#define	VOLATILE#endif#ifdef LANCE_LED#ifdef news3400#define	LED_ON	{ \	VOLATILE u_char *p = (u_char *)DEBUG_PORT; \	*p = DP_WRITE | (*p & ~DP_LED2); \}#define	LED_OFF	{ \	VOLATILE u_char *p = (u_char *)DEBUG_PORT; \	*p = DP_WRITE | (*p | DP_LED2); \}#else /* news3400 */#define	LED_ON#define	LED_OFF#endif /* news3400 */#else /* LANCE_LED */#define	LED_ON#define	LED_OFF#endif /* LANCE_LED *//* *	LANCE memory configuration */#define	INIT_BLOCK		0x000000#define	RECV_MSG_DESC		0x000100#define	XMIT_MSG_DESC		0x000200#ifdef mips#define	RECV_BUFFER		(0x000300 + 2)				/* for data alignment to long word */#else /* mips */#define	RECV_BUFFER		0x000300#endif /* mips */#define	XMIT_BUFFER		(RECV_BUFFER+(RECV_BUFFER_SIZE*RECV_BUFFERS))#define	RECV_RING_LEN		3	/* log2(8) */#define	XMIT_RING_LEN		1	/* log2(2) */#define	RECV_BUFFER_SIZE	0x600#define	XMIT_BUFFER_SIZE	0x600#define	RECV_BUFFERS		(1 << RECV_RING_LEN)#define	XMIT_BUFFERS		(1 << XMIT_RING_LEN)/* *	Initialization block */struct init_block init_block = {	0,	0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0,	RECV_MSG_DESC & 0xffff,	(RECV_RING_LEN << 13) | (RECV_MSG_DESC >> 16),	XMIT_MSG_DESC & 0xffff,	(XMIT_RING_LEN << 13) | (XMIT_MSG_DESC >> 16)};/* *	LANCE control block */Lance_chan lancesw[NEN] = {      {	(Lance_reg *)LANCE_PORT,	(caddr_t)LANCE_MEMORY,	(caddr_t)ETHER_ID },#if NEN > 1      {	(Lance_reg *)LANCE_PORT1,	(caddr_t)LANCE_MEMORY1,	(caddr_t)ETHER_ID1 },#endif#if NEN > 2      {	(Lance_reg *)LANCE_PORT2,	(caddr_t)LANCE_MEMORY2,	(caddr_t)ETHER_ID2 },#endif};lance_probe(chan)	int chan;{	register Lance_chan *lance = &lancesw[chan];	VOLATILE int *p = (VOLATILE int *)lance->lance_memory;	if (badaddr(lance->lance_addr, 1))		return (0);	*p = 0x12345678;	return (*p == 0x12345678);}lance_open(chan)	int chan;{	register Lance_chan *lance = &lancesw[chan];	register recv_msg_desc *rmd;	register xmit_msg_desc *tmd;	register struct init_block *ib;	register int buffer, i;	if ((lance->lance_flags & LANCE_ACTIVE) == 0) {		if (lance->lance_addr == (Lance_reg *)0)			return (-1);		lance_write_reg(chan, CSR0, CSR_STOP);		rmd = (recv_msg_desc *)		    (RECV_MSG_DESC + lance->lance_memory);		lance->lance_last_rmd =		    (lance->lance_rmd = rmd) + RECV_BUFFERS - 1;		buffer = RECV_BUFFER;		for (i = 0; i < RECV_BUFFERS; i++) {			rmd->rmd_ladr = buffer & 0xffff;			rmd->rmd_stat = RMD_OWN | (buffer >> 16);			rmd->rmd_bcnt = -RECV_BUFFER_SIZE;			rmd->rmd_mcnt = 0;			rmd++;			buffer += RECV_BUFFER_SIZE;		}		tmd = (xmit_msg_desc *)		    (XMIT_MSG_DESC + lance->lance_memory);		lance->lance_last_tmd =			(lance->lance_tmd = tmd) + XMIT_BUFFERS - 1;		buffer = XMIT_BUFFER;		for (i = 0; i < XMIT_BUFFERS; i++) {			tmd->tmd_ladr = buffer & 0xffff;			tmd->tmd_stat = buffer >> 16;			tmd->tmd_bcnt = 0;			tmd++;			buffer += XMIT_BUFFER_SIZE;		}		get_hard_addr(chan, lance->lance_stats.ens_addr);		ib = (struct init_block *)(INIT_BLOCK + lance->lance_memory);		lance->lance_ib = ib;		*ib = init_block;		ib->ib_padr[0] = lance->lance_stats.ens_addr[1];		ib->ib_padr[1] = lance->lance_stats.ens_addr[0];		ib->ib_padr[2] = lance->lance_stats.ens_addr[3];		ib->ib_padr[3] = lance->lance_stats.ens_addr[2];		ib->ib_padr[4] = lance->lance_stats.ens_addr[5];		ib->ib_padr[5] = lance->lance_stats.ens_addr[4];		if (lance->lance_flags & LANCE_PROM)			ib->ib_mode |= IB_PROM;		lance->lance_flags |= LANCE_ACTIVE;		lance_init(chan);		if (lance_read_reg(chan, CSR0) !=		    (CSR_INEA|CSR_RXON|CSR_TXON|CSR_STRT|CSR_INIT)) {			lance->lance_flags &= ~LANCE_ACTIVE;			return (-1);		}	}	return (0);}lance_close(chan)	int chan;{	register Lance_chan *lance = &lancesw[chan];	lance_write_reg(chan, CSR0, CSR_STOP);	lance->lance_flags &= ~LANCE_ACTIVE;}#define	RECEIVE(lance, rmd)	{ \	register int i; \	(rmd) = (lance)->lance_last_rmd + 1; \	if ((rmd) >= (lance)->lance_rmd + RECV_BUFFERS) \		(rmd) = (lance)->lance_rmd; \	if (((rmd)->rmd_stat & RMD_OWN) == 0) \		(lance)->lance_last_rmd = (rmd); \	else \		(rmd) = NULL; \}#define	RECV_BUF(lance, rmd)	(char *)((rmd)->rmd_ladr \					+ (((rmd)->rmd_stat & RMD_HADR) << 16) \					+ (lance)->lance_memory)#define	RECV_CNT(rmd)		((rmd)->rmd_mcnt - 4)#define	RECV_ERR(rmd)		((rmd)->rmd_stat & RMD_ERR)#define	RELEASE_RECV_BUF(rmd)	{ \	(rmd)->rmd_mcnt = 0; \	(rmd)->rmd_stat = ((rmd)->rmd_stat & RMD_HADR) | RMD_OWN; \}caddr_tget_recv_buffer(chan)	int chan;{	register Lance_chan *lance = &lancesw[chan];	register recv_msg_desc *rmd;next:	RECEIVE(lance, rmd);	if (rmd == NULL)		return (NULL);	if (RECV_ERR(rmd)) {		recv_error(lance, rmd);		RELEASE_RECV_BUF(rmd);		goto next;	}	return (RECV_BUF(lance, rmd));}get_recv_length(chan)	int chan;{	return (RECV_CNT(lancesw[chan].lance_last_rmd));}free_recv_buffer(chan)	int chan;{	register recv_msg_desc *rmd = lancesw[chan].lance_last_rmd;	RELEASE_RECV_BUF(rmd);}#define	GET_XMIT_BUF(lance, tmd)	{ \	(tmd) = (lance)->lance_last_tmd + 1; \	if ((tmd) >= (lance)->lance_tmd + XMIT_BUFFERS) \		(tmd) = (lance)->lance_tmd; \	if ((tmd)->tmd_stat & TMD_OWN) \		(tmd) = NULL; \	else \		(lance)->lance_last_tmd = (tmd); \}#define	XMIT_BUF(lance, tmd)	(char *)((tmd)->tmd_ladr \					+ (((tmd)->tmd_stat & TMD_HADR) << 16) \					+ (lance)->lance_memory)#define	XMIT_ERR(tmd)		((tmd)->tmd_stat & TMD_ERR)#define	TRANSMIT(lance, tmd, count)	{ \	(tmd)->tmd_bcnt = -(count); \	(tmd)->tmd_error = 0; \	(tmd)->tmd_stat = ((tmd)->tmd_stat & TMD_HADR) | (TMD_OWN|TMD_STP|TMD_ENP); \	(lance)->lance_addr->rap = CSR0; \	(lance)->lance_addr->rdp = (CSR_INEA|CSR_TDMD); \}caddr_tget_xmit_buffer(chan)	int chan;{	register Lance_chan *lance = &lancesw[chan];	register xmit_msg_desc *tmd;	GET_XMIT_BUF(lance, tmd);	if (tmd == NULL)		return (NULL);	return (XMIT_BUF(lance, tmd));}lance_transmit(chan, count)	int chan;	int count;{	register Lance_chan *lance = &lancesw[chan];	register xmit_msg_desc *tmd;	tmd = lance->lance_last_tmd;	TRANSMIT(lance, tmd, count);}lance_xmit_error(chan)	int chan;{	register Lance_chan *lance = &lancesw[chan];	register xmit_msg_desc *tmd;	tmd = lance->lance_last_tmd;	if (XMIT_ERR(tmd)) {		xmit_error(lance, tmd);		return (1);	}	return (0);}lance_collision(chan)	int chan;{	register Lance_chan *lance = &lancesw[chan];	if (lance->lance_last_tmd->tmd_stat & (TMD_MORE|TMD_ONE)) {		lance->lance_stats.ens_collis++;		return (1);	}	return (0);}lance_get_addr(chan, addr)	int chan;	caddr_t addr;{	register Lance_chan *lance = &lancesw[chan];	bcopy(lance->lance_stats.ens_addr, addr,		sizeof(lance->lance_stats.ens_addr));}lance_prom_mode(chan, cmd)	int chan;{	register Lance_chan *lance = &lancesw[chan];	lance_close(chan);	if (cmd)		lance->lance_flags |= LANCE_PROM;	else		lance->lance_flags &= ~LANCE_PROM;	lance_open(chan);}lance_get_status(chan, addr)	int chan;	caddr_t addr;{	register Lance_chan *lance = &lancesw[chan];	register int s;	s = splimp();	bcopy(&lance->lance_stats.ens_frames, addr,	    sizeof(lance->lance_stats) - sizeof (lance->lance_stats.ens_addr));	bzero(&lance->lance_stats.ens_frames,	    sizeof(lance->lance_stats) - sizeof (lance->lance_stats.ens_addr));	(void) splx(s);}lance_intr(){	register Lance_chan *lance;	register Lance_reg *reg;	register int stat, chan;	int retval = 0;	LED_ON;	for (chan = 0, lance = lancesw; chan < NEN ; lance++, chan++) {		if ((lance->lance_flags & LANCE_ACTIVE) == 0)			continue;		reg = lance->lance_addr;		reg->rap = CSR0;		stat = reg->rdp & ~CSR_INEA;		if ((stat & CSR_INTR) == 0)			continue;		retval = 1;		reg->rdp = stat;		reg->rdp = CSR_INEA;		if (stat & CSR_ERR) {			if (stat & CSR_BABL)				printf("lance %d error: babl\n", chan);			if (stat & CSR_MISS)				lance->lance_stats.ens_lost++;			if (stat & CSR_MERR)				printf("lance %d error: merr\n", chan);		}		if (stat & CSR_RINT) {			lance->lance_stats.ens_frames++;			enrint(chan);		}		if (stat & CSR_TINT) {			lance->lance_stats.ens_xmit++;			enxint(chan);		}		if (stat & CSR_IDON)			lance->lance_flags |= LANCE_IDON;	}	LED_OFF;	return (retval);}lance_init(chan)	int chan;{	register Lance_chan *lance = &lancesw[chan];	register int s;	s = splimp();	lance_write_reg(chan, CSR1, INIT_BLOCK & 0xffff);	lance_write_reg(chan, CSR2, INIT_BLOCK >> 16);	lance_write_reg(chan, CSR3, CSR_BSWP|CSR_BCON);	lance_write_reg(chan, CSR0, CSR_INEA|CSR_STRT|CSR_INIT);	(void) splx(s);	while ((lance->lance_flags & LANCE_IDON) == 0)		;}recv_error(lance, rmd)	register Lance_chan *lance;	register recv_msg_desc *rmd;{	register int status = rmd->rmd_stat;	register int chan = lance - lancesw;	if (status & RMD_FRAM)		lance->lance_stats.ens_align++;	if (status & RMD_OFLO)		printf("lance %d recv error: overflow\n", chan);	if (status & RMD_CRC)		lance->lance_stats.ens_crc++;	if (status & RMD_BUFF)		printf("lance %d:recv error: buffer\n", chan);}xmit_error(lance, tmd)	register Lance_chan *lance;	register xmit_msg_desc *tmd;{	register int status = tmd->tmd_error;	register int chan = lance - lancesw;	if (status & TMD_BUFF)		printf("lance %d: xmit error: buffer\n", chan);	if (status & TMD_UFLO)		printf("lance %d: xmit error: underflow\n", chan);	if (status & TMD_LCOL) {		printf("lance %d: xmit error: late collision\n", chan);		lance->lance_stats.ens_owcollis++;	}	if (status & TMD_LCAR)		printf("lance %d: xmit error: loss of carrier\n", chan);	if (status & TMD_RTRY) {		printf("lance %d: xmit error: retry tdr=%d\n",		    chan, status & TMD_TDR);		lance->lance_stats.ens_xcollis++;	}}lance_write_reg(chan, reg, data)	int chan, reg, data;{	register Lance_reg *lance = lancesw[chan].lance_addr;	register int s;	s = spl7();	lance->rap = reg;	lance->rdp = data;	(void) splx(s);}lance_read_reg(chan, reg)	int chan, reg;{	register Lance_reg *lance = lancesw[chan].lance_addr;	register int s, d;	s = spl7();	lance->rap = reg;	d = lance->rdp;	(void) splx(s);	return (d);}get_hard_addr(chan, addr)	int chan;	u_short *addr;{	register unsigned char *p, *q;	register int i;	register Lance_chan *lance = &lancesw[chan];	unsigned char hard_addr[6];	p = (unsigned char *)lance->lance_rom + 16;	q = hard_addr;	for (i = 0; i < 6; i++) {		*q = (*p++ & 0xf) << 4;		*q++ |= *p++ & 0xf;	}		bcopy(hard_addr, (char *)addr, 6);}#if defined(mips) && defined(CPU_SINGLE)bxcopy(s, d, n)	caddr_t s, d;	int n;{	if (n <= 0)		return;	switch ((((int)s & 03) << 2) + ((int)d & 03)) {	case 0x0:		blcopy((long *)s, (long *)d, n);		return;	case 0x5:		*(char *)d = *(char *)s;		blcopy((long *)(s + 1), (long *)(d + 1), n - 1);		return;	case 0xa:		switch (n) {		case 1:			*(char *)d = *(char *)s;			return;		case 2:			*(short *)d = *(short *)s;			return;		default:			*(short *)d = *(short *)s;			blcopy((long *)(s + 2), (long *)(d + 2), n - 2);			return;		}	case 0xf:		switch (n) {		case 1:			*(char *)d = *(char *)s;			return;		case 2:			*(char *)d = *(char *)s;			*(char *)(d + 1) = *(char *)(s + 1);			return;		case 3:			*(char *)d = *(char *)s;			*(short *)(d + 1) = *(short *)(s + 1);			return;		default:			*(char *)d = *(char *)s;			*(short *)(d + 1) = *(short *)(s + 1);			blcopy((long *)(s + 3), (long *)(d + 3), n - 3);			return;		}	case 0x7:	case 0xd:		switch (n) {		case 1:			*(char *)d = *(char *)s;			return;		case 2:			*(char *)d = *(char *)s;			*(char *)(d + 1) = *(char *)(s + 1);			return;		default:			*(char *)d = *(char *)s;			bwcopy((short *)(s + 1), (short *)(d + 1), n);			return;		}	case 0x2:	case 0x8:		bwcopy((short *)s, (short *)d, n);		return;	default:		bbcopy((char *)s, (char *)d, n);		return;	}}#define	COPY(s, d, n, t) \	while ((n) >= 8 * sizeof (t)) { \		int t0, t1, t2, t3, t4, t5, t6, t7; \		t0 = (s)[0]; \		t1 = (s)[1]; \		t2 = (s)[2]; \		t3 = (s)[3]; \		t4 = (s)[4]; \		t5 = (s)[5]; \		t6 = (s)[6]; \		t7 = (s)[7]; \		(d)[0] = t0; \		(d)[1] = t1; \		(d)[2] = t2; \		(d)[3] = t3; \		(d)[4] = t4; \		(d)[5] = t5; \		(d)[6] = t6; \		(d)[7] = t7; \		(s) += 8; \		(d) += 8; \		(n) -= 8 * sizeof (t); \	} \	while ((n) >= sizeof (t)) { \		(d)[0] = (s)[0]; \		(s)++; \		(d)++; \		(n) -= sizeof (t); \	}blcopy(s, d, n)	long *s, *d;	int n;{	COPY(s, d, n, long);	switch (n) {	case 0:		return;	case 1:		*(char *)d = *(char *)s;		return;	case 2:		*(short *)d = *(short *)s;		return;	case 3:		*(short *)d = *(short *)s;		*((char *)d + 2) = *((char *)s + 2);		return;	}}bwcopy(s, d, n)	short *s, *d;	int n;{	COPY(s, d, n, short);	if (n == 1)		*(char *)d = *(char *)s;}bbcopy(s, d, n)	char *s, *d;	int n;{	COPY(s, d, n, char);}#endif /* defined(mips) && defined(CPU_SINGLE) */#endif /* NEN > 0 */

⌨️ 快捷键说明

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