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

📄 ether2114x.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Digital Semiconductor DECchip 2114x PCI Fast Ethernet LAN Controller. * To do: *	thresholds; *	ring sizing; *	handle more error conditions; *	tidy setup packet mess; *	push initialisation back to attach; *	full SROM decoding. */#include "all.h"#include "io.h"#include "mem.h"#include "../ip/ip.h"#include "etherif.h"#define DEBUG		(0)#define debug		if(DEBUG)printenum {	Nrde		= 64,	Ntde		= 64,};#define Rbsz		ROUNDUP(sizeof(Enpkt)+4, 4)enum {					/* CRS0 - Bus Mode */	Swr		= 0x00000001,	/* Software Reset */	Bar		= 0x00000002,	/* Bus Arbitration */	Dsl		= 0x0000007C,	/* Descriptor Skip Length (field) */	Ble		= 0x00000080,	/* Big/Little Endian */	Pbl		= 0x00003F00,	/* Programmable Burst Length (field) */	Cal		= 0x0000C000,	/* Cache Alignment (field) */	Cal8		= 0x00004000,	/* 8 longword boundary alignment */	Cal16		= 0x00008000,	/* 16 longword boundary alignment */	Cal32		= 0x0000C000,	/* 32 longword boundary alignment */	Tap		= 0x000E0000,	/* Transmit Automatic Polling (field) */	Dbo		= 0x00100000,	/* Descriptor Byte Ordering Mode */	Rml		= 0x00200000,	/* Read Multiple */}; enum {					/* CSR[57] - Status and Interrupt Enable */	Ti		= 0x00000001,	/* Transmit Interrupt */	Tps		= 0x00000002,	/* Transmit Process Stopped */	Tu		= 0x00000004,	/* Transmit buffer Unavailable */	Tjt		= 0x00000008,	/* Transmit Jabber Timeout */	Unf		= 0x00000020,	/* transmit UNderFlow */	Ri		= 0x00000040,	/* Receive Interrupt */	Ru		= 0x00000080,	/* Receive buffer Unavailable */	Rps		= 0x00000100,	/* Receive Process Stopped */	Rwt		= 0x00000200,	/* Receive Watchdog Timeout */	Eti		= 0x00000400,	/* Early Transmit Interrupt */	Gte		= 0x00000800,	/* General purpose Timer Expired */	Fbe		= 0x00002000,	/* Fatal Bit Error */	Ais		= 0x00008000,	/* Abnormal Interrupt Summary */	Nis		= 0x00010000,	/* Normal Interrupt Summary */	Rs		= 0x000E0000,	/* Receive process State (field) */	Ts		= 0x00700000,	/* Transmit process State (field) */	Eb		= 0x03800000,	/* Error bits */};enum {					/* CSR6 - Operating Mode */	Hp		= 0x00000001,	/* Hash/Perfect receive filtering mode */	Sr		= 0x00000002,	/* Start/stop Receive */	Ho		= 0x00000004,	/* Hash-Only filtering mode */	Pb		= 0x00000008,	/* Pass Bad frames */	If		= 0x00000010,	/* Inverse Filtering */	Sb		= 0x00000020,	/* Start/stop Backoff counter */	Pr		= 0x00000040,	/* Promiscuous Mode */	Pm		= 0x00000080,	/* Pass all Multicast */	Fd		= 0x00000200,	/* Full Duplex mode */	Om		= 0x00000C00,	/* Operating Mode (field) */	Fc		= 0x00001000,	/* Force Collision */	St		= 0x00002000,	/* Start/stop Transmission Command */	Tr		= 0x0000C000,	/* ThReshold control bits (field) */	Tr128		= 0x00000000,	Tr256		= 0x00004000,	Tr512		= 0x00008000,	Tr1024		= 0x0000C000,	Ca		= 0x00020000,	/* CApture effect enable */	Ps		= 0x00040000,	/* Port Select */	Hbd		= 0x00080000,	/* HeartBeat Disable */	Imm		= 0x00100000,	/* IMMediate mode */	Sf		= 0x00200000,	/* Store and Forward */	Ttm		= 0x00400000,	/* Transmit Threshold Mode */	Pcs		= 0x00800000,	/* PCS function */	Scr		= 0x01000000,	/* SCRambler mode */	Mbo		= 0x02000000,	/* Must Be One */	Ra		= 0x40000000,	/* Receive All */	Sc		= 0x80000000,	/* Special Capture effect enable */	TrMODE		= Tr512,	/* default transmission threshold */};enum {					/* CSR9 - ROM and MII Management */	Scs		= 0x00000001,	/* serial ROM chip select */	Sclk		= 0x00000002,	/* serial ROM clock */	Sdi		= 0x00000004,	/* serial ROM data in */	Sdo		= 0x00000008,	/* serial ROM data out */	Ss		= 0x00000800,	/* serial ROM select */	Wr		= 0x00002000,	/* write */	Rd		= 0x00004000,	/* read */	Mdc		= 0x00010000,	/* MII management clock */	Mdo		= 0x00020000,	/* MII management write data */	Mii		= 0x00040000,	/* MII management operation mode (W) */	Mdi		= 0x00080000,	/* MII management data in */};enum {					/* CSR12 - General-Purpose Port */	Gpc		= 0x00000100,	/* General Purpose Control */};typedef struct Des {	int	status;	int	control;	ulong	addr;	Msgbuf*	mb;} Des;enum {					/* status */	Of		= 0x00000001,	/* Rx: OverFlow */	Ce		= 0x00000002,	/* Rx: CRC Error */	Db		= 0x00000004,	/* Rx: Dribbling Bit */	Re		= 0x00000008,	/* Rx: Report on MII Error */	Rw		= 0x00000010,	/* Rx: Receive Watchdog */	Ft		= 0x00000020,	/* Rx: Frame Type */	Cs		= 0x00000040,	/* Rx: Collision Seen */	Tl		= 0x00000080,	/* Rx: Frame too Long */	Ls		= 0x00000100,	/* Rx: Last deScriptor */	Fs		= 0x00000200,	/* Rx: First deScriptor */	Mf		= 0x00000400,	/* Rx: Multicast Frame */	Rf		= 0x00000800,	/* Rx: Runt Frame */	Dt		= 0x00003000,	/* Rx: Data Type (field) */	De		= 0x00004000,	/* Rx: Descriptor Error */	Fl		= 0x3FFF0000,	/* Rx: Frame Length (field) */	Ff		= 0x40000000,	/* Rx: Filtering Fail */	Def		= 0x00000001,	/* Tx: DEFerred */	Uf		= 0x00000002,	/* Tx: UnderFlow error */	Lf		= 0x00000004,	/* Tx: Link Fail report */	Cc		= 0x00000078,	/* Tx: Collision Count (field) */	Hf		= 0x00000080,	/* Tx: Heartbeat Fail */	Ec		= 0x00000100,	/* Tx: Excessive Collisions */	Lc		= 0x00000200,	/* Tx: Late Collision */	Nc		= 0x00000400,	/* Tx: No Carrier */	Lo		= 0x00000800,	/* Tx: LOss of carrier */	To		= 0x00004000,	/* Tx: Transmission jabber timeOut */	Es		= 0x00008000,	/* [RT]x: Error Summary */	Own		= 0x80000000,	/* [RT]x: OWN bit */};enum {					/* control */	Bs1		= 0x000007FF,	/* [RT]x: Buffer 1 Size */	Bs2		= 0x003FF800,	/* [RT]x: Buffer 2 Size */	Ch		= 0x01000000,	/* [RT]x: second address CHained */	Er		= 0x02000000,	/* [RT]x: End of Ring */	Ft0		= 0x00400000,	/* Tx: Filtering Type 0 */	Dpd		= 0x00800000,	/* Tx: Disabled PaDding */	Ac		= 0x04000000,	/* Tx: Add CRC disable */	Set		= 0x08000000,	/* Tx: SETup packet */	Ft1		= 0x10000000,	/* Tx: Filtering Type 1 */	Fseg		= 0x20000000,	/* Tx: First SEGment */	Lseg		= 0x40000000,	/* Tx: Last SEGment */	Ic		= 0x80000000,	/* Tx: Interrupt on Completion */};enum {					/* PHY registers */	Bmcr		= 0,		/* Basic Mode Control */	Bmsr		= 1,		/* Basic Mode Status */	Phyidr1		= 2,		/* PHY Identifier #1 */	Phyidr2		= 3,		/* PHY Identifier #2 */	Anar		= 4,		/* Auto-Negotiation Advertisment */	Anlpar		= 5,		/* Auto-Negotiation Link Partner Ability */	Aner		= 6,		/* Auto-Negotiation Expansion */};enum {					/* Variants */	Tulip0		= (0x0009<<16)|0x1011,	Tulip3		= (0x0019<<16)|0x1011,	Pnic		= (0x0002<<16)|0x11AD,	Pnic2		= (0xC115<<16)|0x11AD,};typedef struct Ctlr Ctlr;typedef struct Ctlr {	int	port;	Pcidev*	pcidev;	Ctlr*	next;	int	active;	int	id;			/* (pcidev->did<<16)|pcidev->vid */	uchar	srom[128];	uchar*	sromea;			/* MAC address */	uchar*	leaf;	int	sct;			/* selected connection type */	int	k;			/* info block count */	uchar*	infoblock[16];	int	sctk;			/* sct block index */	int	curk;			/* current block index */	uchar*	type5block;	int	phy[32];		/* logical to physical map */	int	phyreset;		/* reset bitmap */	int	curphyad;	int	fdx;	int	ttm;	uchar	fd;			/* option */	int	medium;			/* option */	int	csr6;			/* CSR6 - operating mode */	int	mask;			/* CSR[57] - interrupt mask */	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;	Msgbuf*	setupmb;	ulong	of;			/* receive statistics */	ulong	ce;	ulong	cs;	ulong	tl;	ulong	rf;	ulong	de;	ulong	ru;	ulong	rps;	ulong	rwt;	ulong	uf;			/* transmit statistics */	ulong	ec;	ulong	lc;	ulong	nc;	ulong	lo;	ulong	to;	ulong	tps;	ulong	tu;	ulong	tjt;	ulong	unf;} Ctlr;static Ctlr* ctlrhead;static Ctlr* ctlrtail;#define csr32r(c, r)	(inl((c)->port+((r)*8)))#define csr32w(c, r, l)	(outl((c)->port+((r)*8), (ulong)(l)))static voidattach(Ether* ether){	Ctlr *ctlr;	ctlr = ether->ctlr;	ilock(&ctlr->lock);	if(!(ctlr->csr6 & Sr)){		ctlr->csr6 |= Sr;		csr32w(ctlr, 6, ctlr->csr6);	}	iunlock(&ctlr->lock);}static voidtxstart(Ether* ether){	Ctlr *ctlr;	Msgbuf *mb;	Des *des;	int control;	ctlr = ether->ctlr;	while(ctlr->ntq < (ctlr->ntdr-1)){		if(ctlr->setupmb){			mb = ctlr->setupmb;			ctlr->setupmb = 0;			control = Ic|Set|mb->count;		}		else{			mb = etheroq(ether);			if(mb == nil)				break;			control = Ic|Lseg|Fseg|mb->count;		}		ctlr->tdr[PREV(ctlr->tdrh, ctlr->ntdr)].control &= ~Ic;		des = &ctlr->tdr[ctlr->tdrh];		des->mb = mb;		des->addr = PADDR(mb->data);		des->control |= control;		ctlr->ntq++;		coherence();		des->status = Own;		csr32w(ctlr, 1, 0);		ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);	}	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 voidinterrupt(Ureg*, void* arg){	Ctlr *ctlr;	Ether *ether;	int len, status;	Des *des;	Msgbuf *mb, *rmb;	ether = arg;	ctlr = ether->ctlr;	while((status = csr32r(ctlr, 5)) & (Nis|Ais)){		/*		 * Acknowledge the interrupts and mask-out		 * the ones that are implicitly handled.		 */		csr32w(ctlr, 5, status);		status &= (ctlr->mask & ~(Nis|Ti));		if(status & Ais){			if(status & Tps)				ctlr->tps++;			if(status & Tu)				ctlr->tu++;			if(status & Tjt)				ctlr->tjt++;			if(status & Ru)				ctlr->ru++;			if(status & Rps)				ctlr->rps++;			if(status & Rwt)				ctlr->rwt++;			status &= ~(Ais|Rwt|Rps|Ru|Tjt|Tu|Tps);		}		/*		 * Received packets.		 */		if(status & Ri){			des = &ctlr->rdr[ctlr->rdrx];			while(!(des->status & Own)){				if(des->status & Es){					if(des->status & Of)						ctlr->of++;					if(des->status & Ce)						ctlr->ce++;					if(des->status & Cs)						ctlr->cs++;					if(des->status & Tl)						ctlr->tl++;					if(des->status & Rf)						ctlr->rf++;					if(des->status & De)						ctlr->de++;				}				else if(mb = mballoc(Rbsz, 0, Mbeth1)){					rmb = des->mb;					rmb->count = ((des->status & Fl)>>16)-4;					etheriq(ether, rmb);					des->mb = mb;					des->addr = PADDR(mb->data);				}				des->control &= Er;				des->control |= Rbsz;				coherence();				des->status = Own;				ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);				des = &ctlr->rdr[ctlr->rdrx];			}			status &= ~Ri;		}		/*		 * Check the transmit side:		 *	check for Transmit Underflow and Adjust		 *	the threshold upwards;		 *	free any transmitted buffers and try to		 *	top-up the ring.		 */		if(status & Unf){			ctlr->unf++;			ilock(&ctlr->lock);			csr32w(ctlr, 6, ctlr->csr6 & ~St);			switch(ctlr->csr6 & Tr){			case Tr128:				len = Tr256;				break;			case Tr256:				len = Tr512;				break;			case Tr512:				len = Tr1024;				break;			default:			case Tr1024:				len = Sf;				break;			}			ctlr->csr6 = (ctlr->csr6 & ~Tr)|len;			csr32w(ctlr, 6, ctlr->csr6);			iunlock(&ctlr->lock);			csr32w(ctlr, 5, Tps);			status &= ~(Unf|Tps);		}		ilock(&ctlr->tlock);		while(ctlr->ntq){			des = &ctlr->tdr[ctlr->tdri];			if(des->status & Own)				break;			if(des->status & Es){				if(des->status & Uf)					ctlr->uf++;				if(des->status & Ec)					ctlr->ec++;				if(des->status & Lc)					ctlr->lc++;				if(des->status & Nc)					ctlr->nc++;				if(des->status & Lo)					ctlr->lo++;				if(des->status & To)					ctlr->to++;			}			mbfree(des->mb);			des->control &= Er;			ctlr->ntq--;			ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);		}		txstart(ether);		iunlock(&ctlr->tlock);		/*		 * Anything left not catered for?		 */		if(status)			panic("#l%d: status %8.8uX\n", ether->ctlrno, status);	}}static voidctlrinit(Ether* ether){

⌨️ 快捷键说明

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