natsemi.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,270 行 · 第 1/5 页

C
2,270
字号
/* natsemi.c: A Linux PCI Ethernet driver for the NatSemi DP8381x series. *//*	Written/copyright 1999-2001 by Donald Becker.	Portions copyright (c) 2001,2002 Sun Microsystems (thockin@sun.com)	Portions copyright 2001,2002 Manfred Spraul (manfred@colorfullife.com)	This software may be used and distributed according to the terms of	the GNU General Public License (GPL), incorporated herein by reference.	Drivers based on or derived from this code fall under the GPL and must	retain the authorship, copyright and license notice.  This file is not	a complete program and may only be used when the entire operating	system is licensed under the GPL.  License for under other terms may be	available.  Contact the original author for details.	The original author may be reached as becker@scyld.com, or at	Scyld Computing Corporation	410 Severn Ave., Suite 210	Annapolis MD 21403	Support information and updates available at	http://www.scyld.com/network/netsemi.html	Linux kernel modifications:	Version 1.0.1:		- Spinlock fixes		- Bug fixes and better intr performance (Tjeerd)	Version 1.0.2:		- Now reads correct MAC address from eeprom	Version 1.0.3:		- Eliminate redundant priv->tx_full flag		- Call netif_start_queue from dev->tx_timeout		- wmb() in start_tx() to flush data		- Update Tx locking		- Clean up PCI enable (davej)	Version 1.0.4:		- Merge Donald Becker's natsemi.c version 1.07	Version 1.0.5:		- { fill me in }	Version 1.0.6:		* ethtool support (jgarzik)		* Proper initialization of the card (which sometimes		fails to occur and leaves the card in a non-functional		state). (uzi)		* Some documented register settings to optimize some		of the 100Mbit autodetection circuitry in rev C cards. (uzi)		* Polling of the PHY intr for stuff like link state		change and auto- negotiation to finally work properly. (uzi)		* One-liner removal of a duplicate declaration of		netdev_error(). (uzi)	Version 1.0.7: (Manfred Spraul)		* pci dma		* SMP locking update		* full reset added into tx_timeout		* correct multicast hash generation (both big and little endian)			[copied from a natsemi driver version			 from Myrio Corporation, Greg Smith]		* suspend/resume	version 1.0.8 (Tim Hockin <thockin@sun.com>)		* ETHTOOL_* support		* Wake on lan support (Erik Gilling)		* MXDMA fixes for serverworks		* EEPROM reload	version 1.0.9 (Manfred Spraul)		* Main change: fix lack of synchronize		netif_close/netif_suspend against a last interrupt		or packet.		* do not enable superflous interrupts (e.g. the		drivers relies on TxDone - TxIntr not needed)		* wait that the hardware has really stopped in close		and suspend.		* workaround for the (at least) gcc-2.95.1 compiler		problem. Also simplifies the code a bit.		* disable_irq() in tx_timeout - needed to protect		against rx interrupts.		* stop the nic before switching into silent rx mode		for wol (required according to docu).	version 1.0.10:		* use long for ee_addr (various)		* print pointers properly (DaveM)		* include asm/irq.h (?)	version 1.0.11:		* check and reset if PHY errors appear (Adrian Sun)		* WoL cleanup (Tim Hockin)		* Magic number cleanup (Tim Hockin)		* Don't reload EEPROM on every reset (Tim Hockin)		* Save and restore EEPROM state across reset (Tim Hockin)		* MDIO Cleanup (Tim Hockin)		* Reformat register offsets/bits (jgarzik)	version 1.0.12:		* ETHTOOL_* further support (Tim Hockin)	version 1.0.13:		* ETHTOOL_[G]EEPROM support (Tim Hockin)	version 1.0.13:		* crc cleanup (Matt Domsch <Matt_Domsch@dell.com>)	version 1.0.14:		* Cleanup some messages and autoneg in ethtool (Tim Hockin)	version 1.0.15:		* Get rid of cable_magic flag		* use new (National provided) solution for cable magic issue	version 1.0.16:		* call netdev_rx() for RxErrors (Manfred Spraul)		* formatting and cleanups		* change options and full_duplex arrays to be zero		  initialized		* enable only the WoL and PHY interrupts in wol mode	version 1.0.17:		* only do cable_magic on 83815 and early 83816 (Tim Hockin)		* create a function for rx refill (Manfred Spraul)		* combine drain_ring and init_ring (Manfred Spraul)		* oom handling (Manfred Spraul)		* hands_off instead of playing with netif_device_{de,a}ttach		  (Manfred Spraul)		* be sure to write the MAC back to the chip (Manfred Spraul)		* lengthen EEPROM timeout, and always warn about timeouts		  (Manfred Spraul)		* comments update (Manfred)		* do the right thing on a phy-reset (Manfred and Tim)	TODO:	* big endian support with CFG:BEM instead of cpu_to_le32	* support for an external PHY	* NAPI*/#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/init.h>#include <linux/spinlock.h>#include <linux/ethtool.h>#include <linux/delay.h>#include <linux/rtnetlink.h>#include <linux/mii.h>#include <linux/crc32.h>#include <asm/processor.h>	/* Processor type for cache alignment. */#include <asm/bitops.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/uaccess.h>#define DRV_NAME	"natsemi"#define DRV_VERSION	"1.07+LK1.0.17"#define DRV_RELDATE	"Sep 27, 2002"#define RX_OFFSET	2/* Updated to recommendations in pci-skeleton v2.03. *//* The user-configurable values.   These may be modified when a driver module is loaded.*/#define NATSEMI_DEF_MSG		(NETIF_MSG_DRV		| \				 NETIF_MSG_LINK		| \				 NETIF_MSG_WOL		| \				 NETIF_MSG_RX_ERR	| \				 NETIF_MSG_TX_ERR)static int debug = -1;/* Maximum events (Rx packets, etc.) to handle at each interrupt. */static int max_interrupt_work = 20;static int mtu;/* Maximum number of multicast addresses to filter (vs. rx-all-multicast).   This chip uses a 512 element hash table based on the Ethernet CRC.  */static int multicast_filter_limit = 100;/* Set the copy breakpoint for the copy-only-tiny-frames scheme.   Setting to > 1518 effectively disables this feature. */static int rx_copybreak;/* Used to pass the media type, etc.   Both 'options[]' and 'full_duplex[]' should exist for driver   interoperability.   The media type is usually passed in 'options[]'.*/#define MAX_UNITS 8		/* More are supported, limit only on options */static int options[MAX_UNITS];static int full_duplex[MAX_UNITS];/* Operational parameters that are set at compile time. *//* Keep the ring sizes a power of two for compile efficiency.   The compiler will convert <unsigned>'%'<2^N> into a bit mask.   Making the Tx ring too large decreases the effectiveness of channel   bonding and packet priority.   There are no ill effects from too-large receive rings. */#define TX_RING_SIZE	16#define TX_QUEUE_LEN	10 /* Limit ring entries actually used, min 4. */#define RX_RING_SIZE	32/* Operational parameters that usually are not changed. *//* Time in jiffies before concluding the transmitter is hung. */#define TX_TIMEOUT  (2*HZ)#define NATSEMI_HW_TIMEOUT	400#define NATSEMI_TIMER_FREQ	3*HZ#define NATSEMI_PG0_NREGS	64#define NATSEMI_RFDR_NREGS	8#define NATSEMI_PG1_NREGS	4#define NATSEMI_NREGS		(NATSEMI_PG0_NREGS + NATSEMI_RFDR_NREGS + \				 NATSEMI_PG1_NREGS)#define NATSEMI_REGS_VER	1 /* v1 added RFDR registers */#define NATSEMI_REGS_SIZE	(NATSEMI_NREGS * sizeof(u32))#define NATSEMI_EEPROM_SIZE	24 /* 12 16-bit values *//* Buffer sizes: * The nic writes 32-bit values, even if the upper bytes of * a 32-bit value are beyond the end of the buffer. */#define NATSEMI_HEADERS		22	/* 2*mac,type,vlan,crc */#define NATSEMI_PADDING		16	/* 2 bytes should be sufficient */#define NATSEMI_LONGPKT		1518	/* limit for normal packets */#define NATSEMI_RX_LIMIT	2046	/* maximum supported by hardware *//* These identify the driver base version and may not be removed. */static char version[] __devinitdata =  KERN_INFO DRV_NAME " dp8381x driver, version "      DRV_VERSION ", " DRV_RELDATE "\n"  KERN_INFO "  originally by Donald Becker <becker@scyld.com>\n"  KERN_INFO "  http://www.scyld.com/network/natsemi.html\n"  KERN_INFO "  2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n";MODULE_AUTHOR("Donald Becker <becker@scyld.com>");MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver");MODULE_LICENSE("GPL");MODULE_PARM(max_interrupt_work, "i");MODULE_PARM(mtu, "i");MODULE_PARM(debug, "i");MODULE_PARM(rx_copybreak, "i");MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM_DESC(max_interrupt_work, 	"DP8381x maximum events handled per interrupt");MODULE_PARM_DESC(mtu, "DP8381x MTU (all boards)");MODULE_PARM_DESC(debug, "DP8381x default debug level");MODULE_PARM_DESC(rx_copybreak, 	"DP8381x copy breakpoint for copy-only-tiny-frames");MODULE_PARM_DESC(options, 	"DP8381x: Bits 0-3: media type, bit 17: full duplex");MODULE_PARM_DESC(full_duplex, "DP8381x full duplex setting(s) (1)");/*				Theory of OperationI. Board CompatibilityThis driver is designed for National Semiconductor DP83815 PCI Ethernet NIC.It also works with other chips in in the DP83810 series.II. Board-specific settingsThis driver requires the PCI interrupt line to be valid.It honors the EEPROM-set values.III. Driver operationIIIa. Ring buffersThis driver uses two statically allocated fixed-size descriptor listsformed into rings by a branch from the final descriptor to the beginning ofthe list.  The ring sizes are set at compile time by RX/TX_RING_SIZE.The NatSemi design uses a 'next descriptor' pointer that the driver formsinto a list.IIIb/c. Transmit/Receive StructureThis driver uses a zero-copy receive and transmit scheme.The driver allocates full frame size skbuffs for the Rx ring buffers atopen() time and passes the skb->data field to the chip as receive databuffers.  When an incoming frame is less than RX_COPYBREAK bytes long,a fresh skbuff is allocated and the frame is copied to the new skbuff.When the incoming frame is larger, the skbuff is passed directly up theprotocol stack.  Buffers consumed this way are replaced by newly allocatedskbuffs in a later phase of receives.The RX_COPYBREAK value is chosen to trade-off the memory wasted byusing a full-sized skbuff for small frames vs. the copying costs of largerframes.  New boards are typically used in generously configured machinesand the underfilled buffers have negligible impact compared to the benefit ofa single allocation size, so the default value of zero results in nevercopying packets.  When copying is done, the cost is usually mitigated by usinga combined copy/checksum routine.  Copying also preloads the cache, which ismost useful with small frames.A subtle aspect of the operation is that unaligned buffers are not permittedby the hardware.  Thus the IP header at offset 14 in an ethernet frame isn'tlongword aligned for further processing.  On copies frames are put into theskbuff at an offset of "+2", 16-byte aligning the IP header.IIId. SynchronizationMost operations are synchronized on the np->lock irq spinlock, except theperformance critical codepaths:The rx process only runs in the interrupt handler. Access from outsidethe interrupt handler is only permitted after disable_irq().The rx process usually runs under the dev->xmit_lock. If np->intr_tx_reapis set, then access is permitted under spin_lock_irq(&np->lock).Thus configuration functions that want to access everything must call	disable_irq(dev->irq);	spin_lock_bh(dev->xmit_lock);	spin_lock_irq(&np->lock);IV. NotesNatSemi PCI network controllers are very uncommon.IVb. Referenceshttp://www.scyld.com/expert/100mbps.htmlhttp://www.scyld.com/expert/NWay.htmlDatasheet is available from:http://www.national.com/pf/DP/DP83815.htmlIVc. ErrataNone characterised.*/enum pcistuff {	PCI_USES_IO = 0x01,	PCI_USES_MEM = 0x02,	PCI_USES_MASTER = 0x04,	PCI_ADDR0 = 0x08,	PCI_ADDR1 = 0x10,};/* MMIO operations required */#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR1)/* * Support for fibre connections on Am79C874: * This phy needs a special setup when connected to a fibre cable. * http://www.amd.com/files/connectivitysolutions/networking/archivednetworking/22235.pdf */#define PHYID_AM79C874	0x0022561b#define MII_MCTRL	0x15	/* mode control register */#define MII_FX_SEL	0x0001	/* 100BASE-FX (fiber) */#define MII_EN_SCRM	0x0004	/* enable scrambler (tp) */ /* array of board data directly indexed by pci_tbl[x].driver_data */static struct {	const char *name;	unsigned long flags;} natsemi_pci_info[] __devinitdata = {	{ "NatSemi DP8381[56]", PCI_IOTYPE },};static struct pci_device_id natsemi_pci_tbl[] = {	{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_83815, PCI_ANY_ID, PCI_ANY_ID, },	{ 0, },};MODULE_DEVICE_TABLE(pci, natsemi_pci_tbl);/* Offsets to the device registers.   Unlike software-only systems, device drivers interact with complex hardware.   It's not useful to define symbolic names for every register bit in the   device.*/enum register_offsets {	ChipCmd			= 0x00,	ChipConfig		= 0x04,	EECtrl			= 0x08,	PCIBusCfg		= 0x0C,	IntrStatus		= 0x10,	IntrMask		= 0x14,	IntrEnable		= 0x18,	IntrHoldoff		= 0x1C, /* DP83816 only */	TxRingPtr		= 0x20,	TxConfig		= 0x24,	RxRingPtr		= 0x30,	RxConfig		= 0x34,	ClkRun			= 0x3C,	WOLCmd			= 0x40,	PauseCmd		= 0x44,	RxFilterAddr		= 0x48,	RxFilterData		= 0x4C,	BootRomAddr		= 0x50,	BootRomData		= 0x54,	SiliconRev		= 0x58,	StatsCtrl		= 0x5C,	StatsData		= 0x60,	RxPktErrs		= 0x60,	RxMissed		= 0x68,	RxCRCErrs		= 0x64,	BasicControl		= 0x80,	BasicStatus		= 0x84,	AnegAdv			= 0x90,	AnegPeer		= 0x94,	PhyStatus		= 0xC0,	MIntrCtrl		= 0xC4,	MIntrStatus		= 0xC8,	PhyCtrl			= 0xE4,	/* These are from the spec, around page 78... on a separate table.	 * The meaning of these registers depend on the value of PGSEL. */	PGSEL			= 0xCC,	PMDCSR			= 0xE4,	TSTDAT			= 0xFC,	DSPCFG			= 0xF4,	SDCFG			= 0xF8};/* the values for the 'magic' registers above (PGSEL=1) */#define PMDCSR_VAL	0x189c	/* enable preferred adaptation circuitry */#define TSTDAT_VAL	0x0#define DSPCFG_VAL	0x5040#define SDCFG_VAL	0x008c	/* set voltage thresholds for Signal Detect */#define DSPCFG_LOCK	0x20	/* coefficient lock bit in DSPCFG */#define TSTDAT_FIXED	0xe8	/* magic number for bad coefficients *//* misc PCI space registers */enum pci_register_offsets {	PCIPM			= 0x44,};enum ChipCmd_bits {	ChipReset		= 0x100,	RxReset			= 0x20,	TxReset			= 0x10,

⌨️ 快捷键说明

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