natsemi.c

来自「linux 内核源代码」· C语言 代码 · 共 2,280 行 · 第 1/5 页

C
2,280
字号
/* 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)	Portions copyright 2004 Harald Welte <laforge@gnumonks.org>	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	[link no longer provides useful info -jgarzik]	TODO:	* big endian support with CFG:BEM instead of cpu_to_le32*/#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 <linux/bitops.h>#include <linux/prefetch.h>#include <asm/processor.h>	/* Processor type for cache alignment. */#include <asm/io.h>#include <asm/irq.h>#include <asm/uaccess.h>#define DRV_NAME	"natsemi"#define DRV_VERSION	"2.1"#define DRV_RELDATE	"Sept 11, 2006"#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;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 const 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;static int dspcfg_workaround = 1;/* 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	5*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))/* 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 const 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 "  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_param(mtu, int, 0);module_param(debug, int, 0);module_param(rx_copybreak, int, 0);module_param(dspcfg_workaround, int, 1);module_param_array(options, int, NULL, 0);module_param_array(full_duplex, int, NULL, 0);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(dspcfg_workaround, "DP8381x: control DspCfg workaround");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 netif_tx_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);	netif_tx_lock_bh(dev);	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.*//* * 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	0x0022561benum {	MII_MCTRL	= 0x15,		/* mode control register */	MII_FX_SEL	= 0x0001,	/* 100BASE-FX (fiber) */	MII_EN_SCRM	= 0x0004,	/* enable scrambler (tp) */};enum {	NATSEMI_FLAG_IGNORE_PHY		= 0x1,};/* array of board data directly indexed by pci_tbl[x].driver_data */static const struct {	const char *name;	unsigned long flags;	unsigned int eeprom_size;} natsemi_pci_info[] __devinitdata = {	{ "Aculab E1/T1 PMXc cPCI carrier card", NATSEMI_FLAG_IGNORE_PHY, 128 },	{ "NatSemi DP8381[56]", 0, 24 },};static const struct pci_device_id natsemi_pci_tbl[] __devinitdata = {	{ PCI_VENDOR_ID_NS, 0x0020, 0x12d9,     0x000c,     0, 0, 0 },	{ PCI_VENDOR_ID_NS, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },	{ }	/* terminate list */};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 DSPCFG_COEF	0x1000	/* see coefficient (in TSTDAT) 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,	RxOff			= 0x08,	RxOn			= 0x04,	TxOff			= 0x02,	TxOn			= 0x01,};enum ChipConfig_bits {	CfgPhyDis		= 0x200,	CfgPhyRst		= 0x400,	CfgExtPhy		= 0x1000,	CfgAnegEnable		= 0x2000,	CfgAneg100		= 0x4000,	CfgAnegFull		= 0x8000,	CfgAnegDone		= 0x8000000,	CfgFullDuplex		= 0x20000000,	CfgSpeed100		= 0x40000000,	CfgLink			= 0x80000000,};enum EECtrl_bits {	EE_ShiftClk		= 0x04,	EE_DataIn		= 0x01,	EE_ChipSelect		= 0x08,	EE_DataOut		= 0x02,	MII_Data 		= 0x10,	MII_Write		= 0x20,	MII_ShiftClk		= 0x40,};enum PCIBusCfg_bits {	EepromReload		= 0x4,};/* Bits in the interrupt status/mask registers. */enum IntrStatus_bits {	IntrRxDone		= 0x0001,	IntrRxIntr		= 0x0002,	IntrRxErr		= 0x0004,	IntrRxEarly		= 0x0008,	IntrRxIdle		= 0x0010,	IntrRxOverrun		= 0x0020,	IntrTxDone		= 0x0040,	IntrTxIntr		= 0x0080,	IntrTxErr		= 0x0100,	IntrTxIdle		= 0x0200,	IntrTxUnderrun		= 0x0400,	StatsMax		= 0x0800,	SWInt			= 0x1000,	WOLPkt			= 0x2000,	LinkChange		= 0x4000,	IntrHighBits		= 0x8000,	RxStatusFIFOOver	= 0x10000,	IntrPCIErr		= 0xf00000,	RxResetDone		= 0x1000000,	TxResetDone		= 0x2000000,	IntrAbnormalSummary	= 0xCD20,};/* * Default Interrupts: * Rx OK, Rx Packet Error, Rx Overrun, * Tx OK, Tx Packet Error, Tx Underrun, * MIB Service, Phy Interrupt, High Bits, * Rx Status FIFO overrun, * Received Target Abort, Received Master Abort, * Signalled System Error, Received Parity Error */#define DEFAULT_INTR 0x00f1cd65enum TxConfig_bits {	TxDrthMask		= 0x3f,	TxFlthMask		= 0x3f00,	TxMxdmaMask		= 0x700000,	TxMxdma_512		= 0x0,	TxMxdma_4		= 0x100000,	TxMxdma_8		= 0x200000,	TxMxdma_16		= 0x300000,	TxMxdma_32		= 0x400000,	TxMxdma_64		= 0x500000,	TxMxdma_128		= 0x600000,	TxMxdma_256		= 0x700000,	TxCollRetry		= 0x800000,	TxAutoPad		= 0x10000000,	TxMacLoop		= 0x20000000,	TxHeartIgn		= 0x40000000,	TxCarrierIgn		= 0x80000000};/* * Tx Configuration: * - 256 byte DMA burst length * - fill threshold 512 bytes (i.e. restart DMA when 512 bytes are free) * - 64 bytes initial drain threshold (i.e. begin actual transmission *   when 64 byte are in the fifo) * - on tx underruns, increase drain threshold by 64. * - at most use a drain threshold of 1472 bytes: The sum of the fill *   threshold and the drain threshold must be less than 2016 bytes. * */#define TX_FLTH_VAL		((512/32) << 8)#define TX_DRTH_VAL_START	(64/32)#define TX_DRTH_VAL_INC		2#define TX_DRTH_VAL_LIMIT	(1472/32)enum RxConfig_bits {	RxDrthMask		= 0x3e,	RxMxdmaMask		= 0x700000,	RxMxdma_512		= 0x0,	RxMxdma_4		= 0x100000,	RxMxdma_8		= 0x200000,	RxMxdma_16		= 0x300000,	RxMxdma_32		= 0x400000,	RxMxdma_64		= 0x500000,	RxMxdma_128		= 0x600000,	RxMxdma_256		= 0x700000,	RxAcceptLong		= 0x8000000,	RxAcceptTx		= 0x10000000,	RxAcceptRunt		= 0x40000000,	RxAcceptErr		= 0x80000000};

⌨️ 快捷键说明

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