📄 e100.c
字号:
/******************************************************************************* Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. The full GNU General Public License is included in this distribution in the file called LICENSE. Contact Information: Linux NICS <linux.nics@intel.com> 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/config.h>#include <linux/module.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/netdevice.h>#include <linux/etherdevice.h>#include <linux/mii.h>#ifdef NETIF_F_HW_VLAN_TX#include <linux/if_vlan.h>#endif#include <linux/skbuff.h>#include <linux/ethtool.h>#include <linux/string.h>#include <asm/unaligned.h>#include "kcompat.h"#ifdef ETHTOOL_OPS_COMPAT#include "ethtool.c"#endif#define DRV_NAME "e100"#ifndef CONFIG_E100_NAPI#define DRV_EXT#else#define DRV_EXT "-NAPI"#endif#define DRV_VERSION "3.5.14"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;module_param(debug, int, 0);MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");#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),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -