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

📄 etherga620.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Netgear GA620 Gigabit Ethernet Card. * Specific for the Alteon Tigon 2 and Intel Pentium or later. * To Do: *	cache alignment for PCI Write-and-Invalidate *	mini ring (what size)? *	tune coalescing values *	statistics formatting *	don't update Spi if nothing to send *	receive ring alignment *	watchdog for link management? */#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"#define malign(n)	xspanalloc((n), 32, 0)#include "etherif.h"#include "etherga620fw.h"enum {	Mhc		= 0x0040,	/* Miscellaneous Host Control */	Mlc		= 0x0044,	/* Miscellaneous Local Control */	Mc		= 0x0050,	/* Miscellaneous Configuration */	Ps		= 0x005C,	/* PCI State */	Wba		= 0x0068,	/* Window Base Address */	Wd		= 0x006C,	/* Window Data */	DMAas		= 0x011C,	/* DMA Assist State */	CPUAstate	= 0x0140,	/* CPU A State */	CPUApc		= 0x0144,	/* CPU A Programme Counter */	CPUBstate	= 0x0240,	/* CPU B State */	Hi		= 0x0504,	/* Host In Interrupt Handler */	Cpi		= 0x050C,	/* Command Producer Index */	Spi		= 0x0514,	/* Send Producer Index */	Rspi		= 0x051C,	/* Receive Standard Producer Index */	Rjpi		= 0x0524,	/* Receive Jumbo Producer Index */	Rmpi		= 0x052C,	/* Receive Mini Producer Index */	Mac		= 0x0600,	/* MAC Address */	Gip		= 0x0608,	/* General Information Pointer */	Om		= 0x0618,	/* Operating Mode */	DMArc		= 0x061C,	/* DMA Read Configuration */	DMAwc		= 0x0620,	/* DMA Write Configuration */	Tbr		= 0x0624,	/* Transmit Buffer Ratio */	Eci		= 0x0628,	/* Event Consumer Index */	Cci		= 0x062C,	/* Command Consumer Index */	Rct		= 0x0630,	/* Receive Coalesced Ticks */	Sct		= 0x0634,	/* Send Coalesced Ticks */	St		= 0x0638,	/* Stat Ticks */	SmcBD		= 0x063C,	/* Send Max. Coalesced BDs */	RmcBD		= 0x0640,	/* Receive Max. Coalesced BDs */	Nt		= 0x0644,	/* NIC Tracing */	Gln		= 0x0648,	/* Gigabit Link Negotiation */	Fln		= 0x064C,	/* 10/100 Link Negotiation */	Ifx		= 0x065C,	/* Interface Index */	IfMTU		= 0x0660,	/* Interface MTU */	Mi		= 0x0664,	/* Mask Interrupts */	Gls		= 0x0668,	/* Gigabit Link State */	Fls		= 0x066C,	/* 10/100 Link State */	Cr		= 0x0700,	/* Command Ring */	Lmw		= 0x0800,	/* Local Memory Window */};enum {					/* Mhc */	Is		= 0x00000001,	/* Interrupt State */	Ci		= 0x00000002,	/* Clear Interrupt */	Hr		= 0x00000008,	/* Hard Reset */	Eebs		= 0x00000010,	/* Enable Endian Byte Swap */	Eews		= 0x00000020,	/* Enable Endian Word (64-bit) swap */	Mpio		= 0x00000040,	/* Mask PCI Interrupt Output */};enum {					/* Mlc */	SRAM512		= 0x00000200,	/* SRAM Bank Size of 512KB */	SRAMmask	= 0x00000300,	EEclk		= 0x00100000,	/* Serial EEPROM Clock Output */	EEdoe		= 0x00200000,	/* Serial EEPROM Data Out Enable */	EEdo		= 0x00400000,	/* Serial EEPROM Data Out Value */	EEdi		= 0x00800000,	/* Serial EEPROM Data Input */};enum {					/* Mc */	SyncSRAM	= 0x00100000,	/* Set Synchronous SRAM Timing */};enum {					/* Ps */	PCIwm32		= 0x000000C0,	/* Write Max DMA 32 */	PCImrm		= 0x00020000,	/* Use Memory Read Multiple Command */	PCI66		= 0x00080000,	PCI32		= 0x00100000,	PCIrcmd		= 0x06000000,	/* PCI Read Command */	PCIwcmd		= 0x70000000,	/* PCI Write Command */};enum {					/* CPUAstate */	CPUrf		= 0x00000010,	/* ROM Fail */	CPUhalt		= 0x00010000,	/* Halt the internal CPU */	CPUhie		= 0x00040000,	/* HALT instruction executed */};enum {					/* Om */	BswapBD		= 0x00000002,	/* Byte Swap Buffer Descriptors */	WswapBD		= 0x00000004,	/* Word Swap Buffer Descriptors */	Warn		= 0x00000008,	BswapDMA	= 0x00000010,	/* Byte Swap DMA Data */	Only1DMA	= 0x00000040,	/* Only One DMA Active at a time */	NoJFrag		= 0x00000200,	/* Don't Fragment Jumbo Frames */	Fatal		= 0x40000000,};enum {					/* Lmw */	Lmwsz		= 2*1024,	/* Local Memory Window Size */	Sr		= 0x3800,	/* Send Ring (accessed via Lmw) */};enum {					/* Link */	Lpref		= 0x00008000,	/* Preferred Link */	L10MB		= 0x00010000,	L100MB		= 0x00020000,	L1000MB		= 0x00040000,	Lfd		= 0x00080000,	/* Full Duplex */	Lhd		= 0x00100000,	/* Half Duplex */	Lefc		= 0x00200000,	/* Emit Flow Control Packets */	Lofc		= 0x00800000,	/* Obey Flow Control Packets */	Lean		= 0x20000000,	/* Enable Autonegotiation/Sensing */	Le		= 0x40000000,	/* Link Enable */};typedef struct Host64 {	uint	hi;	uint	lo;} Host64;typedef struct Ere {			/* Event Ring Element */	int	event;			/* (event<<24)|(code<<12)|index */	int	unused;} Ere;typedef int Cmd;			/* (cmd<<24)|(flags<<12)|index */typedef struct Rbd {			/* Receive Buffer Descriptor */	Host64	addr;	int	indexlen;		/* (ring-index<<16)|buffer-length */	int	flags;			/* only lower 16-bits */	int	checksum;		/* (ip<<16)|tcp/udp */	int	error;			/* only upper 16-bits */	int	reserved;	void*	opaque;			/* passed to receive return ring */} Rbd;typedef struct Sbd {			/* Send Buffer Descriptor */	Host64	addr;	int	lenflags;		/* (len<<16)|flags */	int	reserved;} Sbd;enum {					/* Buffer Descriptor Flags */	Fend		= 0x00000004,	/* Frame Ends in this Buffer */	Frjr		= 0x00000010,	/* Receive Jumbo Ring Buffer */	Funicast	= 0x00000020,	/* Unicast packet (2-bit field) */	Fmulticast	= 0x00000040,	/* Multicast packet */	Fbroadcast	= 0x00000060,	/* Broadcast packet */	Ferror		= 0x00000400,	/* Frame Has Error */	Frmr		= 0x00001000,	/* Receive Mini Ring Buffer */};enum {					/* Buffer Error Flags */	Ecrc		= 0x00010000,	/* bad CRC */	Ecollision	= 0x00020000,	/* collision */	Elink		= 0x00040000,	/* link lost */	Ephy		= 0x00080000,	/* unspecified PHY frame decode error */	Eodd		= 0x00100000,	/* odd number of nibbles */	Emac		= 0x00200000,	/* unspecified MAC abort */	Elen64		= 0x00400000,	/* short packet */	Eresources	= 0x00800000,	/* MAC out of internal resources */	Egiant		= 0x01000000,	/* packet too big */};typedef struct Rcb {			/* Ring Control Block */	Host64	addr;			/* points to the Rbd ring */	int	control;		/* (max_len<<16)|flags */	int	unused;} Rcb;enum {	TcpUdpCksum	= 0x0001,	/* Perform TCP or UDP checksum */	IpCksum		= 0x0002,	/* Perform IP checksum */	NoPseudoHdrCksum= 0x0008,	/* Don't include the pseudo header */	VlanAssist	= 0x0010,	/* Enable VLAN tagging */	CoalUpdateOnly	= 0x0020,	/* Coalesce transmit interrupts */	HostRing	= 0x0040,	/* Sr in host memory */	SnapCksum	= 0x0080,	/* Parse + offload 802.3 SNAP frames */	UseExtRxBd	= 0x0100,	/* Extended Rbd for Jumbo frames */	RingDisabled	= 0x0200,	/* Jumbo or Mini RCB only */};typedef struct Gib {			/* General Information Block */	int	statistics[256];	/* Statistics */	Rcb	ercb;			/* Event Ring */	Rcb	crcb;			/* Command Ring */	Rcb	srcb;			/* Send Ring */	Rcb	rsrcb;			/* Receive Standard Ring */	Rcb	rjrcb;			/* Receive Jumbo Ring */	Rcb	rmrcb;			/* Receive Mini Ring */	Rcb	rrrcb;			/* Receive Return Ring */	Host64	epp;			/* Event Producer */	Host64	rrrpp;			/* Receive Return Ring Producer */	Host64	scp;			/* Send Consumer */	Host64	rsp;			/* Refresh Stats */} Gib;enum {					/* Host/NIC Interface ring sizes */	Ner		= 256,		/* event ring */	Ncr		= 64,		/* command ring */	Nsr		= 512,		/* send ring */	Nrsr		= 512,		/* receive standard ring */	Nrjr		= 256,		/* receive jumbo ring */	Nrmr		= 1024,		/* receive mini ring */	Nrrr		= 2048,		/* receive return ring */};enum {	NrsrHI		= 72,		/* Fill-level of Rsr (m.b. < Nrsr) */	NrsrLO		= 54,		/* Level at which to top-up ring */	NrjrHI		= 0,		/* Fill-level of Rjr (m.b. < Nrjr) */	NrjrLO		= 0,		/* Level at which to top-up ring */	NrmrHI		= 0,		/* Fill-level of Rmr (m.b. < Nrmr) */	NrmrLO		= 0,		/* Level at which to top-up ring */};typedef struct Ctlr Ctlr;typedef struct Ctlr {	int	port;	Pcidev*	pcidev;	Ctlr*	next;	int	active;	int	id;	uchar	ea[Eaddrlen];	int*	nic;	Gib*	gib;	Ere*	er;	Lock	srlock;	Sbd*	sr;	Block**	srb;	int	nsr;			/* currently in send ring */	Rbd*	rsr;	int	nrsr;			/* currently in Receive Standard Ring */	Rbd*	rjr;	int	nrjr;			/* currently in Receive Jumbo Ring */	Rbd*	rmr;	int	nrmr;			/* currently in Receive Mini Ring */	Rbd*	rrr;	int	rrrci;			/* Receive Return Ring Consumer Index */	int	epi[2];			/* Event Producer Index */	int	rrrpi[2];		/* Receive Return Ring Producer Index */	int	sci[3];			/* Send Consumer Index ([2] is host) */	int	interrupts;		/* statistics */	int	mi;	uvlong	ticks;	int	coalupdateonly;		/* tuning */	int	hardwarecksum;	int	rct;			/* Receive Coalesce Ticks */	int	sct;			/* Send Coalesce Ticks */	int	st;			/* Stat Ticks */	int	smcbd;			/* Send Max. Coalesced BDs */	int	rmcbd;			/* Receive Max. Coalesced BDs */} Ctlr;static Ctlr* ctlrhead;static Ctlr* ctlrtail;#define csr32r(c, r)	(*((c)->nic+((r)/4)))#define csr32w(c, r, v)	(*((c)->nic+((r)/4)) = (v))static voidsethost64(Host64* host64, void* addr){	uvlong uvl;	uvl = PCIWADDR(addr);	host64->hi = uvl>>32;	host64->lo = uvl & 0xFFFFFFFFL;}static voidga620command(Ctlr* ctlr, int cmd, int flags, int index){	int cpi;	cpi = csr32r(ctlr, Cpi);	csr32w(ctlr, Cr+(cpi*4), (cmd<<24)|(flags<<12)|index);	cpi = NEXT(cpi, Ncr);	csr32w(ctlr, Cpi, cpi);}static voidga620attach(Ether* edev){	Ctlr *ctlr;	ctlr = edev->ctlr;	USED(ctlr);}static longga620ifstat(Ether* edev, void* a, long n, ulong offset){	char *p;	Ctlr *ctlr;	int i, l, r;	ctlr = edev->ctlr;	if(n == 0)		return 0;	p = malloc(READSTR);	l = 0;	for(i = 0; i < 256; i++){		if((r = ctlr->gib->statistics[i]) == 0)			continue;		l += snprint(p+l, READSTR-l, "%d: %ud\n", i, r);	}	l += snprint(p+l, READSTR-l, "interrupts: %ud\n", ctlr->interrupts);	l += snprint(p+l, READSTR-l, "mi: %ud\n", ctlr->mi);	l += snprint(p+l, READSTR-l, "ticks: %llud\n", ctlr->ticks);	l += snprint(p+l, READSTR-l, "coalupdateonly: %d\n", ctlr->coalupdateonly);	l += snprint(p+l, READSTR-l, "hardwarecksum: %d\n", ctlr->hardwarecksum);	l += snprint(p+l, READSTR-l, "rct: %d\n", ctlr->rct);	l += snprint(p+l, READSTR-l, "sct: %d\n", ctlr->sct);	l += snprint(p+l, READSTR-l, "smcbd: %d\n", ctlr->smcbd);	snprint(p+l, READSTR-l, "rmcbd: %d\n", ctlr->rmcbd);	n = readstr(offset, a, n, p);	free(p);	return n;}static longga620ctl(Ether* edev, void* buf, long n){	char *p;	Cmdbuf *cb;	Ctlr *ctlr;	int control, i, r;	ctlr = edev->ctlr;	if(ctlr == nil)		error(Enonexist);	r = 0;	cb = parsecmd(buf, n);	if(cb->nf < 2)		r = -1;	else if(cistrcmp(cb->f[0], "coalupdateonly") == 0){		if(cistrcmp(cb->f[1], "off") == 0){			control = ctlr->gib->srcb.control;			control &= ~CoalUpdateOnly;			ctlr->gib->srcb.control = control;			ctlr->coalupdateonly = 0;		}		else if(cistrcmp(cb->f[1], "on") == 0){			control = ctlr->gib->srcb.control;			control |= CoalUpdateOnly;			ctlr->gib->srcb.control = control;			ctlr->coalupdateonly = 1;		}		else			r = -1;	}	else if(cistrcmp(cb->f[0], "hardwarecksum") == 0){		if(cistrcmp(cb->f[1], "off") == 0){			control = ctlr->gib->srcb.control;			control &= ~(TcpUdpCksum|NoPseudoHdrCksum);			ctlr->gib->srcb.control = control;			control = ctlr->gib->rsrcb.control;			control &= ~(TcpUdpCksum|NoPseudoHdrCksum);			ctlr->gib->rsrcb.control = control;			ctlr->hardwarecksum = 0;		}		else if(cistrcmp(cb->f[1], "on") == 0){			control = ctlr->gib->srcb.control;			control |= (TcpUdpCksum|NoPseudoHdrCksum);			ctlr->gib->srcb.control = control;			control = ctlr->gib->rsrcb.control;			control |= (TcpUdpCksum|NoPseudoHdrCksum);			ctlr->gib->rsrcb.control = control;			ctlr->hardwarecksum = 1;		}		else			r = -1;	}	else if(cistrcmp(cb->f[0], "rct") == 0){		i = strtol(cb->f[1], &p, 0);		if(i < 0 || p == cb->f[1])			r = -1;		else{			ctlr->rct = i;			csr32w(ctlr, Rct, ctlr->rct);		}	}	else if(cistrcmp(cb->f[0], "sct") == 0){		i = strtol(cb->f[1], &p, 0);		if(i < 0 || p == cb->f[1])			r = -1;		else{			ctlr->sct = i;			csr32w(ctlr, Sct, ctlr->sct);		}	}	else if(cistrcmp(cb->f[0], "st") == 0){		i = strtol(cb->f[1], &p, 0);		if(i < 0 || p == cb->f[1])			r = -1;		else{			ctlr->st = i;			csr32w(ctlr, St, ctlr->st);		}	}	else if(cistrcmp(cb->f[0], "smcbd") == 0){		i = strtol(cb->f[1], &p, 0);		if(i < 0 || p == cb->f[1])			r = -1;		else{			ctlr->smcbd = i;			csr32w(ctlr, SmcBD, ctlr->smcbd);		}	}	else if(cistrcmp(cb->f[0], "rmcbd") == 0){		i = strtol(cb->f[1], &p, 0);		if(i < 0 || p == cb->f[1])			r = -1;		else{			ctlr->rmcbd = i;			csr32w(ctlr, RmcBD, ctlr->rmcbd);		}	}	else		r = -1;	free(cb);	if(r == 0)		return n;	return r;}static int_ga620transmit(Ether* edev){	Sbd *sbd;	Block *bp;	Ctlr *ctlr;	int sci, spi, work;	/*	 * For now there are no smarts here, just empty the	 * ring and try to fill it back up. Tuning comes later.	 */	ctlr = edev->ctlr;	ilock(&ctlr->srlock);	/*	 * Free any completed packets.	 * Ctlr->sci[0] is where the NIC has got to consuming the ring.	 * Ctlr->sci[2] is where the host has got to tidying up after the	 * NIC has done with the packets.	 */	work = 0;	for(sci = ctlr->sci[2]; sci != ctlr->sci[0]; sci = NEXT(sci, Nsr)){		if(ctlr->srb[sci] == nil)			continue;		freeb(ctlr->srb[sci]);		ctlr->srb[sci] = nil;		work++;	}	ctlr->sci[2] = sci;	sci = PREV(sci, Nsr);	for(spi = csr32r(ctlr, Spi); spi != sci; spi = NEXT(spi, Nsr)){		if((bp = qget(edev->oq)) == nil)			break;		sbd = &ctlr->sr[spi];		sethost64(&sbd->addr, bp->rp);		sbd->lenflags = (BLEN(bp)<<16)|Fend;		ctlr->srb[spi] = bp;		work++;	}	csr32w(ctlr, Spi, spi);	iunlock(&ctlr->srlock);	return work;}static voidga620transmit(Ether* edev){	_ga620transmit(edev);}static voidga620replenish(Ctlr* ctlr){	Rbd *rbd;	int rspi;	Block *bp;	rspi = csr32r(ctlr, Rspi);	while(ctlr->nrsr < NrsrHI){		if((bp = iallocb(ETHERMAXTU+4)) == nil)			break;		rbd = &ctlr->rsr[rspi];		sethost64(&rbd->addr, bp->rp);		rbd->indexlen = (rspi<<16)|(ETHERMAXTU+4);		rbd->flags = 0;		rbd->opaque = bp;		rspi = NEXT(rspi, Nrsr);		ctlr->nrsr++;	}	csr32w(ctlr, Rspi, rspi);}static voidga620event(Ctlr* ctlr, int eci, int epi){	int event;	while(eci != epi){		event = ctlr->er[eci].event;		switch(event>>24){		case 0x01:		/* firmware operational */			ga620command(ctlr, 0x01, 0x01, 0x00);			ga620command(ctlr, 0x0B, 0x00, 0x00);print("%8.8uX: %8.8uX\n", ctlr->port, event);			break;		case 0x04:		/* statistics updated */			break;		case 0x06:		/* link state changed */print("%8.8uX: %8.8uX %8.8uX %8.8uX\n",    ctlr->port, event, csr32r(ctlr, Gls), csr32r(ctlr, Fls));			break;		case 0x07:		/* event error */		default:			print("er[%d] = %8.8uX\n", eci, event);			break;		}		eci = NEXT(eci, Ner);	}	csr32w(ctlr, Eci, eci);}static voidga620receive(Ether* edev){	int len;	Rbd *rbd;	Block *bp;	Ctlr* ctlr;	ctlr = edev->ctlr;	while(ctlr->rrrci != ctlr->rrrpi[0]){		rbd = &ctlr->rrr[ctlr->rrrci];		/*		 * Errors are collected in the statistics block so		 * no need to tally them here, let ifstat do the work.		 */		len = rbd->indexlen & 0xFFFF;		if(!(rbd->flags & Ferror) && len != 0){			bp = rbd->opaque;			bp->wp = bp->rp+len;			etheriq(edev, bp, 1);		}		else			freeb(rbd->opaque);		rbd->opaque = nil;		if(rbd->flags & Frjr)			ctlr->nrjr--;		else if(rbd->flags & Frmr)			ctlr->nrmr--;		else			ctlr->nrsr--;		ctlr->rrrci = NEXT(ctlr->rrrci, Nrrr);

⌨️ 快捷键说明

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