📄 natsemi.c
字号:
/* natsemi.c: A Linux PCI Ethernet driver for the NatSemi DP8381x series. *//* Written/copyright 1999-2001 by Donald Becker. Portions copyright (c) 2001 Sun Microsystems (thockin@sun.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_GEEPROM support (Tim Hockin) version 1.0.14: * Cleanup some messages and autoneg in ethtool (Tim Hockin) TODO: * big endian support with CFG:BEM instead of cpu_to_le32 * support for an external PHY * flow control*/#if !defined(__OPTIMIZE__)#warning You must compile this file with the correct options!#warning See the last lines of the source file.#error You must compile this driver with "-O".#endif#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 <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.14"#define DRV_RELDATE "Nov 27, 2001"/* Updated to recommendations in pci-skeleton v2.03. *//* Automatically extracted configuration info:probe-func: natsemi_probeconfig-in: tristate 'National Semiconductor DP8381x series PCI Ethernet support' CONFIG_NATSEMIc-help-name: National Semiconductor DP8381x series PCI Ethernet supportc-help-symbol: CONFIG_NATSEMIc-help: This driver is for the National Semiconductor DP8381x series,c-help: including the 8381[56] chips.c-help: More specific information and updates are available from c-help: http://www.scyld.com/network/natsemi.html*//* 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 = NATSEMI_DEF_MSG;/* 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] = {-1, -1, -1, -1, -1, -1, -1, -1};static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};/* 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 64/* 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 */#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. *//* These identify the driver base version and may not be removed. */static char version[] __devinitdata =KERN_INFO DRV_NAME ".c:v1.07 1/9/2001 Written by Donald Becker <becker@scyld.com>\n"KERN_INFO " http://www.scyld.com/network/natsemi.html\n"KERN_INFO " (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE " 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 debug bitmask");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. SynchronizationThe driver runs as two independent, single-threaded flows of control. Oneis the send-packet routine, which enforces single-threaded use by thedev->tbusy flag. The other thread is the interrupt handler, which is singlethreaded by the hardware and interrupt handling software.The send packet thread has partial control over the Tx ring and 'dev->tbusy'flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the nextqueue slot is empty, it clears the tbusy flag when finished otherwise it setsthe 'lp->tx_full' flag.The interrupt handler has exclusive control over the Rx ring and records statsfrom the Tx ring. After reaping the stats, it marks the Tx queue entry asempty by incrementing the dirty_tx mark. Iff the 'lp->tx_full' flag is set, itclears both the tx_full and tbusy flags.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)/* 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[] __devinitdata = { { 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, 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) */#ifdef CONFIG_NATSEMI_CABLE_MAGIC#define PMDCSR_VAL 0x1898#else#define PMDCSR_VAL 0x189C#endif#define TSTDAT_VAL 0x0#define DSPCFG_VAL 0x5040#define SDCFG_VAL 0x008c/* 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,};enum PCIBusCfg_bits { EepromReload = 0x4,};/* Bits in the interrupt status/mask registers. */enum IntrStatus_bits { IntrRxDone = 0x0001, IntrRxIntr = 0x0002, IntrRxErr = 0x0004,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -