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

📄 ethervt6102.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * VIA VT6102 Fast Ethernet Controller (Rhine II). * To do: *	cache-line size alignments - done *	reduce tx interrupts *	use 2 descriptors on tx for alignment - done *	reorganise initialisation/shutdown/reset *	adjust Tx FIFO threshold on underflow - untested *	why does the link status never cause an interrupt? *	use the lproc as a periodic timer for stalls, etc. */#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"#include "etherif.h"#include "ethermii.h"enum {	Par0		= 0x00,		/* Ethernet Address */	Rcr		= 0x06,		/* Receive Configuration */	Tcr		= 0x07,		/* Transmit Configuration */	Cr		= 0x08,		/* Control */	Isr		= 0x0C,		/* Interrupt Status */	Imr		= 0x0E,		/* Interrupt Mask */	Rxdaddr		= 0x18,		/* Current Rx Descriptor Address */	Txdaddr		= 0x1C,		/* Current Tx Descriptor Address */	Phyadr		= 0x6C,		/* Phy Address */	Miisr		= 0x6D,		/* MII Status */	Bcr0		= 0x6E,		/* Bus Control */	Bcr1		= 0x6F,	Miicr		= 0x70,		/* MII Control */	Miiadr		= 0x71,		/* MII Address */	Miidata		= 0x72,		/* MII Data */	Eecsr		= 0x74,		/* EEPROM Control and Status */};enum {					/* Rcr */	Sep		= 0x01,		/* Accept Error Packets */	Ar		= 0x02,		/* Accept Small Packets */	Am		= 0x04,		/* Accept Multicast */	Ab		= 0x08,		/* Accept Broadcast */	Prom		= 0x10,		/* Accept Physical Address Packets */	RrftMASK	= 0xE0,		/* Receive FIFO Threshold */	RrftSHIFT	= 5,	Rrft64		= 0<<RrftSHIFT,	Rrft32		= 1<<RrftSHIFT,	Rrft128		= 2<<RrftSHIFT,	Rrft256		= 3<<RrftSHIFT,	Rrft512		= 4<<RrftSHIFT,	Rrft768		= 5<<RrftSHIFT,	Rrft1024	= 6<<RrftSHIFT,	RrftSAF		= 7<<RrftSHIFT,};enum {					/* Tcr */	Lb0		= 0x02,		/* Loopback Mode */	Lb1		= 0x04,	Ofset		= 0x08,		/* Back-off Priority Selection */	RtsfMASK	= 0xE0,		/* Transmit FIFO Threshold */	RtsfSHIFT	= 5,	Rtsf128		= 0<<RtsfSHIFT,	Rtsf256		= 1<<RtsfSHIFT,	Rtsf512		= 2<<RtsfSHIFT,	Rtsf1024	= 3<<RtsfSHIFT,	RtsfSAF		= 7<<RtsfSHIFT,};enum {					/* Cr */	Init		= 0x0001,	/* INIT Process Begin */	Strt		= 0x0002,	/* Start NIC */	Stop		= 0x0004,	/* Stop NIC */	Rxon		= 0x0008,	/* Turn on Receive Process */	Txon		= 0x0010,	/* Turn on Transmit Process */	Tdmd		= 0x0020,	/* Transmit Poll Demand */	Rdmd		= 0x0040,	/* Receive Poll Demand */	Eren		= 0x0100,	/* Early Receive Enable */	Fdx		= 0x0400,	/* Set MAC to Full Duplex Mode */	Dpoll		= 0x0800,	/* Disable Td/Rd Auto Polling */	Tdmd1		= 0x2000,	/* Transmit Poll Demand 1 */	Rdmd1		= 0x4000,	/* Receive Poll Demand 1 */	Sfrst		= 0x8000,	/* Software Reset */};enum {					/* Isr/Imr */	Prx		= 0x0001,	/* Received Packet Successfully */	Ptx		= 0x0002,	/* Transmitted Packet Successfully */	Rxe		= 0x0004,	/* Receive Error */	Txe		= 0x0008,	/* Transmit Error */	Tu		= 0x0010,	/* Transmit Buffer Underflow */	Ru		= 0x0020,	/* Receive Buffer Link Error */	Be		= 0x0040,	/* PCI Bus Error */	Cnt		= 0x0080,	/* Counter Overflow */	Eri		= 0x0100,	/* Early Receive Interrupt */	Udfi		= 0x0200,	/* Tx FIFO Underflow */	Ovfi		= 0x0400,	/* Receive FIFO Overflow */	Pktrace		= 0x0800,	/* Hmmm... */	Norbf		= 0x1000,	/* No Receive Buffers */	Abti		= 0x2000,	/* Transmission Abort */	Srci		= 0x4000,	/* Port State Change */	Geni		= 0x8000,	/* General Purpose Interrupt */};enum {					/* Phyadr */	PhyadMASK	= 0x1F,		/* PHY Address */	PhyadSHIFT	= 0,	Mfdc		= 0x20,		/* Accelerate MDC Speed */	Mpo0		= 0x40,		/* MII Polling Timer Interval */	Mpo1		= 0x80,};enum {					/* Bcr0 */	DmaMASK		= 0x07,		/* DMA Length */	DmaSHIFT	= 0,	Dma32		= 0<<DmaSHIFT,	Dma64		= 1<<DmaSHIFT,	Dma128		= 2<<DmaSHIFT,	Dma256		= 3<<DmaSHIFT,	Dma512		= 4<<DmaSHIFT,	Dma1024		= 5<<DmaSHIFT,	DmaSAF		= 7<<DmaSHIFT,	CrftMASK	= 0x38,		/* Rx FIFO Threshold */	CrftSHIFT	= 3,	Crft64		= 1<<CrftSHIFT,	Crft128		= 2<<CrftSHIFT,	Crft256		= 3<<CrftSHIFT,	Crft512		= 4<<CrftSHIFT,	Crft1024	= 5<<CrftSHIFT,	CrftSAF		= 7<<CrftSHIFT,	Extled		= 0x40,		/* Extra LED Support Control */	Med2		= 0x80,		/* Medium Select Control */};enum {					/* Bcr1 */	PotMASK		= 0x07,		/* Polling Timer Interval */	PotSHIFT	= 0,	CtftMASK	= 0x38,		/* Tx FIFO Threshold */	CtftSHIFT	= 3,	Ctft64		= 1<<CtftSHIFT,	Ctft128		= 2<<CtftSHIFT,	Ctft256		= 3<<CtftSHIFT,	Ctft512		= 4<<CtftSHIFT,	Ctft1024	= 5<<CtftSHIFT,	CtftSAF		= 7<<CtftSHIFT,};enum {					/* Miicr */	Mdc		= 0x01,		/* Clock */	Mdi		= 0x02,		/* Data In */	Mdo		= 0x04,		/* Data Out */	Mout		= 0x08,		/* Output Enable */	Mdpm		= 0x10,		/* Direct Program Mode Enable */	Wcmd		= 0x20,		/* Write Enable */	Rcmd		= 0x40,		/* Read Enable */	Mauto		= 0x80,		/* Auto Polling Enable */};enum {					/* Miiadr */	MadMASK		= 0x1F,		/* MII Port Address */	MadSHIFT	= 0,	Mdone		= 0x20,		/* Accelerate MDC Speed */	Msrcen		= 0x40,		/* MII Polling Timer Interval */	Midle		= 0x80,};enum {					/* Eecsr */	Edo		= 0x01,		/* Data Out */	Edi		= 0x02,		/* Data In */	Eck		= 0x04,		/* Clock */	Ecs		= 0x08,		/* Chip Select */	Dpm		= 0x10,		/* Direct Program Mode Enable */	Autold		= 0x20,		/* Dynamic Reload */	Embp		= 0x40,		/* Embedded Program Enable */	Eepr		= 0x80,		/* Programmed */};/* * Ring descriptor. The space allocated for each * of these will be rounded up to a cache-line boundary. * The first 4 elements are known to the hardware. */typedef struct Ds Ds;typedef struct Ds {	uint	status;	uint	control;	uint	addr;	uint	branch;	Block*	bp;	void*	bounce;	Ds*	next;	Ds*	prev;} Ds;enum {					/* Rx Ds status */	Rerr		= 0x00000001,	/* Receiver Error */	Crc		= 0x00000002,	/* CRC Error */	Fae		= 0x00000004,	/* Frame Alignment Error */	Fov		= 0x00000008,	/* FIFO Overflow */	Long		= 0x00000010,	/* A Long Packet */	Runt		= 0x00000020,	/* A Runt Packet */	Rxserr		= 0x00000040,	/* System Error */	Buff		= 0x00000080,	/* Buffer Underflow Error */	Rxedp		= 0x00000100,	/* End of Packet Buffer */	Rxstp		= 0x00000200,	/* Packet Start */	Chn		= 0x00000400,	/* Chain Buffer */	Phy		= 0x00000800,	/* Physical Address Packet */	Bar		= 0x00001000,	/* Broadcast Packet */	Mar		= 0x00002000,	/* Multicast Packet */	Rxok		= 0x00008000,	/* Packet Received Successfully */	LengthMASK	= 0x07FF0000,	/* Received Packet Length */	LengthSHIFT	= 16,	Own		= 0x80000000,	/* Descriptor Owned by NIC */};enum {					/* Tx Ds status */	NcrMASK		= 0x0000000F,	/* Collision Retry Count */	NcrSHIFT	= 0,	Cols		= 0x00000010,	/* Experienced Collisions */	Cdh		= 0x00000080,	/* CD Heartbeat */	Abt		= 0x00000100,	/* Aborted after Excessive Collisions */	Owc		= 0x00000200,	/* Out of Window Collision Seen */	Crs		= 0x00000400,	/* Carrier Sense Lost */	Udf		= 0x00000800,	/* FIFO Underflow */	Tbuff		= 0x00001000,	/* Invalid Td */	Txserr		= 0x00002000,	/* System Error */	Terr		= 0x00008000,	/* Excessive Collisions */};enum {					/* Tx Ds control */	TbsMASK		= 0x000007FF,	/* Tx Buffer Size */	TbsSHIFT	= 0,	Chain		= 0x00008000,	/* Chain Buffer */	Crcdisable	= 0x00010000,	/* Disable CRC generation */	Stp		= 0x00200000,	/* Start of Packet */	Edp		= 0x00400000,	/* End of Packet */	Ic		= 0x00800000,	/* Assert Interrupt Immediately */};enum {	Nrd		= 64,	Ntd		= 64,	Rdbsz		= ROUNDUP(ETHERMAXTU+4, 4),	Nrxstats	= 8,	Ntxstats	= 9,	Txcopy		= 128,};typedef struct Ctlr Ctlr;typedef struct Ctlr {	int	port;	Pcidev*	pcidev;	Ctlr*	next;	int	active;	int	id;	uchar	par[Eaddrlen];	QLock	alock;			/* attach */	void*	alloc;			/* receive/transmit descriptors */	int	cls;			/* alignment */	int	nrd;	int	ntd;	Ds*	rd;	Ds*	rdh;	Lock	tlock;	Ds*	td;	Ds*	tdh;	Ds*	tdt;	int	tdused;	Lock	clock;			/*  */	int	cr;	int	imr;	int	tft;			/* Tx threshold */	Mii*	mii;	Rendez	lrendez;	int	lwakeup;	uint	rxstats[Nrxstats];	/* statistics */	uint	txstats[Ntxstats];	uint	intr;	uint	lintr;				uint	lsleep;	uint	rintr;	uint	tintr;	uint	taligned;	uint	tsplit;	uint	tcopied;	uint	txdw;} Ctlr;static Ctlr* vt6102ctlrhead;static Ctlr* vt6102ctlrtail;#define csr8r(c, r)	(inb((c)->port+(r)))#define csr16r(c, r)	(ins((c)->port+(r)))#define csr32r(c, r)	(inl((c)->port+(r)))#define csr8w(c, r, b)	(outb((c)->port+(r), (int)(b)))#define csr16w(c, r, w)	(outs((c)->port+(r), (ushort)(w)))#define csr32w(c, r, w)	(outl((c)->port+(r), (ulong)(w)))static char* rxstats[Nrxstats] = {	"Receiver Error",	"CRC Error",	"Frame Alignment Error",	"FIFO Overflow",	"Long Packet",	"Runt Packet",	"System Error",	"Buffer Underflow Error",};static char* txstats[Ntxstats] = {	"Aborted after Excessive Collisions",	"Out of Window Collision Seen",	"Carrier Sense Lost",	"FIFO Underflow",	"Invalid Td",	"System Error",	nil,	"Excessive Collisions",};static longvt6102ifstat(Ether* edev, void* a, long n, ulong offset){	char *p;	Ctlr *ctlr;	int i, l, r;	ctlr = edev->ctlr;	p = malloc(2*READSTR);	l = 0;	for(i = 0; i < Nrxstats; i++){		l += snprint(p+l, 2*READSTR-l, "%s: %ud\n",			rxstats[i], ctlr->rxstats[i]);	}	for(i = 0; i < Ntxstats; i++){		if(txstats[i] == nil)			continue;		l += snprint(p+l, 2*READSTR-l, "%s: %ud\n",			txstats[i], ctlr->txstats[i]);	}	l += snprint(p+l, 2*READSTR-l, "cls: %ud\n", ctlr->cls);	l += snprint(p+l, 2*READSTR-l, "intr: %ud\n", ctlr->intr);	l += snprint(p+l, 2*READSTR-l, "lintr: %ud\n", ctlr->lintr);	l += snprint(p+l, 2*READSTR-l, "lsleep: %ud\n", ctlr->lsleep);	l += snprint(p+l, 2*READSTR-l, "rintr: %ud\n", ctlr->rintr);	l += snprint(p+l, 2*READSTR-l, "tintr: %ud\n", ctlr->tintr);	l += snprint(p+l, 2*READSTR-l, "taligned: %ud\n", ctlr->taligned);	l += snprint(p+l, 2*READSTR-l, "tsplit: %ud\n", ctlr->tsplit);	l += snprint(p+l, 2*READSTR-l, "tcopied: %ud\n", ctlr->tcopied);	l += snprint(p+l, 2*READSTR-l, "txdw: %ud\n", ctlr->txdw);	l += snprint(p+l, 2*READSTR-l, "tft: %ud\n", ctlr->tft);	if(ctlr->mii != nil && ctlr->mii->curphy != nil){		l += snprint(p+l, 2*READSTR, "phy:   ");		for(i = 0; i < NMiiPhyr; i++){			if(i && ((i & 0x07) == 0))				l += snprint(p+l, 2*READSTR-l, "\n       ");			r = miimir(ctlr->mii, i);			l += snprint(p+l, 2*READSTR-l, " %4.4uX", r);		}		snprint(p+l, 2*READSTR-l, "\n");	}	snprint(p+l, 2*READSTR-l, "\n");	n = readstr(offset, a, n, p);	free(p);	return n;}static voidvt6102promiscuous(void* arg, int on){	int rcr;	Ctlr *ctlr;	Ether *edev;	edev = arg;	ctlr = edev->ctlr;	rcr = csr8r(ctlr, Rcr);	if(on)		rcr |= Prom;	else		rcr &= ~Prom;	csr8w(ctlr, Rcr, rcr);}static voidvt6102multicast(void* arg, uchar* addr, int on){	/*	 * For now Am is set in Rcr.	 * Will need to interlock with promiscuous	 * when this gets filled in.	 */	USED(arg, addr, on);}static intvt6102wakeup(void* v){	return *((int*)v) != 0;}static voidvt6102imr(Ctlr* ctlr, int imr){	ilock(&ctlr->clock);	ctlr->imr |= imr;	csr16w(ctlr, Imr, ctlr->imr);	iunlock(&ctlr->clock);}static voidvt6102lproc(void* arg){	Ctlr *ctlr;	Ether *edev;	MiiPhy *phy;	edev = arg;	ctlr = edev->ctlr;	for(;;){		if(ctlr->mii == nil || ctlr->mii->curphy == nil)			break;		if(miistatus(ctlr->mii) < 0)			goto enable;		phy = ctlr->mii->curphy;		ilock(&ctlr->clock);		if(phy->fd)			ctlr->cr |= Fdx;		else			ctlr->cr &= ~Fdx;		csr16w(ctlr, Cr, ctlr->cr);		iunlock(&ctlr->clock);enable:		ctlr->lwakeup = 0;		vt6102imr(ctlr, Srci);		ctlr->lsleep++;		sleep(&ctlr->lrendez, vt6102wakeup, &ctlr->lwakeup);	}	pexit("vt6102lproc: done", 1);}static voidvt6102attach(Ether* edev){	int i;	Ctlr *ctlr;	Ds *ds, *prev;	uchar *alloc, *bounce;	char name[KNAMELEN];	ctlr = edev->ctlr;	qlock(&ctlr->alock);	if(ctlr->alloc != nil){		qunlock(&ctlr->alock);		return;	}	/*	 * Descriptor and bounce-buffer space.	 * Must all be aligned on a 4-byte boundary,	 * but try to align on cache-lines.	 */	ctlr->nrd = Nrd;	ctlr->ntd = Ntd;	alloc = malloc((ctlr->nrd+ctlr->ntd)*ctlr->cls + ctlr->ntd*Txcopy + ctlr->cls-1);	if(alloc == nil){		qunlock(&ctlr->alock);		return;	}	ctlr->alloc = alloc;	alloc = (uchar*)ROUNDUP((ulong)alloc, ctlr->cls);	ctlr->rd = (Ds*)alloc;	if(waserror()){		ds = ctlr->rd;		for(i = 0; i < ctlr->nrd; i++){			if(ds->bp != nil){				freeb(ds->bp);				ds->bp = nil;			}			if((ds = ds->next) == nil)				break;		}		free(ctlr->alloc);		ctlr->alloc = nil;		qunlock(&ctlr->alock);		nexterror();	}	prev = ctlr->rd + ctlr->nrd-1;	for(i = 0; i < ctlr->nrd; i++){

⌨️ 快捷键说明

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