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

📄 etherfcc.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * FCCn ethernet */#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "imm.h"#include "../port/error.h"#include "../port/netif.h"#include "etherif.h"#include "../ppc/ethermii.h"#define DBG 1enum {	Nrdre		= 128,			/* receive descriptor ring entries */	Ntdre		= 128,			/* transmit descriptor ring entries */	Rbsize		= ETHERMAXTU+4,		/* ring buffer size (+4 for CRC) */	Bufsize		= Rbsize+CACHELINESZ,	/* extra room for alignment */};enum {	/* ether-specific Rx BD bits */	RxMiss=		SBIT(7),	RxeLG=		SBIT(10),	RxeNO=		SBIT(11),	RxeSH=		SBIT(12),	RxeCR=		SBIT(13),	RxeOV=		SBIT(14),	RxeCL=		SBIT(15),	RxError=	(RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL),	/* various error flags */	/* ether-specific Tx BD bits */	TxPad=		SBIT(1),	/* pad short frames */	TxTC=		SBIT(5),	/* transmit CRC */	TxeDEF=		SBIT(6),	TxeHB=		SBIT(7),	TxeLC=		SBIT(8),	TxeRL=		SBIT(9),	TxeUN=		SBIT(14),	TxeCSL=		SBIT(15),	/* psmr */	CRCE=		BIT(24),	/* Ethernet CRC */	FCE=		BIT(10),	/* flow control */	PRO=		BIT(9),		/* promiscuous mode */	FDE=		BIT(5),		/* full duplex ethernet */	LPB=		BIT(3),		/* local protect bit */	/* gfmr */	ENET=		0xc,		/* ethernet mode */	ENT=		BIT(27),	ENR=		BIT(26),	TCI=		BIT(2),	/* FCC function code register */	GBL=		0x20,	BO=		0x18,	EB=		0x10,		/* Motorola byte order */	TC2=		0x04,	DTB=		0x02,	BDB=		0x01,	/* FCC Event/Mask bits */	GRA=		SBIT(8),	RXC=		SBIT(9),	TXC=		SBIT(10),	TXE=		SBIT(11),	RXF=		SBIT(12),	BSY=		SBIT(13),	TXB=		SBIT(14),	RXB=		SBIT(15),};enum {		/* Mcr */	MDIread	=	0x60020000,	/* read opcode */	MDIwrite =	0x50020000,	/* write opcode */};typedef struct Etherparam Etherparam;struct Etherparam {/*0x00*/	FCCparam;/*0x3c*/	ulong	stat_buf;/*0x40*/	ulong	cam_ptr;/*0x44*/	ulong	cmask;/*0x48*/	ulong	cpres;/*0x4c*/	ulong	crcec;/*0x50*/	ulong	alec;/*0x54*/	ulong	disfc;/*0x58*/	ushort	retlim;/*0x5a*/	ushort	retcnt;/*0x5c*/	ushort	p_per;/*0x5e*/	ushort	boff_cnt;/*0x60*/	ulong	gaddr[2];/*0x68*/	ushort	tfcstat;/*0x6a*/	ushort	tfclen;/*0x6c*/	ulong	tfcptr;/*0x70*/	ushort	mflr;/*0x72*/	ushort	paddr[3];/*0x78*/	ushort	ibd_cnt;/*0x7a*/	ushort	ibd_start;/*0x7c*/	ushort	ibd_end;/*0x7e*/	ushort	tx_len;/*0x80*/	uchar	ibd_base[32];/*0xa0*/	ulong	iaddr[2];/*0xa8*/	ushort	minflr;/*0xaa*/	ushort	taddr[3];/*0xb0*/	ushort	padptr;/*0xb2*/	ushort	Rsvdb2;/*0xb4*/	ushort	cf_range;/*0xb6*/	ushort	max_b;/*0xb8*/	ushort	maxd1;/*0xba*/	ushort	maxd2;/*0xbc*/	ushort	maxd;/*0xbe*/	ushort	dma_cnt;/*0xc0*/	ulong	octc;/*0xc4*/	ulong	colc;/*0xc8*/	ulong	broc;/*0xcc*/	ulong	mulc;/*0xd0*/	ulong	uspc;/*0xd4*/	ulong	frgc;/*0xd8*/	ulong	ospc;/*0xdc*/	ulong	jbrc;/*0xe0*/	ulong	p64c;/*0xe4*/	ulong	p65c;/*0xe8*/	ulong	p128c;/*0xec*/	ulong	p256c;/*0xf0*/	ulong	p512c;/*0xf4*/	ulong	p1024c;/*0xf8*/	ulong	cam_buf;/*0xfc*/	ulong	Rsvdfc;/*0x100*/};typedef struct Ctlr Ctlr;struct Ctlr {	Lock;	int	fccid;	int	port;	ulong	pmdio;	ulong	pmdck;	int	init;	int	active;	int	duplex;		/* 1 == full */	FCC*	fcc;	Ring;	Block*	rcvbufs[Nrdre];	Mii*	mii;	Timer;	ulong	interrupts;	/* statistics */	ulong	deferred;	ulong	heartbeat;	ulong	latecoll;	ulong	retrylim;	ulong	underrun;	ulong	overrun;	ulong	carrierlost;	ulong	retrycount;};static	int	fccirq[] = {0x20, 0x21, 0x22};static	int	fccid[] = {FCC1ID, FCC2ID, FCC3ID};#ifdef DBGulong fccrhisto[16];ulong fccthisto[16];ulong fccrthisto[16];ulong fcctrhisto[16];ulong ehisto[0x80];#endifstatic int fccmiimir(Mii*, int, int);static int fccmiimiw(Mii*, int, int, int);static void fccltimer(Ureg*, Timer*);static voidattach(Ether *ether){	Ctlr *ctlr;	ctlr = ether->ctlr;	ilock(ctlr);	ctlr->active = 1;	ctlr->fcc->gfmr |= ENR|ENT;	iunlock(ctlr);	ctlr->tmode = Tperiodic;	ctlr->tf = fccltimer;	ctlr->ta = ether;	ctlr->tns = 5000000000LL;	/* 5 seconds */	timeradd(ctlr);}static voidclosed(Ether *ether){	Ctlr *ctlr;	ctlr = ether->ctlr;	ilock(ctlr);	ctlr->active = 0;	ctlr->fcc->gfmr &= ~(ENR|ENT);	iunlock(ctlr);	print("Ether closed\n");}static voidpromiscuous(void* arg, int on){	Ether *ether;	Ctlr *ctlr;	ether = (Ether*)arg;	ctlr = ether->ctlr;	ilock(ctlr);	if(on || ether->nmaddr)		ctlr->fcc->fpsmr |= PRO;	else		ctlr->fcc->fpsmr &= ~PRO;	iunlock(ctlr);}static voidmulticast(void* arg, uchar *addr, int on){	Ether *ether;	Ctlr *ctlr;	USED(addr, on);	/* if on, could SetGroupAddress; if !on, it's hard */	ether = (Ether*)arg;	ctlr = ether->ctlr;	ilock(ctlr);	if(ether->prom || ether->nmaddr)		ctlr->fcc->fpsmr |= PRO;	else		ctlr->fcc->fpsmr &= ~PRO;	iunlock(ctlr);}static voidtxstart(Ether *ether){	int len;	Ctlr *ctlr;	Block *b;	BD *dre;	ctlr = ether->ctlr;	if(ctlr->init)		return;	while(ctlr->ntq < Ntdre-1){		b = qget(ether->oq);		if(b == 0)			break;		dre = &ctlr->tdr[ctlr->tdrh];		dczap(dre, sizeof(BD));		if(dre->status & BDReady)			panic("ether: txstart");		/*		 * Give ownership of the descriptor to the chip, increment the		 * software ring descriptor pointer and tell the chip to poll.		 */		len = BLEN(b);		if(ctlr->txb[ctlr->tdrh] != nil)			panic("fcc/ether: txstart");		ctlr->txb[ctlr->tdrh] = b;		if((ulong)b->rp&1)			panic("fcc/ether: txstart align");	/* TO DO: ensure alignment */		dre->addr = PADDR(b->rp);		dre->length = len;		dcflush(b->rp, len);		dcflush(dre, sizeof(BD));		dre->status = (dre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;		dcflush(dre, sizeof(BD));/*		ctlr->fcc->ftodr = 1<<15;	/* transmit now; Don't do this according to errata */		ctlr->ntq++;		ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);	}}static voidtransmit(Ether* ether){	Ctlr *ctlr;	ctlr = ether->ctlr;	ilock(ctlr);	txstart(ether);	iunlock(ctlr);}static voidinterrupt(Ureg*, void *arg){	int len, status, rcvd, xmtd, restart;	ushort events;	Ctlr *ctlr;	BD *dre;	Block *b, *nb;	Ether *ether = arg;	ctlr = ether->ctlr;	if(!ctlr->active)		return;	/* not ours */	/*	 * Acknowledge all interrupts and whine about those that shouldn't	 * happen.	 */	events = ctlr->fcc->fcce;	ctlr->fcc->fcce = events;		/* clear events */#ifdef DBG	ehisto[events & 0x7f]++;#endif	ctlr->interrupts++;	if(events & BSY)		ctlr->overrun++;	if(events & TXE)		ether->oerrs++;#ifdef DBG	rcvd = xmtd = 0;#endif	/*	 * Receiver interrupt: run round the descriptor ring logging	 * errors and passing valid receive data up to the higher levels	 * until we encounter a descriptor still owned by the chip.	 */	if(events & RXF){		dre = &ctlr->rdr[ctlr->rdrx];		dczap(dre, sizeof(BD));		while(((status = dre->status) & BDEmpty) == 0){			rcvd++;			if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){				if(status & (RxeLG|RxeSH))					ether->buffs++;				if(status & RxeNO)					ether->frames++;				if(status & RxeCR)					ether->crcs++;				if(status & RxeOV)					ether->overflows++;				print("eth rx: %ux\n", status);			}else{				/*				 * We have a packet. Read it in.				 */				len = dre->length-4;				b = ctlr->rcvbufs[ctlr->rdrx];				assert(dre->addr == PADDR(b->rp));				dczap(b->rp, len);				if(nb = iallocb(Bufsize)){					b->wp += len;					etheriq(ether, b, 1);					b = nb;					b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1));					b->wp = b->rp;					ctlr->rcvbufs[ctlr->rdrx] = b;					ctlr->rdr[ctlr->rdrx].addr = PADDR(b->wp);				}else					ether->soverflows++;			}			/*			 * Finished with this descriptor, reinitialise it,			 * give it back to the chip, then on to the next...			 */			dre->length = 0;			dre->status = (status & BDWrap) | BDEmpty | BDInt;			dcflush(dre, sizeof(BD));			ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);			dre = &ctlr->rdr[ctlr->rdrx];			dczap(dre, sizeof(BD));		}	}	/*	 * Transmitter interrupt: handle anything queued for a free descriptor.	 */	if(events & (TXB|TXE)){		ilock(ctlr);		restart = 0;		while(ctlr->ntq){			dre = &ctlr->tdr[ctlr->tdri];			dczap(dre, sizeof(BD));			status = dre->status;			if(status & BDReady)				break;			if(status & TxeDEF)				ctlr->deferred++;			if(status & TxeHB)				ctlr->heartbeat++;			if(status & TxeLC)				ctlr->latecoll++;			if(status & TxeRL)				ctlr->retrylim++;			if(status & TxeUN)				ctlr->underrun++;			if(status & TxeCSL)				ctlr->carrierlost++;			if(status & (TxeLC|TxeRL|TxeUN))				restart = 1;			ctlr->retrycount += (status>>2)&0xF;			b = ctlr->txb[ctlr->tdri];			if(b == nil)				panic("fcce/interrupt: bufp");			ctlr->txb[ctlr->tdri] = nil;			freeb(b);			ctlr->ntq--;			ctlr->tdri = NEXT(ctlr->tdri, Ntdre);			xmtd++;		}		if(restart){			ctlr->fcc->gfmr &= ~ENT;			delay(10);			ctlr->fcc->gfmr |= ENT;			cpmop(RestartTx, ctlr->fccid, 0xc);		}		txstart(ether);		iunlock(ctlr);	}#ifdef DBG	if(rcvd >= nelem(fccrhisto))		rcvd = nelem(fccrhisto) - 1;	if(xmtd >= nelem(fccthisto))		xmtd = nelem(fccthisto) - 1;	if(rcvd)		fcctrhisto[xmtd]++;

⌨️ 快捷键说明

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