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

📄 ether2114x.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		1#define debug		if(DEBUG)printenum {	Nrde		= 4,	Ntde		= 1,};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 */};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 */};typedef struct Ctlr Ctlr;typedef struct Ctlr {	int	port;	Pcidev*	pcidev;	Ctlr*	next;	int	active;	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;	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;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 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("#l%d: status %8.8uX\n", ether->ctlrno, status);	}}static voidctlrinit(Ether* ether){	Ctlr *ctlr;	Des *des;	int i;	uchar bi[Eaddrlen*2];	ctlr = ether->ctlr;	/*	 * 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] = ether->ea[i*2];		bi[i*4+1] = ether->ea[i*2+1];		bi[i*4+2] = ether->ea[i*2+1];		bi[i*4+3] = ether->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 voidcsr9w(Ctlr* ctlr, int data){	csr32w(ctlr, 9, data);	microdelay(1);}static intmiimdi(Ctlr* ctlr, int n){	int data, i;	/*	 * Read n bits from the MII Management Register.	 */	data = 0;	for(i = n-1; i >= 0; i--){		if(csr32r(ctlr, 9) & Mdi)			data |= (1<<i);		csr9w(ctlr, Mii|Mdc);		csr9w(ctlr, Mii);	}	csr9w(ctlr, 0);	return data;}static voidmiimdo(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;		csr9w(ctlr, mdo);		csr9w(ctlr, mdo|Mdc);		csr9w(ctlr, mdo);	}}static intmiir(Ctlr* ctlr, int phyad, int regad){	int data;	/*	 * Preamble;	 * ST+OP+PHYAD+REGAD;	 * TA + 16 data bits.	 */	miimdo(ctlr, 0xFFFFFFFF, 32);	miimdo(ctlr, 0x1800|(phyad<<5)|regad, 14);	data = miimdi(ctlr, 18);	if(data & 0x10000)		return -1;	return data & 0xFFFF;}static voidmiiw(Ctlr* ctlr, int phyad, int regad, int data){	/*	 * Preamble;	 * ST+OP+PHYAD+REGAD+TA + 16 data bits;	 * Z.	 */	miimdo(ctlr, 0xFFFFFFFF, 32);	data &= 0xFFFF;	data |= (0x05<<(5+5+2+16))|(phyad<<(5+2+16))|(regad<<(2+16))|(0x02<<16);	miimdo(ctlr, data, 32);	csr9w(ctlr, Mdc);	csr9w(ctlr, 0);}static intsromr(Ctlr* ctlr, int r){	int i, op, data;	/*	 * This sequence for reading a 16-bit register 'r'	 * in the EEPROM is taken straight from Section	 * 7.4 of the 21140 Hardware Reference Manual.	 */	csr9w(ctlr, Rd|Ss);	csr9w(ctlr, Rd|Ss|Scs);	csr9w(ctlr, Rd|Ss|Sclk|Scs);	csr9w(ctlr, Rd|Ss);	op = 0x06;	for(i = 3-1; i >= 0; i--){		data = Rd|Ss|(((op>>i) & 0x01)<<2)|Scs;		csr9w(ctlr, data);		csr9w(ctlr, data|Sclk);		csr9w(ctlr, data);	}	for(i = 6-1; i >= 0; i--){		data = Rd|Ss|(((r>>i) & 0x01)<<2)|Scs;		csr9w(ctlr, data);		csr9w(ctlr, data|Sclk);		csr9w(ctlr, data);	}	data = 0;	for(i = 16-1; i >= 0; i--){		csr9w(ctlr, Rd|Ss|Sclk|Scs);		if(csr32r(ctlr, 9) & Sdo)			data |= (1<<i);		csr9w(ctlr, Rd|Ss|Scs);	}	csr9w(ctlr, 0);	return data & 0xFFFF;}static voidsoftreset(Ctlr* ctlr){	/*	 * Soft-reset the controller and initialise bus mode.	 * Delay should be >= 50 PCI cycles (2×S @ 25MHz).	 */	csr32w(ctlr, 0, Swr);	microdelay(10);	csr32w(ctlr, 0, Rml|Cal16);	delay(1);}static inttype5block(Ctlr* ctlr, uchar* block){	int csr15, i, len;	/*	 * Reset or GPR sequence. Reset should be once only,	 * before the GPR sequence.	 * Note 'block' is not a pointer to the block head but	 * a pointer to the data in the block starting at the	 * reset length value so type5block can be used for the	 * sequences contained in type 1 and type 3 blocks.	 * The SROM docs state the 21140 type 5 block is the	 * same as that for the 21143, but the two controllers	 * use different registers and sequence-element lengths	 * so the 21140 code here is a guess for a real type 5	 * sequence.	 */	len = *block++;	if(ctlr->pcidev->did == 0x0009){		for(i = 0; i < len; i++){			csr32w(ctlr, 12, *block);			block++;		}		return len;	}	for(i = 0; i < len; i++){		csr15 = *block++<<16;		csr15 |= *block++<<24;		csr32w(ctlr, 15, csr15);		debug("%8.8uX ", csr15);	}	return 2*len;}static inttypephylink(Ctlr* ctlr, uchar*){	int an, bmcr, bmsr, csr6, x;

⌨️ 快捷键说明

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