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

📄 ether83815.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * National Semiconductor DP83815 * * Supports only internal PHY and has been tested on: *	Netgear FA311TX (using Netgear DS108 10/100 hub) *	SiS 900 (works under light load only) * To do: *	check Ethernet address; *	test autonegotiation on 10 Mbit, and 100 Mbit full duplex; *	external PHY via MII (should be common code for MII); *	thresholds; *	ring sizing; *	physical link changes/disconnect; *	push initialisation back to attach. * * C H Forsyth, forsyth@vitanuova.com, 18th June 2001. */#ifdef FS#include "all.h"#include "io.h"#include "mem.h"#include "../ip/ip.h"#else				/* FS */#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "../port/error.h"#include "../port/netif.h"#endif				/* FS */#include "etherif.h"#include "compat.h"#define DEBUG		(0)#define debug		if(DEBUG)printenum {	Nrde		= 64,	Ntde		= 64,};#define Rbsz		ROUNDUP(sizeof(Etherpkt)+4, 4)typedef struct Des {	ulong	next;	int	cmdsts;	ulong	addr;	Block*	bp;} Des;enum {	/* cmdsts */	Own	= 1<<31,	/* set by data producer to hand to consumer */	More	= 1<<30,	/* more of packet in next descriptor */	Intr	= 1<<29,	/* interrupt when device is done with it */	Supcrc	= 1<<28,	/* suppress crc on transmit */	Inccrc	= 1<<28,	/* crc included on receive (always) */	Ok	= 1<<27,	/* packet ok */	Size	= 0xFFF,	/* packet size in bytes */	/* transmit */	Txa	= 1<<26,	/* transmission aborted */	Tfu	= 1<<25,	/* transmit fifo underrun */	Crs	= 1<<24,	/* carrier sense lost */	Td	= 1<<23,	/* transmission deferred */	Ed	= 1<<22,	/* excessive deferral */	Owc	= 1<<21,	/* out of window collision */	Ec	= 1<<20,	/* excessive collisions */	/* 19-16 collision count */	/* receive */	Rxa	= 1<<26,	/* receive aborted (same as Rxo) */	Rxo	= 1<<25,	/* receive overrun */	Dest	= 3<<23,	/* destination class */	  Drej=	0<<23,		/* packet was rejected */	  Duni=	1<<23,		/* unicast */	  Dmulti=	2<<23,		/* multicast */	  Dbroad=	3<<23,		/* broadcast */	Long = 1<<22,		/* too long packet received */	Runt =  1<<21,		/* packet less than 64 bytes */	Ise =	1<<20,		/* invalid symbol */	Crce =	1<<19,		/* invalid crc */	Fae =	1<<18,		/* frame alignment error */	Lbp =	1<<17,		/* loopback packet */	Col =	1<<16,		/* collision during receive */};enum {				/* PCI vendor & device IDs */	Nat83815	= (0x0020<<16)|0x100B,	SiS = 	0x1039,	SiS900 =	(0x0900<<16)|SiS,	SiS7016 =	(0x7016<<16)|SiS,	SiS630bridge	= 0x0008,	/* SiS 900 PCI revision codes */	SiSrev630s =	0x81,	SiSrev630e =	0x82,	SiSrev630ea1 =	0x83,	SiSeenodeaddr =	8,		/* short addr of SiS eeprom mac addr */	SiS630eenodeaddr =	9,	/* likewise for the 630 */	Nseenodeaddr =	6,		/* " for NS eeprom */};typedef struct Ctlr Ctlr;typedef struct Ctlr {	int	port;	Pcidev*	pcidev;	Ctlr*	next;	int	active;	int	id;			/* (pcidev->did<<16)|pcidev->vid */	ushort	srom[0xB+1];	uchar	sromea[Eaddrlen];	/* MAC address */	uchar	fd;			/* option or auto negotiation */	int	mbps;	Lock	lock;	Des*	rdr;			/* receive descriptor ring */	int	nrdr;			/* size of rdr */	int	rdrx;			/* index into rdr */	Lock	tlock;	Des*	tdr;			/* transmit descriptor ring */	int	ntdr;			/* size of tdr */	int	tdrh;			/* host index into tdr */	int	tdri;			/* interface index into tdr */	int	ntq;			/* descriptors active */	int	ntqmax;	ulong	rxa;			/* receive statistics */	ulong	rxo;	ulong	rlong;	ulong	runt;	ulong	ise;	ulong	crce;	ulong	fae;	ulong	lbp;	ulong	col;	ulong	rxsovr;	ulong	rxorn;	ulong	txa;			/* transmit statistics */	ulong	tfu;	ulong	crs;	ulong	td;	ulong	ed;	ulong	owc;	ulong	ec;	ulong	txurn;	ulong	dperr;			/* system errors */	ulong	rmabt;	ulong	rtabt;	ulong	sserr;	ulong	rxsover;} Ctlr;static Ctlr* ctlrhead;static Ctlr* ctlrtail;enum {	/* registers (could memory map) */	Rcr=	0x00,		/* command register */	  Rst=		1<<8,	  Rxr=		1<<5,	/* receiver reset */	  Txr=		1<<4,	/* transmitter reset */	  Rxd=		1<<3,	/* receiver disable */	  Rxe=		1<<2,	/* receiver enable */	  Txd=		1<<1,	/* transmitter disable */	  Txe=		1<<0,	/* transmitter enable */	Rcfg=	0x04,		/* configuration */	  Lnksts=	1<<31,	/* link good */	  Speed100=	1<<30,	/* 100 Mb/s link */	  Fdup=		1<<29,	/* full duplex */	  Pol=		1<<28,	/* polarity reversal (10baseT) */	  Aneg_dn=	1<<27,	/* autonegotiation done */	  Pint_acen=	1<<17,	/* PHY interrupt auto clear enable */	  Pause_adv=	1<<16,	/* advertise pause during auto neg */	  Paneg_ena=	1<<13,	/* auto negotiation enable */	  Paneg_all=	7<<13,	/* auto negotiation enable 10/100 half & full */	  Ext_phy=	1<<12,	/* enable MII for external PHY */	  Phy_rst=	1<<10,	/* reset internal PHY */	  Phy_dis=	1<<9,	/* disable internal PHY (eg, low power) */	  Req_alg=	1<<7,	/* PCI bus request: set means less aggressive */	  Sb=		1<<6,	/* single slot back-off not random */	  Pow=		1<<5,	/* out of window timer selection */	  Exd=		1<<4,	/* disable excessive deferral timer */	  Pesel=	1<<3,	/* parity error algorithm selection */	  Brom_dis=	1<<2,	/* disable boot rom interface */	  Bem=		1<<0,	/* big-endian mode */	Rmear=	0x08,		/* eeprom access */	  Mdc=		1<<6,	/* MII mangement check */	  Mddir=	1<<5,	/* MII management direction */	  Mdio=		1<<4,	/* MII mangement data */	  Eesel=	1<<3,	/* EEPROM chip select */	  Eeclk=	1<<2,	/* EEPROM clock */	  Eedo=		1<<1,	/* EEPROM data out (from chip) */	  Eedi=		1<<0,	/* EEPROM data in (to chip) */	Rptscr=	0x0C,		/* pci test control */	Risr=	0x10,		/* interrupt status */	  Txrcmp=	1<<25,	/* transmit reset complete */	  Rxrcmp=	1<<24,	/* receiver reset complete */	  Dperr=	1<<23,	/* detected parity error */	  Sserr=	1<<22,	/* signalled system error */	  Rmabt=	1<<21,	/* received master abort */	  Rtabt=	1<<20,	/* received target abort */	  Rxsovr=	1<<16,	/* RX status FIFO overrun */	  Hiberr=	1<<15,	/* high bits error set (OR of 25-16) */	  Phy=		1<<14,	/* PHY interrupt */	  Pme=		1<<13,	/* power management event (wake online) */	  Swi=		1<<12,	/* software interrupt */	  Mib=		1<<11,	/* MIB service */	  Txurn=	1<<10,	/* TX underrun */	  Txidle=	1<<9,	/* TX idle */	  Txerr=	1<<8,	/* TX packet error */	  Txdesc=	1<<7,	/* TX descriptor (with Intr bit done) */	  Txok=		1<<6,	/* TX ok */	  Rxorn=	1<<5,	/* RX overrun */	  Rxidle=	1<<4,	/* RX idle */	  Rxearly=	1<<3,	/* RX early threshold */	  Rxerr=	1<<2,	/* RX packet error */	  Rxdesc=	1<<1,	/* RX descriptor (with Intr bit done) */	  Rxok=		1<<0,	/* RX ok */	Rimr=	0x14,		/* interrupt mask */	Rier=	0x18,		/* interrupt enable */	  Ie=		1<<0,	/* interrupt enable */	Rtxdp=	0x20,		/* transmit descriptor pointer */	Rtxcfg=	0x24,		/* transmit configuration */	  Csi=		1<<31,	/* carrier sense ignore (needed for full duplex) */	  Hbi=		1<<30,	/* heartbeat ignore (needed for full duplex) */	  Atp=		1<<28,	/* automatic padding of runt packets */	  Mxdma=	7<<20,	/* maximum dma transfer field */	  Mxdma32=	4<<20,	/* 4x32-bit words (32 bytes) */	  Mxdma64=	5<<20,	/* 8x32-bit words (64 bytes) */	  Flth=		0x3F<<8,/* Tx fill threshold, units of 32 bytes (must be > Mxdma) */	  Drth=		0x3F<<0,/* Tx drain threshold (units of 32 bytes) */	  Flth128=	4<<8,	/* fill at 128 bytes */	/* seems to be the same on SiS 900; maybe use larger value @ 100Mb/s */	  Drth512=	16<<0,	/* drain at 512 bytes */	Rrxdp=	0x30,		/* receive descriptor pointer */	Rrxcfg=	0x34,		/* receive configuration */	  Atx=		1<<28,	/* accept transmit packets (needed for full duplex) */	  Rdrth=	0x1F<<1,/* Rx drain threshold (units of 32 bytes) */	  Rdrth64=	2<<1,	/* drain at 64 bytes */	Rccsr=	0x3C,		/* CLKRUN control/status */	  Pmests=	1<<15,	/* PME status */	Rwcsr=	0x40,		/* wake on lan control/status */	Rpcr=	0x44,		/* pause control/status */	/* TODO: different on SiS, but does it matter? Rfen - Aau are same. */	Rrfcr=	0x48,		/* receive filter/match control */	  Rfen=		1<<31,	/* receive filter enable */	  Aab=		1<<30,	/* accept all broadcast */	  Aam=		1<<29,	/* accept all multicast */	  Aau=		1<<28,	/* accept all unicast */	  Apm=		1<<27,	/* accept on perfect match */	  Apat=		0xF<<23,/* accept on pattern match */	  Aarp=		1<<22,	/* accept ARP */	  Mhen=		1<<21,	/* multicast hash enable */	  Uhen=		1<<20,	/* unicast hash enable */	  Ulm=		1<<19,	/* U/L bit mask */				/* bits 0-9 are rfaddr */	Rrfdr=	0x4C,		/* receive filter/match data */	Rbrar=	0x50,		/* boot rom address */	Rbrdr=	0x54,		/* boot rom data */	Rsrr=	0x58,		/* silicon revision */	Rmibc=	0x5C,		/* MIB control */				/* 60-78 MIB data */	/* PHY registers */	Rbmcr=	0x80,		/* basic mode configuration */	  Reset=	1<<15,	  Sel100=	1<<13,	/* select 100Mb/sec if no auto neg */	  Anena=	1<<12,	/* auto negotiation enable */	  Anrestart=	1<<9,	/* restart auto negotiation */	  Selfdx=	1<<8,	/* select full duplex if no auto neg */	Rbmsr=	0x84,		/* basic mode status */	  Ancomp=	1<<5,	/* autonegotiation complete */	Rphyidr1= 0x88,	Rphyidr2= 0x8C,	Ranar=	0x90,		/* autonegotiation advertisement */	Ranlpar= 0x94,		/* autonegotiation link partner ability */	Raner=	0x98,		/* autonegotiation expansion */	Rannptr= 0x9C,		/* autonegotiation next page TX */	Rphysts= 0xC0,		/* PHY status */	Rmicr=	0xC4,		/* MII control */	  Inten=	1<<1,	/* PHY interrupt enable */	Rmisr=	0xC8,		/* MII status */	Rfcscr=	0xD0,		/* false carrier sense counter */	Rrecr=	0xD4,		/* receive error counter */	Rpcsr=	0xD8,		/* 100Mb config/status */	Rphycr=	0xE4,		/* PHY control */	Rtbscr=	0xE8,		/* 10BaseT status/control */};/* * eeprom addresses * 	7 to 9 (16 bit words): mac address, shifted and reversed */#define csr32r(c, r)	(inl((c)->port+(r)))#define csr32w(c, r, l)	(outl((c)->port+(r), (ulong)(l)))#define csr16r(c, r)	(ins((c)->port+(r)))#define csr16w(c, r, l)	(outs((c)->port+(r), (ulong)(l)))static voiddumpcregs(Ctlr *ctlr){	int i;	for(i=0; i<=0x5C; i+=4)		print("%2.2ux %8.8lux\n", i, csr32r(ctlr, i));}static voidpromiscuous(void* arg, int on){	Ctlr *ctlr;	ulong w;	ctlr = ((Ether*)arg)->ctlr;	ilock(&ctlr->lock);	w = csr32r(ctlr, Rrfcr);	if(on != ((w&Aau)!=0)){		csr32w(ctlr, Rrfcr, w & ~Rfen);		csr32w(ctlr, Rrfcr, Rfen | (w ^ Aau));	}	iunlock(&ctlr->lock);}static voidattach(Ether* ether){	Ctlr *ctlr;	ctlr = ether->ctlr;	ilock(&ctlr->lock);	if(0)		dumpcregs(ctlr);	csr32w(ctlr, Rcr, Rxe);	iunlock(&ctlr->lock);}#ifndef FSstatic longifstat(Ether* ether, void* a, long n, ulong offset){	Ctlr *ctlr;	char *buf, *p;	int i, l, len;	ctlr = ether->ctlr;	ether->crcs = ctlr->crce;	ether->frames = ctlr->runt+ctlr->ise+ctlr->rlong+ctlr->fae;	ether->buffs = ctlr->rxorn+ctlr->tfu;	ether->overflows = ctlr->rxsovr;	if(n == 0)		return 0;	p = malloc(READSTR);	l = snprint(p, READSTR, "Rxa: %lud\n", ctlr->rxa);	l += snprint(p+l, READSTR-l, "Rxo: %lud\n", ctlr->rxo);	l += snprint(p+l, READSTR-l, "Rlong: %lud\n", ctlr->rlong);	l += snprint(p+l, READSTR-l, "Runt: %lud\n", ctlr->runt);	l += snprint(p+l, READSTR-l, "Ise: %lud\n", ctlr->ise);	l += snprint(p+l, READSTR-l, "Fae: %lud\n", ctlr->fae);	l += snprint(p+l, READSTR-l, "Lbp: %lud\n", ctlr->lbp);	l += snprint(p+l, READSTR-l, "Tfu: %lud\n", ctlr->tfu);	l += snprint(p+l, READSTR-l, "Txa: %lud\n", ctlr->txa);	l += snprint(p+l, READSTR-l, "CRC Error: %lud\n", ctlr->crce);	l += snprint(p+l, READSTR-l, "Collision Seen: %lud\n", ctlr->col);	l += snprint(p+l, READSTR-l, "Frame Too Long: %lud\n", ctlr->rlong);	l += snprint(p+l, READSTR-l, "Runt Frame: %lud\n", ctlr->runt);	l += snprint(p+l, READSTR-l, "Rx Underflow Error: %lud\n", ctlr->rxorn);	l += snprint(p+l, READSTR-l, "Tx Underrun: %lud\n", ctlr->txurn);	l += snprint(p+l, READSTR-l, "Excessive Collisions: %lud\n", ctlr->ec);	l += snprint(p+l, READSTR-l, "Late Collision: %lud\n", ctlr->owc);	l += snprint(p+l, READSTR-l, "Loss of Carrier: %lud\n", ctlr->crs);	l += snprint(p+l, READSTR-l, "Parity: %lud\n", ctlr->dperr);	l += snprint(p+l, READSTR-l, "Aborts: %lud\n", ctlr->rmabt+ctlr->rtabt);	l += snprint(p+l, READSTR-l, "RX Status overrun: %lud\n", ctlr->rxsover);	snprint(p+l, READSTR-l, "ntqmax: %d\n", ctlr->ntqmax);	ctlr->ntqmax = 0;	buf = a;	len = readstr(offset, buf, n, p);	if(offset > l)		offset -= l;	else		offset = 0;	buf += len;	n -= len;	l = snprint(p, READSTR, "srom:");	for(i = 0; i < nelem(ctlr->srom); i++){		if(i && ((i & 0x0F) == 0))			l += snprint(p+l, READSTR-l, "\n     ");		l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->srom[i]);	}	snprint(p+l, READSTR-l, "\n");	len += readstr(offset, buf, n, p);	free(p);	return len;}#endifstatic voidtxstart(Ether* ether){	Ctlr *ctlr;	Block *bp;	Des *des;	int started;	ctlr = ether->ctlr;	started = 0;	while(ctlr->ntq < ctlr->ntdr-1){		bp = etheroq(ether);		if(bp == nil)			break;		des = &ctlr->tdr[ctlr->tdrh];		des->bp = bp;		des->addr = PADDR(bp->rp);		ctlr->ntq++;		coherence();		des->cmdsts = Own | BLEN(bp);		ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);		started = 1;	}	if(started){		coherence();		csr32w(ctlr, Rcr, Txe);	/* prompt */	}	if(ctlr->ntq > ctlr->ntqmax)		ctlr->ntqmax = ctlr->ntq;}static voidtransmit(Ether* ether){	Ctlr *ctlr;	ctlr = ether->ctlr;	ilock(&ctlr->tlock);	txstart(ether);	iunlock(&ctlr->tlock);}static voidtxrxcfg(Ctlr *ctlr, int txdrth){	ulong rx, tx;	rx = csr32r(ctlr, Rrxcfg);	tx = csr32r(ctlr, Rtxcfg);	if(ctlr->fd){		rx |= Atx;		tx |= Csi | Hbi;	}else{		rx &= ~Atx;		tx &= ~(Csi | Hbi);	}	tx &= ~(Mxdma|Drth|Flth);	tx |= Mxdma64 | Flth128 | txdrth;	csr32w(ctlr, Rtxcfg, tx);	rx &= ~(Mxdma|Rdrth);	rx |= Mxdma64 | Rdrth64;	csr32w(ctlr, Rrxcfg, rx);}static voidinterrupt(Ureg*, void* arg){	Ctlr *ctlr;	Ether *ether;	int len, status, cmdsts;	Des *des;	Block *bp;	ether = arg;	ctlr = ether->ctlr;	while((status = csr32r(ctlr, Risr)) != 0){		status &= ~(Pme|Mib);		if(status & Hiberr){			if(status & Rxsovr)				ctlr->rxsover++;			if(status & Sserr)				ctlr->sserr++;			if(status & Dperr)				ctlr->dperr++;			if(status & Rmabt)				ctlr->rmabt++;			if(status & Rtabt)				ctlr->rtabt++;			status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt);		}		/*		 * Received packets.		 */		if(status & (Rxdesc|Rxok|Rxerr|Rxearly|Rxorn)){			des = &ctlr->rdr[ctlr->rdrx];			while((cmdsts = des->cmdsts) & Own){				if((cmdsts&Ok) == 0){					if(cmdsts & Rxa)						ctlr->rxa++;					if(cmdsts & Rxo)						ctlr->rxo++;					if(cmdsts & Long)						ctlr->rlong++;					if(cmdsts & Runt)						ctlr->runt++;					if(cmdsts & Ise)						ctlr->ise++;					if(cmdsts & Crce)						ctlr->crce++;					if(cmdsts & Fae)						ctlr->fae++;					if(cmdsts & Lbp)						ctlr->lbp++;					if(cmdsts & Col)						ctlr->col++;				}				else if(bp = iallocb(Rbsz)){					len = (cmdsts&Size)-4;					if(len <= 0){						debug("ns83815: packet len %d <=0\n", len);						freeb(des->bp);					}else{						SETWPCNT(des->bp, len);						ETHERIQ(ether, des->bp, 1);					}					des->bp = bp;					des->addr = PADDR(bp->rp);					coherence();				}else{					debug("ns83815: interrupt: iallocb for input buffer failed\n");					des->bp->next = 0;				}				des->cmdsts = Rbsz;				coherence();				ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);				des = &ctlr->rdr[ctlr->rdrx];			}			status &= ~(Rxdesc|Rxok|Rxerr|Rxearly|Rxorn);		}		/*		 * Check the transmit side:		 *	check for Transmit Underflow and Adjust		 *	the threshold upwards;		 *	free any transmitted buffers and try to		 *	top-up the ring.		 */

⌨️ 快捷键说明

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