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

📄 ether21140.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Digital Semiconductor DECchip 21140 PCI Fast Ethernet LAN Controller * as found on the Digital Fast EtherWORKS PCI 10/100 adapter (DE-500-X). * To do: *	thresholds; *	ring sizing; *	handle more error conditions; *	all the rest of it... */#include "u.h"#include "lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "etherif.h"#define DEBUG		if(1)printenum {	Nrde		= 4,	Ntde		= 1,};enum {	VendorID	= 0x1011,	/* PCI configuration vendor ID */	DeviceID	= 0x0009,	/* PCI configuration device ID */};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		= Sf,		/* 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 */	Mdi		= 0x00080000,	/* MII management data in */};enum {					/* CSR12 - General-Purpose Port */	Gpc		= 0x00000100,	/* General Purpose Control */	De500xFSYM	= 0x00000001,	/* output, force 100Mb mode */	De500xHD	= 0x00000008,	/* output, half-duplex mode */	De500xNoSYM	= 0x00000040,	/* input, 100Mb mode unavailable */	De500xNoTBT	= 0x00000080,	/* input, 10Mb mode unavailable */};typedef struct Des {	int	status;	int	control;	ulong	addr;	void*	bp;} 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 */};typedef struct Ctlr {	int	port;	uchar	srom[128*2];	uchar*	sromea;	int	phy[32];	uchar	fd;	int	ctlrno;	char*	type;	int	csr6;			/* CSR6 - operating mode */	int	mask;			/* CSR[57] - interrupt mask */	int	mbps;	Des*	rdr;			/* receive descriptor ring */	int	nrdr;			/* size of rdr */	int	rdrx;			/* index into rdr */	Des*	tdr;			/* transmit descriptor ring */	int	ntdr;			/* size of tdr */	int	tdrh;			/* host index into tdr */	int	tdri;			/* interface index into tdr */	ulong	of;			/* receive statistics */	ulong	ce;	ulong	cs;	ulong	tl;	ulong	rf;	ulong	de;	ulong	uf;			/* transmit statistics */	ulong	ec;	ulong	lc;	ulong	nc;	ulong	lo;	ulong	to;} Ctlr;#define csr32r(c, r)	(inl((c)->port+((r)*8)))#define csr32w(c, r, l)	(outl((c)->port+((r)*8), (ulong)(l)))static uchar setup[Eaddrlen*2*16];static voidattach(Ether* ether){	Ctlr *ctlr;	ctlr = ether->ctlr;	if((ctlr->csr6 & Sr) == 0){		ctlr->csr6 |= Sr;		csr32w(ctlr, 6, ctlr->csr6);	}}static voidtransmit(Ether* ether){	Ctlr *ctlr;	Des *des;	RingBuf *tb;	ctlr = ether->ctlr;	des = &ctlr->tdr[ctlr->tdri];	tb = &ether->tb[ether->ti];	if((des->status & Own) == 0 && tb->owner == Interface){		ctlr->tdr[PREV(ctlr->tdri, ctlr->ntdr)].control &= ~Ic;		des->addr = PADDR(tb->pkt);		des->bp = tb->pkt;		des->control |= Ic|Lseg|Fseg|tb->len;		des->status = Own;		csr32w(ctlr, 1, 0);	}}static voidinterrupt(Ureg*, void* arg){	Ctlr *ctlr;	Ether *ether;	int len, status;	Des *des;	RingBuf *ring;	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|Ais|Ti));		/*		 * Received packets.		 */		if(status & Ri){			des = &ctlr->rdr[ctlr->rdrx];			while((des->status & Own) == 0){				len = ((des->status & Fl)>>16)-4;				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{					ring = &ether->rb[ether->ri];					if(ring->owner == Interface){						ring->owner = Host;						ring->len = len;						memmove(ring->pkt, des->bp, len);						ether->ri = NEXT(ether->ri, ether->nrb);					}				}				des->control &= Er;				des->control |= ROUNDUP(sizeof(Etherpkt)+4, 4);				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){			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);			csr32w(ctlr, 5, Tps);			status &= ~(Unf|Tps);		}		des = &ctlr->tdr[ctlr->tdri];		while((des->status & Own) == 0 && des->bp){			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++;			}			ring = &ether->tb[ether->ti];			ring->owner = Host;			/*			 */			if((uchar*)des->bp != setup)				ether->ti = NEXT(ether->ti, ether->ntb);			des->control &= Er;			des->bp = 0;			ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);			des = &ctlr->tdr[ctlr->tdri];		}		transmit(ether);		/*		 * Anything left not catered for?		 */		if(status)			panic("%s#%d: status %8.8uX\n", ctlr->type, ctlr->ctlrno, status);	}}static voidctlrinit(Ctlr* ctlr, uchar ea[Eaddrlen]){	Des *des;	int i;	uchar bi[Eaddrlen*2];	/*	 * Allocate and initialise the receive ring;	 * allocate and initialise the transmit ring;	 * unmask interrupts and start the transmit side;	 * create and post a setup packet to initialise	 * the physical ethernet address.	 */	ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des));	for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){		des->bp = malloc(sizeof(Etherpkt)+4);		des->status = Own;		des->control = ROUNDUP(sizeof(Etherpkt)+4, 4);		des->addr = PADDR(des->bp);	}	ctlr->rdr[ctlr->nrdr-1].control |= Er;	ctlr->rdrx = 0;	csr32w(ctlr, 3, PADDR(ctlr->rdr));	ctlr->tdr = malloc(ctlr->ntdr*sizeof(Des));	ctlr->tdr[ctlr->ntdr-1].control |= Er;	ctlr->tdrh = 0;	ctlr->tdri = 0;	csr32w(ctlr, 4, PADDR(ctlr->tdr));	ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti;	csr32w(ctlr, 7, ctlr->mask);	ctlr->csr6 |= St;	csr32w(ctlr, 6, ctlr->csr6);	for(i = 0; i < Eaddrlen/2; i++){		bi[i*4] = ea[i*2];		bi[i*4+1] = ea[i*2+1];		bi[i*4+2] = ea[i*2+1];		bi[i*4+3] = ea[i*2];	}	memset(setup, 0xFF, sizeof(bi));	for(i = sizeof(bi); i < sizeof(bi)*16; i += sizeof(bi))		memmove(setup+i, bi, sizeof(bi));	des = &ctlr->tdr[ctlr->tdrh];	des->bp = setup;	des->addr = PADDR(setup);	des->control |= Ic|Set|sizeof(setup);	des->status = Own;	ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);	csr32w(ctlr, 1, 0);}static voidsrmiiw(Ctlr* ctlr, int data){	csr32w(ctlr, 9, data);	microdelay(1);}static voidmiimrw(Ctlr* ctlr, int bits, int n){	int i, mdo;	/*	 * Write n bits to the MII Management Register.	 */	for(i = n-1; i >= 0; i--){		if(bits & (1<<i))			mdo = Mdo;		else			mdo = 0;		srmiiw(ctlr, mdo);		srmiiw(ctlr, mdo|Mdc);		srmiiw(ctlr, mdo);	}}static intmiir(Ctlr* ctlr, int phyad, int regad){	int data, i;	/*	 * Preamble;	 * ST+OP+PHYAD+REGAD;	 * turnaround + 16 data bits.	 */	miimrw(ctlr, 0xFFFFFFFF, 32);	miimrw(ctlr, 0x1800|(phyad<<5)|regad, 14);	data = 0;	for(i = 18-1; i >= 0; i--){		if(csr32r(ctlr, 9) & Mdi)			data |= (1<<i);		srmiiw(ctlr, Mii|Mdc);		srmiiw(ctlr, Mii);	}	srmiiw(ctlr, 0);	if(data & 0x10000)		return -1;

⌨️ 快捷键说明

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