📄 8139too.c
字号:
/* 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux. Maintained by Jeff Garzik <jgarzik@mandrakesoft.com> Much code comes from Donald Becker's rtl8139.c driver, versions 1.11 and older. This driver was originally based on rtl8139.c version 1.07. Header of rtl8139.c version 1.11: -----<snip>----- Written 1997-2000 by Donald Becker. 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. This driver is for boards based on the RTL8129 and RTL8139 PCI ethernet chips. 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/rtl8139.html Twister-tuning table provided by Kinston <shangh@realtek.com.tw>. -----<snip>----- This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. Contributors: Donald Becker - he wrote the original driver, kudos to him! (but please don't e-mail him for support, this isn't his driver) Tigran Aivazian - bug fixes, skbuff free cleanup Martin Mares - suggestions for PCI cleanup David S. Miller - PCI DMA and softnet updates Ernst Gill - fixes ported from BSD driver Daniel Kobras - identified specific locations of posted MMIO write bugginess Gerard Sharp - bug fix, testing and feedback David Ford - Rx ring wrap fix Dan DeMaggio - swapped RTL8139 cards with me, and allowed me to find and fix a crucial bug on older chipsets. Donald Becker/Chris Butterworth/Marcus Westergren - Noticed various Rx packet size-related buglets. Santiago Garcia Mantinan - testing and feedback Jens David - 2.2.x kernel backports Martin Dennett - incredibly helpful insight on undocumented features of the 8139 chips Jean-Jacques Michel - bug fix Tobias Ringstr鰉 - Rx interrupt status checking suggestion Andrew Morton - (v0.9.13): clear blocked signals, avoid buffer overrun setting current->comm. Submitting bug reports: "rtl8139-diag -mmmaaavvveefN" output enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log See 8139too.txt for more details.----------------------------------------------------------------------------- Theory of OperationI. Board CompatibilityThis device driver is designed for the RealTek RTL8139 series, the RealTekFast Ethernet controllers for PCI and CardBus. This chip is used on manylow-end boards, sometimes with its markings changed.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 will assign thePCI INTA signal to a (preferably otherwise unused) system IRQ line.III. Driver operationIIIa. Rx Ring buffersThe receive unit uses a single linear ring buffer rather than the morecommon (and more efficient) descriptor-based architecture. Incoming framesare sequentially stored into the Rx region, and the host copies them intoskbuffs.Comment: While it is theoretically possible to process many frames in place,any delay in Rx processing would cause us to drop frames. More importantly,the Linux protocol stack is not designed to operate in this manner.IIIb. Tx operationThe RTL8139 uses a fixed set of four Tx descriptors in register space.In a stunningly bad design choice, Tx frames must be 32 bit aligned. Linuxaligns the IP header on word boundaries, and 14 byte ethernet header meansthat almost all frames will need to be copied to an alignment buffer.IVb. Referenceshttp://www.realtek.com.tw/cn/cn.htmlhttp://www.scyld.com/expert/NWay.htmlIVc. Errata1) The RTL-8139 has a serious problem with motherboards which doposted MMIO writes to PCI space. This driver works around theproblem by having an MMIO register write be immediately followed byan MMIO register read.2) The RTL-8129 is only supported in Donald Becker's rtl8139 driver.*/#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/ioport.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/rtnetlink.h>#include <linux/delay.h>#include <asm/io.h>#define RTL8139_VERSION "0.9.13"#define MODNAME "8139too"#define RTL8139_DRIVER_NAME MODNAME " Fast Ethernet driver " RTL8139_VERSION#define PFX MODNAME ": "/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */#ifdef CONFIG_8139TOO_PIO#define USE_IO_OPS 1#endif/* define to 1 to enable copious debugging info */#undef RTL8139_DEBUG/* define to 1 to disable lightweight runtime debugging checks */#undef RTL8139_NDEBUG#ifdef RTL8139_DEBUG/* note: prints function name for you */# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)#else# define DPRINTK(fmt, args...)#endif#ifdef RTL8139_NDEBUG# define assert(expr) do {} while (0)#else# define assert(expr) \ if(!(expr)) { \ printk( "Assertion failed! %s,%s,%s,line=%d\n", \ #expr,__FILE__,__FUNCTION__,__LINE__); \ }#endif/* A few user-configurable values. *//* media options */static int media[] = {-1, -1, -1, -1, -1, -1, -1, -1};/* 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). The RTL chips use a 64 element hash table based on the Ethernet CRC. */static int multicast_filter_limit = 32;/* Size of the in-memory receive ring. */#define RX_BUF_LEN_IDX 2 /* 0==8K, 1==16K, 2==32K, 3==64K */#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)#define RX_BUF_PAD 16#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)/* Number of Tx descriptor registers. */#define NUM_TX_DESC 4/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/#define MAX_ETH_FRAME_SIZE 1536/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC)/* PCI Tuning Parameters Threshold is bytes transferred to chip before transmission starts. */#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. *//* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */#define RX_FIFO_THRESH 6 /* Rx buffer level before first PCI xfer. */#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 *//* Operational parameters that usually are not changed. *//* Time in jiffies before concluding the transmitter is hung. */#define TX_TIMEOUT (6*HZ)enum { HAS_CHIP_XCVR = 0x020000, HAS_LNK_CHNG = 0x040000,};#define RTL_MIN_IO_SIZE 0x80#define RTL8139B_IO_SIZE 256#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNGtypedef enum { RTL8139 = 0, RTL8139_CB, SMC1211TX, /*MPX5030,*/ DELTA8139, ADDTRON8139,} board_t;/* indexed by board_t, above */static struct { const char *name;} board_info[] __devinitdata = { { "RealTek RTL8139 Fast Ethernet" }, { "RealTek RTL8139B PCI/CardBus" }, { "SMC1211TX EZCard 10/100 (RealTek RTL8139)" },/* { MPX5030, "Accton MPX5030 (RealTek RTL8139)" },*/ { "Delta Electronics 8139 10/100BaseTX" }, { "Addtron Technolgy 8139 10/100BaseTX" },};static struct pci_device_id rtl8139_pci_tbl[] __devinitdata = { {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139_CB }, {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMC1211TX },/* {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MPX5030 },*/ {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DELTA8139 }, {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 }, {0,}};MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl);/* The rest of these values should never change. *//* Symbolic offsets to registers. */enum RTL8139_registers { MAC0 = 0, /* Ethernet hardware address. */ MAR0 = 8, /* Multicast filter. */ TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ RxBuf = 0x30, RxEarlyCnt = 0x34, RxEarlyStatus = 0x36, ChipCmd = 0x37, RxBufPtr = 0x38, RxBufAddr = 0x3A, IntrMask = 0x3C, IntrStatus = 0x3E, TxConfig = 0x40, ChipVersion = 0x43, RxConfig = 0x44, Timer = 0x48, /* A general-purpose counter. */ RxMissed = 0x4C, /* 24 bits valid, write clears. */ Cfg9346 = 0x50, Config0 = 0x51, Config1 = 0x52, FlashReg = 0x54, MediaStatus = 0x58, Config3 = 0x59, Config4 = 0x5A, /* absent on RTL-8139A */ HltClk = 0x5B, MultiIntr = 0x5C, TxSummary = 0x60, BasicModeCtrl = 0x62, BasicModeStatus = 0x64, NWayAdvert = 0x66, NWayLPAR = 0x68, NWayExpansion = 0x6A, /* Undocumented registers, but required for proper operation. */ FIFOTMS = 0x70, /* FIFO Control and test. */ CSCR = 0x74, /* Chip Status and Configuration Register. */ PARA78 = 0x78, PARA7c = 0x7c, /* Magic transceiver parameter register. */ Config5 = 0xD8, /* absent on RTL-8139A */};enum ClearBitMasks { MultiIntrClear = 0xF000, ChipCmdClear = 0xE2, Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1),};enum ChipCmdBits { CmdReset = 0x10, CmdRxEnb = 0x08, CmdTxEnb = 0x04, RxBufEmpty = 0x01,};/* Interrupt register bits, using my own meaningful names. */enum IntrStatusBits { PCIErr = 0x8000, PCSTimeout = 0x4000, RxFIFOOver = 0x40, RxUnderrun = 0x20, RxOverflow = 0x10, TxErr = 0x08, TxOK = 0x04, RxErr = 0x02, RxOK = 0x01,};enum TxStatusBits { TxHostOwns = 0x2000, TxUnderrun = 0x4000, TxStatOK = 0x8000, TxOutOfWindow = 0x20000000, TxAborted = 0x40000000, TxCarrierLost = 0x80000000,};enum RxStatusBits { RxMulticast = 0x8000, RxPhysical = 0x4000, RxBroadcast = 0x2000, RxBadSymbol = 0x0020, RxRunt = 0x0010, RxTooLong = 0x0008, RxCRCErr = 0x0004, RxBadAlign = 0x0002, RxStatusOK = 0x0001,};/* Bits in RxConfig. */enum rx_mode_bits { AcceptErr = 0x20, AcceptRunt = 0x10, AcceptBroadcast = 0x08, AcceptMulticast = 0x04, AcceptMyPhys = 0x02, AcceptAllPhys = 0x01,};/* Bits in TxConfig. */enum tx_config_bits { TxIFG1 = (1 << 25), /* Interframe Gap Time */ TxIFG0 = (1 << 24), /* Enabling these bits violates IEEE 802.3 */ TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ TxClearAbt = (1 << 0), /* Clear abort (WO) */ TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */};/* Bits in Config1 */enum Config1Bits { Cfg1_PM_Enable = 0x01, Cfg1_VPD_Enable = 0x02, Cfg1_PIO = 0x04, Cfg1_MMIO = 0x08, Cfg1_LWAKE = 0x10, Cfg1_Driver_Load = 0x20, Cfg1_LED0 = 0x40, Cfg1_LED1 = 0x80,};enum RxConfigBits { /* Early Rx threshold, none or X/16 */ RxCfgEarlyRxNone = 0, RxCfgEarlyRxShift = 24, /* rx fifo threshold */ RxCfgFIFOShift = 13, RxCfgFIFONone = (7 << RxCfgFIFOShift), /* Max DMA burst */ RxCfgDMAShift = 8, RxCfgDMAUnlimited = (7 << RxCfgDMAShift), /* rx ring buffer length */ RxCfgRcv8K = 0, RxCfgRcv16K = (1 << 11), RxCfgRcv32K = (1 << 12), RxCfgRcv64K = (1 << 11) | (1 << 12), /* Disable packet wrap at end of Rx buffer */ RxNoWrap = (1 << 7),};/* Twister tuning parameters from RealTek. Completely undocumented, but required to tune bad links. */enum CSCRBits { CSCR_LinkOKBit = 0x0400, CSCR_LinkChangeBit = 0x0800, CSCR_LinkStatusBits = 0x0f000, CSCR_LinkDownOffCmd = 0x003c0, CSCR_LinkDownCmd = 0x0f3c0,};enum Cfg9346Bits { Cfg9346_Lock = 0x00, Cfg9346_Unlock = 0xC0,};#define PARA78_default 0x78fa8388#define PARA7c_default 0xcb38de43 /* param[0][3] */#define PARA7c_xxx 0xcb38de43static const unsigned long param[4][4] = { {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83}};struct ring_info { struct sk_buff *skb; dma_addr_t mapping;};typedef enum { CH_8139 = 0, CH_8139_K, CH_8139A, CH_8139B, CH_8130, CH_8139C,} chip_t;/* directly indexed by chip_t, above */const static struct { const char *name; u8 version; /* from RTL8139C docs */ u32 RxConfigMask; /* should clear the bits supported by this chip */} rtl_chip_info[] = { { "RTL-8139", 0x40, 0xf0fe0040, /* XXX copied from RTL8139A, verify */ }, { "RTL-8139 rev K", 0x60, 0xf0fe0040, }, { "RTL-8139A", 0x70, 0xf0fe0040, }, { "RTL-8139B", 0x78, 0xf0fc0040 }, { "RTL-8130", 0x7C, 0xf0fe0040, /* XXX copied from RTL8139A, verify */ }, { "RTL-8139C", 0x74, 0xf0fc0040, /* XXX copied from RTL8139B, verify */ },};struct rtl8139_private { board_t board; void *mmio_addr; int drv_flags; struct pci_dev *pci_dev; struct net_device_stats stats; unsigned char *rx_ring; unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ unsigned int tx_flag; unsigned int cur_tx; unsigned int dirty_tx; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ struct ring_info tx_info[NUM_TX_DESC]; unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ unsigned char *tx_bufs; /* Tx bounce buffer region. */ dma_addr_t rx_ring_dma; dma_addr_t tx_bufs_dma; char phys[4]; /* MII device addresses. */ char twistie, twist_row, twist_col; /* Twister tune state. */ unsigned int full_duplex:1; /* Full-duplex operation requested. */ unsigned int duplex_lock:1; unsigned int default_port:4; /* Last dev->if_port value. */ unsigned int media2:4; /* Secondary monitored media port. */ unsigned int medialock:1; /* Don't sense media type. */ unsigned int mediasense:1; /* Media sensing in progress. */ spinlock_t lock; chip_t chipset; pid_t thr_pid; wait_queue_head_t thr_wait; struct semaphore thr_exited;};MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver");MODULE_PARM (multicast_filter_limit, "i");MODULE_PARM (max_interrupt_work, "i");MODULE_PARM (media, "1-" __MODULE_STRING(8) "i");static int read_eeprom (void *ioaddr, int location, int addr_len);static int rtl8139_open (struct net_device *dev);static int mdio_read (struct net_device *dev, int phy_id, int location);static void mdio_write (struct net_device *dev, int phy_id, int location, int val);static int rtl8139_thread (void *data);static void rtl8139_tx_timeout (struct net_device *dev);static void rtl8139_init_ring (struct net_device *dev);static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev);static void rtl8139_interrupt (int irq, void *dev_instance, struct pt_regs *regs);static int rtl8139_close (struct net_device *dev);static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);static struct net_device_stats *rtl8139_get_stats (struct net_device *dev);static inline u32 ether_crc (int length, unsigned char *data);static void rtl8139_set_rx_mode (struct net_device *dev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -