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

📄 eepro100.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/* drivers/net/eepro100.c: An Intel i82557 Ethernet driver for Linux. *//*   NOTICE: this version tested with kernels 1.3.72 and later only!	Written 1996-1998 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 Intel EtherExpress Pro 100B boards.	It should work with other i82557 and i82558 boards.	To use a built-in driver, install as drivers/net/eepro100.c.	To use as a module, use the compile-command at the end of the file.	The author may be reached as becker@CESDIS.usra.edu, or C/O	Center of Excellence in Space Data and Information Sciences	   Code 930.5, NASA Goddard Space Flight Center, Greenbelt MD 20771	For updates see		http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html	There is also a mailing list based at		linux-eepro100@cesdis.gsfc.nasa.gov*/static const char *version ="eepro100.c:v1.06 10/16/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n";/* A few user-configurable values that apply to all boards.   First set are 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 = 200;/* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */static int multicast_filter_limit = 64;#include <linux/module.h>#include <linux/version.h>#include <linux/kernel.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 <asm/spinlock.h>#include <asm/bitops.h>#include <asm/io.h>/* * Module documentation */MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver");MODULE_PARM(debug, "i");MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "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");#define RUN_AT(x) (jiffies + (x))#define dev_free_skb(skb) dev_kfree_skb(skb);/* The total I/O port extent of the board.   The registers beyond 0x18 only exist on the i82558. */#define SPEEDO3_TOTAL_SIZE 0x20int speedo_debug = 0;/*				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!*//* A few values that may be tweaked. *//* The ring sizes should be a power of two for efficiency. */#define TX_RING_SIZE	16		/* Effectively 2 entries fewer. */#define RX_RING_SIZE	16/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/#define PKT_BUF_SZ		1536/* Time in jiffies before concluding the transmitter is hung. */#define TX_TIMEOUT  ((800*HZ)/1000)/* How to wait for the command unit to accept a command.   Typically this takes 0 ticks. */static inline void wait_for_cmd_done(long cmd_ioaddr){	int wait = 100;	do   ;	while(inb(cmd_ioaddr) && --wait >= 0);}/* Operational parameter that usually are not changed. *//* The rest of these values should never change. *//* Offsets to the various registers.   All accesses need not be longword aligned. */enum speedo_offsets {	SCBStatus = 0, SCBCmd = 2,	/* Rx/Command Unit command and status. */	SCBPointer = 4,				/* General purpose pointer. */	SCBPort = 8,				/* Misc. commands and operands.  */	SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */	SCBCtrlMDI = 16,			/* MDI interface control. */	SCBEarlyRx = 20,			/* Early receive byte count. */};/* Commands that can be put in a command list entry. */enum commands {	CmdNOp = 0, CmdIASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,	CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7,	CmdSuspend = 0x4000,		/* Suspend after completion. */	CmdIntr = 0x2000,			/* Interrupt after completion. */	CmdTxFlex = 0x0008,			/* Use "Flexible mode" for CmdTx command. */};/* The SCB accepts the following controls for the Tx and Rx units: */#define	 CU_START		0x0010#define	 CU_RESUME		0x0020#define	 CU_STATSADDR	0x0040#define	 CU_SHOWSTATS	0x0050	/* Dump statistics counters. */#define	 CU_CMD_BASE	0x0060	/* Base address to add to add CU commands. */#define	 CU_DUMPSTATS	0x0070	/* Dump then reset stats counters. */#define	 RX_START	0x0001#define	 RX_RESUME	0x0002#define	 RX_ABORT	0x0004#define	 RX_ADDR_LOAD	0x0006#define	 RX_RESUMENR	0x0007#define INT_MASK	0x0100#define DRVR_INT	0x0200		/* Driver generated interrupt. *//* The Speedo3 Rx and Tx frame/buffer descriptors. */struct descriptor {			/* A generic descriptor. */	s16 status;		/* Offset 0. */	s16 command;		/* Offset 2. */	u32 link;					/* struct descriptor *  */	unsigned char params[0];};/* The Speedo3 Rx and Tx buffer descriptors. */struct RxFD {					/* Receive frame descriptor. */	s32 status;	u32 link;					/* struct RxFD * */	u32 rx_buf_addr;			/* void * */	u16 count;	u16 size;};/* Selected elements of the Tx/RxFD.status word. */enum RxFD_bits {	RxComplete=0x8000, RxOK=0x2000,	RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010,	RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002,	StatusComplete=0x8000,};struct TxFD {					/* Transmit frame descriptor set. */	s32 status;	u32 link;					/* void * */	u32 tx_desc_addr;			/* Always points to the tx_buf_addr element. */	s32 count;					/* # of TBD (=1), Tx start thresh., etc. */	/* This constitutes two "TBD" entries -- we only use one. */	u32 tx_buf_addr0;			/* void *, frame to be transmitted.  */	s32 tx_buf_size0;			/* Length of Tx frame. */	u32 tx_buf_addr1;			/* void *, frame to be transmitted.  */	s32 tx_buf_size1;			/* Length of Tx frame. */};/* Elements of the dump_statistics block. This block must be lword aligned. */struct speedo_stats {	u32 tx_good_frames;	u32 tx_coll16_errs;	u32 tx_late_colls;	u32 tx_underruns;	u32 tx_lost_carrier;	u32 tx_deferred;	u32 tx_one_colls;	u32 tx_multi_colls;	u32 tx_total_colls;	u32 rx_good_frames;	u32 rx_crc_errs;	u32 rx_align_errs;	u32 rx_resource_errs;	u32 rx_overrun_errs;	u32 rx_colls_errs;	u32 rx_runt_errs;	u32 done_marker;};struct speedo_private {	char devname[8];			/* Used only for kernel debugging. */	const char *product_name;	struct device *next_module;	spinlock_t lock;	struct TxFD	tx_ring[TX_RING_SIZE];	/* Commands (usually CmdTxPacket). */	/* The saved address of a sent-in-place packet/buffer, for skfree(). */	struct sk_buff* tx_skbuff[TX_RING_SIZE];	struct descriptor  *last_cmd;	/* Last command sent. */	/* Rx descriptor ring & addresses of receive-in-place skbuffs. */	struct RxFD *rx_ringp[RX_RING_SIZE];	struct sk_buff* rx_skbuff[RX_RING_SIZE];	struct RxFD *last_rxf;	/* Last command sent. */	struct enet_statistics stats;	struct speedo_stats lstats;	struct timer_list timer;	/* Media selection timer. */	long last_rx_time;			/* Last Rx, in jiffies, to handle Rx hang. */	unsigned int cur_rx, cur_tx;		/* The next free ring entry */	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */	int mc_setup_frm_len;			 	/* The length of an allocated.. */	struct descriptor *mc_setup_frm; 	/* ..multicast setup frame. */	int mc_setup_busy;					/* Avoid double-use of setup frame. */	char rx_mode;						/* Current PROMISC/ALLMULTI setting. */	unsigned int tx_full:1;				/* The Tx queue is full. */	unsigned int full_duplex:1;			/* Full-duplex operation requested. */	unsigned int default_port:1;		/* Last dev->if_port value. */	unsigned int rx_bug:1;				/* Work around receiver hang errata. */	unsigned int rx_bug10:1;			/* Receiver might hang at 10mbps. */	unsigned int rx_bug100:1;			/* Receiver might hang at 100mbps. */	unsigned short phy[2];				/* PHY media interfaces available. */};/* The parameters for a CmdConfigure operation.   There are so many options that it would be difficult to document each bit.   We mostly use the default or recommended settings. */const char i82557_config_cmd[22] = {	22, 0x08, 0, 0,  0, 0x80, 0x32, 0x03,  1, /* 1=Use MII  0=Use AUI */	0, 0x2E, 0,  0x60, 0,	0xf2, 0x48,   0, 0x40, 0xf2, 0x80, 		/* 0x40=Force full-duplex */	0x3f, 0x05, };const char i82558_config_cmd[22] = {	22, 0x08, 0, 1,  0, 0x80, 0x22, 0x03,  1, /* 1=Use MII  0=Use AUI */	0, 0x2E, 0,  0x60, 0x08, 0x88,	0x68, 0, 0x40, 0xf2, 0xBD, 		/* 0xBD->0xFD=Force full-duplex */	0x31, 0x05, };/* PHY media interface chips. */static const char *phys[] = {	"None", "i82553-A/B", "i82553-C", "i82503",	"DP83840", "80c240", "80c24", "i82555",	"unknown-8", "unknown-9", "DP83840A", "unknown-11",	"unknown-12", "unknown-13", "unknown-14", "unknown-15", };enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,					 S80C24, I82555, DP83840A=10, };static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 };static void speedo_found1(struct device *dev, long ioaddr, int irq,						  int card_idx);static int read_eeprom(long ioaddr, int location, int addr_len);static int mdio_read(long ioaddr, int phy_id, int location);static int mdio_write(long ioaddr, int phy_id, int location, int value);static int speedo_open(struct device *dev);static void speedo_timer(unsigned long data);static void speedo_init_rx_ring(struct device *dev);static int speedo_start_xmit(struct sk_buff *skb, struct device *dev);static int speedo_rx(struct device *dev);static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);static int speedo_close(struct device *dev);

⌨️ 快捷键说明

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