📄 tulip.c
字号:
/* tulip.c: A DEC 21040-family ethernet driver for Linux. *//* Written/copyright 1994-1999 by Donald Becker. This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. This driver is for the Digital "Tulip" Ethernet adapter interface. It should work with most DEC 21*4*-based chips/ethercards, as well as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX. The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O Center of Excellence in Space Data and Information Sciences Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 Support and updates available at http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html This driver also contains updates by Wolfgang Walter and others. For this specific driver variant please use linux-kernel for bug reports.*/#define SMP_CHECKstatic const char version[] = "tulip.c:v0.91g-ppc 7/16/99 becker@cesdis.gsfc.nasa.gov\n";/* A few user-configurable values. *//* Maximum events (Rx packets, etc.) to handle at each interrupt. */static int max_interrupt_work = 25;#define MAX_UNITS 8/* Used to pass the full-duplex flag, etc. */static int full_duplex[MAX_UNITS] = {0, };static int options[MAX_UNITS] = {0, };static int mtu[MAX_UNITS] = {0, }; /* Jumbo MTU for interfaces. *//* The possible media types that can be set in options[] are: */static const char * const medianame[] = { "10baseT", "10base2", "AUI", "100baseTx", "10baseT-FD", "100baseTx-FD", "100baseT4", "100baseFx", "100baseFx-FD", "MII 10baseT", "MII 10baseT-FD", "MII", "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FD", "MII 100baseT4",};/* Set if the PCI BIOS detects the chips on a multiport board backwards. */#ifdef REVERSE_PROBE_ORDERstatic int reverse_probe = 1;#elsestatic int reverse_probe = 0;#endif/* Keep the ring sizes a power of two for efficiency. 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 RX_RING_SIZE 32/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */#ifdef __alpha__static int rx_copybreak = 1518;#elsestatic int rx_copybreak = 100;#endif/* Set the bus performance register. Typical: Set 16 longword cache alignment, no burst limit. Cache alignment bits 15:14 Burst length 13:8 0000 No alignment 0x00000000 unlimited 0800 8 longwords 4000 8 longwords 0100 1 longword 1000 16 longwords 8000 16 longwords 0200 2 longwords 2000 32 longwords C000 32 longwords 0400 4 longwords Warning: many older 486 systems are broken and require setting 0x00A04800 8 longword cache alignment, 8 longword burst. ToDo: Non-Intel setting could be better.*/#if defined(__alpha__)static int csr0 = 0x01A00000 | 0xE000;#elif defined(__i386__) || defined(__powerpc__) || defined(__sparc__)static int csr0 = 0x01A00000 | 0x8000;#else#warning Processor architecture undefined!static int csr0 = 0x00A00000 | 0x4800;#endif/* Operational parameters that usually are not changed. *//* Time in jiffies before concluding the transmitter is hung. */#define TX_TIMEOUT (4*HZ)#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*//* This is a mysterious value that can be written to CSR11 in the 21040 (only) to support a pre-NWay full-duplex signaling mechanism using short frames. No one knows what it should be, but if left at its default value some 10base2(!) packets trigger a full-duplex-request interrupt. */#define FULL_DUPLEX_MAGIC 0x6969#if !defined(__OPTIMIZE__) || !defined(__KERNEL__)#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/version.h>#ifdef MODULE#ifdef MODVERSIONS#include <linux/modversions.h>#endif#include <linux/module.h>#else#define MOD_INC_USE_COUNT#define MOD_DEC_USE_COUNT#endif#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/malloc.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <asm/processor.h> /* Processor type for cache alignment. */#include <asm/bitops.h>#include <asm/io.h>#include <asm/unaligned.h>/* Kernel compatibility defines, some common to David Hind's PCMCIA package. This is only in the support-all-kernels source code. */#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");MODULE_PARM(debug, "i");MODULE_PARM(max_interrupt_work, "i");MODULE_PARM(reverse_probe, "i");MODULE_PARM(rx_copybreak, "i");MODULE_PARM(csr0, "i");MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");#endif#define RUN_AT(x) (jiffies + (x))#if (LINUX_VERSION_CODE >= 0x20100)static char kernel_version[] = UTS_RELEASE;#endif#if LINUX_VERSION_CODE < 0x20123#define hard_smp_processor_id() smp_processor_id()#define test_and_set_bit(val, addr) set_bit(val, addr)#define le16_to_cpu(val) (val)#define le32_to_cpu(val) (val)#define cpu_to_le32(val) (val)#endif#if LINUX_VERSION_CODE <= 0x20139#define net_device_stats enet_statistics#else#define NETSTATS_VER2#endif#if LINUX_VERSION_CODE < 0x20155/* Grrrr, the PCI code changed, but did not consider CardBus... */#include <linux/bios32.h>#define PCI_SUPPORT_VER1#else#define PCI_SUPPORT_VER2#endif#if LINUX_VERSION_CODE < 0x20159#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE);#else#define dev_free_skb(skb) dev_kfree_skb(skb);#endif#if ! defined(CAP_NET_ADMIN)#define capable(CAP_XXX) (suser())#endif#if ! defined(HAS_NETIF_QUEUE)#define netif_wake_queue(dev) mark_bh(NET_BH);#endif/* Condensed operations for readability. */#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))#define tulip_debug debug#ifdef TULIP_DEBUGstatic int tulip_debug = TULIP_DEBUG;#elsestatic int tulip_debug = 1;#endif/* Theory of OperationI. Board CompatibilityThis device driver is designed for the DECchip "Tulip", Digital'ssingle-chip ethernet controllers for PCI. Supported members of the familyare the 21040, 21041, 21140, 21140A, 21142, and 21143. Similar work-alikechips from Lite-On, Macronics, ASIX, Compex and other listed below are alsosupported. These chips are used on at least 140 unique PCI board designs. The greatnumber of chips and board designs supported is the reason for thedriver size and complexity. Almost of the increasing complexity is in theboard configuration and media selection code. There is very littleincreasing in the operational critical path length.II. Board-specific settingsPCI bus devices are configured by the system at boot time, so no jumpersneed to be set on the board. The system BIOS preferably should assign thePCI INTA signal to an otherwise unused system IRQ line.Some boards have EEPROMs tables with default media entry. The factory defaultis usually "autoselect". This should only be overridden when usingtransceiver connections without link beat e.g. 10base2 or AUI, or (rarely!)for forcing full-duplex when used with old link partners that do not doautonegotiation. III. Driver operationIIIa. Ring buffersThe Tulip can use either ring buffers or lists of Tx and Rx descriptors.This driver uses statically allocated rings of Rx and Tx descriptors, set atcompile time by RX/TX_RING_SIZE. This version of the driver allocates skbuffsfor the Rx ring buffers at open() time and passes the skb->data field to theTulip as receive data buffers. When an incoming frame is less thanRX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame iscopied to the new skbuff. When the incoming frame is larger, the skbuff ispassed directly up the protocol stack and replaced by a newly allocatedskbuff.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. For small frames the copying cost is negligible (esp. consideringthat we are pre-loading the cache with immediately useful headerinformation). For large frames the copying cost is non-trivial, and thelarger copy might flush the cache of useful data. A subtle aspect of thischoice is that the Tulip only receives into longword aligned buffers, thusthe IP header at offset 14 isn't longword aligned for further processing.Copied frames are put into the new skbuff at an offset of "+2", thus copyinghas the beneficial effect of aligning the IP header and preloading thecache.IIIC. 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 other 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 'tp->tx_full' flag.The interrupt handler has exclusive control over the Rx ring and records statsfrom the Tx ring. (The Tx-done interrupt can't be selectively turned off, sowe can't avoid the interrupt overhead by having the Tx routine reap the Txstats.) After reaping the stats, it marks the queue entry as empty by settingthe 'base' to zero. Iff the 'tp->tx_full' flag is set, it clears both thetx_full and tbusy flags.IV. NotesThanks to Duke Kamstra of SMC for long ago providing an EtherPower board.Greg LaPolla at Linksys provided PNIC and other Linksys boards.Znyx provided a four-port card for testing.IVb. Referenceshttp://cesdis.gsfc.nasa.gov/linux/misc/NWay.htmlhttp://www.digital.com (search for current 21*4* datasheets and "21X4 SROM")http://www.national.com/pf/DP/DP83840A.htmlhttp://www.asix.com.tw/pmac.htmhttp://www.admtek.com.tw/IVc. ErrataThe old DEC databooks were light on details.The 21040 databook claims that CSR13, CSR14, and CSR15 should each be the lastregister of the set CSR12-15 written. Hmmm, now how is that possible?The DEC SROM format is very badly designed not precisely defined, leading topart of the media selection junkheap below. Some boards do not have EEPROMmedia tables and need to be patched up. Worse, other boards use the DECdesign kit media table when it isn't correct for their board.We cannot use MII interrupts because there is no defined GPIO pin to attachthem. The MII transceiver status is polled using an kernel timer.*/static struct device *tulip_probe1(int pci_bus, int pci_devfn, struct device *dev, long ioaddr, int irq, int chip_idx, int board_idx);/* This table drives the PCI probe routines. It's mostly boilerplate in all of the drivers, and will likely be provided by some future kernel. Note the matching code -- the first table entry matchs all 56** cards but second only the 1234 card.*/enum pci_flags_bit { PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,};#define PCI_ADDR0_IO (PCI_USES_IO|PCI_ADDR0)struct pci_id_info { const char *name; u16 vendor_id, device_id, device_id_mask, flags; int io_size, min_latency; struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev, long ioaddr, int irq, int chip_idx, int fnd_cnt);};#ifndef CARDBUSstatic struct pci_id_info pci_tbl[] = { { "Digital DC21040 Tulip", 0x1011, 0x0002, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, { "Digital DC21041 Tulip", 0x1011, 0x0014, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, { "Digital DS21140 Tulip", 0x1011, 0x0009, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, { "Digital DS21143 Tulip", 0x1011, 0x0019, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, { "Lite-On 82c168 PNIC", 0x11AD, 0x0002, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 }, { "Macronix 98713 PMAC", 0x10d9, 0x0512, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 }, { "Macronix 98715 PMAC", 0x10d9, 0x0531, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 }, { "Macronix 98725 PMAC", 0x10d9, 0x0531, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 }, { "ASIX AX88140", 0x125B, 0x1400, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, { "Lite-On LC82C115 PNIC-II", 0x11AD, 0xc115, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 }, { "ADMtek AN981 Comet", 0x1317, 0x0981, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 }, { "Compex RL100-TX", 0x11F6, 0x9881, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, { "Intel 21145 Tulip", 0x8086, 0x0039, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, { "Xircom Tulip clone", 0x115d, 0x0003, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, {0},};#endif /* !CARD_BUS *//* This table use during operation for capabilities and media timer. */static void tulip_timer(unsigned long data);static void t21142_timer(unsigned long data);static void mxic_timer(unsigned long data);static void pnic_timer(unsigned long data);static void comet_timer(unsigned long data);enum tbl_flag { HAS_MII=1, HAS_MEDIA_TABLE=2, CSR12_IN_SROM=4, ALWAYS_CHECK_MII=8, HAS_PWRDWN=0x10, MC_HASH_ONLY=0x20, /* Hash-only multicast filter. */ HAS_PNICNWAY=0x80, HAS_NWAY143=0x40, /* Uses internal NWay xcvr. */ HAS_8023X=0x100,};static struct tulip_chip_table { char *chip_name; int io_size; int valid_intrs; /* CSR7 interrupt enable settings */ int flags; void (*media_timer)(unsigned long data);} tulip_tbl[] = { { "Digital DC21040 Tulip", 128, 0x0001ebef, 0, tulip_timer }, { "Digital DC21041 Tulip", 128, 0x0001ebff, HAS_MEDIA_TABLE, tulip_timer }, { "Digital DS21140 Tulip", 128, 0x0001ebef, HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, tulip_timer }, { "Digital DS21143 Tulip", 128, 0x0801fbff, HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_PWRDWN | HAS_NWAY143, t21142_timer }, { "Lite-On 82c168 PNIC", 256, 0x0001ebef, HAS_MII | HAS_PNICNWAY, pnic_timer },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -