📄 e100.c
字号:
/******************************************************************************* Intel PRO/100 Linux driver Copyright(c) 1999 - 2006 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: Linux NICS <linux.nics@intel.com> e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************//* * e100.c: Intel(R) PRO/100 ethernet driver * * (Re)written 2003 by scott.feldman@intel.com. Based loosely on * original e100 driver, but better described as a munging of * e100, e1000, eepro100, tg3, 8139cp, and other drivers. * * References: * Intel 8255x 10/100 Mbps Ethernet Controller Family, * Open Source Software Developers Manual, * http://sourceforge.net/projects/e1000 * * * Theory of Operation * * I. General * * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet * controller family, which includes the 82557, 82558, 82559, 82550, * 82551, and 82562 devices. 82558 and greater controllers * integrate the Intel 82555 PHY. The controllers are used in * server and client network interface cards, as well as in * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx * configurations. 8255x supports a 32-bit linear addressing * mode and operates at 33Mhz PCI clock rate. * * II. Driver Operation * * Memory-mapped mode is used exclusively to access the device's * shared-memory structure, the Control/Status Registers (CSR). All * setup, configuration, and control of the device, including queuing * of Tx, Rx, and configuration commands is through the CSR. * cmd_lock serializes accesses to the CSR command register. cb_lock * protects the shared Command Block List (CBL). * * 8255x is highly MII-compliant and all access to the PHY go * through the Management Data Interface (MDI). Consequently, the * driver leverages the mii.c library shared with other MII-compliant * devices. * * Big- and Little-Endian byte order as well as 32- and 64-bit * archs are supported. Weak-ordered memory and non-cache-coherent * archs are supported. * * III. Transmit * * A Tx skb is mapped and hangs off of a TCB. TCBs are linked * together in a fixed-size ring (CBL) thus forming the flexible mode * memory structure. A TCB marked with the suspend-bit indicates * the end of the ring. The last TCB processed suspends the * controller, and the controller can be restarted by issue a CU * resume command to continue from the suspend point, or a CU start * command to start at a given position in the ring. * * Non-Tx commands (config, multicast setup, etc) are linked * into the CBL ring along with Tx commands. The common structure * used for both Tx and non-Tx commands is the Command Block (CB). * * cb_to_use is the next CB to use for queuing a command; cb_to_clean * is the next CB to check for completion; cb_to_send is the first * CB to start on in case of a previous failure to resume. CB clean * up happens in interrupt context in response to a CU interrupt. * cbs_avail keeps track of number of free CB resources available. * * Hardware padding of short packets to minimum packet size is * enabled. 82557 pads with 7Eh, while the later controllers pad * with 00h. * * IV. Recieve * * The Receive Frame Area (RFA) comprises a ring of Receive Frame * Descriptors (RFD) + data buffer, thus forming the simplified mode * memory structure. Rx skbs are allocated to contain both the RFD * and the data buffer, but the RFD is pulled off before the skb is * indicated. The data buffer is aligned such that encapsulated * protocol headers are u32-aligned. Since the RFD is part of the * mapped shared memory, and completion status is contained within * the RFD, the RFD must be dma_sync'ed to maintain a consistent * view from software and hardware. * * Under typical operation, the receive unit (RU) is start once, * and the controller happily fills RFDs as frames arrive. If * replacement RFDs cannot be allocated, or the RU goes non-active, * the RU must be restarted. Frame arrival generates an interrupt, * and Rx indication and re-allocation happen in the same context, * therefore no locking is required. A software-generated interrupt * is generated from the watchdog to recover from a failed allocation * senario where all Rx resources have been indicated and none re- * placed. * * V. Miscellaneous * * VLAN offloading of tagging, stripping and filtering is not * supported, but driver will accommodate the extra 4-byte VLAN tag * for processing by upper layers. Tx/Rx Checksum offloading is not * supported. Tx Scatter/Gather is not supported. Jumbo Frames is * not supported (hardware limitation). * * MagicPacket(tm) WoL support is enabled/disabled via ethtool. * * Thanks to JC (jchapman@katalix.com) for helping with * testing/troubleshooting the development driver. * * TODO: * o several entry points race with dev->close * o check for tx-no-resources/stop Q races with tx clean/wake Q * * FIXES: * 2005/12/02 - Michael O'Donnell <Michael.ODonnell at stratus dot com> * - Stratus87247: protect MDI control register manipulations */#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/kernel.h>#include <linux/types.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/dma-mapping.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/mii.h>#include <linux/if_vlan.h>#include <linux/skbuff.h>#include <linux/ethtool.h>#include <linux/string.h>#include <asm/unaligned.h>#define DRV_NAME "e100"#define DRV_EXT "-NAPI"#define DRV_VERSION "3.5.17-k2"DRV_EXT#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation"#define PFX DRV_NAME ": "#define E100_WATCHDOG_PERIOD (2 * HZ)#define E100_NAPI_WEIGHT 16MODULE_DESCRIPTION(DRV_DESCRIPTION);MODULE_AUTHOR(DRV_COPYRIGHT);MODULE_LICENSE("GPL");MODULE_VERSION(DRV_VERSION);static int debug = 3;static int eeprom_bad_csum_allow = 0;module_param(debug, int, 0);module_param(eeprom_bad_csum_allow, int, 0);MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums");#define DPRINTK(nlevel, klevel, fmt, args...) \ (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ __FUNCTION__ , ## args))#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich }static struct pci_device_id e100_id_table[] = { INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), INTEL_8255X_ETHERNET_DEVICE(0x1091, 7), INTEL_8255X_ETHERNET_DEVICE(0x1092, 7), INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7), { 0, }};MODULE_DEVICE_TABLE(pci, e100_id_table);enum mac { mac_82557_D100_A = 0, mac_82557_D100_B = 1, mac_82557_D100_C = 2, mac_82558_D101_A4 = 4, mac_82558_D101_B0 = 5, mac_82559_D101M = 8, mac_82559_D101S = 9, mac_82550_D102 = 12, mac_82550_D102_C = 13, mac_82551_E = 14, mac_82551_F = 15, mac_82551_10 = 16, mac_unknown = 0xFF,};enum phy { phy_100a = 0x000003E0, phy_100c = 0x035002A8, phy_82555_tx = 0x015002A8, phy_nsc_tx = 0x5C002000, phy_82562_et = 0x033002A8, phy_82562_em = 0x032002A8, phy_82562_ek = 0x031002A8, phy_82562_eh = 0x017002A8, phy_unknown = 0xFFFFFFFF,};/* CSR (Control/Status Registers) */struct csr { struct { u8 status; u8 stat_ack; u8 cmd_lo; u8 cmd_hi; u32 gen_ptr; } scb; u32 port; u16 flash_ctrl; u8 eeprom_ctrl_lo; u8 eeprom_ctrl_hi; u32 mdi_ctrl; u32 rx_dma_count;};enum scb_status { rus_ready = 0x10, rus_mask = 0x3C,};enum ru_state { RU_SUSPENDED = 0, RU_RUNNING = 1, RU_UNINITIALIZED = -1,};enum scb_stat_ack { stat_ack_not_ours = 0x00, stat_ack_sw_gen = 0x04, stat_ack_rnr = 0x10, stat_ack_cu_idle = 0x20, stat_ack_frame_rx = 0x40, stat_ack_cu_cmd_done = 0x80, stat_ack_not_present = 0xFF, stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done),};enum scb_cmd_hi { irq_mask_none = 0x00, irq_mask_all = 0x01, irq_sw_gen = 0x02,};enum scb_cmd_lo { cuc_nop = 0x00, ruc_start = 0x01, ruc_load_base = 0x06, cuc_start = 0x10, cuc_resume = 0x20, cuc_dump_addr = 0x40, cuc_dump_stats = 0x50, cuc_load_base = 0x60, cuc_dump_reset = 0x70,};enum cuc_dump { cuc_dump_complete = 0x0000A005, cuc_dump_reset_complete = 0x0000A007,};enum port { software_reset = 0x0000, selftest = 0x0001, selective_reset = 0x0002,};enum eeprom_ctrl_lo { eesk = 0x01, eecs = 0x02, eedi = 0x04, eedo = 0x08,};enum mdi_ctrl { mdi_write = 0x04000000, mdi_read = 0x08000000, mdi_ready = 0x10000000,};enum eeprom_op { op_write = 0x05, op_read = 0x06, op_ewds = 0x10, op_ewen = 0x13,};enum eeprom_offsets { eeprom_cnfg_mdix = 0x03, eeprom_id = 0x0A, eeprom_config_asf = 0x0D, eeprom_smbus_addr = 0x90,};enum eeprom_cnfg_mdix { eeprom_mdix_enabled = 0x0080,};enum eeprom_id { eeprom_id_wol = 0x0020,};enum eeprom_config_asf { eeprom_asf = 0x8000, eeprom_gcl = 0x4000,};enum cb_status { cb_complete = 0x8000, cb_ok = 0x2000,};enum cb_command { cb_nop = 0x0000, cb_iaaddr = 0x0001, cb_config = 0x0002, cb_multi = 0x0003, cb_tx = 0x0004, cb_ucode = 0x0005, cb_dump = 0x0006, cb_tx_sf = 0x0008, cb_cid = 0x1f00, cb_i = 0x2000, cb_s = 0x4000, cb_el = 0x8000,};struct rfd { u16 status; u16 command; u32 link; u32 rbd; u16 actual_size; u16 size;};struct rx { struct rx *next, *prev; struct sk_buff *skb; dma_addr_t dma_addr;};#if defined(__BIG_ENDIAN_BITFIELD)#define X(a,b) b,a#else#define X(a,b) a,b#endifstruct config {/*0*/ u8 X(byte_count:6, pad0:2);/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1);/*2*/ u8 adaptive_ifs;/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), term_write_cache_line:1), pad3:4);/*4*/ u8 X(rx_dma_max_count:7, pad4:1);/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1);/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), rx_discard_overruns:1), rx_save_bad_frames:1);/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), tx_dynamic_tbd:1);/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1);/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), link_status_wake:1), arp_wake:1), mcmatch_wake:1);/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), loopback:2);/*11*/ u8 X(linear_priority:3, pad11:5);/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4);/*13*/ u8 ip_addr_lo;/*14*/ u8 ip_addr_hi;/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -