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

📄 ether82557.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Intel 82557 Fast Ethernet PCI Bus LAN Controller * as found on the Intel EtherExpress PRO/100B. This chip is full * of smarts, unfortunately none of them are in the right place. * To do: *	the PCI scanning code could be made common to other adapters; *	PCI code needs rewritten to handle byte, word, dword accesses *	  and using the devno as a bus+dev+function triplet. */#include "u.h"#include "lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "etherif.h"enum {	Nrfd		= 4,		/* receive frame area */	NullPointer	= 0xFFFFFFFF,	/* 82557 NULL pointer */};enum {					/* CSR */	Status		= 0x00,		/* byte or word (word includes Ack) */	Ack		= 0x01,		/* byte */	CommandR	= 0x02,		/* byte or word (word includes Interrupt) */	Interrupt	= 0x03,		/* byte */	Pointer		= 0x04,		/* dword */	Port		= 0x08,		/* dword */	Fcr		= 0x0C,		/* Flash control register */	Ecr		= 0x0E,		/* EEPROM control register */	Mcr		= 0x10,		/* MDI control register */};enum {					/* Status */	RUidle		= 0x0000,	RUsuspended	= 0x0004,	RUnoresources	= 0x0008,	RUready		= 0x0010,	RUrbd		= 0x0020,	/* bit */	RUstatus	= 0x003F,	/* mask */	CUidle		= 0x0000,	CUsuspended	= 0x0040,	CUactive	= 0x0080,	CUstatus	= 0x00C0,	/* mask */	StatSWI		= 0x0400,	/* SoftWare generated Interrupt */	StatMDI		= 0x0800,	/* MDI r/w done */	StatRNR		= 0x1000,	/* Receive unit Not Ready */	StatCNA		= 0x2000,	/* Command unit Not Active (Active->Idle) */	StatFR		= 0x4000,	/* Finished Receiving */	StatCX		= 0x8000,	/* Command eXecuted */	StatTNO		= 0x8000,	/* Transmit NOT OK */};enum {					/* Command (byte) */	CUnop		= 0x00,	CUstart		= 0x10,	CUresume	= 0x20,	LoadDCA		= 0x40,		/* Load Dump Counters Address */	DumpSC		= 0x50,		/* Dump Statistical Counters */	LoadCUB		= 0x60,		/* Load CU Base */	ResetSA		= 0x70,		/* Dump and Reset Statistical Counters */	RUstart		= 0x01,	RUresume	= 0x02,	RUabort		= 0x04,	LoadHDS		= 0x05,		/* Load Header Data Size */	LoadRUB		= 0x06,		/* Load RU Base */	RBDresume	= 0x07,		/* Resume frame reception */};enum {					/* Interrupt (byte) */	InterruptM	= 0x01,		/* interrupt Mask */	InterruptSI	= 0x02,		/* Software generated Interrupt */};enum {					/* Ecr */	EEsk		= 0x01,		/* serial clock */	EEcs		= 0x02,		/* chip select */	EEdi		= 0x04,		/* serial data in */	EEdo		= 0x08,		/* serial data out */	EEstart		= 0x04,		/* start bit */	EEread		= 0x02,		/* read opcode */	EEaddrsz	= 6,		/* bits of address */};enum {					/* Mcr */	MDIread		= 0x08000000,	/* read opcode */	MDIwrite	= 0x04000000,	/* write opcode */	MDIready	= 0x10000000,	/* ready bit */	MDIie		= 0x20000000,	/* interrupt enable */};typedef struct Rfd {	int	field;	ulong	link;	ulong	rbd;	ushort	count;	ushort	size;	Etherpkt;} Rfd;enum {					/* field */	RfdCollision	= 0x00000001,	RfdIA		= 0x00000002,	/* IA match */	RfdRxerr	= 0x00000010,	/* PHY character error */	RfdType		= 0x00000020,	/* Type frame */	RfdRunt		= 0x00000080,	RfdOverrun	= 0x00000100,	RfdBuffer	= 0x00000200,	RfdAlignment	= 0x00000400,	RfdCRC		= 0x00000800,	RfdOK		= 0x00002000,	/* frame received OK */	RfdC		= 0x00008000,	/* reception Complete */	RfdSF		= 0x00080000,	/* Simplified or Flexible (1) Rfd */	RfdH		= 0x00100000,	/* Header RFD */	RfdI		= 0x20000000,	/* Interrupt after completion */	RfdS		= 0x40000000,	/* Suspend after completion */	RfdEL		= 0x80000000,	/* End of List */};enum {					/* count */	RfdF		= 0x00004000,	RfdEOF		= 0x00008000,};typedef struct Cb {	int	command;	ulong	link;	uchar	data[24];	/* CbIAS + CbConfigure */} Cb;typedef struct TxCB {	int	command;	ulong	link;	ulong	tbd;	ushort	count;	uchar	threshold;	uchar	number;} TxCB;enum {					/* action command */	CbOK		= 0x00002000,	/* DMA completed OK */	CbC		= 0x00008000,	/* execution Complete */	CbNOP		= 0x00000000,	CbIAS		= 0x00010000,	/* Indvidual Address Setup */	CbConfigure	= 0x00020000,	CbMAS		= 0x00030000,	/* Multicast Address Setup */	CbTransmit	= 0x00040000,	CbDump		= 0x00060000,	CbDiagnose	= 0x00070000,	CbCommand	= 0x00070000,	/* mask */	CbSF		= 0x00080000,	/* CbTransmit */	CbI		= 0x20000000,	/* Interrupt after completion */	CbS		= 0x40000000,	/* Suspend after completion */	CbEL		= 0x80000000,	/* End of List */};enum {					/* CbTransmit count */	CbEOF		= 0x00008000,};typedef struct Ctlr {	int	port;	ushort	eeprom[0x40];	int	ctlrno;	char*	type;	uchar	configdata[24];	Rfd	rfd[Nrfd];	int	rfdl;	int	rfdx;	Block*	cbqhead;	Block*	cbqtail;	int	cbqbusy;} Ctlr;static uchar configdata[24] = {	0x16,				/* byte count */	0x44,				/* Rx/Tx FIFO limit */	0x00,				/* adaptive IFS */	0x00,		0x04,				/* Rx DMA maximum byte count */	0x84,				/* Tx DMA maximum byte count */	0x33,				/* late SCB, CNA interrupts */	0x01,				/* discard short Rx frames */	0x00,				/* 503/MII */	0x00,		0x2E,				/* normal operation, NSAI */	0x00,				/* linear priority */	0x60,				/* inter-frame spacing */	0x00,		0xF2,		0x48,				/* promiscuous mode off */	0x00,		0x40,		0xF2,				/* transmit padding enable */	0x80,				/* full duplex pin enable */	0x3F,				/* no Multi IA */	0x05,				/* no Multi Cast ALL */};#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 voidcustart(Ctlr* ctlr){	if(ctlr->cbqhead == 0){		ctlr->cbqbusy = 0;		return;	}	ctlr->cbqbusy = 1;	csr32w(ctlr, Pointer, PADDR(ctlr->cbqhead->rp));	while(csr8r(ctlr, CommandR))		;	csr8w(ctlr, CommandR, CUstart);}static voidaction(Ctlr* ctlr, Block* bp){	Cb *cb;	cb = (Cb*)bp->rp;	cb->command |= CbEL;	if(ctlr->cbqhead){		ctlr->cbqtail->next = bp;		cb = (Cb*)ctlr->cbqtail->rp;		cb->link = PADDR(bp->rp);		cb->command &= ~CbEL;	}	else		ctlr->cbqhead = bp;	ctlr->cbqtail = bp;	if(ctlr->cbqbusy == 0)		custart(ctlr);}static voidattach(Ether* ether){	int status;	Ctlr *ctlr;	ctlr = ether->ctlr;	status = csr16r(ctlr, Status);	if((status & RUstatus) == RUidle){		csr32w(ctlr, Pointer, PADDR(&ctlr->rfd[ctlr->rfdx]));		while(csr8r(ctlr, CommandR))			;		csr8w(ctlr, CommandR, RUstart);	}}static voidconfigure(void* arg, int promiscuous){	Ctlr *ctlr;	Block *bp;	Cb *cb;	ctlr = ((Ether*)arg)->ctlr;	bp = allocb(sizeof(Cb));	cb = (Cb*)bp->rp;	bp->wp += sizeof(Cb);	cb->command = CbConfigure;	cb->link = NullPointer;	memmove(cb->data, ctlr->configdata, sizeof(ctlr->configdata));	if(promiscuous)		cb->data[15] |= 0x01;	action(ctlr, bp);}static voidtransmit(Ether* ether){	Block *bp;	TxCB *txcb;	RingBuf *tb;	for(tb = &ether->tb[ether->ti]; tb->owner == Interface; tb = &ether->tb[ether->ti]){		bp = allocb(tb->len+sizeof(TxCB));		txcb = (TxCB*)bp->wp;		bp->wp += sizeof(TxCB);		txcb->command = CbTransmit;		txcb->link = NullPointer;		txcb->tbd = NullPointer;		txcb->count = CbEOF|tb->len;		txcb->threshold = 2;		txcb->number = 0;		memmove(bp->wp, tb->pkt, tb->len);		memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);		bp->wp += tb->len;		action(ether->ctlr, bp);		tb->owner = Host;		ether->ti = NEXT(ether->ti, ether->ntb);	}}static voidinterrupt(Ureg*, void* arg){	Rfd *rfd;	Block *bp;	Ctlr *ctlr;	Ether *ether;	int status;	RingBuf *rb;	ether = arg;	ctlr = ether->ctlr;	for(;;){		status = csr16r(ctlr, Status);		csr8w(ctlr, Ack, (status>>8) & 0xFF);		if((status & (StatCX|StatFR|StatCNA|StatRNR)) == 0)			return;		if(status & StatFR){			rfd = &ctlr->rfd[ctlr->rfdx];			while(rfd->field & RfdC){				rb = &ether->rb[ether->ri];				if(rb->owner == Interface){					rb->owner = Host;					rb->len = rfd->count & 0x3FFF;					memmove(rb->pkt, rfd->d, rfd->count & 0x3FFF);					ether->ri = NEXT(ether->ri, ether->nrb);				}				/*				 * Reinitialise the frame for reception and bump				 * the receive frame processing index;				 * bump the sentinel index, mark the new sentinel				 * and clear the old sentinel suspend bit;				 * set bp and rfd for the next receive frame to				 * process.				 */				rfd->field = 0;				rfd->count = 0;				ctlr->rfdx = NEXT(ctlr->rfdx, Nrfd);				rfd = &ctlr->rfd[ctlr->rfdl];				ctlr->rfdl = NEXT(ctlr->rfdl, Nrfd);				ctlr->rfd[ctlr->rfdl].field |= RfdS;				rfd->field &= ~RfdS;				rfd = &ctlr->rfd[ctlr->rfdx];			}			status &= ~StatFR;		}		if(status & StatRNR){			while(csr8r(ctlr, CommandR))				;			csr8w(ctlr, CommandR, RUresume);			status &= ~StatRNR;		}		if(status & StatCNA){			while(bp = ctlr->cbqhead){				if((((Cb*)bp->rp)->command & CbC) == 0)					break;				ctlr->cbqhead = bp->next;				freeb(bp);			}			custart(ctlr);			status &= ~StatCNA;		}		if(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI))			panic("%s#%d: status %uX\n", ctlr->type,  ctlr->ctlrno, status);	}}static voidctlrinit(Ctlr* ctlr){	int i;	Rfd *rfd;	ulong link;	link = NullPointer;	for(i = Nrfd-1; i >= 0; i--){		rfd = &ctlr->rfd[i];		rfd->field = 0;		rfd->link = link;		link = PADDR(rfd);		rfd->rbd = NullPointer;		rfd->count = 0;		rfd->size = sizeof(Etherpkt);	}	ctlr->rfd[Nrfd-1].link = PADDR(&ctlr->rfd[0]);

⌨️ 快捷键说明

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