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

📄 eepro100_cb.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 5 页
字号:
/* drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux. *//*   NOTICE: For use with kernel versions 1.3.72 and later only!	Written 1996-1999 by Donald Becker.	This software may be used and distributed according to the terms	of the GNU General Public License, incorporated herein by reference.	This driver is for the Intel EtherExpress Pro100 (Speedo3) design.	It should work with all i82557/558/559 boards.	To use as a module, use the compile-command at the end of the file.	The author may be reached as becker@scyld.com, or C/O	Scyld Computing Corporation	410 Severn Ave., Suite 210	Annapolis MD 21403	Information and updates available at	http://www.scyld.com/network/eepro100.html    PCMCIA Cardbus support by Peter Naulls <Peter.Naulls@FutureTV.com> and    Philip Blundell <Philip.Blundell@FutureTV.com>*/static const char *version ="eepro100.c:v1.09t 9/29/99 Donald Becker http://www.scyld.com/network/eepro100.html\n";/* A few user-configurable values that apply to all boards.   First set is undocumented and spelled per Intel recommendations. */static int congenb = 0;		/* Enable congestion control in the DP83840. */static int txfifo = 8;		/* Tx FIFO threshold in 4 byte units, 0-15 */static int rxfifo = 8;		/* Rx FIFO threshold, default 32 bytes. *//* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */static int txdmacount = 128;static int rxdmacount = 0;/* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.   Lower values use more memory, but are faster. */static int rx_copybreak = 200;/* Maximum events (Rx packets, etc.) to handle at each interrupt. */static int max_interrupt_work = 20;/* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */static int multicast_filter_limit = 3;/* 'options' is used to pass a transceiver override or full-duplex flag   e.g. "options=16" for FD, "options=32" for 100mbps-only. */#define MAX_UNITS 8		/* More are supported, limit only on options */static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};static int debug = 1;			/* The debug level */#define speedo_debug debug/* A few values that may be tweaked. *//* The ring sizes should be a power of two for efficiency. */#define TX_RING_SIZE	32		/* Effectively 2 entries fewer. */#define RX_RING_SIZE	32/* Actual number of TX packets queued, must be <= TX_RING_SIZE-2. */#define TX_QUEUE_LIMIT  12#define TX_QUEUE_UNFULL 8		/* Hysteresis marking queue as no longer full. *//* Operational parameters that usually are not changed. *//* Time in jiffies before concluding the transmitter is hung. */#define TX_TIMEOUT  (2*HZ)/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/#define PKT_BUF_SZ		1536#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>#include <linux/module.h>#if defined(MODVERSIONS)#include <linux/modversions.h>#endif#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 <asm/bitops.h>#include <asm/io.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/delay.h>MODULE_AUTHOR("Donald Becker <becker@www.scyld.com>");MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver");MODULE_LICENSE("GPL");MODULE_PARM(debug, "i");MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");MODULE_PARM(congenb, "i");MODULE_PARM(txfifo, "i");MODULE_PARM(rxfifo, "i");MODULE_PARM(txdmacount, "i");MODULE_PARM(rxdmacount, "i");MODULE_PARM(rx_copybreak, "i");MODULE_PARM(max_interrupt_work, "i");MODULE_PARM(multicast_filter_limit, "i");/* Condensed bus+endian portability operations. */#define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))#define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))#if (LINUX_VERSION_CODE >= 0x20100)char kernel_version[] = UTS_RELEASE;#endif#if LINUX_VERSION_CODE < 0x20100  &&  ! defined(__alpha__)#define ioremap vremap#define iounmap vfree#endif#if (LINUX_VERSION_CODE < 0x20123)#define test_and_set_bit(val, addr) set_bit(val, addr)typedef long spinlock_t;#define SPIN_LOCK_UNLOCKED 0#define spin_lock(lock)#define spin_unlock(lock)#define spin_lock_irqsave(lock, flags)	save_flags(flags); cli();#define spin_unlock_irqrestore(lock, flags) restore_flags(flags);#endif#if LINUX_VERSION_CODE < 0x20155#include <linux/bios32.h>/* A minimal version of the 2.2.* PCI support that handles configuration   space access.   Drivers that actually use pci_dev fields must do explicit compatibility.   Note that the struct pci_dev * "pointer" is actually a byte mapped integer!*/#if LINUX_VERSION_CODE < 0x20020struct pci_dev { int not_used; };#endif#define pci_find_slot(bus, devfn) (struct pci_dev*)((bus<<8) | devfn | 0xf0000)#define bus_number(pci_dev) ((((int)(pci_dev))>>8) & 0xff)#define devfn_number(pci_dev) (((int)(pci_dev)) & 0xff)#ifndef CONFIG_PCIextern inline int pci_present(void) { return 0; }#else#define pci_present pcibios_present#endif#define pci_read_config_byte(pdev, where, valp)\	pcibios_read_config_byte(bus_number(pdev), devfn_number(pdev), where, valp)#define pci_read_config_word(pdev, where, valp)\	pcibios_read_config_word(bus_number(pdev), devfn_number(pdev), where, valp)#define pci_read_config_dword(pdev, where, valp)\	pcibios_read_config_dword(bus_number(pdev), devfn_number(pdev), where, valp)#define pci_write_config_byte(pdev, where, val)\	pcibios_write_config_byte(bus_number(pdev), devfn_number(pdev), where, val)#define pci_write_config_word(pdev, where, val)\	pcibios_write_config_word(bus_number(pdev), devfn_number(pdev), where, val)#define pci_write_config_dword(pdev, where, val)\	pcibios_write_config_dword(bus_number(pdev), devfn_number(pdev), where, val)#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 LINUX_VERSION_CODE < 0x2030d#define net_device device#endif#if ! defined(CAP_NET_ADMIN)#define capable(CAP_XXX) (suser())#endif#if  ! defined(HAS_PCI_NETIF)enum pci_id_flags_bits {	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,	PCI_ADDR0=0<<4, PCI_ADDR1=1<<4, PCI_ADDR2=2<<4, PCI_ADDR3=3<<4,};struct pci_id_info {	const char *name;	struct match_info {		int	pci, pci_mask, subsystem, subsystem_mask, revision, revision_mask;	} id;	enum pci_id_flags_bits pci_flags;	int io_size;				/* Needed for I/O region check or ioremap(). */	int drv_flags;				/* Driver use, intended as capability flags. */};struct drv_id_info {	const char *name;			/* Single-word driver name. */	int flags;	int pci_class;	struct pci_id_info *pci_dev_tbl;	void *(*probe1)(struct pci_dev *pdev, void *init_dev,					long ioaddr, int irq, int table_idx, int fnd_cnt);	/* Optional, called for suspend, resume and detach. */	int (*pwr_event)(void *dev, int event);};#define acpi_set_pwr_state(pci_dev, state) nullop()static __inline__ int nullop(void) { return 0;}#endif/*				Theory of OperationI. Board CompatibilityThis device driver is designed for the Intel i82557 "Speedo3" chip, Intel'ssingle-chip fast Ethernet controller for PCI, as used on the IntelEtherExpress Pro 100 adapter.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 should be set to assign thePCI INTA signal to an otherwise unused system IRQ line.  While it'spossible to share PCI interrupt lines, it negatively impacts performance andonly recent kernels support it.III. Driver operationIIIA. GeneralThe Speedo3 is very similar to other Intel network chips, that is to say"apparently designed on a different planet".  This chips retains the complexRx and Tx descriptors and multiple buffers pointers as previous chips, butalso has simplified Tx and Rx buffer modes.  This driver uses the "flexible"Tx mode, but in a simplified lower-overhead manner: it associates only asingle buffer descriptor with each frame descriptor.Despite the extra space overhead in each receive skbuff, the driver must usethe simplified Rx buffer mode to assure that only a single data buffer isassociated with each RxFD. The driver implements this by reserving spacefor the Rx descriptor at the head of each Rx skbuff.The Speedo-3 has receive and command unit base addresses that are added toalmost all descriptor pointers.  The driver sets these to zero, so that allpointer fields are absolute addresses.The System Control Block (SCB) of some previous Intel chips exists on thechip in both PCI I/O and memory space.  This driver uses the I/O spaceregisters, but might switch to memory mapped mode to better support non-x86processors.IIIB. Transmit structureThe driver must use the complex Tx command+descriptor mode in order tohave a indirect pointer to the skbuff data section.  Each Tx command block(TxCB) is associated with two immediately appended Tx Buffer Descriptor(TxBD).  A fixed ring of these TxCB+TxBD pairs are kept as part of thespeedo_private data structure for each adapter instance.The newer i82558 explicitly supports this structure, and can read the twoTxBDs in the same PCI burst as the TxCB.This ring structure is used for all normal transmit packets, but thetransmit packet descriptors aren't long enough for most non-Tx commands suchas CmdConfigure.  This is complicated by the possibility that the chip hasalready loaded the link address in the previous descriptor.  So for thesecommands we convert the next free descriptor on the ring to a NoOp, and pointthat descriptor's link to the complex command.An additional complexity of these non-transmit commands are that they may beadded asynchronous to the normal transmit queue, so we disable interruptswhenever the Tx descriptor ring is manipulated.A notable aspect of these special configure commands is that they dowork with the normal Tx ring entry scavenge method.  The Tx ring scavengeis done at interrupt time using the 'dirty_tx' index, and checking for thecommand-complete bit.  While the setup frames may have the NoOp command on theTx ring marked as complete, but not have completed the setup command, thisis not a problem.  The tx_ring entry can be still safely reused, as thetx_skbuff[] entry is always empty for config_cmd and mc_setup frames.Commands may have bits set e.g. CmdSuspend in the command word to eithersuspend or stop the transmit/command unit.  This driver always flags the lastcommand with CmdSuspend, erases the CmdSuspend in the previous command, andthen issues a CU_RESUME.Note: Watch out for the potential race condition here: imagine	erasing the previous suspend		the chip processes the previous command		the chip processes the final command, and suspends	doing the CU_RESUME		the chip processes the next-yet-valid post-final-command.So blindly sending a CU_RESUME is only safe if we do it immediately afterafter erasing the previous CmdSuspend, without the possibility of anintervening delay.  Thus the resume command is always within theinterrupts-disabled region.  This is a timing dependence, but handling thiscondition in a timing-independent way would considerably complicate the code.Note: In previous generation Intel chips, restarting the command unit was anotoriously slow process.  This is presumably no longer true.IIIC. Receive structureBecause of the bus-master support on the Speedo3 this driver uses the newSKBUFF_RX_COPYBREAK scheme, rather than a fixed intermediate receive buffer.This scheme allocates full-sized skbuffs as receive buffers.  The valueSKBUFF_RX_COPYBREAK is used as the copying breakpoint: it is chosen totrade-off the memory wasted by passing the full-sized skbuff to the queuelayer for all frames vs. the copying cost of copying a frame to acorrectly-sized skbuff.For small frames the copying cost is negligible (esp. considering that weare pre-loading the cache with immediately useful header information), so weallocate a new, minimally-sized skbuff.  For large frames the copying costis non-trivial, and the larger copy might flush the cache of useful data, sowe pass up the skbuff the packet was received into.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 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 'sp->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 'sp->tx_full' flag is set, it clears both thetx_full and tbusy flags.IV. NotesThanks to Steve Williams of Intel for arranging the non-disclosure agreementthat stated that I could disclose the information.  But I still resenthaving to sign an Intel NDA when I'm helping Intel sell their own product!*//* This table drives the PCI probe routines. */static void *speedo_found1(struct pci_dev *pdev, void *init_dev,						   long ioaddr, int irq, int chip_idx, int fnd_cnt);/* I/O registers beyond 0x18 do not exist on the i82557. */#ifdef USE_IO_OPS#define SPEEDO_IOTYPE   PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR1#define SPEEDO_SIZE		32#else#define SPEEDO_IOTYPE   PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR0#define SPEEDO_SIZE		0x1000#endifstruct pci_id_info static pci_id_tbl[] = {	{"Intel PCI EtherExpress Pro100", { 0x12298086, 0xffffffff,},	 SPEEDO_IOTYPE, SPEEDO_SIZE, 0,},	{"Intel EtherExpress Pro/100+ i82559ER",   { 0x12098086, 0xffffffff,},	 SPEEDO_IOTYPE, SPEEDO_SIZE, 0,},	{"Intel EtherExpress Pro/100 #1029",   { 0x10298086, 0xffffffff,},	 SPEEDO_IOTYPE, SPEEDO_SIZE, 0, },	{0,},						/* 0 terminated list. */};struct drv_id_info eepro100_drv_id = {	"eepro100_cb", 0, PCI_CLASS_NETWORK_ETHERNET<<8, pci_id_tbl,	speedo_found1, };#ifndef USE_IO_OPS#undef inb#undef inw#undef inl#undef outb#undef outw#undef outl#define inb readb#define inw readw#define inl readl#define outb writeb#define outw writew#define outl writel#endif

⌨️ 快捷键说明

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