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

📄 etherelnk3.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Etherlink III and Fast EtherLink adapters. * To do: *	autoSelect; *	busmaster channel; *	PCMCIA; *	PCI latency timer and master enable; *	errata list. * * Product ID: *	9150 ISA	3C509[B] *	9050 ISA	3C509[B]-TP *	9450 ISA	3C509[B]-COMBO *	9550 ISA	3C509[B]-TPO * *	9350 EISA	3C579 *	9250 EISA	3C579-TP * *	5920 EISA	3C592-[TP|COMBO|TPO] *	5970 EISA	3C597-TX	Fast Etherlink 10BASE-T/100BASE-TX *	5971 EISA	3C597-T4	Fast Etherlink 10BASE-T/100BASE-T4 *	5972 EISA	3C597-MII	Fast Etherlink 10BASE-T/MII * *	5900 PCI	3C590-[TP|COMBO|TPO] *	5950 PCI	3C595-TX	Fast Etherlink Shared 10BASE-T/100BASE-TX *	5951 PCI	3C595-T4	Fast Etherlink Shared 10BASE-T/100BASE-T4 *	5952 PCI	3C595-MII	Fast Etherlink 10BASE-T/MII * *	9058 PCMCIA	3C589[B]-[TP|COMBO] * *	627C MCA	3C529 *	627D MCA	3C529-TP */#include "u.h"#include "lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "etherif.h"enum {	IDport			= 0x0110,	/* anywhere between 0x0100 and 0x01F0 */};enum {						/* all windows */	CommandR		= 0x000E,	IntStatus		= 0x000E,};enum {						/* Commands */	GlobalReset		= 0x0000,	SelectRegisterWindow	= 0x0001,	EnableDcConverter	= 0x0002,	RxDisable		= 0x0003,	RxEnable		= 0x0004,	RxReset			= 0x0005,	Stall			= 0x0006,	/* 3C90x */	TxDone			= 0x0007,	RxDiscard		= 0x0008,	TxEnable		= 0x0009,	TxDisable		= 0x000A,	TxReset			= 0x000B,	RequestInterrupt	= 0x000C,	AcknowledgeInterrupt	= 0x000D,	SetInterruptEnable	= 0x000E,	SetIndicationEnable	= 0x000F,	/* SetReadZeroMask */	SetRxFilter		= 0x0010,	SetRxEarlyThresh	= 0x0011,	SetTxAvailableThresh	= 0x0012,	SetTxStartThresh	= 0x0013,	StartDma		= 0x0014,	/* initiate busmaster operation */	StatisticsEnable	= 0x0015,	StatisticsDisable	= 0x0016,	DisableDcConverter	= 0x0017,	SetTxReclaimThresh	= 0x0018,	/* PIO-only adapters */	PowerUp			= 0x001B,	/* not all adapters */	PowerDownFull		= 0x001C,	/* not all adapters */	PowerAuto		= 0x001D,	/* not all adapters */};enum {						/* (Global|Rx|Tx)Reset command bits */	tpAuiReset		= 0x0001,	/* 10BaseT and AUI transceivers */	endecReset		= 0x0002,	/* internal Ethernet encoder/decoder */	networkReset		= 0x0004,	/* network interface logic */	fifoReset		= 0x0008,	/* FIFO control logic */	aismReset		= 0x0010,	/* autoinitialise state-machine logic */	hostReset		= 0x0020,	/* bus interface logic */	dmaReset		= 0x0040,	/* bus master logic */	vcoReset		= 0x0080,	/* on-board 10Mbps VCO */	updnReset		= 0x0100,	/* upload/download (Rx/TX) logic */	resetMask		= 0x01FF,};enum {						/* Stall command bits */	upStall			= 0x0000,	upUnStall		= 0x0001,	dnStall			= 0x0002,	dnUnStall		= 0x0003,};enum {						/* SetRxFilter command bits */	receiveIndividual	= 0x0001,	/* match station address */	receiveMulticast	= 0x0002,	receiveBroadcast	= 0x0004,	receiveAllFrames	= 0x0008,	/* promiscuous */};enum {						/* StartDma command bits */	Upload			= 0x0000,	/* transfer data from adapter to memory */	Download		= 0x0001,	/* transfer data from memory to adapter */};enum {						/* IntStatus bits */	interruptLatch		= 0x0001,	hostError		= 0x0002,	/* Adapter Failure */	txComplete		= 0x0004,	txAvailable		= 0x0008,	rxComplete		= 0x0010,	rxEarly			= 0x0020,	intRequested		= 0x0040,	updateStats		= 0x0080,	transferInt		= 0x0100,	/* Bus Master Transfer Complete */	dnComplete		= 0x0200,	upComplete		= 0x0400,	busMasterInProgress	= 0x0800,	commandInProgress	= 0x1000,	interruptMask		= 0x07FE,};#define COMMAND(port, cmd, a)	outs((port)+CommandR, ((cmd)<<11)|(a))#define STATUS(port)		ins((port)+IntStatus)enum {						/* Window 0 - setup */	Wsetup			= 0x0000,						/* registers */	ManufacturerID		= 0x0000,	/* 3C5[08]*, 3C59[27] */	ProductID		= 0x0002,	/* 3C5[08]*, 3C59[27] */	ConfigControl		= 0x0004,	/* 3C5[08]*, 3C59[27] */	AddressConfig		= 0x0006,	/* 3C5[08]*, 3C59[27] */	ResourceConfig		= 0x0008,	/* 3C5[08]*, 3C59[27] */	EepromCommand		= 0x000A,	EepromData		= 0x000C,						/* AddressConfig Bits */	autoSelect9		= 0x0080,	xcvrMask9		= 0xC000,						/* ConfigControl bits */	Ena			= 0x0001,	base10TAvailable9	= 0x0200,	coaxAvailable9		= 0x1000,	auiAvailable9		= 0x2000,						/* EepromCommand bits */	EepromReadRegister	= 0x0080,	EepromBusy		= 0x8000,};#define EEPROMCMD(port, cmd, a)	outs((port)+EepromCommand, (cmd)|(a))#define EEPROMBUSY(port)	(ins((port)+EepromCommand) & EepromBusy)#define EEPROMDATA(port)	ins((port)+EepromData)enum {						/* Window 1 - operating set */	Wop			= 0x0001,						/* registers */	Fifo			= 0x0000,	RxError			= 0x0004,	/* 3C59[0257] only */	RxStatus		= 0x0008,	Timer			= 0x000A,	TxStatus		= 0x000B,	TxFree			= 0x000C,						/* RxError bits */	rxOverrun		= 0x0001,	runtFrame		= 0x0002,	alignmentError		= 0x0004,	/* Framing */	crcError		= 0x0008,	oversizedFrame		= 0x0010,	dribbleBits		= 0x0080,						/* RxStatus bits */	rxBytes			= 0x1FFF,	/* 3C59[0257] mask */	rxBytes9		= 0x07FF,	/* 3C5[078]9 mask */	rxError9		= 0x3800,	/* 3C5[078]9 error mask */	rxOverrun9		= 0x0000,	oversizedFrame9		= 0x0800,	dribbleBits9		= 0x1000,	runtFrame9		= 0x1800,	alignmentError9		= 0x2000,	/* Framing */	crcError9		= 0x2800,	rxError			= 0x4000,	rxIncomplete		= 0x8000,						/* TxStatus Bits */	txStatusOverflow	= 0x0004,	maxCollisions		= 0x0008,	txUnderrun		= 0x0010,	txJabber		= 0x0020,	interruptRequested	= 0x0040,	txStatusComplete	= 0x0080,};enum {						/* Window 2 - station address */	Wstation		= 0x0002,};enum {						/* Window 3 - FIFO management */	Wfifo			= 0x0003,						/* registers */	InternalConfig		= 0x0000,	/* 3C509B, 3C589, 3C59[0257] */	OtherInt		= 0x0004,	/* 3C59[0257] */	RomControl		= 0x0006,	/* 3C509B, 3C59[27] */	MacControl		= 0x0006,	/* 3C59[0257] */	ResetOptions		= 0x0008,	/* 3C59[0257] */	RxFree			= 0x000A,						/* InternalConfig bits */	disableBadSsdDetect	= 0x00000100,	ramLocation		= 0x00000200,	/* 0 external, 1 internal */	ramPartition5to3	= 0x00000000,	ramPartition3to1	= 0x00010000,	ramPartition1to1	= 0x00020000,	ramPartition3to5	= 0x00030000,	ramPartitionMask	= 0x00030000,	xcvr10BaseT		= 0x00000000,	xcvrAui			= 0x00100000,	/* 10BASE5 */	xcvr10Base2		= 0x00300000,	xcvr100BaseTX		= 0x00400000,	xcvr100BaseFX		= 0x00500000,	xcvrMii			= 0x00600000,	xcvrMask		= 0x00700000,	autoSelect		= 0x01000000,						/* MacControl bits */	deferExtendEnable	= 0x0001,	deferTimerSelect	= 0x001E,	/* mask */	fullDuplexEnable	= 0x0020,	allowLargePackets	= 0x0040,						/* ResetOptions bits */	baseT4Available		= 0x0001,	baseTXAvailable		= 0x0002,	baseFXAvailable		= 0x0004,	base10TAvailable	= 0x0008,	coaxAvailable		= 0x0010,	auiAvailable		= 0x0020,	miiConnector		= 0x0040,};enum {						/* Window 4 - diagnostic */	Wdiagnostic		= 0x0004,						/* registers */	VcoDiagnostic		= 0x0002,	FifoDiagnostic		= 0x0004,	NetworkDiagnostic	= 0x0006,	PhysicalMgmt		= 0x0008,	MediaStatus		= 0x000A,	BadSSD			= 0x000C,						/* FifoDiagnostic bits */	txOverrun		= 0x0400,	rxUnderrun		= 0x2000,	receiving		= 0x8000,						/* PhysicalMgmt bits */	mgmtClk			= 0x0001,	mgmtData		= 0x0002,	mgmtDir			= 0x0004,	cat5LinkTestDefeat	= 0x8000,						/* MediaStatus bits */	dataRate100		= 0x0002,	crcStripDisable		= 0x0004,	enableSqeStats		= 0x0008,	collisionDetect		= 0x0010,	carrierSense		= 0x0020,	jabberGuardEnable	= 0x0040,	linkBeatEnable		= 0x0080,	jabberDetect		= 0x0200,	polarityReversed	= 0x0400,	linkBeatDetect		= 0x0800,	txInProg		= 0x1000,	dcConverterEnabled	= 0x4000,	auiDisable		= 0x8000,};enum {						/* Window 5 - internal state */	Wstate			= 0x0005,						/* registers */	TxStartThresh		= 0x0000,	TxAvalableThresh	= 0x0002,	RxEarlyThresh		= 0x0006,	RxFilter		= 0x0008,	InterruptEnable		= 0x000A,	IndicationEnable	= 0x000C,};enum {						/* Window 6 - statistics */	Wstatistics		= 0x0006,						/* registers */	CarrierLost		= 0x0000,	SqeErrors		= 0x0001,	MultipleColls		= 0x0002,	SingleCollFrames	= 0x0003,	LateCollisions		= 0x0004,	RxOverruns		= 0x0005,	FramesXmittedOk		= 0x0006,	FramesRcvdOk		= 0x0007,	FramesDeferred		= 0x0008,	UpperFramesOk		= 0x0009,	BytesRcvdOk		= 0x000A,	BytesXmittedOk		= 0x000C,};enum {						/* Window 7 - bus master operations */	Wmaster			= 0x0007,						/* registers */	MasterAddress		= 0x0000,	MasterLen		= 0x0006,	MasterStatus		= 0x000C,						/* MasterStatus bits */	masterAbort		= 0x0001,	targetAbort		= 0x0002,	targetRetry		= 0x0004,	targetDisc		= 0x0008,	masterDownload		= 0x1000,	masterUpload		= 0x4000,	masterInProgress	= 0x8000,	masterMask		= 0xD00F,};	enum {						/* 3C90x extended register set */	PktStatus		= 0x0020,	/* 32-bits */	DnListPtr		= 0x0024,	/* 32-bits, 8-byte aligned */	FragAddr		= 0x0028,	/* 32-bits */	FragLen			= 0x002C,	/* 16-bits */	ListOffset		= 0x002E,	/* 8-bits */	TxFreeThresh		= 0x002F,	/* 8-bits */	UpPktStatus		= 0x0030,	/* 32-bits */	FreeTimer		= 0x0034,	/* 16-bits */	UpListPtr		= 0x0038,	/* 32-bits, 8-byte aligned */						/* PktStatus bits */	fragLast		= 0x00000001,	dnCmplReq		= 0x00000002,	dnStalled		= 0x00000004,	upCompleteX		= 0x00000008,	dnCompleteX		= 0x00000010,	upRxEarlyEnable		= 0x00000020,	armCountdown		= 0x00000040,	dnInProg		= 0x00000080,	counterSpeed		= 0x00000010,	/* 0 3.2uS, 1 320nS */	countdownMode		= 0x00000020,						/* UpPktStatus bits (dpd->control) */	upPktLenMask		= 0x00001FFF,	upStalled		= 0x00002000,	upError			= 0x00004000,	upPktComplete		= 0x00008000,	upOverrun		= 0x00010000,	/* RxError<<16 */	upRuntFrame		= 0x00020000,	upAlignmentError	= 0x00040000,	upCRCError		= 0x00080000,	upOversizedFrame	= 0x00100000,	upDribbleBits		= 0x00800000,	upOverflow		= 0x01000000,	dnIndicate		= 0x80000000,	/* FrameStartHeader (dpd->control) */	updnLastFrag		= 0x80000000,	/* (dpd->len) */	Nup			= 16,	Ndn			= 4,};/* * Up/Dn Packet Descriptors. * The hardware info (np, control, addr, len) must be 8-byte aligned * and this structure size must be a multiple of 8. */typedef struct Pd Pd;typedef struct Pd {	ulong	np;			/* next pointer */	ulong	control;		/* FSH or UpPktStatus */	ulong	addr;	ulong	len;	Pd*	next;	void*	vaddr;} Pd;typedef struct {	Lock	wlock;	int	busmaster;	int	txthreshold;	int	nup;			/* full-busmaster -based reception */	void*	upbase;	Pd*	upr;	Pd*	uphead;	int	ndn;			/* full-busmaster -based transmission */	void*	dnbase;	Pd*	dnr;	Pd*	dnhead;	Pd*	dntail;	int	dnq;	int	xcvr;			/* transceiver type */	int	rxstatus9;		/* old-style RxStatus register */	int	rxearly;		/* RxEarlyThreshold */	int	ts;			/* threshold shift */} Ctlr;static voidinit905(Ctlr* ctlr){	Pd *pd, *prev;	uchar *vaddr;	/*	 * Create rings for the receive and transmit sides.	 * Take care with alignment:	 *	make sure ring base is 8-byte aligned;	 *	make sure each entry is 8-byte aligned.	 */	ctlr->upr = ialloc(ctlr->nup*sizeof(Pd), 8);	vaddr = ialloc(ctlr->nup*ROUNDUP(sizeof(Etherpkt)+4, 8), 8);	prev = ctlr->upr;	for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){		pd->np = PADDR(&prev->np);		pd->control = 0;		pd->vaddr = vaddr;		pd->addr = PADDR(vaddr);		vaddr += ROUNDUP(sizeof(Etherpkt)+4, 8);		pd->len = updnLastFrag|sizeof(Etherpkt);		pd->next = prev;		prev = pd;	}	ctlr->uphead = ctlr->upr;	ctlr->dnr = ialloc(ctlr->ndn*sizeof(Pd), 8);	prev = ctlr->dnr;	for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){		pd->next = prev;		prev = pd;	}	ctlr->dnhead = ctlr->dnr;	ctlr->dntail = ctlr->dnr;	ctlr->dnq = 0;}static voidattach(Ether* ether){	Ctlr *ctlr;	int port, x;	ctlr = ether->ctlr;	port = ether->port;	/*	 * Set the receiver packet filter for this and broadcast addresses,	 * set the interrupt masks for all interrupts, enable the receiver	 * and transmitter.	 */	x = receiveBroadcast|receiveIndividual;	COMMAND(port, SetRxFilter, x);	x = interruptMask;	if(ctlr->busmaster == 2)		x &= ~(transferInt|rxEarly|rxComplete);	COMMAND(port, SetIndicationEnable, x);	COMMAND(port, SetInterruptEnable, x);	COMMAND(port, RxEnable, 0);	COMMAND(port, TxEnable, 0);	if(ctlr->busmaster == 2)		outl(port+UpListPtr, PADDR(&ctlr->uphead->np));}static voidtxstart(Ether* ether){	int port, len;	RingBuf *tb;	/*	 * Attempt to top-up the transmit FIFO. If there's room simply	 * stuff in the packet length (unpadded to a dword boundary), the	 * packet data (padded) and remove the packet from the queue.	 * If there's no room post an interrupt for when there is.	 * This routine is called both from the top level and from interrupt	 * level.	 */	port = ether->port;	for(tb = &ether->tb[ether->ti]; tb->owner == Interface; tb = &ether->tb[ether->ti]){		if(debug) print("transmit...");		len = ROUNDUP(tb->len, 4);		if(len+4 <= ins(port+TxFree)){			outl(port+Fifo, tb->len);			if(debug) print("send...");			outsl(port+Fifo, tb->pkt, len/4);			tb->owner = Host;			ether->ti = NEXT(ether->ti, ether->ntb);		}		else{			if(debug) print("setthresh...");			COMMAND(port, SetTxAvailableThresh, len);			break;		}	}}static voidtxstart905(Ether* ether){	Ctlr *ctlr;	int port, stalled, timeo;	RingBuf *tb;	Pd *pd;	ctlr = ether->ctlr;	port = ether->port;	/*

⌨️ 快捷键说明

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