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

📄 ether8139.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Realtek 8139 (but not the 8129). * Error recovery for the various over/under -flow conditions * may need work. */#ifdef FS#include "all.h"#include "io.h"#include "mem.h"#include "../ip/ip.h"#else#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"#endif			/* FS */#include "etherif.h"#include "compat.h"enum {					/* registers */	Idr0		= 0x0000,	/* MAC address */	Mar0		= 0x0008,	/* Multicast address */	Tsd0		= 0x0010,	/* Transmit Status Descriptor0 */	Tsad0		= 0x0020,	/* Transmit Start Address Descriptor0 */	Rbstart		= 0x0030,	/* Receive Buffer Start Address */	Erbcr		= 0x0034,	/* Early Receive Byte Count */	Ersr		= 0x0036,	/* Early Receive Status */	Cr		= 0x0037,	/* Command Register */	Capr		= 0x0038,	/* Current Address of Packet Read */	Cbr		= 0x003A,	/* Current Buffer Address */	Imr		= 0x003C,	/* Interrupt Mask */	Isr		= 0x003E,	/* Interrupt Status */	Tcr		= 0x0040,	/* Transmit Configuration */	Rcr		= 0x0044,	/* Receive Configuration */	Tctr		= 0x0048,	/* Timer Count */	Mpc		= 0x004C,	/* Missed Packet Counter */	Cr9346		= 0x0050,	/* 9346 Command Register */	Config0		= 0x0051,	/* Configuration Register 0 */	Config1		= 0x0052,	/* Configuration Register 1 */	TimerInt	= 0x0054,	/* Timer Interrupt */	Msr		= 0x0058,	/* Media Status */	Config3		= 0x0059,	/* Configuration Register 3 */	Config4		= 0x005A,	/* Configuration Register 4 */	Mulint		= 0x005C,	/* Multiple Interrupt Select */	RerID		= 0x005E,	/* PCI Revision ID */	Tsad		= 0x0060,	/* Transmit Status of all Descriptors */	Bmcr		= 0x0062,	/* Basic Mode Control */	Bmsr		= 0x0064,	/* Basic Mode Status */	Anar		= 0x0066,	/* Auto-Negotiation Advertisment */	Anlpar		= 0x0068,	/* Auto-Negotiation Link Partner */	Aner		= 0x006A,	/* Auto-Negotiation Expansion */	Dis		= 0x006C,	/* Disconnect Counter */	Fcsc		= 0x006E,	/* False Carrier Sense Counter */	Nwaytr		= 0x0070,	/* N-way Test */	Rec		= 0x0072,	/* RX_ER Counter */	Cscr		= 0x0074,	/* CS Configuration */	Phy1parm	= 0x0078,	/* PHY Parameter 1 */	Twparm		= 0x007C,	/* Twister Parameter */	Phy2parm	= 0x0080,	/* PHY Parameter 2 */};enum {					/* Cr */	Bufe		= 0x01,		/* Rx Buffer Empty */	Te		= 0x04,		/* Transmitter Enable */	Re		= 0x08,		/* Receiver Enable */	Rst		= 0x10,		/* Software Reset */};enum {					/* Imr/Isr */	Rok		= 0x0001,	/* Receive OK */	Rer		= 0x0002,	/* Receive Error */	Tok		= 0x0004,	/* Transmit OK */	Ter		= 0x0008,	/* Transmit Error */	Rxovw		= 0x0010,	/* Receive Buffer Overflow */	PunLc		= 0x0020,	/* Packet Underrun or Link Change */	Fovw		= 0x0040,	/* Receive FIFO Overflow */	Clc		= 0x2000,	/* Cable Length Change */	Timerbit	= 0x4000,	/* Timer */	Serr		= 0x8000,	/* System Error */};enum {					/* Tcr */	Clrabt		= 0x00000001,	/* Clear Abort */	TxrrSHIFT	= 4,		/* Transmit Retry Count */	TxrrMASK	= 0x000000F0,	MtxdmaSHIFT	= 8,		/* Max. DMA Burst Size */	MtxdmaMASK	= 0x00000700,	Mtxdma2048	= 0x00000700,	Acrc		= 0x00010000,	/* Append CRC (not) */	LbkSHIFT	= 17,		/* Loopback Test */	LbkMASK		= 0x00060000,	Rtl8139ArevG	= 0x00800000,	/* RTL8139A Rev. G ID */	IfgSHIFT	= 24,		/* Interframe Gap */	IfgMASK		= 0x03000000,	HwveridSHIFT	= 26,		/* Hardware Version ID */	HwveridMASK	= 0x7C000000,};enum {					/* Rcr */	Aap		= 0x00000001,	/* Accept All Packets */	Apm		= 0x00000002,	/* Accept Physical Match */	Am		= 0x00000004,	/* Accept Multicast */	Ab		= 0x00000008,	/* Accept Broadcast */	Ar		= 0x00000010,	/* Accept Runt */	Aer		= 0x00000020,	/* Accept Error */	Sel9356		= 0x00000040,	/* 9356 EEPROM used */	Wrap		= 0x00000080,	/* Rx Buffer Wrap Control */	MrxdmaSHIFT	= 8,		/* Max. DMA Burst Size */	MrxdmaMASK	= 0x00000700,	Mrxdmaunlimited	= 0x00000700,	RblenSHIFT	= 11,		/* Receive Buffer Length */	RblenMASK	= 0x00001800,	Rblen8K		= 0x00000000,	/* 8KB+16 */	Rblen16K	= 0x00000800,	/* 16KB+16 */	Rblen32K	= 0x00001000,	/* 32KB+16 */	Rblen64K	= 0x00001800,	/* 64KB+16 */	RxfthSHIFT	= 13,		/* Receive Buffer Length */	RxfthMASK	= 0x0000E000,	Rxfth256	= 0x00008000,	Rxfthnone	= 0x0000E000,	Rer8		= 0x00010000,	/* Accept Error Packets > 8 bytes */	MulERINT	= 0x00020000,	/* Multiple Early Interrupt Select */	ErxthSHIFT	= 24,		/* Early Rx Threshold */	ErxthMASK	= 0x0F000000,	Erxthnone	= 0x00000000,};enum {					/* Received Packet Status */	Rcok		= 0x0001,	/* Receive Completed OK */	Fae		= 0x0002,	/* Frame Alignment Error */	Crc		= 0x0004,	/* CRC Error */	Long		= 0x0008,	/* Long Packet */	Runt		= 0x0010,	/* Runt Packet Received */	Ise		= 0x0020,	/* Invalid Symbol Error */	Bar		= 0x2000,	/* Broadcast Address Received */	Pam		= 0x4000,	/* Physical Address Matched */	Mar		= 0x8000,	/* Multicast Address Received */};enum {					/* Media Status Register */	Rxpf		= 0x01,		/* Pause Flag */	Txpf		= 0x02,		/* Pause Flag */	Linkb		= 0x04,		/* Inverse of Link Status */	Speed10		= 0x08,		/* 10Mbps */	Auxstatus	= 0x10,		/* Aux. Power Present Status */	Rxfce		= 0x40,		/* Receive Flow Control Enable */	Txfce		= 0x80,		/* Transmit Flow Control Enable */};typedef struct {			/* Soft Transmit Descriptor */	int	tsd;	int	tsad;	uchar*	data;	Block*	bp;} Td;enum {					/* Tsd0 */	SizeSHIFT	= 0,		/* Descriptor Size */	SizeMASK	= 0x00001FFF,	Own		= 0x00002000,	Tun		= 0x00004000,	/* Transmit FIFO Underrun */	Tcok		= 0x00008000,	/* Transmit COmpleted OK */	EtxthSHIFT	= 16,		/* Early Tx Threshold */	EtxthMASK	= 0x001F0000,	NccSHIFT	= 24,		/* Number of Collisions Count */	NccMASK		= 0x0F000000,	Cdh		= 0x10000000,	/* CD Heartbeat */	Owc		= 0x20000000,	/* Out of Window Collision */	Tabt		= 0x40000000,	/* Transmit Abort */	Crs		= 0x80000000,	/* Carrier Sense Lost */};enum {	Rblen		= Rblen64K,	/* Receive Buffer Length */	Ntd		= 4,		/* Number of Transmit Descriptors */	Tdbsz		= ROUNDUP(sizeof(Etherpkt), 4),};typedef struct Ctlr Ctlr;typedef struct Ctlr {	int	port;	Pcidev*	pcidev;	Ctlr*	next;	int	active;	int	id;	QLock	alock;			/* attach */	Lock	ilock;			/* init */	void*	alloc;			/* base of per-Ctlr allocated data */	int	rcr;			/* receive configuration register */	uchar*	rbstart;		/* receive buffer */	int	rblen;			/* receive buffer length */	int	ierrs;			/* receive errors */	Lock	tlock;			/* transmit */	Td	td[Ntd];	int	ntd;			/* descriptors active */	int	tdh;			/* host index into td */	int	tdi;			/* interface index into td */	int	etxth;			/* early transmit threshold */	int	taligned;		/* packet required no alignment */	int	tunaligned;		/* packet required alignment */	int	dis;			/* disconnect counter */	int	fcsc;			/* false carrier sense counter */	int	rec;			/* RX_ER counter */} Ctlr;static Ctlr* ctlrhead;static Ctlr* ctlrtail;#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, l)	(outl((c)->port+(r), (ulong)(l)))static voidrtl8139promiscuous(void* arg, int on){	Ether *edev;	Ctlr * ctlr;	edev = arg;	ctlr = edev->ctlr;	ilock(&ctlr->ilock);	if(on)		ctlr->rcr |= Aap;	else		ctlr->rcr &= ~Aap;	csr32w(ctlr, Rcr, ctlr->rcr);	iunlock(&ctlr->ilock);}static longrtl8139ifstat(Ether* edev, void* a, long n, ulong offset){	int l;	char *p;	Ctlr *ctlr;	ctlr = edev->ctlr;	p = malloc(READSTR);	l = snprint(p, READSTR, "rcr %8.8uX\n", ctlr->rcr);	l += snprint(p+l, READSTR-l, "ierrs %d\n", ctlr->ierrs);	l += snprint(p+l, READSTR-l, "etxth %d\n", ctlr->etxth);	l += snprint(p+l, READSTR-l, "taligned %d\n", ctlr->taligned);	l += snprint(p+l, READSTR-l, "tunaligned %d\n", ctlr->tunaligned);	ctlr->dis += csr16r(ctlr, Dis);	l += snprint(p+l, READSTR-l, "dis %d\n", ctlr->dis);	ctlr->fcsc += csr16r(ctlr, Fcsc);	l += snprint(p+l, READSTR-l, "fcscnt %d\n", ctlr->fcsc);	ctlr->rec += csr16r(ctlr, Rec);	l += snprint(p+l, READSTR-l, "rec %d\n", ctlr->rec);	l += snprint(p+l, READSTR-l, "Tcr %8.8luX\n", csr32r(ctlr, Tcr));	l += snprint(p+l, READSTR-l, "Config0 %2.2uX\n", csr8r(ctlr, Config0));	l += snprint(p+l, READSTR-l, "Config1 %2.2uX\n", csr8r(ctlr, Config1));	l += snprint(p+l, READSTR-l, "Msr %2.2uX\n", csr8r(ctlr, Msr));	l += snprint(p+l, READSTR-l, "Config3 %2.2uX\n", csr8r(ctlr, Config3));	l += snprint(p+l, READSTR-l, "Config4 %2.2uX\n", csr8r(ctlr, Config4));	l += snprint(p+l, READSTR-l, "Bmcr %4.4uX\n", csr16r(ctlr, Bmcr));	l += snprint(p+l, READSTR-l, "Bmsr %4.4uX\n", csr16r(ctlr, Bmsr));	l += snprint(p+l, READSTR-l, "Anar %4.4uX\n", csr16r(ctlr, Anar));	l += snprint(p+l, READSTR-l, "Anlpar %4.4uX\n", csr16r(ctlr, Anlpar));	l += snprint(p+l, READSTR-l, "Aner %4.4uX\n", csr16r(ctlr, Aner));	l += snprint(p+l, READSTR-l, "Nwaytr %4.4uX\n", csr16r(ctlr, Nwaytr));	snprint(p+l, READSTR-l, "Cscr %4.4uX\n", csr16r(ctlr, Cscr));	n = readstr(offset, a, n, p);	free(p);	return n;}static intrtl8139reset(Ctlr* ctlr){	int timeo;	/*	 * Soft reset the controller.	 */	csr8w(ctlr, Cr, Rst);	for(timeo = 0; timeo < 1000; timeo++){		if(!(csr8r(ctlr, Cr) & Rst))			return 0;		delay(1);	}	return -1;}static voidrtl8139halt(Ctlr* ctlr){	int i;	csr8w(ctlr, Cr, 0);	csr16w(ctlr, Imr, 0);	csr16w(ctlr, Isr, ~0);	for(i = 0; i < Ntd; i++){		if(ctlr->td[i].bp == nil)			continue;		freeb(ctlr->td[i].bp);		ctlr->td[i].bp = nil;	}}static voidrtl8139init(Ether* edev){	int i;	ulong r;	Ctlr *ctlr;	uchar *alloc;	ctlr = edev->ctlr;	ilock(&ctlr->ilock);	rtl8139halt(ctlr);	/*	 * MAC Address.	 */	r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];	csr32w(ctlr, Idr0, r);	r = (edev->ea[5]<<8)|edev->ea[4];	csr32w(ctlr, Idr0+4, r);	/*	 * Receiver	 */	alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 32);	ctlr->rbstart = alloc;	alloc += ctlr->rblen+16;	memset(ctlr->rbstart, 0, ctlr->rblen+16);	csr32w(ctlr, Rbstart, PCIWADDR(ctlr->rbstart));	ctlr->rcr = Rxfth256|Rblen|Mrxdmaunlimited|Ab|Apm;	/*	 * Transmitter.	 */	for(i = 0; i < Ntd; i++){		ctlr->td[i].tsd = Tsd0+i*4;		ctlr->td[i].tsad = Tsad0+i*4;		ctlr->td[i].data = alloc;		alloc += Tdbsz;		ctlr->td[i].bp = nil;	}	ctlr->ntd = ctlr->tdh = ctlr->tdi = 0;	ctlr->etxth = 128/32;	/*	 * Interrupts.	 */	csr32w(ctlr, TimerInt, 0);	csr16w(ctlr, Imr, Serr|Timerbit|Fovw|PunLc|Rxovw|Ter|Tok|Rer|Rok);	csr32w(ctlr, Mpc, 0);	/*	 * Enable receiver/transmitter.	 * Need to enable before writing the Rcr or it won't take.	 */	csr8w(ctlr, Cr, Te|Re);	csr32w(ctlr, Tcr, Mtxdma2048);	csr32w(ctlr, Rcr, ctlr->rcr);	iunlock(&ctlr->ilock);}static voidrtl8139attach(Ether* edev){	Ctlr *ctlr;

⌨️ 快捷键说明

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