📄 rtl8139.c
字号:
/* rtl8139.c: A RealTek RTL8129/8139 Fast Ethernet driver for Linux. *//* 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>.*//* These identify the driver base version and may not be removed. */static const char versionA[] ="rtl8139.c:v1.11a 7/14/2000 Donald Becker, becker@scyld.com.\n";static const char versionB[] =" http://www.scyld.com/network/rtl8139.html\n";static const char versionC[] ="rtl8139.c:vR1.0, Support Realtek 8139C+ Fast Ethernet.\n";/*------------------------------------------------------------------------------------------------- 2001/10/24 ShuChen Shao1.This driver is based on rtl8139.c version 1.11 written by Donald Becker and modified by Clifford Chiang, wrchiang@realtek.com.tw, to support C+ mode operation with Link Down Power Saving and ShuChen Shao, shuchen@realtek.com.tw, to support both C and C+ mode operation with Medium type selection.2.It has been tested in 2.2.14 kernel.3.RTL8139C+ PCI ethernet chips is set to support C+ mode by default. If FORCE_8139CP_TO_C_MODE below is enable, the RTL8139C+ chip will be forced to support C mode after reboot.4.This object file obtained after compiling rtl8139.c is supposed to be at /lib/modules/2.2.14-5.0/net.------------------------------------------------------------------------------------------------- *///#define FORCE_8139CP_TO_C_MODE#define CPlus8139Version 0x76#ifndef USE_MEM_OPS/* Note: Register access width and timing restrictions apply in MMIO mode. This updated driver should nominally work, but I/O mode is better tested. */#define USE_IO_OPS#endif/* The user-configurable values. These may be modified when a driver module is loaded.*/static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. *//* 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. It is efficient to update the hardware filter, but recalculating the table for a long filter list is painful. */static int multicast_filter_limit = 32;/* Used to pass the full-duplex flag, etc. */#define MAX_UNITS 8 /* More are supported, limit only on options */static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};/* Operational parameters that are set at compile time. *//* 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)/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */#define TX_BUF_SIZE 1536/* 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. */#define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */#define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */#define TX_DMA_BURST 4 /* Calculate as 16<<val. *//* Operational parameters that usually are not changed. *//* Time in jiffies before concluding the transmitter is hung. */#define TX_TIMEOUT (6*HZ)#ifndef __KERNEL__#define __KERNEL__#endif#if !defined(__OPTIMIZE__)#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>#if defined(CONFIG_SMP) && ! defined(__SMP__)#define __SMP__#endif#if defined(CONFIG_MODVERSIONS) && ! defined(MODVERSIONS)#define MODVERSIONS#endif#include <linux/version.h>#include <linux/module.h>#if LINUX_VERSION_CODE < 0x20300 && 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/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>#if LINUX_VERSION_CODE >= 0x20300#include <linux/spinlock.h>#elif LINUX_VERSION_CODE >= 0x20200#include <asm/spinlock.h>#endif#ifdef INLINE_PCISCAN#include "k_compat.h"#else// #include "pci-scan.h"#include "kern_compat.h"#endif#if (LINUX_VERSION_CODE >= 0x20100) && defined(MODULE)char kernel_version[] = UTS_RELEASE;#endif/* Theory of OperationI. Board CompatibilityThis device driver is designed for the RealTek RTL8129 series, the RealTekFast Ethernet controllers for PCI and CardBus. This chip is used on manylow-end boards, sometimes with custom chip labels.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.Note: Kernel versions earlier than 1.3.73 do not support shared PCIinterrupt lines.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 block the Rx ring and cause us to dropframes. It would be difficult to design a protocol stack where the databuffer could be recalled by the device driver.IIIb. Tx operationThe RTL8129 uses a fixed set of four Tx descriptors in register space. Txframes must be 32 bit aligned. Linux aligns the IP header on wordboundaries, and 14 byte ethernet header means that almost all frames willneed to be copied to an alignment buffer. The driver statically allocatesalignment the four alignment buffers at open() time.IVb. Referenceshttp://www.realtek.com.tw/cn/cn.htmlhttp://cesdis.gsfc.nasa.gov/linux/misc/NWay.htmlIVc. Errata*/static void *rtl8139_probe1(struct pci_dev *pdev, void *init_dev, long ioaddr, int irq, int chip_idx, int find_cnt);static int rtl_pwr_event(void *dev_instance, int event);enum chip_capability_flags {HAS_MII_XCVR=0x01, HAS_CHIP_XCVR=0x02, HAS_LNK_CHNG=0x04};#ifdef USE_IO_OPS#define RTL8139_IOTYPE PCI_USES_MASTER|PCI_USES_IO |PCI_ADDR0#else#define RTL8139_IOTYPE PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR1#endif#define RTL8129_CAPS HAS_MII_XCVR#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG/* Note: Update the marked constant in _attach() if the RTL8139B entry moves.*/static struct pci_id_info pci_tbl[] = { {"RealTek RTL8129 Fast Ethernet", { 0x812910ec, 0xffffffff,}, RTL8139_IOTYPE, 0x80, RTL8129_CAPS, }, {"RealTek RTL8139 Fast Ethernet", { 0x813910ec, 0xffffffff,}, RTL8139_IOTYPE, 0x80, RTL8139_CAPS, }, {"RealTek RTL8139B PCI/CardBus", { 0x813810ec, 0xffffffff,}, RTL8139_IOTYPE, 0x80, RTL8139_CAPS, }, {"SMC1211TX EZCard 10/100 (RealTek RTL8139)", { 0x12111113, 0xffffffff,}, RTL8139_IOTYPE, 0x80, RTL8139_CAPS, }, {"Accton MPX5030 (RealTek RTL8139)", { 0x12111113, 0xffffffff,}, RTL8139_IOTYPE, 0x80, RTL8139_CAPS, }, {0,}, /* 0 terminated list. */};struct drv_id_info rtl8139_drv_id = { "realtek", PCI_HOTSWAP, PCI_CLASS_NETWORK_ETHERNET<<8, pci_tbl, rtl8139_probe1, rtl_pwr_event };#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/* The rest of these values should never change. */#define NUM_TX_DESC 4 /* Number of Tx descriptor registers. */#define NUM_CP_TX_DESC 64 /* Number of Tx descriptor registers for C+*/#define NUM_CP_RX_DESC 64 /* Number of Rx descriptor registers for C+*/#define RX_BUF_SIZE 2000#define CPEarlyTxThld 0x06/* Symbolic offsets to registers. */enum RTL8129_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, RxConfig=0x44, Timer=0x48, /* A general-purpose counter. */ RxMissed=0x4C, /* 24 bits valid, write clears. */ Cfg9346=0x50, Config0=0x51, Config1=0x52, FlashReg=0x54, GPPinData=0x58, GPPinDir=0x59, MII_SMI=0x5A, HltClk=0x5B, MultiIntr=0x5C, TxSummary=0x60, MII_BMCR=0x62, MII_BMSR=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,// For C+ Registers MediaStatus = 0x58, BasicModeCtrl = 0x62, CPlusTxPoll=0xD9, CPlusCmd=0xE0, CPlusRxStartAddr=0xE4, CPlusTxStartAddr=0x20, CPlusEarlyTxThld=0xEC,};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,};/* 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 CpChipCmdBits { CpCmdTxEnb=0x0001, CpCmdRxEnb=0x0002, CpCmdMulRWEnb=0x0008, CpCmdDACEnb=0x0010, CpCmdRxChkSumEnb=0x0020, CpCmdRxVlanEnb=0x0040, CpCmdTxVlanEnb=0x0080, };enum Cfg9346Bits { Cfg9346_Lock = 0x00, Cfg9346_Unlock = 0xC0,};enum NegotiationBits { AutoNegotiationEnable = 0x1000, AutoNegotiationRestart = 0x0200, AutoNegoAbility10half = 0x21, AutoNegoAbility10full = 0x41, AutoNegoAbility100half = 0x81, AutoNegoAbility100full = 0x101,};enum MediaStatusBit { SPEED_10_Bit = 0x08, LINK_Status = 0x04, Duplex_Mode = 0x0100,};enum ShiftNum { TX_DMA_BURST_SHIFT = 8, TX_FIFO_THRESH_SHIFT = 11, RX_DMA_BURST_SHIFT = 8, RX_FIFO_THRESH_SHIFT = 13, RX_BUF_LEN_IDX_SHIFT = 11,};#define PARA78_default 0x78fa8388#define PARA7c_default 0xcb38de43 /* param[0][3] */#define PARA7c_xxx 0xcb38de43unsigned long param[4][4]={ {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43}, {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83}, {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83}};struct CPlusTxDesc { u32 status; u32 vlan_tag; u32 buf_addr; u32 buf_Haddr;};struct CPlusRxDesc { u32 status; u32 vlan_tag; u32 buf_addr; u32 buf_Haddr;};#define PRIV_ALIGN 15 /* Desired alignment mask */struct rtl8129_private { struct net_device *next_module; void *priv_addr; /* Unaligned address for kfree */ int chip_id; int drv_flags; struct pci_dev *pci_dev; struct net_device_stats stats; struct timer_list timer; /* Media selection timer. */ unsigned char *rx_ring; unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ unsigned int rx_config; unsigned int cur_tx, dirty_tx, tx_flag; unsigned long tx_full; /* The Tx queue is full. */ /* The saved address of a sent-in-place packet/buffer, for skfree(). */ struct sk_buff* tx_skbuffa[NUM_TX_DESC]; struct sk_buff* tx_skbuff[NUM_CP_TX_DESC]; unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ unsigned char *tx_bufs; /* Tx bounce buffer region. */ 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. */ // For 8139C+ int AutoNegoAbility; unsigned char *txDescArrays; unsigned char *rxDescArrays; struct CPlusTxDesc *txDescArray; struct CPlusRxDesc *rxDescArray; unsigned char *rxBufferRing[NUM_CP_RX_DESC]; unsigned char txPtr; unsigned char rxPtr;};#ifdef MODULE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -