📄 starfire.c
字号:
/* starfire.c: Linux device driver for the Adaptec Starfire network adapter. *//* Written 1998-2000 by Donald Becker. Current maintainer is Ion Badulescu <ionut@cs.columbia.edu>. Please send all bug reports to me, and not to Donald Becker, as this code has been modified quite a bit from Donald's original version. 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. The author may be reached as becker@scyld.com, or C/O Scyld Computing Corporation 410 Severn Ave., Suite 210 Annapolis MD 21403 Support and updates available at http://www.scyld.com/network/starfire.html ----------------------------------------------------------- Linux kernel-specific changes: LK1.1.1 (jgarzik): - Use PCI driver interface - Fix MOD_xxx races - softnet fixups LK1.1.2 (jgarzik): - Merge Becker version 0.15 LK1.1.3 (Andrew Morton) - Timer cleanups LK1.1.4 (jgarzik): - Merge Becker version 1.03 LK1.2.1 (Ion Badulescu <ionut@cs.columbia.edu>) - Support hardware Rx/Tx checksumming - Use the GFP firmware taken from Adaptec's Netware driver LK1.2.2 (Ion Badulescu) - Backported to 2.2.x LK1.2.3 (Ion Badulescu) - Fix the flaky mdio interface - More compat clean-ups LK1.2.4 (Ion Badulescu) - More 2.2.x initialization fixes LK1.2.5 (Ion Badulescu) - Several fixes from Manfred Spraul LK1.2.6 (Ion Badulescu) - Fixed ifup/ifdown/ifup problem in 2.4.x LK1.2.7 (Ion Badulescu) - Removed unused code - Made more functions static and __init LK1.2.8 (Ion Badulescu) - Quell bogus error messages, inform about the Tx threshold - Removed #ifdef CONFIG_PCI, this driver is PCI only LK1.2.9 (Ion Badulescu) - Merged Jeff Garzik's changes from 2.4.4-pre5 - Added 2.2.x compatibility stuff required by the above changes LK1.2.9a (Ion Badulescu) - More updates from Jeff Garzik LK1.3.0 (Ion Badulescu) - Merged zerocopy support LK1.3.1 (Ion Badulescu) - Added ethtool support - Added GPIO (media change) interrupt support LK1.3.2 (Ion Badulescu) - Fixed 2.2.x compatibility issues introduced in 1.3.1 - Fixed ethtool ioctl returning uninitialized memory LK1.3.3 (Ion Badulescu) - Initialize the TxMode register properly - Don't dereference dev->priv after freeing it LK1.3.4 (Ion Badulescu) - Fixed initialization timing problems - Fixed interrupt mask definitions LK1.3.5 (jgarzik) - ethtool NWAY_RST, GLINK, [GS]MSGLVL supportTODO: - implement tx_timeout() properly*/#define DRV_NAME "starfire"#define DRV_VERSION "1.03+LK1.3.5"#define DRV_RELDATE "November 17, 2001"#include <linux/version.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/pci.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/processor.h> /* Processor type for cache alignment. */#include <asm/uaccess.h>#include <asm/io.h>/* * Adaptec's license for their Novell drivers (which is where I got the * firmware files) does not allow one to redistribute them. Thus, we can't * include the firmware with this driver. * * However, an end-user is allowed to download and use it, after * converting it to C header files using starfire_firmware.pl. * Once that's done, the #undef below must be changed into a #define * for this driver to really use the firmware. Note that Rx/Tx * hardware TCP checksumming is not possible without the firmware. * * I'm currently [Feb 2001] talking to Adaptec about this redistribution * issue. Stay tuned... */#undef HAS_FIRMWARE/* * The current frame processor firmware fails to checksum a fragment * of length 1. If and when this is fixed, the #define below can be removed. */#define HAS_BROKEN_FIRMWARE/* * Define this if using the driver with the zero-copy patch */#if defined(HAS_FIRMWARE) && defined(MAX_SKB_FRAGS)#define ZEROCOPY#endif#ifdef HAS_FIRMWARE#include "starfire_firmware.h"#endif /* HAS_FIRMWARE *//* The user-configurable values. These may be modified when a driver module is loaded.*//* Used for tuning interrupt latency vs. overhead. */static int interrupt_mitigation;static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */static int max_interrupt_work = 20;static int mtu;/* Maximum number of multicast addresses to filter (vs. rx-all-multicast). The Starfire has a 512 element hash table based on the Ethernet CRC. */static int multicast_filter_limit = 512;#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*//* * Set the copy breakpoint for the copy-only-tiny-frames scheme. * Setting to > 1518 effectively disables this feature. * * NOTE: * The ia64 doesn't allow for unaligned loads even of integers being * misaligned on a 2 byte boundary. Thus always force copying of * packets as the starfire doesn't allow for misaligned DMAs ;-( * 23/10/2000 - Jes * * The Alpha and the Sparc don't allow unaligned loads, either. -Ion */#if defined(__ia64__) || defined(__alpha__) || defined(__sparc__)static int rx_copybreak = PKT_BUF_SZ;#elsestatic int rx_copybreak /* = 0 */;#endif/* Used to pass the media type, etc. Both 'options[]' and 'full_duplex[]' 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] = {0, };static int full_duplex[MAX_UNITS] = {0, };/* Operational parameters that are set at compile time. *//* The "native" ring sizes are either 256 or 2048. However in some modes a descriptor may be marked to wrap the ring earlier. The driver allocates a single page for each descriptor ring, constraining the maximum size in an architecture-dependent way.*/#define RX_RING_SIZE 256#define TX_RING_SIZE 32/* The completion queues are fixed at 1024 entries i.e. 4K or 8KB. */#define DONE_Q_SIZE 1024/* Operational parameters that usually are not changed. *//* Time in jiffies before concluding the transmitter is hung. */#define TX_TIMEOUT (2 * HZ)#ifdef ZEROCOPY#if MAX_SKB_FRAGS <= 6#define MAX_STARFIRE_FRAGS 6#else /* MAX_STARFIRE_FRAGS > 6 */#warning This driver will not work with more than 6 skb fragments.#warning Turning off zerocopy support.#undef ZEROCOPY#endif /* MAX_STARFIRE_FRAGS > 6 */#endif /* ZEROCOPY */#ifdef ZEROCOPY#define skb_first_frag_len(skb) skb_headlen(skb)#else /* not ZEROCOPY */#define skb_first_frag_len(skb) (skb->len)#endif /* not ZEROCOPY *//* 2.2.x compatibility code */#if LINUX_VERSION_CODE < 0x20300#include "starfire-kcomp22.h"#else /* LINUX_VERSION_CODE > 0x20300 */#include <linux/ethtool.h>#include <linux/mii.h>#define COMPAT_MOD_INC_USE_COUNT#define COMPAT_MOD_DEC_USE_COUNT#define init_tx_timer(dev, func, timeout) \ dev->tx_timeout = func; \ dev->watchdog_timeo = timeout;#define kick_tx_timer(dev, func, timeout)#define netif_start_if(dev)#define netif_stop_if(dev)#define PCI_SLOT_NAME(pci_dev) (pci_dev)->slot_name#endif /* LINUX_VERSION_CODE > 0x20300 *//* end of compatibility code *//* These identify the driver base version and may not be removed. */static char version[] __devinitdata =KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n"KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";MODULE_AUTHOR("Donald Becker <becker@scyld.com>");MODULE_DESCRIPTION("Adaptec Starfire 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(interrupt_mitigation, "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, "Starfire maximum events handled per interrupt");MODULE_PARM_DESC(mtu, "Starfire MTU (all boards)");MODULE_PARM_DESC(debug, "Starfire debug level (0-6)");MODULE_PARM_DESC(rx_copybreak, "Starfire copy breakpoint for copy-only-tiny-frames");MODULE_PARM_DESC(options, "Starfire: Bits 0-3: media type, bit 17: full duplex");MODULE_PARM_DESC(full_duplex, "Starfire full duplex setting(s) (1)");/* Theory of OperationI. Board CompatibilityThis driver is for the Adaptec 6915 "Starfire" 64 bit PCI Ethernet adapter.II. Board-specific settingsIII. Driver operationIIIa. Ring buffersThe Starfire hardware uses multiple fixed-size descriptor queues/rings. Thering sizes are set fixed by the hardware, but may optionally be wrappedearlier by the END bit in the descriptor.This driver uses that hardware queue size for the Rx ring, where a largenumber of entries has no ill effect beyond increases the potential backlog.The Tx ring is wrapped with the END bit, since a large hardware Tx queuedisables the queue layer priority ordering and we have no mechanism toutilize the hardware two-level priority queue. When modifying theRX/TX_RING_SIZE pay close attention to page sizes and the ring-empty warninglevels.IIIb/c. Transmit/Receive StructureSee the Adaptec manual for the many possible structures, and options foreach structure. There are far too many to document here.For transmit this driver uses type 0/1 transmit descriptors (dependingon the presence of the zerocopy infrastructure), and relies on automaticminimum-length padding. It does not use the completion queueconsumer index, but instead checks for non-zero status entries.For receive this driver uses type 0 receive descriptors. The driverallocates full frame size skbuffs for the Rx ring buffers, so all framesshould fit in a single descriptor. The driver does not use the completionqueue consumer index, but instead checks for non-zero status entries.When an incoming frame is less than RX_COPYBREAK bytes long, a fresh skbuffis allocated and the frame is copied to the new skbuff. When the incomingframe is larger, the skbuff is passed directly up the protocol stack.Buffers consumed this way are replaced by newly allocated skbuffs in a laterphase of receive.A notable aspect of operation is that unaligned buffers are not permitted bythe Starfire hardware. Thus the IP header at offset 14 in an ethernet frameisn't longword aligned, which may cause problems on some machinee.g. Alphas and IA64. For these architectures, the driver is forced to copythe frame into a new skbuff unconditionally. Copied frames are put into theskbuff at an offset of "+2", thus 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. NotesIVb. ReferencesThe Adaptec Starfire manuals, available only from Adaptec.http://www.scyld.com/expert/100mbps.htmlhttp://www.scyld.com/expert/NWay.htmlIVc. Errata*/enum chip_capability_flags {CanHaveMII=1, };#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR0)#if 0#define ADDR_64BITS 1 /* This chip uses 64 bit addresses. */#endif#define HAS_IP_COPYSUM 1enum chipset { CH_6915 = 0,};static struct pci_device_id starfire_pci_tbl[] __devinitdata = { { 0x9004, 0x6915, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_6915 }, { 0, }};MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);/* A chip capabilities table, matching the CH_xxx entries in xxx_pci_tbl[] above. */static struct chip_info { const char *name; int drv_flags;} netdrv_tbl[] __devinitdata = { { "Adaptec Starfire 6915", CanHaveMII },};/* 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. The name can only partially document the semantics and make the driver longer and more difficult to read. In general, only the important configuration values or bits changed multiple times should be defined symbolically.*/enum register_offsets { PCIDeviceConfig=0x50040, GenCtrl=0x50070, IntrTimerCtrl=0x50074, IntrClear=0x50080, IntrStatus=0x50084, IntrEnable=0x50088, MIICtrl=0x52000, StationAddr=0x50120, EEPROMCtrl=0x51000, GPIOCtrl=0x5008C, TxDescCtrl=0x50090, TxRingPtr=0x50098, HiPriTxRingPtr=0x50094, /* Low and High priority. */ TxRingHiAddr=0x5009C, /* 64 bit address extension. */ TxProducerIdx=0x500A0, TxConsumerIdx=0x500A4, TxThreshold=0x500B0, CompletionHiAddr=0x500B4, TxCompletionAddr=0x500B8, RxCompletionAddr=0x500BC, RxCompletionQ2Addr=0x500C0, CompletionQConsumerIdx=0x500C4, RxDMACtrl=0x500D0, RxDescQCtrl=0x500D4, RxDescQHiAddr=0x500DC, RxDescQAddr=0x500E0, RxDescQIdx=0x500E8, RxDMAStatus=0x500F0, RxFilterMode=0x500F4, TxMode=0x55000, PerfFilterTable=0x56000, HashTable=0x56100, TxGfpMem=0x58000, RxGfpMem=0x5a000,};/* Bits in the interrupt status/mask registers. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -