⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xircom_tulip_cb.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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*/#define SMP_CHECK#define CARDBUS 1static const char version[] = "xircom_tulip_cb.c:v0.91 4/14/99 becker@cesdis.gsfc.nasa.gov (modified by danilo@cs.uni-magdeburg.de for XIRCOM CBE, fixed by Doug Ledford)\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];static int options[MAX_UNITS];static int mtu[MAX_UNITS];			/* 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",};/* 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(__powerpc__)static int csr0 = 0x01B00000 | 0x8000;#elif defined(__sparc__)static int csr0 = 0x01B00080 | 0x8000;#elif defined(__i386__)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/version.h>#include <linux/module.h>#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 <linux/delay.h>#include <linux/init.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 Hinds' PCMCIA package.   This is only in the support-all-kernels source code. */MODULE_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");#define RUN_AT(x) (jiffies + (x))#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.*//* 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_ACPI=0x10, MC_HASH_ONLY=0x20, /* Hash-only multicast filter. */	HAS_NWAY143=0x40,			/* Uses 21143-like internal NWay. */};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, 0x0001ebef, 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_ACPI | HAS_NWAY143, t21142_timer },  { "Lite-On 82c168 PNIC", 256, 0x0001ebef,	HAS_MII, pnic_timer },  { "Macronix 98713 PMAC", 128, 0x0001ebef,	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer },  { "Macronix 98715 PMAC", 256, 0x0001ebef,	HAS_MEDIA_TABLE, mxic_timer },  { "Macronix 98725 PMAC", 256, 0x0001ebef,	HAS_MEDIA_TABLE, mxic_timer },  { "ASIX AX88140", 128, 0x0001fbff,	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY, tulip_timer },  { "Lite-On PNIC-II", 256, 0x0001ebef,	HAS_MII | HAS_NWAY143, pnic_timer },  { "ADMtek Comet", 256, 0x0001abef,	MC_HASH_ONLY, comet_timer },  { "Compex 9881 PMAC", 128, 0x0001ebef,	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer },  { "Xircom Cardbus Adapter (DEC 21143 compatible mode)", 128, 0x0801fbff,       HAS_MII | HAS_ACPI, tulip_timer },   {0},};/* This matches the table above.  Note 21142 == 21143. */enum chips {	DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3,	LC82C168, MX98713, MX98715, MX98725, AX88140, PNIC2, COMET, COMPEX9881,	X3201_3,};/* A full-duplex map for media types. */enum MediaIs {	MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,	MediaIs100=16};static const char media_cap[] ={0,0,0,16,  3,19,16,24,  27,4,7,5, 0,20,23,20 };static u8 t21040_csr13[] = {2,0x0C,8,4,  4,0,0,0, 0,0,0,0, 4,0,0,0};/* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD*/static u16 t21041_csr13[] = { 0xEF05, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };static u16 t21041_csr14[] = { 0x7F3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };static u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, };static u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, };static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };/* Offsets to the Command and Status Registers, "CSRs".  All accesses   must be longword instructions and quadword aligned. */enum tulip_offsets {	CSR0=0,    CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,	CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,	CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78 };/* The bits in the CSR5 status registers, mostly interrupt sources. */enum status_bits {	TimerInt=0x800, TPLnkFail=0x1000, TPLnkPass=0x10,	NormalIntr=0x10000, AbnormalIntr=0x8000,	RxJabber=0x200, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40,	TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,};/* The Tulip Rx and Tx buffer descriptors. */struct tulip_rx_desc {	s32 status;	s32 length;	u32 buffer1, buffer2;};struct tulip_tx_desc {	s32 status;	s32 length;	u32 buffer1, buffer2;				/* We use only buffer 1.  */};enum desc_status_bits {	DescOwned=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300,};/* Ring-wrap flag in length field, use for last ring entry.	0x01000000 means chain on buffer2 address,	0x02000000 means use the ring start address in CSR2/3.   Note: Some work-alike chips do not function correctly in chained mode.   The ASIX chip works only in chained mode.   Thus we indicates ring mode, but always write the 'next' field for   chained mode as well.*/#define DESC_RING_WRAP 0x02000000#ifdef CARDBUS#define EEPROM_ADDRLEN (chip_rev == 65 ? 8 : 6)#else#define EEPROM_ADDRLEN 6#endif#define EEPROM_SIZE 128 	/* 2 << EEPROM_ADDRLEN */struct medialeaf {	u8 type;	u8 media;	unsigned char *leafdata;};struct mediatable {	u16 defaultmedia;	u8 leafcount, csr12dir;				/* General purpose pin directions. */	unsigned has_mii:1, has_nonmii:1, has_reset:6;	u32 csr15dir, csr15val;				/* 21143 NWay setting. */	struct medialeaf mleaf[0];};struct mediainfo {	struct mediainfo *next;	int info_type;	int index;	unsigned char *info;};struct tulip_private {	char devname[8];			/* Used only for kernel debugging. */

⌨️ 快捷键说明

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