gpx e1000 driver.
authorRonald G. Minnich <rminnich@google.com>
Sun, 26 Jan 2014 16:41:33 +0000 (08:41 -0800)
committerRonald G. Minnich <rminnich@google.com>
Sun, 26 Jan 2014 16:41:33 +0000 (08:41 -0800)
15KLOC. Geez. Which of the subdrivers can we do without?

Signed-off-by: Ronald G. Minnich <rminnich@google.com>
24 files changed:
kern/drivers/net/e1000/e1000.c [new file with mode: 0644]
kern/drivers/net/e1000/e1000.h [new file with mode: 0644]
kern/drivers/net/e1000/e1000_82540.c [new file with mode: 0644]
kern/drivers/net/e1000/e1000_82541.c [new file with mode: 0644]
kern/drivers/net/e1000/e1000_82541.h [new file with mode: 0644]
kern/drivers/net/e1000/e1000_82542.c [new file with mode: 0644]
kern/drivers/net/e1000/e1000_82543.c [new file with mode: 0644]
kern/drivers/net/e1000/e1000_82543.h [new file with mode: 0644]
kern/drivers/net/e1000/e1000_api.c [new file with mode: 0644]
kern/drivers/net/e1000/e1000_api.h [new file with mode: 0644]
kern/drivers/net/e1000/e1000_defines.h [new file with mode: 0644]
kern/drivers/net/e1000/e1000_hw.h [new file with mode: 0644]
kern/drivers/net/e1000/e1000_mac.c [new file with mode: 0644]
kern/drivers/net/e1000/e1000_mac.h [new file with mode: 0644]
kern/drivers/net/e1000/e1000_main.c [new file with mode: 0644]
kern/drivers/net/e1000/e1000_manage.c [new file with mode: 0644]
kern/drivers/net/e1000/e1000_manage.h [new file with mode: 0644]
kern/drivers/net/e1000/e1000_nvm.c [new file with mode: 0644]
kern/drivers/net/e1000/e1000_nvm.h [new file with mode: 0644]
kern/drivers/net/e1000/e1000_osdep.h [new file with mode: 0644]
kern/drivers/net/e1000/e1000_phy.c [new file with mode: 0644]
kern/drivers/net/e1000/e1000_phy.h [new file with mode: 0644]
kern/drivers/net/e1000/e1000_regs.h [new file with mode: 0644]
kern/drivers/net/r8169.c

diff --git a/kern/drivers/net/e1000/e1000.c b/kern/drivers/net/e1000/e1000.c
new file mode 100644 (file)
index 0000000..a32a4d7
--- /dev/null
@@ -0,0 +1,35 @@
+/*******************************************************************************
+
+  Intel PRO/1000 Linux driver
+  Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+REQUIRE_OBJECT(e1000_main);
+REQUIRE_OBJECT(e1000_82540);
+REQUIRE_OBJECT(e1000_82541);
+REQUIRE_OBJECT(e1000_82542);
+REQUIRE_OBJECT(e1000_82543);
diff --git a/kern/drivers/net/e1000/e1000.h b/kern/drivers/net/e1000/e1000.h
new file mode 100644 (file)
index 0000000..31dbb85
--- /dev/null
@@ -0,0 +1,326 @@
+/*******************************************************************************
+
+  Intel PRO/1000 Linux driver
+  Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_ONLY );
+
+/* Linux PRO/1000 Ethernet Driver main header file */
+
+#ifndef _E1000_H_
+#define _E1000_H_
+
+#include "e1000_api.h"
+
+#define BAR_0          0
+#define BAR_1          1
+#define BAR_5          5
+
+struct e1000_adapter;
+
+/* TX/RX descriptor defines */
+#define E1000_DEFAULT_TXD                  256
+#define E1000_MAX_TXD                      256
+#define E1000_MIN_TXD                       80
+#define E1000_MAX_82544_TXD               4096
+
+#define E1000_DEFAULT_TXD_PWR               12
+#define E1000_MAX_TXD_PWR                   12
+#define E1000_MIN_TXD_PWR                    7
+
+#define E1000_DEFAULT_RXD                  256
+#define E1000_MAX_RXD                      256
+
+#define E1000_MIN_RXD                       80
+#define E1000_MAX_82544_RXD               4096
+
+#define E1000_MIN_ITR_USECS                 10 /* 100000 irq/sec */
+#define E1000_MAX_ITR_USECS              10000 /* 100    irq/sec */
+
+
+/* this is the size past which hardware will drop packets when setting LPE=0 */
+#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
+
+/* Supported Rx Buffer Sizes */
+#define E1000_RXBUFFER_128   128
+#define E1000_RXBUFFER_256   256
+#define E1000_RXBUFFER_512   512
+#define E1000_RXBUFFER_1024  1024
+#define E1000_RXBUFFER_2048  2048
+#define E1000_RXBUFFER_4096  4096
+#define E1000_RXBUFFER_8192  8192
+#define E1000_RXBUFFER_16384 16384
+
+/* SmartSpeed delimiters */
+#define E1000_SMARTSPEED_DOWNSHIFT 3
+#define E1000_SMARTSPEED_MAX       15
+
+/* Packet Buffer allocations */
+#define E1000_PBA_BYTES_SHIFT 0xA
+#define E1000_TX_HEAD_ADDR_SHIFT 7
+#define E1000_PBA_TX_MASK 0xFFFF0000
+
+/* Early Receive defines */
+#define E1000_ERT_2048 0x100
+
+#define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */
+
+/* How many Tx Descriptors do we need to call netif_wake_queue ? */
+#define E1000_TX_QUEUE_WAKE    16
+/* How many Rx Buffers do we bundle into one write to the hardware ? */
+#define E1000_RX_BUFFER_WRITE  16      /* Must be power of 2 */
+
+#define AUTO_ALL_MODES            0
+#define E1000_EEPROM_82544_APM    0x0004
+#define E1000_EEPROM_APME         0x0400
+
+/* wrapper around a pointer to a socket buffer,
+ * so a DMA handle can be stored along with the buffer */
+struct e1000_buffer {
+       struct sk_buff *skb;
+       dma_addr_t dma;
+       unsigned long time_stamp;
+       u16 length;
+       u16 next_to_watch;
+};
+
+struct e1000_rx_buffer {
+       struct sk_buff *skb;
+       dma_addr_t dma;
+       struct page *page;
+};
+
+
+
+struct e1000_tx_ring {
+       /* pointer to the descriptor ring memory */
+       void *desc;
+       /* physical address of the descriptor ring */
+       dma_addr_t dma;
+       /* length of descriptor ring in bytes */
+       unsigned int size;
+       /* number of descriptors in the ring */
+       unsigned int count;
+       /* next descriptor to associate a buffer with */
+       unsigned int next_to_use;
+       /* next descriptor to check for DD status bit */
+       unsigned int next_to_clean;
+       /* array of buffer information structs */
+       struct e1000_buffer *buffer_info;
+
+       spinlock_t tx_lock;
+       u16 tdh;
+       u16 tdt;
+
+       /* TXDdescriptor index increment to be used when advancing
+       * to the next descriptor. This is normally one, but on some
+       * architectures, but on some architectures there are cache
+       * coherency issues that require only the first descriptor in
+       * cache line can be used.
+       */
+       unsigned int step;
+
+       bool last_tx_tso;
+};
+
+struct e1000_rx_ring {
+       struct e1000_adapter *adapter; /* back link */
+       /* pointer to the descriptor ring memory */
+       void *desc;
+       /* physical address of the descriptor ring */
+       dma_addr_t dma;
+       /* length of descriptor ring in bytes */
+       unsigned int size;
+       /* number of descriptors in the ring */
+       unsigned int count;
+       /* next descriptor to associate a buffer with */
+       unsigned int next_to_use;
+       /* next descriptor to check for DD status bit */
+       unsigned int next_to_clean;
+       /* array of buffer information structs */
+       struct e1000_rx_buffer *buffer_info;
+       struct sk_buff *rx_skb_top;
+
+       /* cpu for rx queue */
+       int cpu;
+
+       u16 rdh;
+       u16 rdt;
+};
+
+
+#define E1000_TX_DESC_INC(R,index) \
+       {index += (R)->step; if (index == (R)->count) index = 0; }
+
+#define E1000_TX_DESC_DEC(R,index) \
+       { if (index == 0) index = (R)->count - (R)->step; \
+       else index -= (R)->step; }
+
+#define E1000_DESC_UNUSED(R) \
+       ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
+       (R)->next_to_clean - (R)->next_to_use - 1)
+
+#define E1000_RX_DESC_EXT(R, i)            \
+       (&(((union e1000_rx_desc_extended *)((R).desc))[i]))
+#define E1000_GET_DESC(R, i, type)     (&(((struct type *)((R).desc))[i]))
+#define E1000_RX_DESC(R, i)            E1000_GET_DESC(R, i, e1000_rx_desc)
+#define E1000_TX_DESC(R, i)            E1000_GET_DESC(R, i, e1000_tx_desc)
+#define E1000_CONTEXT_DESC(R, i)       E1000_GET_DESC(R, i, e1000_context_desc)
+
+/* board specific private data structure */
+
+struct e1000_adapter {
+       u32 bd_number;
+       u32 rx_buffer_len;
+       u32 wol;
+       u32 smartspeed;
+       u32 en_mng_pt;
+       u16 link_speed;
+       u16 link_duplex;
+       spinlock_t stats_lock;
+       unsigned int total_tx_bytes;
+       unsigned int total_tx_packets;
+       unsigned int total_rx_bytes;
+       unsigned int total_rx_packets;
+       /* Interrupt Throttle Rate */
+       u32 itr;
+       u32 itr_setting;
+       u16 tx_itr;
+       u16 rx_itr;
+
+       bool fc_autoneg;
+
+       /* TX */
+       struct e1000_tx_ring *tx_ring;
+       unsigned int restart_queue;
+       unsigned long tx_queue_len;
+       u32 txd_cmd;
+       u32 tx_int_delay;
+       u32 tx_abs_int_delay;
+       u32 gotc;
+       u64 gotc_old;
+       u64 tpt_old;
+       u64 colc_old;
+       u32 tx_timeout_count;
+       u32 tx_fifo_head;
+       u32 tx_head_addr;
+       u32 tx_fifo_size;
+       u8 tx_timeout_factor;
+       bool pcix_82544;
+       bool detect_tx_hung;
+
+       /* RX */
+       bool (*clean_rx) (struct e1000_adapter *adapter,
+                              struct e1000_rx_ring *rx_ring);
+       void (*alloc_rx_buf) (struct e1000_adapter *adapter,
+                             struct e1000_rx_ring *rx_ring,
+                               int cleaned_count);
+       struct e1000_rx_ring *rx_ring;
+
+       u64 hw_csum_err;
+       u64 hw_csum_good;
+       u32 alloc_rx_buff_failed;
+       u32 rx_int_delay;
+       u32 rx_abs_int_delay;
+       bool rx_csum;
+       u32 gorc;
+       u64 gorc_old;
+       u32 max_frame_size;
+       u32 min_frame_size;
+
+
+       /* OS defined structs */
+       struct net_device *netdev;
+       struct pci_device *pdev;
+       struct net_device_stats net_stats;
+
+       /* structs defined in e1000_hw.h */
+       struct e1000_hw hw;
+       struct e1000_hw_stats stats;
+       struct e1000_phy_info phy_info;
+       struct e1000_phy_stats phy_stats;
+
+       int msg_enable;
+       /* to not mess up cache alignment, always add to the bottom */
+       unsigned long state;
+       u32 eeprom_wol;
+
+       u32 *config_space;
+
+       /* hardware capability, feature, and workaround flags */
+       unsigned int flags;
+
+       /* upper limit parameter for tx desc size */
+       u32 tx_desc_pwr;
+
+#define NUM_TX_DESC    8
+#define NUM_RX_DESC    8
+
+       struct io_buffer *tx_iobuf[NUM_TX_DESC];
+       struct io_buffer *rx_iobuf[NUM_RX_DESC];
+
+       struct e1000_tx_desc *tx_base;
+       struct e1000_rx_desc *rx_base;
+
+       uint32_t tx_ring_size;
+       uint32_t rx_ring_size;
+
+       uint32_t tx_head;
+       uint32_t tx_tail;
+       uint32_t tx_fill_ctr;
+
+       uint32_t rx_curr;
+
+       uint32_t ioaddr;
+       uint32_t irqno;
+};
+
+#define E1000_FLAG_HAS_SMBUS                (1 << 0)
+#define E1000_FLAG_HAS_INTR_MODERATION      (1 << 4)
+#define E1000_FLAG_BAD_TX_CARRIER_STATS_FD  (1 << 6)
+#define E1000_FLAG_QUAD_PORT_A              (1 << 8)
+#define E1000_FLAG_SMART_POWER_DOWN         (1 << 9)
+
+extern char e1000_driver_name[];
+extern const char e1000_driver_version[];
+
+extern void e1000_power_up_phy(struct e1000_hw *hw);
+
+extern void e1000_set_ethtool_ops(struct net_device *netdev);
+extern void e1000_check_options(struct e1000_adapter *adapter);
+
+extern int e1000_up(struct e1000_adapter *adapter);
+extern void e1000_down(struct e1000_adapter *adapter);
+extern void e1000_reinit_locked(struct e1000_adapter *adapter);
+extern void e1000_reset(struct e1000_adapter *adapter);
+extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
+extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_update_stats(struct e1000_adapter *adapter);
+
+#endif /* _E1000_H_ */
diff --git a/kern/drivers/net/e1000/e1000_82540.c b/kern/drivers/net/e1000/e1000_82540.c
new file mode 100644 (file)
index 0000000..935f0a3
--- /dev/null
@@ -0,0 +1,754 @@
+/*******************************************************************************
+
+  Intel PRO/1000 Linux driver
+  Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * 82540EM Gigabit Ethernet Controller
+ * 82540EP Gigabit Ethernet Controller
+ * 82545EM Gigabit Ethernet Controller (Copper)
+ * 82545EM Gigabit Ethernet Controller (Fiber)
+ * 82545GM Gigabit Ethernet Controller
+ * 82546EB Gigabit Ethernet Controller (Copper)
+ * 82546EB Gigabit Ethernet Controller (Fiber)
+ * 82546GB Gigabit Ethernet Controller
+ */
+
+#include "e1000_api.h"
+
+static s32  e1000_init_phy_params_82540(struct e1000_hw *hw);
+static s32  e1000_init_nvm_params_82540(struct e1000_hw *hw);
+static s32  e1000_init_mac_params_82540(struct e1000_hw *hw);
+static s32  e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw);
+static void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw);
+static s32  e1000_init_hw_82540(struct e1000_hw *hw);
+static s32  e1000_reset_hw_82540(struct e1000_hw *hw);
+static s32  e1000_set_phy_mode_82540(struct e1000_hw *hw);
+static s32  e1000_set_vco_speed_82540(struct e1000_hw *hw);
+static s32  e1000_setup_copper_link_82540(struct e1000_hw *hw);
+static s32  e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw);
+static void e1000_power_down_phy_copper_82540(struct e1000_hw *hw);
+static s32  e1000_read_mac_addr_82540(struct e1000_hw *hw);
+
+/**
+ * e1000_init_phy_params_82540 - Init PHY func ptrs.
+ * @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_phy_params_82540(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val = E1000_SUCCESS;
+
+       phy->addr                      = 1;
+       phy->autoneg_mask              = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+       phy->reset_delay_us            = 10000;
+       phy->type                      = e1000_phy_m88;
+
+       /* Function Pointers */
+       phy->ops.check_polarity        = e1000_check_polarity_m88;
+       phy->ops.commit                = e1000_phy_sw_reset_generic;
+#if 0
+       phy->ops.force_speed_duplex    = e1000_phy_force_speed_duplex_m88;
+#endif
+#if 0
+       phy->ops.get_cable_length      = e1000_get_cable_length_m88;
+#endif
+       phy->ops.get_cfg_done          = e1000_get_cfg_done_generic;
+       phy->ops.read_reg              = e1000_read_phy_reg_m88;
+       phy->ops.reset                 = e1000_phy_hw_reset_generic;
+       phy->ops.write_reg             = e1000_write_phy_reg_m88;
+       phy->ops.get_info              = e1000_get_phy_info_m88;
+       phy->ops.power_up              = e1000_power_up_phy_copper;
+       phy->ops.power_down            = e1000_power_down_phy_copper_82540;
+
+       ret_val = e1000_get_phy_id(hw);
+       if (ret_val)
+               goto out;
+
+       /* Verify phy id */
+       switch (hw->mac.type) {
+       case e1000_82540:
+       case e1000_82545:
+       case e1000_82545_rev_3:
+       case e1000_82546:
+       case e1000_82546_rev_3:
+               if (phy->id == M88E1011_I_PHY_ID)
+                       break;
+               /* Fall Through */
+       default:
+               ret_val = -E1000_ERR_PHY;
+               goto out;
+               break;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ * e1000_init_nvm_params_82540 - Init NVM func ptrs.
+ * @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_nvm_params_82540(struct e1000_hw *hw)
+{
+       struct e1000_nvm_info *nvm = &hw->nvm;
+       u32 eecd = E1000_READ_REG(hw, E1000_EECD);
+
+       DEBUGFUNC("e1000_init_nvm_params_82540");
+
+       nvm->type               = e1000_nvm_eeprom_microwire;
+       nvm->delay_usec         = 50;
+       nvm->opcode_bits        = 3;
+       switch (nvm->override) {
+       case e1000_nvm_override_microwire_large:
+               nvm->address_bits       = 8;
+               nvm->word_size          = 256;
+               break;
+       case e1000_nvm_override_microwire_small:
+               nvm->address_bits       = 6;
+               nvm->word_size          = 64;
+               break;
+       default:
+               nvm->address_bits       = eecd & E1000_EECD_SIZE ? 8 : 6;
+               nvm->word_size          = eecd & E1000_EECD_SIZE ? 256 : 64;
+               break;
+       }
+
+       /* Function Pointers */
+       nvm->ops.acquire            = e1000_acquire_nvm_generic;
+       nvm->ops.read               = e1000_read_nvm_microwire;
+       nvm->ops.release            = e1000_release_nvm_generic;
+       nvm->ops.update             = e1000_update_nvm_checksum_generic;
+       nvm->ops.valid_led_default  = e1000_valid_led_default_generic;
+       nvm->ops.validate           = e1000_validate_nvm_checksum_generic;
+       nvm->ops.write              = e1000_write_nvm_microwire;
+
+       return E1000_SUCCESS;
+}
+
+/**
+ * e1000_init_mac_params_82540 - Init MAC func ptrs.
+ * @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_mac_params_82540(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_init_mac_params_82540");
+
+       /* Set media type */
+       switch (hw->device_id) {
+       case E1000_DEV_ID_82545EM_FIBER:
+       case E1000_DEV_ID_82545GM_FIBER:
+       case E1000_DEV_ID_82546EB_FIBER:
+       case E1000_DEV_ID_82546GB_FIBER:
+               hw->phy.media_type = e1000_media_type_fiber;
+               break;
+       case E1000_DEV_ID_82545GM_SERDES:
+       case E1000_DEV_ID_82546GB_SERDES:
+               hw->phy.media_type = e1000_media_type_internal_serdes;
+               break;
+       default:
+               hw->phy.media_type = e1000_media_type_copper;
+               break;
+       }
+
+       /* Set mta register count */
+       mac->mta_reg_count = 128;
+       /* Set rar entry count */
+       mac->rar_entry_count = E1000_RAR_ENTRIES;
+
+       /* Function pointers */
+
+       /* bus type/speed/width */
+       mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
+       /* function id */
+       mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci;
+       /* reset */
+       mac->ops.reset_hw = e1000_reset_hw_82540;
+       /* hw initialization */
+       mac->ops.init_hw = e1000_init_hw_82540;
+       /* link setup */
+       mac->ops.setup_link = e1000_setup_link_generic;
+       /* physical interface setup */
+       mac->ops.setup_physical_interface =
+               (hw->phy.media_type == e1000_media_type_copper)
+                       ? e1000_setup_copper_link_82540
+                       : e1000_setup_fiber_serdes_link_82540;
+       /* check for link */
+       switch (hw->phy.media_type) {
+       case e1000_media_type_copper:
+               mac->ops.check_for_link = e1000_check_for_copper_link_generic;
+               break;
+       case e1000_media_type_fiber:
+               mac->ops.check_for_link = e1000_check_for_fiber_link_generic;
+               break;
+       case e1000_media_type_internal_serdes:
+               mac->ops.check_for_link = e1000_check_for_serdes_link_generic;
+               break;
+       default:
+               ret_val = -E1000_ERR_CONFIG;
+               goto out;
+               break;
+       }
+       /* link info */
+       mac->ops.get_link_up_info =
+               (hw->phy.media_type == e1000_media_type_copper)
+                       ? e1000_get_speed_and_duplex_copper_generic
+                       : e1000_get_speed_and_duplex_fiber_serdes_generic;
+       /* multicast address update */
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
+       /* writing VFTA */
+       mac->ops.write_vfta = e1000_write_vfta_generic;
+       /* clearing VFTA */
+       mac->ops.clear_vfta = e1000_clear_vfta_generic;
+       /* setting MTA */
+       mac->ops.mta_set = e1000_mta_set_generic;
+       /* read mac address */
+       mac->ops.read_mac_addr = e1000_read_mac_addr_82540;
+       /* ID LED init */
+       mac->ops.id_led_init = e1000_id_led_init_generic;
+       /* setup LED */
+       mac->ops.setup_led = e1000_setup_led_generic;
+       /* cleanup LED */
+       mac->ops.cleanup_led = e1000_cleanup_led_generic;
+       /* turn on/off LED */
+       mac->ops.led_on = e1000_led_on_generic;
+       mac->ops.led_off = e1000_led_off_generic;
+       /* clear hardware counters */
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82540;
+
+out:
+       return ret_val;
+}
+
+/**
+ * e1000_init_function_pointers_82540 - Init func ptrs.
+ * @hw: pointer to the HW structure
+ *
+ * Called to initialize all function pointers and parameters.
+ **/
+void e1000_init_function_pointers_82540(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_init_function_pointers_82540");
+
+       hw->mac.ops.init_params = e1000_init_mac_params_82540;
+       hw->nvm.ops.init_params = e1000_init_nvm_params_82540;
+       hw->phy.ops.init_params = e1000_init_phy_params_82540;
+}
+
+/**
+ *  e1000_reset_hw_82540 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+static s32 e1000_reset_hw_82540(struct e1000_hw *hw)
+{
+       u32 ctrl, icr, manc;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_reset_hw_82540");
+
+       DEBUGOUT("Masking off all interrupts\n");
+       E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
+
+       E1000_WRITE_REG(hw, E1000_RCTL, 0);
+       E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
+       E1000_WRITE_FLUSH(hw);
+
+       /*
+        * Delay to allow any outstanding PCI transactions to complete
+        * before resetting the device.
+        */
+       msec_delay(10);
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       DEBUGOUT("Issuing a global reset to 82540/82545/82546 MAC\n");
+       switch (hw->mac.type) {
+       case e1000_82545_rev_3:
+       case e1000_82546_rev_3:
+               E1000_WRITE_REG(hw, E1000_CTRL_DUP, ctrl | E1000_CTRL_RST);
+               break;
+       default:
+               /*
+                * These controllers can't ack the 64-bit write when
+                * issuing the reset, so we use IO-mapping as a
+                * workaround to issue the reset.
+                */
+               E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
+               break;
+       }
+
+       /* Wait for EEPROM reload */
+       msec_delay(5);
+
+       /* Disable HW ARPs on ASF enabled adapters */
+       manc = E1000_READ_REG(hw, E1000_MANC);
+       manc &= ~E1000_MANC_ARP_EN;
+       E1000_WRITE_REG(hw, E1000_MANC, manc);
+
+       E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+       icr = E1000_READ_REG(hw, E1000_ICR);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_init_hw_82540 - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation.
+ **/
+static s32 e1000_init_hw_82540(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       u32 txdctl, ctrl_ext;
+       s32 ret_val = E1000_SUCCESS;
+       u16 i;
+
+       DEBUGFUNC("e1000_init_hw_82540");
+
+       /* Initialize identification LED */
+       ret_val = mac->ops.id_led_init(hw);
+       if (ret_val) {
+               DEBUGOUT("Error initializing identification LED\n");
+               /* This is not fatal and we should not stop init due to this */
+       }
+
+       /* Disabling VLAN filtering */
+       DEBUGOUT("Initializing the IEEE VLAN\n");
+       if (mac->type < e1000_82545_rev_3)
+               E1000_WRITE_REG(hw, E1000_VET, 0);
+
+       mac->ops.clear_vfta(hw);
+
+       /* Setup the receive address. */
+       e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
+
+       /* Zero out the Multicast HASH table */
+       DEBUGOUT("Zeroing the MTA\n");
+       for (i = 0; i < mac->mta_reg_count; i++) {
+               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
+               /*
+                * Avoid back to back register writes by adding the register
+                * read (flush).  This is to protect against some strange
+                * bridge configurations that may issue Memory Write Block
+                * (MWB) to our register space.  The *_rev_3 hardware at
+                * least doesn't respond correctly to every other dword in an
+                * MWB to our register space.
+                */
+               E1000_WRITE_FLUSH(hw);
+       }
+
+       if (mac->type < e1000_82545_rev_3)
+               e1000_pcix_mmrbc_workaround_generic(hw);
+
+       /* Setup link and flow control */
+       ret_val = mac->ops.setup_link(hw);
+
+       txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
+       txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
+                E1000_TXDCTL_FULL_TX_DESC_WB;
+       E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
+
+       /*
+        * Clear all of the statistics registers (clear on read).  It is
+        * important that we do this after we have tried to establish link
+        * because the symbol error count will increment wildly if there
+        * is no link.
+        */
+       e1000_clear_hw_cntrs_82540(hw);
+
+       if ((hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER) ||
+           (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3)) {
+               ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+               /*
+                * Relaxed ordering must be disabled to avoid a parity
+                * error crash in a PCI slot.
+                */
+               ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
+               E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_copper_link_82540 - Configure copper link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Calls the appropriate function to configure the link for auto-neg or forced
+ *  speed and duplex.  Then we check for link, once link is established calls
+ *  to configure collision distance and flow control are called.  If link is
+ *  not established, we return -E1000_ERR_PHY (-2).
+ **/
+static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw)
+{
+       u32 ctrl;
+       s32 ret_val = E1000_SUCCESS;
+       u16 data;
+
+       DEBUGFUNC("e1000_setup_copper_link_82540");
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+       ctrl |= E1000_CTRL_SLU;
+       ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+       ret_val = e1000_set_phy_mode_82540(hw);
+       if (ret_val)
+               goto out;
+
+       if (hw->mac.type == e1000_82545_rev_3 ||
+           hw->mac.type == e1000_82546_rev_3) {
+               ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &data);
+               if (ret_val)
+                       goto out;
+               data |= 0x00000008;
+               ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, data);
+               if (ret_val)
+                       goto out;
+       }
+
+       ret_val = e1000_copper_link_setup_m88(hw);
+       if (ret_val)
+               goto out;
+
+       ret_val = e1000_setup_copper_link_generic(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_fiber_serdes_link_82540 - Setup link for fiber/serdes
+ *  @hw: pointer to the HW structure
+ *
+ *  Set the output amplitude to the value in the EEPROM and adjust the VCO
+ *  speed to improve Bit Error Rate (BER) performance.  Configures collision
+ *  distance and flow control for fiber and serdes links.  Upon successful
+ *  setup, poll for link.
+ **/
+static s32 e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_setup_fiber_serdes_link_82540");
+
+       switch (mac->type) {
+       case e1000_82545_rev_3:
+       case e1000_82546_rev_3:
+               if (hw->phy.media_type == e1000_media_type_internal_serdes) {
+                       /*
+                        * If we're on serdes media, adjust the output
+                        * amplitude to value set in the EEPROM.
+                        */
+                       ret_val = e1000_adjust_serdes_amplitude_82540(hw);
+                       if (ret_val)
+                               goto out;
+               }
+               /* Adjust VCO speed to improve BER performance */
+               ret_val = e1000_set_vco_speed_82540(hw);
+               if (ret_val)
+                       goto out;
+       default:
+               break;
+       }
+
+       ret_val = e1000_setup_fiber_serdes_link_generic(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_adjust_serdes_amplitude_82540 - Adjust amplitude based on EEPROM
+ *  @hw: pointer to the HW structure
+ *
+ *  Adjust the SERDES output amplitude based on the EEPROM settings.
+ **/
+static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u16 nvm_data;
+
+       DEBUGFUNC("e1000_adjust_serdes_amplitude_82540");
+
+       ret_val = hw->nvm.ops.read(hw, NVM_SERDES_AMPLITUDE, 1, &nvm_data);
+       if (ret_val)
+               goto out;
+
+       if (nvm_data != NVM_RESERVED_WORD) {
+               /* Adjust serdes output amplitude only. */
+               nvm_data &= NVM_SERDES_AMPLITUDE_MASK;
+               ret_val = hw->phy.ops.write_reg(hw,
+                                            M88E1000_PHY_EXT_CTRL,
+                                            nvm_data);
+               if (ret_val)
+                       goto out;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_set_vco_speed_82540 - Set VCO speed for better performance
+ *  @hw: pointer to the HW structure
+ *
+ *  Set the VCO speed to improve Bit Error Rate (BER) performance.
+ **/
+static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw)
+{
+       s32  ret_val = E1000_SUCCESS;
+       u16 default_page = 0;
+       u16 phy_data;
+
+       DEBUGFUNC("e1000_set_vco_speed_82540");
+
+       /* Set PHY register 30, page 5, bit 8 to 0 */
+
+       ret_val = hw->phy.ops.read_reg(hw,
+                                   M88E1000_PHY_PAGE_SELECT,
+                                   &default_page);
+       if (ret_val)
+               goto out;
+
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005);
+       if (ret_val)
+               goto out;
+
+       ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
+       if (ret_val)
+               goto out;
+
+       phy_data &= ~M88E1000_PHY_VCO_REG_BIT8;
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
+       if (ret_val)
+               goto out;
+
+       /* Set PHY register 30, page 4, bit 11 to 1 */
+
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004);
+       if (ret_val)
+               goto out;
+
+       ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
+       if (ret_val)
+               goto out;
+
+       phy_data |= M88E1000_PHY_VCO_REG_BIT11;
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
+       if (ret_val)
+               goto out;
+
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT,
+                                     default_page);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_set_phy_mode_82540 - Set PHY to class A mode
+ *  @hw: pointer to the HW structure
+ *
+ *  Sets the PHY to class A mode and assumes the following operations will
+ *  follow to enable the new class mode:
+ *    1.  Do a PHY soft reset.
+ *    2.  Restart auto-negotiation or force link.
+ **/
+static s32 e1000_set_phy_mode_82540(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val = E1000_SUCCESS;
+       u16 nvm_data;
+
+       DEBUGFUNC("e1000_set_phy_mode_82540");
+
+       if (hw->mac.type != e1000_82545_rev_3)
+               goto out;
+
+       ret_val = hw->nvm.ops.read(hw, NVM_PHY_CLASS_WORD, 1, &nvm_data);
+       if (ret_val) {
+               ret_val = -E1000_ERR_PHY;
+               goto out;
+       }
+
+       if ((nvm_data != NVM_RESERVED_WORD) && (nvm_data & NVM_PHY_CLASS_A)) {
+               ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT,
+                                             0x000B);
+               if (ret_val) {
+                       ret_val = -E1000_ERR_PHY;
+                       goto out;
+               }
+               ret_val = hw->phy.ops.write_reg(hw,
+                                             M88E1000_PHY_GEN_CONTROL,
+                                             0x8104);
+               if (ret_val) {
+                       ret_val = -E1000_ERR_PHY;
+                       goto out;
+               }
+
+               phy->reset_disable = false;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ * e1000_power_down_phy_copper_82540 - Remove link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, remove the link.
+ **/
+static void e1000_power_down_phy_copper_82540(struct e1000_hw *hw)
+{
+       /* If the management interface is not enabled, then power down */
+       if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN))
+               e1000_power_down_phy_copper(hw);
+
+       return;
+}
+
+/**
+ *  e1000_clear_hw_cntrs_82540 - Clear device specific hardware counters
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the hardware counters by reading the counter registers.
+ **/
+static void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_clear_hw_cntrs_82540");
+
+       e1000_clear_hw_cntrs_base_generic(hw);
+
+#if 0
+       E1000_READ_REG(hw, E1000_PRC64);
+       E1000_READ_REG(hw, E1000_PRC127);
+       E1000_READ_REG(hw, E1000_PRC255);
+       E1000_READ_REG(hw, E1000_PRC511);
+       E1000_READ_REG(hw, E1000_PRC1023);
+       E1000_READ_REG(hw, E1000_PRC1522);
+       E1000_READ_REG(hw, E1000_PTC64);
+       E1000_READ_REG(hw, E1000_PTC127);
+       E1000_READ_REG(hw, E1000_PTC255);
+       E1000_READ_REG(hw, E1000_PTC511);
+       E1000_READ_REG(hw, E1000_PTC1023);
+       E1000_READ_REG(hw, E1000_PTC1522);
+
+       E1000_READ_REG(hw, E1000_ALGNERRC);
+       E1000_READ_REG(hw, E1000_RXERRC);
+       E1000_READ_REG(hw, E1000_TNCRS);
+       E1000_READ_REG(hw, E1000_CEXTERR);
+       E1000_READ_REG(hw, E1000_TSCTC);
+       E1000_READ_REG(hw, E1000_TSCTFC);
+
+       E1000_READ_REG(hw, E1000_MGTPRC);
+       E1000_READ_REG(hw, E1000_MGTPDC);
+       E1000_READ_REG(hw, E1000_MGTPTC);
+#endif
+}
+
+/**
+ *  e1000_read_mac_addr_82540 - Read device MAC address
+ *  @hw: pointer to the HW structure
+ *
+ *  Reads the device MAC address from the EEPROM and stores the value.
+ *  Since devices with two ports use the same EEPROM, we increment the
+ *  last bit in the MAC address for the second port.
+ *
+ *  This version is being used over generic because of customer issues
+ *  with VmWare and Virtual Box when using generic. It seems in
+ *  the emulated 82545, RAR[0] does NOT have a valid address after a
+ *  reset, this older method works and using this breaks nothing for
+ *  these legacy adapters.
+ **/
+s32 e1000_read_mac_addr_82540(struct e1000_hw *hw)
+{
+       s32  ret_val = E1000_SUCCESS;
+       u16 offset, nvm_data, i;
+
+       DEBUGFUNC("e1000_read_mac_addr");
+
+       for (i = 0; i < ETH_ADDR_LEN; i += 2) {
+               offset = i >> 1;
+               ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
+               if (ret_val) {
+                       DEBUGOUT("NVM Read Error\n");
+                       goto out;
+               }
+               hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);
+               hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);
+       }
+
+       /* Flip last bit of mac address if we're on second port */
+       if (hw->bus.func == E1000_FUNC_1)
+               hw->mac.perm_addr[5] ^= 1;
+
+       for (i = 0; i < ETH_ADDR_LEN; i++)
+               hw->mac.addr[i] = hw->mac.perm_addr[i];
+
+out:
+       return ret_val;
+}
+
+static struct pci_device_id e1000_82540_nics[] = {
+     PCI_ROM(0x8086, 0x100E, "E1000_DEV_ID_82540EM", "E1000_DEV_ID_82540EM", e1000_82540),
+     PCI_ROM(0x8086, 0x1015, "E1000_DEV_ID_82540EM_LOM", "E1000_DEV_ID_82540EM_LOM", e1000_82540),
+     PCI_ROM(0x8086, 0x1016, "E1000_DEV_ID_82540EP_LOM", "E1000_DEV_ID_82540EP_LOM", e1000_82540),
+     PCI_ROM(0x8086, 0x1017, "E1000_DEV_ID_82540EP", "E1000_DEV_ID_82540EP", e1000_82540),
+     PCI_ROM(0x8086, 0x101E, "E1000_DEV_ID_82540EP_LP", "E1000_DEV_ID_82540EP_LP", e1000_82540),
+     PCI_ROM(0x8086, 0x100F, "E1000_DEV_ID_82545EM_COPPER", "E1000_DEV_ID_82545EM_COPPER", e1000_82545),
+     PCI_ROM(0x8086, 0x1011, "E1000_DEV_ID_82545EM_FIBER", "E1000_DEV_ID_82545EM_FIBER", e1000_82545),
+     PCI_ROM(0x8086, 0x1026, "E1000_DEV_ID_82545GM_COPPER", "E1000_DEV_ID_82545GM_COPPER", e1000_82545_rev_3),
+     PCI_ROM(0x8086, 0x1027, "E1000_DEV_ID_82545GM_FIBER", "E1000_DEV_ID_82545GM_FIBER", e1000_82545_rev_3),
+     PCI_ROM(0x8086, 0x1028, "E1000_DEV_ID_82545GM_SERDES", "E1000_DEV_ID_82545GM_SERDES", e1000_82545_rev_3),
+     PCI_ROM(0x8086, 0x1010, "E1000_DEV_ID_82546EB_COPPER", "E1000_DEV_ID_82546EB_COPPER", e1000_82546),
+     PCI_ROM(0x8086, 0x1012, "E1000_DEV_ID_82546EB_FIBER", "E1000_DEV_ID_82546EB_FIBER", e1000_82546),
+     PCI_ROM(0x8086, 0x101D, "E1000_DEV_ID_82546EB_QUAD_COPPER", "E1000_DEV_ID_82546EB_QUAD_COPPER", e1000_82546),
+     PCI_ROM(0x8086, 0x1079, "E1000_DEV_ID_82546GB_COPPER", "E1000_DEV_ID_82546GB_COPPER", e1000_82546_rev_3),
+     PCI_ROM(0x8086, 0x107A, "E1000_DEV_ID_82546GB_FIBER", "E1000_DEV_ID_82546GB_FIBER", e1000_82546_rev_3),
+     PCI_ROM(0x8086, 0x107B, "E1000_DEV_ID_82546GB_SERDES", "E1000_DEV_ID_82546GB_SERDES", e1000_82546_rev_3),
+     PCI_ROM(0x8086, 0x108A, "E1000_DEV_ID_82546GB_PCIE", "E1000_DEV_ID_82546GB_PCIE", e1000_82546_rev_3),
+     PCI_ROM(0x8086, 0x1099, "E1000_DEV_ID_82546GB_QUAD_COPPER", "E1000_DEV_ID_82546GB_QUAD_COPPER", e1000_82546_rev_3),
+     PCI_ROM(0x8086, 0x10B5, "E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3", "E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3", e1000_82546_rev_3),
+};
+
+struct pci_driver e1000_82540_driver __pci_driver = {
+       .ids = e1000_82540_nics,
+       .id_count = (sizeof (e1000_82540_nics) / sizeof (e1000_82540_nics[0])),
+       .probe = e1000_probe,
+       .remove = e1000_remove,
+};
diff --git a/kern/drivers/net/e1000/e1000_82541.c b/kern/drivers/net/e1000/e1000_82541.c
new file mode 100644 (file)
index 0000000..f1080f6
--- /dev/null
@@ -0,0 +1,1314 @@
+/*******************************************************************************
+
+  Intel PRO/1000 Linux driver
+  Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * 82541EI Gigabit Ethernet Controller
+ * 82541ER Gigabit Ethernet Controller
+ * 82541GI Gigabit Ethernet Controller
+ * 82541PI Gigabit Ethernet Controller
+ * 82547EI Gigabit Ethernet Controller
+ * 82547GI Gigabit Ethernet Controller
+ */
+
+#include "e1000_api.h"
+
+static s32  e1000_init_phy_params_82541(struct e1000_hw *hw);
+static s32  e1000_init_nvm_params_82541(struct e1000_hw *hw);
+static s32  e1000_init_mac_params_82541(struct e1000_hw *hw);
+static s32  e1000_reset_hw_82541(struct e1000_hw *hw);
+static s32  e1000_init_hw_82541(struct e1000_hw *hw);
+static s32  e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
+                                         u16 *duplex);
+static s32  e1000_phy_hw_reset_82541(struct e1000_hw *hw);
+static s32  e1000_setup_copper_link_82541(struct e1000_hw *hw);
+static s32  e1000_check_for_link_82541(struct e1000_hw *hw);
+#if 0
+static s32  e1000_get_cable_length_igp_82541(struct e1000_hw *hw);
+#endif
+static s32  e1000_set_d3_lplu_state_82541(struct e1000_hw *hw,
+                                          bool active);
+static s32  e1000_setup_led_82541(struct e1000_hw *hw);
+static s32  e1000_cleanup_led_82541(struct e1000_hw *hw);
+static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw);
+#if 0
+static s32  e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
+                                                     bool link_up);
+#endif
+static s32  e1000_phy_init_script_82541(struct e1000_hw *hw);
+static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw);
+
+#if 0
+static const u16 e1000_igp_cable_length_table[] =
+    { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+      5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
+      25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
+      40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60,
+      60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90,
+      90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
+      100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+      110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120};
+#define IGP01E1000_AGC_LENGTH_TABLE_SIZE \
+                (sizeof(e1000_igp_cable_length_table) / \
+                 sizeof(e1000_igp_cable_length_table[0]))
+#endif
+/**
+ *  e1000_init_phy_params_82541 - Init PHY func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_phy_params_82541(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_init_phy_params_82541");
+
+       phy->addr                      = 1;
+       phy->autoneg_mask              = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+       phy->reset_delay_us            = 10000;
+       phy->type                      = e1000_phy_igp;
+
+       /* Function Pointers */
+       phy->ops.check_polarity        = e1000_check_polarity_igp;
+#if 0
+       phy->ops.force_speed_duplex    = e1000_phy_force_speed_duplex_igp;
+#endif
+#if 0
+       phy->ops.get_cable_length      = e1000_get_cable_length_igp_82541;
+#endif
+       phy->ops.get_cfg_done          = e1000_get_cfg_done_generic;
+       phy->ops.get_info              = e1000_get_phy_info_igp;
+       phy->ops.read_reg              = e1000_read_phy_reg_igp;
+       phy->ops.reset                 = e1000_phy_hw_reset_82541;
+       phy->ops.set_d3_lplu_state     = e1000_set_d3_lplu_state_82541;
+       phy->ops.write_reg             = e1000_write_phy_reg_igp;
+       phy->ops.power_up              = e1000_power_up_phy_copper;
+       phy->ops.power_down            = e1000_power_down_phy_copper_82541;
+
+       ret_val = e1000_get_phy_id(hw);
+       if (ret_val)
+               goto out;
+
+       /* Verify phy id */
+       if (phy->id != IGP01E1000_I_PHY_ID) {
+               ret_val = -E1000_ERR_PHY;
+               goto out;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_init_nvm_params_82541 - Init NVM func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw)
+{
+       struct   e1000_nvm_info *nvm = &hw->nvm;
+       s32  ret_val = E1000_SUCCESS;
+       u32 eecd = E1000_READ_REG(hw, E1000_EECD);
+       u16 size;
+
+       DEBUGFUNC("e1000_init_nvm_params_82541");
+
+       switch (nvm->override) {
+       case e1000_nvm_override_spi_large:
+               nvm->type = e1000_nvm_eeprom_spi;
+               eecd |= E1000_EECD_ADDR_BITS;
+               break;
+       case e1000_nvm_override_spi_small:
+               nvm->type = e1000_nvm_eeprom_spi;
+               eecd &= ~E1000_EECD_ADDR_BITS;
+               break;
+       case e1000_nvm_override_microwire_large:
+               nvm->type = e1000_nvm_eeprom_microwire;
+               eecd |= E1000_EECD_SIZE;
+               break;
+       case e1000_nvm_override_microwire_small:
+               nvm->type = e1000_nvm_eeprom_microwire;
+               eecd &= ~E1000_EECD_SIZE;
+               break;
+       default:
+               nvm->type = eecd & E1000_EECD_TYPE
+                           ? e1000_nvm_eeprom_spi
+                           : e1000_nvm_eeprom_microwire;
+               break;
+       }
+
+       if (nvm->type == e1000_nvm_eeprom_spi) {
+               nvm->address_bits       = (eecd & E1000_EECD_ADDR_BITS)
+                                         ? 16 : 8;
+               nvm->delay_usec         = 1;
+               nvm->opcode_bits        = 8;
+               nvm->page_size          = (eecd & E1000_EECD_ADDR_BITS)
+                                         ? 32 : 8;
+
+               /* Function Pointers */
+               nvm->ops.acquire        = e1000_acquire_nvm_generic;
+               nvm->ops.read           = e1000_read_nvm_spi;
+               nvm->ops.release        = e1000_release_nvm_generic;
+               nvm->ops.update         = e1000_update_nvm_checksum_generic;
+               nvm->ops.valid_led_default = e1000_valid_led_default_generic;
+               nvm->ops.validate       = e1000_validate_nvm_checksum_generic;
+               nvm->ops.write          = e1000_write_nvm_spi;
+
+               /*
+                * nvm->word_size must be discovered after the pointers
+                * are set so we can verify the size from the nvm image
+                * itself.  Temporarily set it to a dummy value so the
+                * read will work.
+                */
+               nvm->word_size = 64;
+               ret_val = nvm->ops.read(hw, NVM_CFG, 1, &size);
+               if (ret_val)
+                       goto out;
+               size = (size & NVM_SIZE_MASK) >> NVM_SIZE_SHIFT;
+               /*
+                * if size != 0, it can be added to a constant and become
+                * the left-shift value to set the word_size.  Otherwise,
+                * word_size stays at 64.
+                */
+               if (size) {
+                       size += NVM_WORD_SIZE_BASE_SHIFT_82541;
+                       nvm->word_size = 1 << size;
+               }
+       } else {
+               nvm->address_bits       = (eecd & E1000_EECD_ADDR_BITS)
+                                         ? 8 : 6;
+               nvm->delay_usec         = 50;
+               nvm->opcode_bits        = 3;
+               nvm->word_size          = (eecd & E1000_EECD_ADDR_BITS)
+                                         ? 256 : 64;
+
+               /* Function Pointers */
+               nvm->ops.acquire        = e1000_acquire_nvm_generic;
+               nvm->ops.read           = e1000_read_nvm_microwire;
+               nvm->ops.release        = e1000_release_nvm_generic;
+               nvm->ops.update         = e1000_update_nvm_checksum_generic;
+               nvm->ops.valid_led_default = e1000_valid_led_default_generic;
+               nvm->ops.validate       = e1000_validate_nvm_checksum_generic;
+               nvm->ops.write          = e1000_write_nvm_microwire;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_init_mac_params_82541 - Init MAC func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_mac_params_82541(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+
+       DEBUGFUNC("e1000_init_mac_params_82541");
+
+       /* Set media type */
+       hw->phy.media_type = e1000_media_type_copper;
+       /* Set mta register count */
+       mac->mta_reg_count = 128;
+       /* Set rar entry count */
+       mac->rar_entry_count = E1000_RAR_ENTRIES;
+       /* Set if part includes ASF firmware */
+       mac->asf_firmware_present = true;
+
+       /* Function Pointers */
+
+       /* bus type/speed/width */
+       mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
+       /* function id */
+       mac->ops.set_lan_id = e1000_set_lan_id_single_port;
+       /* reset */
+       mac->ops.reset_hw = e1000_reset_hw_82541;
+       /* hw initialization */
+       mac->ops.init_hw = e1000_init_hw_82541;
+       /* link setup */
+       mac->ops.setup_link = e1000_setup_link_generic;
+       /* physical interface link setup */
+       mac->ops.setup_physical_interface = e1000_setup_copper_link_82541;
+       /* check for link */
+       mac->ops.check_for_link = e1000_check_for_link_82541;
+       /* link info */
+       mac->ops.get_link_up_info = e1000_get_link_up_info_82541;
+       /* multicast address update */
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
+       /* writing VFTA */
+       mac->ops.write_vfta = e1000_write_vfta_generic;
+       /* clearing VFTA */
+       mac->ops.clear_vfta = e1000_clear_vfta_generic;
+       /* setting MTA */
+       mac->ops.mta_set = e1000_mta_set_generic;
+       /* ID LED init */
+       mac->ops.id_led_init = e1000_id_led_init_generic;
+       /* setup LED */
+       mac->ops.setup_led = e1000_setup_led_82541;
+       /* cleanup LED */
+       mac->ops.cleanup_led = e1000_cleanup_led_82541;
+       /* turn on/off LED */
+       mac->ops.led_on = e1000_led_on_generic;
+       mac->ops.led_off = e1000_led_off_generic;
+       /* clear hardware counters */
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82541;
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_init_function_pointers_82541 - Init func ptrs.
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to initialize all function pointers and parameters.
+ **/
+void e1000_init_function_pointers_82541(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_init_function_pointers_82541");
+
+       hw->mac.ops.init_params = e1000_init_mac_params_82541;
+       hw->nvm.ops.init_params = e1000_init_nvm_params_82541;
+       hw->phy.ops.init_params = e1000_init_phy_params_82541;
+}
+
+/**
+ *  e1000_reset_hw_82541 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+static s32 e1000_reset_hw_82541(struct e1000_hw *hw)
+{
+       u32 ledctl, ctrl, icr, manc;
+
+       DEBUGFUNC("e1000_reset_hw_82541");
+
+       DEBUGOUT("Masking off all interrupts\n");
+       E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
+
+       E1000_WRITE_REG(hw, E1000_RCTL, 0);
+       E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
+       E1000_WRITE_FLUSH(hw);
+
+       /*
+        * Delay to allow any outstanding PCI transactions to complete
+        * before resetting the device.
+        */
+       msec_delay(10);
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       /* Must reset the Phy before resetting the MAC */
+       if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
+               E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_PHY_RST));
+               msec_delay(5);
+       }
+
+       DEBUGOUT("Issuing a global reset to 82541/82547 MAC\n");
+       switch (hw->mac.type) {
+       case e1000_82541:
+       case e1000_82541_rev_2:
+               /*
+                * These controllers can't ack the 64-bit write when
+                * issuing the reset, so we use IO-mapping as a
+                * workaround to issue the reset.
+                */
+               E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
+               break;
+       default:
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
+               break;
+       }
+
+       /* Wait for NVM reload */
+       msec_delay(20);
+
+       /* Disable HW ARPs on ASF enabled adapters */
+       manc = E1000_READ_REG(hw, E1000_MANC);
+       manc &= ~E1000_MANC_ARP_EN;
+       E1000_WRITE_REG(hw, E1000_MANC, manc);
+
+       if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
+               e1000_phy_init_script_82541(hw);
+
+               /* Configure activity LED after Phy reset */
+               ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
+               ledctl &= IGP_ACTIVITY_LED_MASK;
+               ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
+               E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
+       }
+
+       /* Once again, mask the interrupts */
+       DEBUGOUT("Masking off all interrupts\n");
+       E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
+
+       /* Clear any pending interrupt events. */
+       icr = E1000_READ_REG(hw, E1000_ICR);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_init_hw_82541 - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation.
+ **/
+static s32 e1000_init_hw_82541(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
+       u32 i, txdctl;
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_init_hw_82541");
+
+       /* Initialize identification LED */
+       ret_val = mac->ops.id_led_init(hw);
+       if (ret_val) {
+               DEBUGOUT("Error initializing identification LED\n");
+               /* This is not fatal and we should not stop init due to this */
+       }
+
+       /* Storing the Speed Power Down  value for later use */
+       ret_val = hw->phy.ops.read_reg(hw,
+                                      IGP01E1000_GMII_FIFO,
+                                      &dev_spec->spd_default);
+       if (ret_val)
+               goto out;
+
+       /* Disabling VLAN filtering */
+       DEBUGOUT("Initializing the IEEE VLAN\n");
+       mac->ops.clear_vfta(hw);
+
+       /* Setup the receive address. */
+       e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
+
+       /* Zero out the Multicast HASH table */
+       DEBUGOUT("Zeroing the MTA\n");
+       for (i = 0; i < mac->mta_reg_count; i++) {
+               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
+               /*
+                * Avoid back to back register writes by adding the register
+                * read (flush).  This is to protect against some strange
+                * bridge configurations that may issue Memory Write Block
+                * (MWB) to our register space.
+                */
+               E1000_WRITE_FLUSH(hw);
+       }
+
+       /* Setup link and flow control */
+       ret_val = mac->ops.setup_link(hw);
+
+       txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
+       txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
+                E1000_TXDCTL_FULL_TX_DESC_WB;
+       E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
+
+       /*
+        * Clear all of the statistics registers (clear on read).  It is
+        * important that we do this after we have tried to establish link
+        * because the symbol error count will increment wildly if there
+        * is no link.
+        */
+       e1000_clear_hw_cntrs_82541(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ * e1000_get_link_up_info_82541 - Report speed and duplex
+ * @hw: pointer to the HW structure
+ * @speed: pointer to speed buffer
+ * @duplex: pointer to duplex buffer
+ *
+ * Retrieve the current speed and duplex configuration.
+ **/
+static s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
+                                        u16 *duplex)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
+       u16 data;
+
+       DEBUGFUNC("e1000_get_link_up_info_82541");
+
+       ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex);
+       if (ret_val)
+               goto out;
+
+       if (!phy->speed_downgraded)
+               goto out;
+
+       /*
+        * IGP01 PHY may advertise full duplex operation after speed
+        * downgrade even if it is operating at half duplex.
+        * Here we set the duplex settings to match the duplex in the
+        * link partner's capabilities.
+        */
+       ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_EXP, &data);
+       if (ret_val)
+               goto out;
+
+       if (!(data & NWAY_ER_LP_NWAY_CAPS)) {
+               *duplex = HALF_DUPLEX;
+       } else {
+               ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, &data);
+               if (ret_val)
+                       goto out;
+
+               if (*speed == SPEED_100) {
+                       if (!(data & NWAY_LPAR_100TX_FD_CAPS))
+                               *duplex = HALF_DUPLEX;
+               } else if (*speed == SPEED_10) {
+                       if (!(data & NWAY_LPAR_10T_FD_CAPS))
+                               *duplex = HALF_DUPLEX;
+               }
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_phy_hw_reset_82541 - PHY hardware reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Verify the reset block is not blocking us from resetting.  Acquire
+ *  semaphore (if necessary) and read/set/write the device control reset
+ *  bit in the PHY.  Wait the appropriate delay time for the device to
+ *  reset and release the semaphore (if necessary).
+ **/
+static s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw)
+{
+       s32 ret_val;
+       u32 ledctl;
+
+       DEBUGFUNC("e1000_phy_hw_reset_82541");
+
+       ret_val = e1000_phy_hw_reset_generic(hw);
+       if (ret_val)
+               goto out;
+
+       e1000_phy_init_script_82541(hw);
+
+       if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
+               /* Configure activity LED after PHY reset */
+               ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
+               ledctl &= IGP_ACTIVITY_LED_MASK;
+               ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
+               E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_copper_link_82541 - Configure copper link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Calls the appropriate function to configure the link for auto-neg or forced
+ *  speed and duplex.  Then we check for link, once link is established calls
+ *  to configure collision distance and flow control are called.  If link is
+ *  not established, we return -E1000_ERR_PHY (-2).
+ **/
+static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
+       s32  ret_val;
+       u32 ctrl, ledctl;
+
+       DEBUGFUNC("e1000_setup_copper_link_82541");
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+       ctrl |= E1000_CTRL_SLU;
+       ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+       hw->phy.reset_disable = false;
+
+       /* Earlier revs of the IGP phy require us to force MDI. */
+       if (hw->mac.type == e1000_82541 || hw->mac.type == e1000_82547) {
+               dev_spec->dsp_config = e1000_dsp_config_disabled;
+               phy->mdix = 1;
+       } else {
+               dev_spec->dsp_config = e1000_dsp_config_enabled;
+       }
+
+       ret_val = e1000_copper_link_setup_igp(hw);
+       if (ret_val)
+               goto out;
+
+       if (hw->mac.autoneg) {
+               if (dev_spec->ffe_config == e1000_ffe_config_active)
+                       dev_spec->ffe_config = e1000_ffe_config_enabled;
+       }
+
+       /* Configure activity LED after Phy reset */
+       ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
+       ledctl &= IGP_ACTIVITY_LED_MASK;
+       ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
+       E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
+
+       ret_val = e1000_setup_copper_link_generic(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_link_82541 - Check/Store link connection
+ *  @hw: pointer to the HW structure
+ *
+ *  This checks the link condition of the adapter and stores the
+ *  results in the hw->mac structure.
+ **/
+static s32 e1000_check_for_link_82541(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       s32 ret_val;
+       bool link;
+
+       DEBUGFUNC("e1000_check_for_link_82541");
+
+       /*
+        * We only want to go out to the PHY registers to see if Auto-Neg
+        * has completed and/or if our link status has changed.  The
+        * get_link_status flag is set upon receiving a Link Status
+        * Change or Rx Sequence Error interrupt.
+        */
+       if (!mac->get_link_status) {
+               ret_val = E1000_SUCCESS;
+               goto out;
+       }
+
+       /*
+        * First we want to see if the MII Status Register reports
+        * link.  If so, then we want to get the current speed/duplex
+        * of the PHY.
+        */
+       ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
+       if (ret_val)
+               goto out;
+
+       if (!link) {
+               ret_val = -E1000_ERR_CONFIG;
+#if 0
+               ret_val = e1000_config_dsp_after_link_change_82541(hw, false);
+#endif
+               goto out; /* No link detected */
+       }
+
+       mac->get_link_status = false;
+
+       /*
+        * Check if there was DownShift, must be checked
+        * immediately after link-up
+        */
+       e1000_check_downshift_generic(hw);
+
+       /*
+        * If we are forcing speed/duplex, then we simply return since
+        * we have already determined whether we have link or not.
+        */
+       if (!mac->autoneg) {
+               ret_val = -E1000_ERR_CONFIG;
+               goto out;
+       }
+
+#if 0
+       ret_val = e1000_config_dsp_after_link_change_82541(hw, true);
+#endif
+
+       /*
+        * Auto-Neg is enabled.  Auto Speed Detection takes care
+        * of MAC speed/duplex configuration.  So we only need to
+        * configure Collision Distance in the MAC.
+        */
+       e1000_config_collision_dist_generic(hw);
+
+       /*
+        * Configure Flow Control now that Auto-Neg has completed.
+        * First, we need to restore the desired flow control
+        * settings because we may have had to re-autoneg with a
+        * different link partner.
+        */
+       ret_val = e1000_config_fc_after_link_up_generic(hw);
+       if (ret_val) {
+               DEBUGOUT("Error configuring flow control\n");
+       }
+
+out:
+       return ret_val;
+}
+
+#if 0
+/**
+ *  e1000_config_dsp_after_link_change_82541 - Config DSP after link
+ *  @hw: pointer to the HW structure
+ *  @link_up: boolean flag for link up status
+ *
+ *  Return E1000_ERR_PHY when failing to read/write the PHY, else E1000_SUCCESS
+ *  at any other case.
+ *
+ *  82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a
+ *  gigabit link is achieved to improve link quality.
+ **/
+static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
+                                                    bool link_up)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
+       s32 ret_val;
+       u32 idle_errs = 0;
+       u16 phy_data, phy_saved_data, speed, duplex, i;
+       u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
+       u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
+                                                  {IGP01E1000_PHY_AGC_PARAM_A,
+                                                   IGP01E1000_PHY_AGC_PARAM_B,
+                                                   IGP01E1000_PHY_AGC_PARAM_C,
+                                                   IGP01E1000_PHY_AGC_PARAM_D};
+
+       DEBUGFUNC("e1000_config_dsp_after_link_change_82541");
+
+       if (link_up) {
+               ret_val = hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
+               if (ret_val) {
+                       DEBUGOUT("Error getting link speed and duplex\n");
+                       goto out;
+               }
+
+               if (speed != SPEED_1000) {
+                       ret_val = E1000_SUCCESS;
+                       goto out;
+               }
+
+#if 0
+               ret_val = phy->ops.get_cable_length(hw);
+#endif
+               ret_val = -E1000_ERR_CONFIG;
+               if (ret_val)
+                       goto out;
+
+               if ((dev_spec->dsp_config == e1000_dsp_config_enabled) &&
+                   phy->min_cable_length >= 50) {
+
+                       for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
+                               ret_val = phy->ops.read_reg(hw,
+                                                           dsp_reg_array[i],
+                                                           &phy_data);
+                               if (ret_val)
+                                       goto out;
+
+                               phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
+
+                               ret_val = phy->ops.write_reg(hw,
+                                                            dsp_reg_array[i],
+                                                            phy_data);
+                               if (ret_val)
+                                       goto out;
+                       }
+                       dev_spec->dsp_config = e1000_dsp_config_activated;
+               }
+
+               if ((dev_spec->ffe_config != e1000_ffe_config_enabled) ||
+                   (phy->min_cable_length >= 50)) {
+                       ret_val = E1000_SUCCESS;
+                       goto out;
+               }
+
+               /* clear previous idle error counts */
+               ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
+               if (ret_val)
+                       goto out;
+
+               for (i = 0; i < ffe_idle_err_timeout; i++) {
+                       usec_delay(1000);
+                       ret_val = phy->ops.read_reg(hw,
+                                                   PHY_1000T_STATUS,
+                                                   &phy_data);
+                       if (ret_val)
+                               goto out;
+
+                       idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT);
+                       if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
+                               dev_spec->ffe_config = e1000_ffe_config_active;
+
+                               ret_val = phy->ops.write_reg(hw,
+                                                 IGP01E1000_PHY_DSP_FFE,
+                                                 IGP01E1000_PHY_DSP_FFE_CM_CP);
+                               if (ret_val)
+                                       goto out;
+                               break;
+                       }
+
+                       if (idle_errs)
+                               ffe_idle_err_timeout =
+                                                FFE_IDLE_ERR_COUNT_TIMEOUT_100;
+               }
+       } else {
+               if (dev_spec->dsp_config == e1000_dsp_config_activated) {
+                       /*
+                        * Save off the current value of register 0x2F5B
+                        * to be restored at the end of the routines.
+                        */
+                       ret_val = phy->ops.read_reg(hw,
+                                                   0x2F5B,
+                                                   &phy_saved_data);
+                       if (ret_val)
+                               goto out;
+
+                       /* Disable the PHY transmitter */
+                       ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
+                       if (ret_val)
+                               goto out;
+
+                       msec_delay_irq(20);
+
+                       ret_val = phy->ops.write_reg(hw,
+                                                    0x0000,
+                                                    IGP01E1000_IEEE_FORCE_GIG);
+                       if (ret_val)
+                               goto out;
+                       for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
+                               ret_val = phy->ops.read_reg(hw,
+                                                           dsp_reg_array[i],
+                                                           &phy_data);
+                               if (ret_val)
+                                       goto out;
+
+                               phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
+                               phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
+
+                               ret_val = phy->ops.write_reg(hw,
+                                                            dsp_reg_array[i],
+                                                            phy_data);
+                               if (ret_val)
+                                       goto out;
+                       }
+
+                       ret_val = phy->ops.write_reg(hw,
+                                              0x0000,
+                                              IGP01E1000_IEEE_RESTART_AUTONEG);
+                       if (ret_val)
+                               goto out;
+
+                       msec_delay_irq(20);
+
+                       /* Now enable the transmitter */
+                       ret_val = phy->ops.write_reg(hw,
+                                                    0x2F5B,
+                                                    phy_saved_data);
+                       if (ret_val)
+                               goto out;
+
+                       dev_spec->dsp_config = e1000_dsp_config_enabled;
+               }
+
+               if (dev_spec->ffe_config != e1000_ffe_config_active) {
+                       ret_val = E1000_SUCCESS;
+                       goto out;
+               }
+
+               /*
+                * Save off the current value of register 0x2F5B
+                * to be restored at the end of the routines.
+                */
+               ret_val = phy->ops.read_reg(hw, 0x2F5B, &phy_saved_data);
+               if (ret_val)
+                       goto out;
+
+               /* Disable the PHY transmitter */
+               ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
+               if (ret_val)
+                       goto out;
+
+               msec_delay_irq(20);
+
+               ret_val = phy->ops.write_reg(hw,
+                                            0x0000,
+                                            IGP01E1000_IEEE_FORCE_GIG);
+               if (ret_val)
+                       goto out;
+
+               ret_val = phy->ops.write_reg(hw,
+                                            IGP01E1000_PHY_DSP_FFE,
+                                            IGP01E1000_PHY_DSP_FFE_DEFAULT);
+               if (ret_val)
+                       goto out;
+
+               ret_val = phy->ops.write_reg(hw,
+                                            0x0000,
+                                            IGP01E1000_IEEE_RESTART_AUTONEG);
+               if (ret_val)
+                       goto out;
+
+               msec_delay_irq(20);
+
+               /* Now enable the transmitter */
+               ret_val = phy->ops.write_reg(hw, 0x2F5B, phy_saved_data);
+
+               if (ret_val)
+                       goto out;
+
+               dev_spec->ffe_config = e1000_ffe_config_enabled;
+       }
+
+out:
+       return ret_val;
+}
+#endif
+
+#if 0
+/**
+ *  e1000_get_cable_length_igp_82541 - Determine cable length for igp PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  The automatic gain control (agc) normalizes the amplitude of the
+ *  received signal, adjusting for the attenuation produced by the
+ *  cable.  By reading the AGC registers, which represent the
+ *  combination of coarse and fine gain value, the value can be put
+ *  into a lookup table to obtain the approximate cable length
+ *  for each channel.
+ **/
+static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val = E1000_SUCCESS;
+       u16 i, data;
+       u16 cur_agc_value, agc_value = 0;
+       u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
+       u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
+                                                        {IGP01E1000_PHY_AGC_A,
+                                                         IGP01E1000_PHY_AGC_B,
+                                                         IGP01E1000_PHY_AGC_C,
+                                                         IGP01E1000_PHY_AGC_D};
+
+       DEBUGFUNC("e1000_get_cable_length_igp_82541");
+
+       /* Read the AGC registers for all channels */
+       for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
+               ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &data);
+               if (ret_val)
+                       goto out;
+
+               cur_agc_value = data >> IGP01E1000_AGC_LENGTH_SHIFT;
+
+               /* Bounds checking */
+               if ((cur_agc_value >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) ||
+                   (cur_agc_value == 0)) {
+                       ret_val = -E1000_ERR_PHY;
+                       goto out;
+               }
+
+               agc_value += cur_agc_value;
+
+               if (min_agc_value > cur_agc_value)
+                       min_agc_value = cur_agc_value;
+       }
+
+       /* Remove the minimal AGC result for length < 50m */
+       if (agc_value < IGP01E1000_PHY_CHANNEL_NUM * 50) {
+               agc_value -= min_agc_value;
+               /* Average the three remaining channels for the length. */
+               agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1);
+       } else {
+               /* Average the channels for the length. */
+               agc_value /= IGP01E1000_PHY_CHANNEL_NUM;
+       }
+
+       phy->min_cable_length = (e1000_igp_cable_length_table[agc_value] >
+                                IGP01E1000_AGC_RANGE)
+                               ? (e1000_igp_cable_length_table[agc_value] -
+                                  IGP01E1000_AGC_RANGE)
+                               : 0;
+       phy->max_cable_length = e1000_igp_cable_length_table[agc_value] +
+                               IGP01E1000_AGC_RANGE;
+
+       phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
+
+out:
+       return ret_val;
+}
+#endif
+
+/**
+ *  e1000_set_d3_lplu_state_82541 - Sets low power link up state for D3
+ *  @hw: pointer to the HW structure
+ *  @active: boolean used to enable/disable lplu
+ *
+ *  Success returns 0, Failure returns 1
+ *
+ *  The low power link up (lplu) state is set to the power management level D3
+ *  and SmartSpeed is disabled when active is true, else clear lplu for D3
+ *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
+ *  is used during Dx states where the power conservation is most important.
+ *  During driver activity, SmartSpeed should be enabled so performance is
+ *  maintained.
+ **/
+static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, bool active)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
+       u16 data;
+
+       DEBUGFUNC("e1000_set_d3_lplu_state_82541");
+
+       switch (hw->mac.type) {
+       case e1000_82541_rev_2:
+       case e1000_82547_rev_2:
+               break;
+       default:
+               ret_val = e1000_set_d3_lplu_state_generic(hw, active);
+               goto out;
+               break;
+       }
+
+       ret_val = phy->ops.read_reg(hw, IGP01E1000_GMII_FIFO, &data);
+       if (ret_val)
+               goto out;
+
+       if (!active) {
+               data &= ~IGP01E1000_GMII_FLEX_SPD;
+               ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data);
+               if (ret_val)
+                       goto out;
+
+               /*
+                * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+                * during Dx states where the power conservation is most
+                * important.  During driver activity we should enable
+                * SmartSpeed, so performance is maintained.
+                */
+               if (phy->smart_speed == e1000_smart_speed_on) {
+                       ret_val = phy->ops.read_reg(hw,
+                                                   IGP01E1000_PHY_PORT_CONFIG,
+                                                   &data);
+                       if (ret_val)
+                               goto out;
+
+                       data |= IGP01E1000_PSCFR_SMART_SPEED;
+                       ret_val = phy->ops.write_reg(hw,
+                                                    IGP01E1000_PHY_PORT_CONFIG,
+                                                    data);
+                       if (ret_val)
+                               goto out;
+               } else if (phy->smart_speed == e1000_smart_speed_off) {
+                       ret_val = phy->ops.read_reg(hw,
+                                                   IGP01E1000_PHY_PORT_CONFIG,
+                                                   &data);
+                       if (ret_val)
+                               goto out;
+
+                       data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+                       ret_val = phy->ops.write_reg(hw,
+                                                    IGP01E1000_PHY_PORT_CONFIG,
+                                                    data);
+                       if (ret_val)
+                               goto out;
+               }
+       } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
+                  (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
+                  (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
+               data |= IGP01E1000_GMII_FLEX_SPD;
+               ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data);
+               if (ret_val)
+                       goto out;
+
+               /* When LPLU is enabled, we should disable SmartSpeed */
+               ret_val = phy->ops.read_reg(hw,
+                                           IGP01E1000_PHY_PORT_CONFIG,
+                                           &data);
+               if (ret_val)
+                       goto out;
+
+               data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+               ret_val = phy->ops.write_reg(hw,
+                                            IGP01E1000_PHY_PORT_CONFIG,
+                                            data);
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_led_82541 - Configures SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  This prepares the SW controllable LED for use and saves the current state
+ *  of the LED so it can be later restored.
+ **/
+static s32 e1000_setup_led_82541(struct e1000_hw *hw __unused)
+{
+#if 0
+       struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_setup_led_82541");
+
+       ret_val = hw->phy.ops.read_reg(hw,
+                                      IGP01E1000_GMII_FIFO,
+                                      &dev_spec->spd_default);
+       if (ret_val)
+               goto out;
+
+       ret_val = hw->phy.ops.write_reg(hw,
+                                       IGP01E1000_GMII_FIFO,
+                                       (u16)(dev_spec->spd_default &
+                                               ~IGP01E1000_GMII_SPD));
+       if (ret_val)
+               goto out;
+
+       E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);
+
+out:
+       return ret_val;
+#endif
+        return 0;
+}
+
+/**
+ *  e1000_cleanup_led_82541 - Set LED config to default operation
+ *  @hw: pointer to the HW structure
+ *
+ *  Remove the current LED configuration and set the LED configuration
+ *  to the default value, saved from the EEPROM.
+ **/
+static s32 e1000_cleanup_led_82541(struct e1000_hw *hw __unused)
+{
+#if 0
+       struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_cleanup_led_82541");
+
+       ret_val = hw->phy.ops.write_reg(hw,
+                                       IGP01E1000_GMII_FIFO,
+                                       dev_spec->spd_default);
+       if (ret_val)
+               goto out;
+
+       E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default);
+
+out:
+       return ret_val;
+#endif
+        return 0;
+}
+
+/**
+ *  e1000_phy_init_script_82541 - Initialize GbE PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Initializes the IGP PHY.
+ **/
+static s32 e1000_phy_init_script_82541(struct e1000_hw *hw)
+{
+       struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
+       u32 ret_val;
+       u16 phy_saved_data;
+
+       DEBUGFUNC("e1000_phy_init_script_82541");
+
+       if (!dev_spec->phy_init_script) {
+               ret_val = E1000_SUCCESS;
+               goto out;
+       }
+
+       /* Delay after phy reset to enable NVM configuration to load */
+       msec_delay(20);
+
+       /*
+        * Save off the current value of register 0x2F5B to be restored at
+        * the end of this routine.
+        */
+       ret_val = hw->phy.ops.read_reg(hw, 0x2F5B, &phy_saved_data);
+
+       /* Disabled the PHY transmitter */
+       hw->phy.ops.write_reg(hw, 0x2F5B, 0x0003);
+
+       msec_delay(20);
+
+       hw->phy.ops.write_reg(hw, 0x0000, 0x0140);
+
+       msec_delay(5);
+
+       switch (hw->mac.type) {
+       case e1000_82541:
+       case e1000_82547:
+               hw->phy.ops.write_reg(hw, 0x1F95, 0x0001);
+
+               hw->phy.ops.write_reg(hw, 0x1F71, 0xBD21);
+
+               hw->phy.ops.write_reg(hw, 0x1F79, 0x0018);
+
+               hw->phy.ops.write_reg(hw, 0x1F30, 0x1600);
+
+               hw->phy.ops.write_reg(hw, 0x1F31, 0x0014);
+
+               hw->phy.ops.write_reg(hw, 0x1F32, 0x161C);
+
+               hw->phy.ops.write_reg(hw, 0x1F94, 0x0003);
+
+               hw->phy.ops.write_reg(hw, 0x1F96, 0x003F);
+
+               hw->phy.ops.write_reg(hw, 0x2010, 0x0008);
+               break;
+       case e1000_82541_rev_2:
+       case e1000_82547_rev_2:
+               hw->phy.ops.write_reg(hw, 0x1F73, 0x0099);
+               break;
+       default:
+               break;
+       }
+
+       hw->phy.ops.write_reg(hw, 0x0000, 0x3300);
+
+       msec_delay(20);
+
+       /* Now enable the transmitter */
+       hw->phy.ops.write_reg(hw, 0x2F5B, phy_saved_data);
+
+       if (hw->mac.type == e1000_82547) {
+               u16 fused, fine, coarse;
+
+               /* Move to analog registers page */
+               hw->phy.ops.read_reg(hw,
+                                 IGP01E1000_ANALOG_SPARE_FUSE_STATUS,
+                                 &fused);
+
+               if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
+                       hw->phy.ops.read_reg(hw,
+                                         IGP01E1000_ANALOG_FUSE_STATUS,
+                                         &fused);
+
+                       fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
+                       coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
+
+                       if (coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
+                               coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;
+                               fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
+                       } else if (coarse ==
+                                  IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
+                               fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
+
+                       fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
+                               (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
+                               (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);
+
+                       hw->phy.ops.write_reg(hw,
+                                          IGP01E1000_ANALOG_FUSE_CONTROL,
+                                          fused);
+                       hw->phy.ops.write_reg(hw,
+                                     IGP01E1000_ANALOG_FUSE_BYPASS,
+                                     IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
+               }
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ * e1000_power_down_phy_copper_82541 - Remove link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, remove the link.
+ **/
+static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw)
+{
+       /* If the management interface is not enabled, then power down */
+       if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN))
+               e1000_power_down_phy_copper(hw);
+
+       return;
+}
+
+/**
+ *  e1000_clear_hw_cntrs_82541 - Clear device specific hardware counters
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the hardware counters by reading the counter registers.
+ **/
+static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_clear_hw_cntrs_82541");
+
+       e1000_clear_hw_cntrs_base_generic(hw);
+
+#if 0
+       E1000_READ_REG(hw, E1000_PRC64);
+       E1000_READ_REG(hw, E1000_PRC127);
+       E1000_READ_REG(hw, E1000_PRC255);
+       E1000_READ_REG(hw, E1000_PRC511);
+       E1000_READ_REG(hw, E1000_PRC1023);
+       E1000_READ_REG(hw, E1000_PRC1522);
+       E1000_READ_REG(hw, E1000_PTC64);
+       E1000_READ_REG(hw, E1000_PTC127);
+       E1000_READ_REG(hw, E1000_PTC255);
+       E1000_READ_REG(hw, E1000_PTC511);
+       E1000_READ_REG(hw, E1000_PTC1023);
+       E1000_READ_REG(hw, E1000_PTC1522);
+
+       E1000_READ_REG(hw, E1000_ALGNERRC);
+       E1000_READ_REG(hw, E1000_RXERRC);
+       E1000_READ_REG(hw, E1000_TNCRS);
+       E1000_READ_REG(hw, E1000_CEXTERR);
+       E1000_READ_REG(hw, E1000_TSCTC);
+       E1000_READ_REG(hw, E1000_TSCTFC);
+
+       E1000_READ_REG(hw, E1000_MGTPRC);
+       E1000_READ_REG(hw, E1000_MGTPDC);
+       E1000_READ_REG(hw, E1000_MGTPTC);
+#endif
+}
+
+static struct pci_device_id e1000_82541_nics[] = {
+     PCI_ROM(0x8086, 0x1013, "E1000_DEV_ID_82541EI", "E1000_DEV_ID_82541EI", e1000_82541),
+     PCI_ROM(0x8086, 0x1014, "E1000_DEV_ID_82541ER_LOM", "E1000_DEV_ID_82541ER_LOM", e1000_82541),
+     PCI_ROM(0x8086, 0x1018, "E1000_DEV_ID_82541EI_MOBILE", "E1000_DEV_ID_82541EI_MOBILE", e1000_82541),
+     PCI_ROM(0x8086, 0x1019, "E1000_DEV_ID_82547EI", "E1000_DEV_ID_82547EI", e1000_82547),
+     PCI_ROM(0x8086, 0x101A, "E1000_DEV_ID_82547EI_MOBILE", "E1000_DEV_ID_82547EI_MOBILE", e1000_82547),
+     PCI_ROM(0x8086, 0x1075, "E1000_DEV_ID_82547GI", "E1000_DEV_ID_82547GI", e1000_82547_rev_2),
+     PCI_ROM(0x8086, 0x1076, "E1000_DEV_ID_82541GI", "E1000_DEV_ID_82541GI", e1000_82541_rev_2),
+     PCI_ROM(0x8086, 0x1077, "E1000_DEV_ID_82541GI_MOBILE", "E1000_DEV_ID_82541GI_MOBILE", e1000_82541_rev_2),
+     PCI_ROM(0x8086, 0x1078, "E1000_DEV_ID_82541ER", "E1000_DEV_ID_82541ER", e1000_82541_rev_2),
+     PCI_ROM(0x8086, 0x107C, "E1000_DEV_ID_82541GI_LF", "E1000_DEV_ID_82541GI_LF", e1000_82541_rev_2),
+};
+
+struct pci_driver e1000_82541_driver __pci_driver = {
+       .ids = e1000_82541_nics,
+       .id_count = (sizeof (e1000_82541_nics) / sizeof (e1000_82541_nics[0])),
+       .probe = e1000_probe,
+       .remove = e1000_remove,
+};
diff --git a/kern/drivers/net/e1000/e1000_82541.h b/kern/drivers/net/e1000/e1000_82541.h
new file mode 100644 (file)
index 0000000..f86a148
--- /dev/null
@@ -0,0 +1,86 @@
+/*******************************************************************************
+
+  Intel PRO/1000 Linux driver
+  Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef _E1000_82541_H_
+#define _E1000_82541_H_
+
+#define NVM_WORD_SIZE_BASE_SHIFT_82541 (NVM_WORD_SIZE_BASE_SHIFT + 1)
+
+#define IGP01E1000_PHY_CHANNEL_NUM                    4
+
+#define IGP01E1000_PHY_AGC_A                     0x1172
+#define IGP01E1000_PHY_AGC_B                     0x1272
+#define IGP01E1000_PHY_AGC_C                     0x1472
+#define IGP01E1000_PHY_AGC_D                     0x1872
+
+#define IGP01E1000_PHY_AGC_PARAM_A               0x1171
+#define IGP01E1000_PHY_AGC_PARAM_B               0x1271
+#define IGP01E1000_PHY_AGC_PARAM_C               0x1471
+#define IGP01E1000_PHY_AGC_PARAM_D               0x1871
+
+#define IGP01E1000_PHY_EDAC_MU_INDEX             0xC000
+#define IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS      0x8000
+
+#define IGP01E1000_PHY_DSP_RESET                 0x1F33
+
+#define IGP01E1000_PHY_DSP_FFE                   0x1F35
+#define IGP01E1000_PHY_DSP_FFE_CM_CP             0x0069
+#define IGP01E1000_PHY_DSP_FFE_DEFAULT           0x002A
+
+#define IGP01E1000_IEEE_FORCE_GIG                0x0140
+#define IGP01E1000_IEEE_RESTART_AUTONEG          0x3300
+
+#define IGP01E1000_AGC_LENGTH_SHIFT                   7
+#define IGP01E1000_AGC_RANGE                         10
+
+#define FFE_IDLE_ERR_COUNT_TIMEOUT_20                20
+#define FFE_IDLE_ERR_COUNT_TIMEOUT_100              100
+
+#define IGP01E1000_ANALOG_FUSE_STATUS            0x20D0
+#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS      0x20D1
+#define IGP01E1000_ANALOG_FUSE_CONTROL           0x20DC
+#define IGP01E1000_ANALOG_FUSE_BYPASS            0x20DE
+
+#define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED     0x0100
+#define IGP01E1000_ANALOG_FUSE_FINE_MASK         0x0F80
+#define IGP01E1000_ANALOG_FUSE_COARSE_MASK       0x0070
+#define IGP01E1000_ANALOG_FUSE_COARSE_THRESH     0x0040
+#define IGP01E1000_ANALOG_FUSE_COARSE_10         0x0010
+#define IGP01E1000_ANALOG_FUSE_FINE_1            0x0080
+#define IGP01E1000_ANALOG_FUSE_FINE_10           0x0500
+#define IGP01E1000_ANALOG_FUSE_POLY_MASK         0xF000
+#define IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL 0x0002
+
+#define IGP01E1000_MSE_CHANNEL_D                 0x000F
+#define IGP01E1000_MSE_CHANNEL_C                 0x00F0
+#define IGP01E1000_MSE_CHANNEL_B                 0x0F00
+#define IGP01E1000_MSE_CHANNEL_A                 0xF000
+
+#endif
diff --git a/kern/drivers/net/e1000/e1000_82542.c b/kern/drivers/net/e1000/e1000_82542.c
new file mode 100644 (file)
index 0000000..45f2429
--- /dev/null
@@ -0,0 +1,571 @@
+/*******************************************************************************
+
+  Intel PRO/1000 Linux driver
+  Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * 82542 Gigabit Ethernet Controller
+ */
+
+#include "e1000_api.h"
+
+static s32  e1000_init_phy_params_82542(struct e1000_hw *hw);
+static s32  e1000_init_nvm_params_82542(struct e1000_hw *hw);
+static s32  e1000_init_mac_params_82542(struct e1000_hw *hw);
+static s32  e1000_get_bus_info_82542(struct e1000_hw *hw);
+static s32  e1000_reset_hw_82542(struct e1000_hw *hw);
+static s32  e1000_init_hw_82542(struct e1000_hw *hw);
+static s32  e1000_setup_link_82542(struct e1000_hw *hw);
+static s32  e1000_led_on_82542(struct e1000_hw *hw);
+static s32  e1000_led_off_82542(struct e1000_hw *hw);
+static void e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index);
+static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw);
+
+/**
+ *  e1000_init_phy_params_82542 - Init PHY func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_phy_params_82542(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_init_phy_params_82542");
+
+       phy->type               = e1000_phy_none;
+
+       return ret_val;
+}
+
+/**
+ *  e1000_init_nvm_params_82542 - Init NVM func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_nvm_params_82542(struct e1000_hw *hw)
+{
+       struct e1000_nvm_info *nvm = &hw->nvm;
+
+       DEBUGFUNC("e1000_init_nvm_params_82542");
+
+       nvm->address_bits       =  6;
+       nvm->delay_usec         = 50;
+       nvm->opcode_bits        =  3;
+       nvm->type               = e1000_nvm_eeprom_microwire;
+       nvm->word_size          = 64;
+
+       /* Function Pointers */
+       nvm->ops.read           = e1000_read_nvm_microwire;
+       nvm->ops.release        = e1000_stop_nvm;
+       nvm->ops.write          = e1000_write_nvm_microwire;
+       nvm->ops.update         = e1000_update_nvm_checksum_generic;
+       nvm->ops.validate       = e1000_validate_nvm_checksum_generic;
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_init_mac_params_82542 - Init MAC func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_mac_params_82542(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+
+       DEBUGFUNC("e1000_init_mac_params_82542");
+
+       /* Set media type */
+       hw->phy.media_type = e1000_media_type_fiber;
+
+       /* Set mta register count */
+       mac->mta_reg_count = 128;
+       /* Set rar entry count */
+       mac->rar_entry_count = E1000_RAR_ENTRIES;
+
+       /* Function pointers */
+
+       /* bus type/speed/width */
+       mac->ops.get_bus_info = e1000_get_bus_info_82542;
+       /* function id */
+       mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci;
+       /* reset */
+       mac->ops.reset_hw = e1000_reset_hw_82542;
+       /* hw initialization */
+       mac->ops.init_hw = e1000_init_hw_82542;
+       /* link setup */
+       mac->ops.setup_link = e1000_setup_link_82542;
+       /* phy/fiber/serdes setup */
+       mac->ops.setup_physical_interface = e1000_setup_fiber_serdes_link_generic;
+       /* check for link */
+       mac->ops.check_for_link = e1000_check_for_fiber_link_generic;
+       /* multicast address update */
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
+       /* writing VFTA */
+       mac->ops.write_vfta = e1000_write_vfta_generic;
+       /* clearing VFTA */
+       mac->ops.clear_vfta = e1000_clear_vfta_generic;
+       /* setting MTA */
+       mac->ops.mta_set = e1000_mta_set_generic;
+       /* set RAR */
+       mac->ops.rar_set = e1000_rar_set_82542;
+       /* turn on/off LED */
+       mac->ops.led_on = e1000_led_on_82542;
+       mac->ops.led_off = e1000_led_off_82542;
+       /* clear hardware counters */
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82542;
+       /* link info */
+       mac->ops.get_link_up_info = e1000_get_speed_and_duplex_fiber_serdes_generic;
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_init_function_pointers_82542 - Init func ptrs.
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to initialize all function pointers and parameters.
+ **/
+void e1000_init_function_pointers_82542(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_init_function_pointers_82542");
+
+       hw->mac.ops.init_params = e1000_init_mac_params_82542;
+       hw->nvm.ops.init_params = e1000_init_nvm_params_82542;
+       hw->phy.ops.init_params = e1000_init_phy_params_82542;
+}
+
+/**
+ *  e1000_get_bus_info_82542 - Obtain bus information for adapter
+ *  @hw: pointer to the HW structure
+ *
+ *  This will obtain information about the HW bus for which the
+ *  adapter is attached and stores it in the hw structure.
+ **/
+static s32 e1000_get_bus_info_82542(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_get_bus_info_82542");
+
+       hw->bus.type = e1000_bus_type_pci;
+       hw->bus.speed = e1000_bus_speed_unknown;
+       hw->bus.width = e1000_bus_width_unknown;
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_reset_hw_82542 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+static s32 e1000_reset_hw_82542(struct e1000_hw *hw)
+{
+       struct e1000_bus_info *bus = &hw->bus;
+       s32 ret_val = E1000_SUCCESS;
+       u32 ctrl, icr;
+
+       DEBUGFUNC("e1000_reset_hw_82542");
+
+       if (hw->revision_id == E1000_REVISION_2) {
+               DEBUGOUT("Disabling MWI on 82542 rev 2\n");
+               e1000_pci_clear_mwi(hw);
+       }
+
+       DEBUGOUT("Masking off all interrupts\n");
+       E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+
+       E1000_WRITE_REG(hw, E1000_RCTL, 0);
+       E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
+       E1000_WRITE_FLUSH(hw);
+
+       /*
+        * Delay to allow any outstanding PCI transactions to complete before
+        * resetting the device
+        */
+       msec_delay(10);
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       DEBUGOUT("Issuing a global reset to 82542/82543 MAC\n");
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
+
+       hw->nvm.ops.reload(hw);
+       msec_delay(2);
+
+       E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+       icr = E1000_READ_REG(hw, E1000_ICR);
+
+       if (hw->revision_id == E1000_REVISION_2) {
+               if (bus->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
+                       e1000_pci_set_mwi(hw);
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_init_hw_82542 - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation.
+ **/
+static s32 e1000_init_hw_82542(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       struct e1000_dev_spec_82542 *dev_spec = &hw->dev_spec._82542;
+       s32 ret_val = E1000_SUCCESS;
+       u32 ctrl;
+       u16 i;
+
+       DEBUGFUNC("e1000_init_hw_82542");
+
+       /* Disabling VLAN filtering */
+       E1000_WRITE_REG(hw, E1000_VET, 0);
+       mac->ops.clear_vfta(hw);
+
+       /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
+       if (hw->revision_id == E1000_REVISION_2) {
+               DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
+               e1000_pci_clear_mwi(hw);
+               E1000_WRITE_REG(hw, E1000_RCTL, E1000_RCTL_RST);
+               E1000_WRITE_FLUSH(hw);
+               msec_delay(5);
+       }
+
+       /* Setup the receive address. */
+       e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
+
+       /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
+       if (hw->revision_id == E1000_REVISION_2) {
+               E1000_WRITE_REG(hw, E1000_RCTL, 0);
+               E1000_WRITE_FLUSH(hw);
+               msec_delay(1);
+               if (hw->bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
+                       e1000_pci_set_mwi(hw);
+       }
+
+       /* Zero out the Multicast HASH table */
+       DEBUGOUT("Zeroing the MTA\n");
+       for (i = 0; i < mac->mta_reg_count; i++)
+               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
+
+       /*
+        * Set the PCI priority bit correctly in the CTRL register.  This
+        * determines if the adapter gives priority to receives, or if it
+        * gives equal priority to transmits and receives.
+        */
+       if (dev_spec->dma_fairness) {
+               ctrl = E1000_READ_REG(hw, E1000_CTRL);
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PRIOR);
+       }
+
+       /* Setup link and flow control */
+       ret_val = e1000_setup_link_82542(hw);
+
+       /*
+        * Clear all of the statistics registers (clear on read).  It is
+        * important that we do this after we have tried to establish link
+        * because the symbol error count will increment wildly if there
+        * is no link.
+        */
+       e1000_clear_hw_cntrs_82542(hw);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_link_82542 - Setup flow control and link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Determines which flow control settings to use, then configures flow
+ *  control.  Calls the appropriate media-specific link configuration
+ *  function.  Assuming the adapter has a valid link partner, a valid link
+ *  should be established.  Assumes the hardware has previously been reset
+ *  and the transmitter and receiver are not enabled.
+ **/
+static s32 e1000_setup_link_82542(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_setup_link_82542");
+
+       ret_val = e1000_set_default_fc_generic(hw);
+       if (ret_val)
+               goto out;
+
+       hw->fc.requested_mode &= ~e1000_fc_tx_pause;
+
+       if (mac->report_tx_early == 1)
+               hw->fc.requested_mode &= ~e1000_fc_rx_pause;
+
+       /*
+        * Save off the requested flow control mode for use later.  Depending
+        * on the link partner's capabilities, we may or may not use this mode.
+        */
+       hw->fc.current_mode = hw->fc.requested_mode;
+
+       DEBUGOUT1("After fix-ups FlowControl is now = %x\n",
+                                                    hw->fc.current_mode);
+
+       /* Call the necessary subroutine to configure the link. */
+       ret_val = mac->ops.setup_physical_interface(hw);
+       if (ret_val)
+               goto out;
+
+       /*
+        * Initialize the flow control address, type, and PAUSE timer
+        * registers to their default values.  This is done even if flow
+        * control is disabled, because it does not hurt anything to
+        * initialize these registers.
+        */
+       DEBUGOUT("Initializing Flow Control address, type and timer regs\n");
+
+       E1000_WRITE_REG(hw, E1000_FCAL, FLOW_CONTROL_ADDRESS_LOW);
+       E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH);
+       E1000_WRITE_REG(hw, E1000_FCT, FLOW_CONTROL_TYPE);
+
+       E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time);
+
+       ret_val = e1000_set_fc_watermarks_generic(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_led_on_82542 - Turn on SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED on.
+ **/
+static s32 e1000_led_on_82542(struct e1000_hw *hw __unused)
+{
+#if 0
+       u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       DEBUGFUNC("e1000_led_on_82542");
+
+       ctrl |= E1000_CTRL_SWDPIN0;
+       ctrl |= E1000_CTRL_SWDPIO0;
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+       return E1000_SUCCESS;
+#endif
+       return 0;
+}
+
+/**
+ *  e1000_led_off_82542 - Turn off SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED off.
+ **/
+static s32 e1000_led_off_82542(struct e1000_hw *hw __unused)
+{
+#if 0
+       u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       DEBUGFUNC("e1000_led_off_82542");
+
+       ctrl &= ~E1000_CTRL_SWDPIN0;
+       ctrl |= E1000_CTRL_SWDPIO0;
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+       return E1000_SUCCESS;
+#endif
+       return 0;
+}
+
+/**
+ *  e1000_rar_set_82542 - Set receive address register
+ *  @hw: pointer to the HW structure
+ *  @addr: pointer to the receive address
+ *  @index: receive address array register
+ *
+ *  Sets the receive address array register at index to the address passed
+ *  in by addr.
+ **/
+static void e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index)
+{
+       u32 rar_low, rar_high;
+
+       DEBUGFUNC("e1000_rar_set_82542");
+
+       /*
+        * HW expects these in little endian so we reverse the byte order
+        * from network order (big endian) to little endian
+        */
+       rar_low = ((u32) addr[0] |
+                  ((u32) addr[1] << 8) |
+                  ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+
+       rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+
+       /* If MAC address zero, no need to set the AV bit */
+       if (rar_low || rar_high)
+               rar_high |= E1000_RAH_AV;
+
+       E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low);
+       E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
+}
+
+/**
+ *  e1000_translate_register_82542 - Translate the proper register offset
+ *  @reg: e1000 register to be read
+ *
+ *  Registers in 82542 are located in different offsets than other adapters
+ *  even though they function in the same manner.  This function takes in
+ *  the name of the register to read and returns the correct offset for
+ *  82542 silicon.
+ **/
+u32 e1000_translate_register_82542(u32 reg)
+{
+       /*
+        * Some of the 82542 registers are located at different
+        * offsets than they are in newer adapters.
+        * Despite the difference in location, the registers
+        * function in the same manner.
+        */
+       switch (reg) {
+       case E1000_RA:
+               reg = 0x00040;
+               break;
+       case E1000_RDTR:
+               reg = 0x00108;
+               break;
+       case E1000_RDBAL(0):
+               reg = 0x00110;
+               break;
+       case E1000_RDBAH(0):
+               reg = 0x00114;
+               break;
+       case E1000_RDLEN(0):
+               reg = 0x00118;
+               break;
+       case E1000_RDH(0):
+               reg = 0x00120;
+               break;
+       case E1000_RDT(0):
+               reg = 0x00128;
+               break;
+       case E1000_RDBAL(1):
+               reg = 0x00138;
+               break;
+       case E1000_RDBAH(1):
+               reg = 0x0013C;
+               break;
+       case E1000_RDLEN(1):
+               reg = 0x00140;
+               break;
+       case E1000_RDH(1):
+               reg = 0x00148;
+               break;
+       case E1000_RDT(1):
+               reg = 0x00150;
+               break;
+       case E1000_FCRTH:
+               reg = 0x00160;
+               break;
+       case E1000_FCRTL:
+               reg = 0x00168;
+               break;
+       case E1000_MTA:
+               reg = 0x00200;
+               break;
+       case E1000_TDBAL(0):
+               reg = 0x00420;
+               break;
+       case E1000_TDBAH(0):
+               reg = 0x00424;
+               break;
+       case E1000_TDLEN(0):
+               reg = 0x00428;
+               break;
+       case E1000_TDH(0):
+               reg = 0x00430;
+               break;
+       case E1000_TDT(0):
+               reg = 0x00438;
+               break;
+       case E1000_TIDV:
+               reg = 0x00440;
+               break;
+       case E1000_VFTA:
+               reg = 0x00600;
+               break;
+       case E1000_TDFH:
+               reg = 0x08010;
+               break;
+       case E1000_TDFT:
+               reg = 0x08018;
+               break;
+       default:
+               break;
+       }
+
+       return reg;
+}
+
+/**
+ *  e1000_clear_hw_cntrs_82542 - Clear device specific hardware counters
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the hardware counters by reading the counter registers.
+ **/
+static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_clear_hw_cntrs_82542");
+
+       e1000_clear_hw_cntrs_base_generic(hw);
+
+#if 0
+       E1000_READ_REG(hw, E1000_PRC64);
+       E1000_READ_REG(hw, E1000_PRC127);
+       E1000_READ_REG(hw, E1000_PRC255);
+       E1000_READ_REG(hw, E1000_PRC511);
+       E1000_READ_REG(hw, E1000_PRC1023);
+       E1000_READ_REG(hw, E1000_PRC1522);
+       E1000_READ_REG(hw, E1000_PTC64);
+       E1000_READ_REG(hw, E1000_PTC127);
+       E1000_READ_REG(hw, E1000_PTC255);
+       E1000_READ_REG(hw, E1000_PTC511);
+       E1000_READ_REG(hw, E1000_PTC1023);
+       E1000_READ_REG(hw, E1000_PTC1522);
+#endif
+}
+
+static struct pci_device_id e1000_82542_nics[] = {
+     PCI_ROM(0x8086, 0x1000, "E1000_DEV_ID_82542", "E1000_DEV_ID_82542", e1000_82542),
+};
+
+struct pci_driver e1000_82542_driver __pci_driver = {
+       .ids = e1000_82542_nics,
+       .id_count = (sizeof (e1000_82542_nics) / sizeof (e1000_82542_nics[0])),
+       .probe = e1000_probe,
+       .remove = e1000_remove,
+};
diff --git a/kern/drivers/net/e1000/e1000_82543.c b/kern/drivers/net/e1000/e1000_82543.c
new file mode 100644 (file)
index 0000000..5636094
--- /dev/null
@@ -0,0 +1,1635 @@
+/*******************************************************************************
+
+  Intel PRO/1000 Linux driver
+  Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/*
+ * 82543GC Gigabit Ethernet Controller (Fiber)
+ * 82543GC Gigabit Ethernet Controller (Copper)
+ * 82544EI Gigabit Ethernet Controller (Copper)
+ * 82544EI Gigabit Ethernet Controller (Fiber)
+ * 82544GC Gigabit Ethernet Controller (Copper)
+ * 82544GC Gigabit Ethernet Controller (LOM)
+ */
+
+#include "e1000_api.h"
+
+static s32  e1000_init_phy_params_82543(struct e1000_hw *hw);
+static s32  e1000_init_nvm_params_82543(struct e1000_hw *hw);
+static s32  e1000_init_mac_params_82543(struct e1000_hw *hw);
+static s32  e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset,
+                                     u16 *data);
+static s32  e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset,
+                                      u16 data);
+#if 0
+static s32  e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw);
+#endif
+static s32  e1000_phy_hw_reset_82543(struct e1000_hw *hw);
+static s32  e1000_reset_hw_82543(struct e1000_hw *hw);
+static s32  e1000_init_hw_82543(struct e1000_hw *hw);
+static s32  e1000_setup_link_82543(struct e1000_hw *hw);
+static s32  e1000_setup_copper_link_82543(struct e1000_hw *hw);
+static s32  e1000_setup_fiber_link_82543(struct e1000_hw *hw);
+static s32  e1000_check_for_copper_link_82543(struct e1000_hw *hw);
+static s32  e1000_check_for_fiber_link_82543(struct e1000_hw *hw);
+static s32  e1000_led_on_82543(struct e1000_hw *hw);
+static s32  e1000_led_off_82543(struct e1000_hw *hw);
+static void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset,
+                                   u32 value);
+static void e1000_mta_set_82543(struct e1000_hw *hw, u32 hash_value);
+static void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw);
+static s32  e1000_config_mac_to_phy_82543(struct e1000_hw *hw);
+static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw);
+static void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl);
+static s32  e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw);
+static void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl);
+static u16  e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw);
+static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
+                                           u16 count);
+static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw);
+static void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state);
+static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state);
+
+/**
+ *  e1000_init_phy_params_82543 - Init PHY func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_phy_params_82543(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_init_phy_params_82543");
+
+       if (hw->phy.media_type != e1000_media_type_copper) {
+               phy->type               = e1000_phy_none;
+               goto out;
+       } else {
+               phy->ops.power_up       = e1000_power_up_phy_copper;
+               phy->ops.power_down     = e1000_power_down_phy_copper;
+       }
+
+       phy->addr                       = 1;
+       phy->autoneg_mask               = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+       phy->reset_delay_us             = 10000;
+       phy->type                       = e1000_phy_m88;
+
+       /* Function Pointers */
+       phy->ops.check_polarity         = e1000_check_polarity_m88;
+       phy->ops.commit                 = e1000_phy_sw_reset_generic;
+#if 0
+       phy->ops.force_speed_duplex     = e1000_phy_force_speed_duplex_82543;
+#endif
+#if 0
+       phy->ops.get_cable_length       = e1000_get_cable_length_m88;
+#endif
+       phy->ops.get_cfg_done           = e1000_get_cfg_done_generic;
+       phy->ops.read_reg               = (hw->mac.type == e1000_82543)
+                                         ? e1000_read_phy_reg_82543
+                                         : e1000_read_phy_reg_m88;
+       phy->ops.reset                  = (hw->mac.type == e1000_82543)
+                                         ? e1000_phy_hw_reset_82543
+                                         : e1000_phy_hw_reset_generic;
+       phy->ops.write_reg              = (hw->mac.type == e1000_82543)
+                                         ? e1000_write_phy_reg_82543
+                                         : e1000_write_phy_reg_m88;
+       phy->ops.get_info               = e1000_get_phy_info_m88;
+
+       /*
+        * The external PHY of the 82543 can be in a funky state.
+        * Resetting helps us read the PHY registers for acquiring
+        * the PHY ID.
+        */
+       if (!e1000_init_phy_disabled_82543(hw)) {
+               ret_val = phy->ops.reset(hw);
+               if (ret_val) {
+                       DEBUGOUT("Resetting PHY during init failed.\n");
+                       goto out;
+               }
+               msec_delay(20);
+       }
+
+       ret_val = e1000_get_phy_id(hw);
+       if (ret_val)
+               goto out;
+
+       /* Verify phy id */
+       switch (hw->mac.type) {
+       case e1000_82543:
+               if (phy->id != M88E1000_E_PHY_ID) {
+                       ret_val = -E1000_ERR_PHY;
+                       goto out;
+               }
+               break;
+       case e1000_82544:
+               if (phy->id != M88E1000_I_PHY_ID) {
+                       ret_val = -E1000_ERR_PHY;
+                       goto out;
+               }
+               break;
+       default:
+               ret_val = -E1000_ERR_PHY;
+               goto out;
+               break;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_init_nvm_params_82543 - Init NVM func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_nvm_params_82543(struct e1000_hw *hw)
+{
+       struct e1000_nvm_info *nvm = &hw->nvm;
+
+       DEBUGFUNC("e1000_init_nvm_params_82543");
+
+       nvm->type               = e1000_nvm_eeprom_microwire;
+       nvm->word_size          = 64;
+       nvm->delay_usec         = 50;
+       nvm->address_bits       =  6;
+       nvm->opcode_bits        =  3;
+
+       /* Function Pointers */
+       nvm->ops.read           = e1000_read_nvm_microwire;
+       nvm->ops.update         = e1000_update_nvm_checksum_generic;
+       nvm->ops.valid_led_default = e1000_valid_led_default_generic;
+       nvm->ops.validate       = e1000_validate_nvm_checksum_generic;
+       nvm->ops.write          = e1000_write_nvm_microwire;
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_init_mac_params_82543 - Init MAC func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_mac_params_82543(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+
+       DEBUGFUNC("e1000_init_mac_params_82543");
+
+       /* Set media type */
+       switch (hw->device_id) {
+       case E1000_DEV_ID_82543GC_FIBER:
+       case E1000_DEV_ID_82544EI_FIBER:
+               hw->phy.media_type = e1000_media_type_fiber;
+               break;
+       default:
+               hw->phy.media_type = e1000_media_type_copper;
+               break;
+       }
+
+       /* Set mta register count */
+       mac->mta_reg_count = 128;
+       /* Set rar entry count */
+       mac->rar_entry_count = E1000_RAR_ENTRIES;
+
+       /* Function pointers */
+
+       /* bus type/speed/width */
+       mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
+       /* function id */
+       mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci;
+       /* reset */
+       mac->ops.reset_hw = e1000_reset_hw_82543;
+       /* hw initialization */
+       mac->ops.init_hw = e1000_init_hw_82543;
+       /* link setup */
+       mac->ops.setup_link = e1000_setup_link_82543;
+       /* physical interface setup */
+       mac->ops.setup_physical_interface =
+               (hw->phy.media_type == e1000_media_type_copper)
+                       ? e1000_setup_copper_link_82543
+                       : e1000_setup_fiber_link_82543;
+       /* check for link */
+       mac->ops.check_for_link =
+               (hw->phy.media_type == e1000_media_type_copper)
+                       ? e1000_check_for_copper_link_82543
+                       : e1000_check_for_fiber_link_82543;
+       /* link info */
+       mac->ops.get_link_up_info =
+               (hw->phy.media_type == e1000_media_type_copper)
+                       ? e1000_get_speed_and_duplex_copper_generic
+                       : e1000_get_speed_and_duplex_fiber_serdes_generic;
+       /* multicast address update */
+       mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
+       /* writing VFTA */
+       mac->ops.write_vfta = e1000_write_vfta_82543;
+       /* clearing VFTA */
+       mac->ops.clear_vfta = e1000_clear_vfta_generic;
+       /* setting MTA */
+       mac->ops.mta_set = e1000_mta_set_82543;
+       /* turn on/off LED */
+       mac->ops.led_on = e1000_led_on_82543;
+       mac->ops.led_off = e1000_led_off_82543;
+       /* clear hardware counters */
+       mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82543;
+
+       /* Set tbi compatibility */
+       if ((hw->mac.type != e1000_82543) ||
+           (hw->phy.media_type == e1000_media_type_fiber))
+               e1000_set_tbi_compatibility_82543(hw, false);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_init_function_pointers_82543 - Init func ptrs.
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to initialize all function pointers and parameters.
+ **/
+void e1000_init_function_pointers_82543(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_init_function_pointers_82543");
+
+       hw->mac.ops.init_params = e1000_init_mac_params_82543;
+       hw->nvm.ops.init_params = e1000_init_nvm_params_82543;
+       hw->phy.ops.init_params = e1000_init_phy_params_82543;
+}
+
+/**
+ *  e1000_tbi_compatibility_enabled_82543 - Returns TBI compat status
+ *  @hw: pointer to the HW structure
+ *
+ *  Returns the current status of 10-bit Interface (TBI) compatibility
+ *  (enabled/disabled).
+ **/
+static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw)
+{
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+       bool state = false;
+
+       DEBUGFUNC("e1000_tbi_compatibility_enabled_82543");
+
+       if (hw->mac.type != e1000_82543) {
+               DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
+               goto out;
+       }
+
+       state = (dev_spec->tbi_compatibility & TBI_COMPAT_ENABLED)
+               ? true : false;
+
+out:
+       return state;
+}
+
+/**
+ *  e1000_set_tbi_compatibility_82543 - Set TBI compatibility
+ *  @hw: pointer to the HW structure
+ *  @state: enable/disable TBI compatibility
+ *
+ *  Enables or disabled 10-bit Interface (TBI) compatibility.
+ **/
+static void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state)
+{
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+
+       DEBUGFUNC("e1000_set_tbi_compatibility_82543");
+
+       if (hw->mac.type != e1000_82543) {
+               DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
+               goto out;
+       }
+
+       if (state)
+               dev_spec->tbi_compatibility |= TBI_COMPAT_ENABLED;
+       else
+               dev_spec->tbi_compatibility &= ~TBI_COMPAT_ENABLED;
+
+out:
+       return;
+}
+
+/**
+ *  e1000_tbi_sbp_enabled_82543 - Returns TBI SBP status
+ *  @hw: pointer to the HW structure
+ *
+ *  Returns the current status of 10-bit Interface (TBI) store bad packet (SBP)
+ *  (enabled/disabled).
+ **/
+bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw)
+{
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+       bool state = false;
+
+       DEBUGFUNC("e1000_tbi_sbp_enabled_82543");
+
+       if (hw->mac.type != e1000_82543) {
+               DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
+               goto out;
+       }
+
+       state = (dev_spec->tbi_compatibility & TBI_SBP_ENABLED)
+               ? true : false;
+
+out:
+       return state;
+}
+
+/**
+ *  e1000_set_tbi_sbp_82543 - Set TBI SBP
+ *  @hw: pointer to the HW structure
+ *  @state: enable/disable TBI store bad packet
+ *
+ *  Enables or disabled 10-bit Interface (TBI) store bad packet (SBP).
+ **/
+static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state)
+{
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+
+       DEBUGFUNC("e1000_set_tbi_sbp_82543");
+
+       if (state && e1000_tbi_compatibility_enabled_82543(hw))
+               dev_spec->tbi_compatibility |= TBI_SBP_ENABLED;
+       else
+               dev_spec->tbi_compatibility &= ~TBI_SBP_ENABLED;
+
+       return;
+}
+
+/**
+ *  e1000_init_phy_disabled_82543 - Returns init PHY status
+ *  @hw: pointer to the HW structure
+ *
+ *  Returns the current status of whether PHY initialization is disabled.
+ *  True if PHY initialization is disabled else false.
+ **/
+static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw)
+{
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+       bool ret_val;
+
+       DEBUGFUNC("e1000_init_phy_disabled_82543");
+
+       if (hw->mac.type != e1000_82543) {
+               ret_val = false;
+               goto out;
+       }
+
+       ret_val = dev_spec->init_phy_disabled;
+
+out:
+       return ret_val;
+}
+
+#if 0
+/**
+ *  e1000_tbi_adjust_stats_82543 - Adjust stats when TBI enabled
+ *  @hw: pointer to the HW structure
+ *  @stats: Struct containing statistic register values
+ *  @frame_len: The length of the frame in question
+ *  @mac_addr: The Ethernet destination address of the frame in question
+ *  @max_frame_size: The maximum frame size
+ *
+ *  Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
+ **/
+void e1000_tbi_adjust_stats_82543(struct e1000_hw *hw,
+                                  struct e1000_hw_stats *stats, u32 frame_len,
+                                  u8 *mac_addr, u32 max_frame_size)
+{
+       if (!(e1000_tbi_sbp_enabled_82543(hw)))
+               goto out;
+
+       /* First adjust the frame length. */
+       frame_len--;
+       /*
+        * We need to adjust the statistics counters, since the hardware
+        * counters overcount this packet as a CRC error and undercount
+        * the packet as a good packet
+        */
+       /* This packet should not be counted as a CRC error.    */
+       stats->crcerrs--;
+       /* This packet does count as a Good Packet Received.    */
+       stats->gprc++;
+
+       /* Adjust the Good Octets received counters             */
+       stats->gorc += frame_len;
+
+       /*
+        * Is this a broadcast or multicast?  Check broadcast first,
+        * since the test for a multicast frame will test positive on
+        * a broadcast frame.
+        */
+       if ((mac_addr[0] == 0xff) && (mac_addr[1] == 0xff))
+               /* Broadcast packet */
+               stats->bprc++;
+       else if (*mac_addr & 0x01)
+               /* Multicast packet */
+               stats->mprc++;
+
+       /*
+        * In this case, the hardware has overcounted the number of
+        * oversize frames.
+        */
+       if ((frame_len == max_frame_size) && (stats->roc > 0))
+               stats->roc--;
+
+       /*
+        * Adjust the bin counters when the extra byte put the frame in the
+        * wrong bin. Remember that the frame_len was adjusted above.
+        */
+       if (frame_len == 64) {
+               stats->prc64++;
+               stats->prc127--;
+       } else if (frame_len == 127) {
+               stats->prc127++;
+               stats->prc255--;
+       } else if (frame_len == 255) {
+               stats->prc255++;
+               stats->prc511--;
+       } else if (frame_len == 511) {
+               stats->prc511++;
+               stats->prc1023--;
+       } else if (frame_len == 1023) {
+               stats->prc1023++;
+               stats->prc1522--;
+       } else if (frame_len == 1522) {
+               stats->prc1522++;
+       }
+
+out:
+       return;
+}
+#endif
+
+/**
+ *  e1000_read_phy_reg_82543 - Read PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the PHY at offset and stores the information read to data.
+ **/
+static s32 e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       u32 mdic;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_read_phy_reg_82543");
+
+       if (offset > MAX_PHY_REG_ADDRESS) {
+               DEBUGOUT1("PHY Address %d is out of range\n", offset);
+               ret_val = -E1000_ERR_PARAM;
+               goto out;
+       }
+
+       /*
+        * We must first send a preamble through the MDIO pin to signal the
+        * beginning of an MII instruction.  This is done by sending 32
+        * consecutive "1" bits.
+        */
+       e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
+
+       /*
+        * Now combine the next few fields that are required for a read
+        * operation.  We use this method instead of calling the
+        * e1000_shift_out_mdi_bits routine five different times.  The format
+        * of an MII read instruction consists of a shift out of 14 bits and
+        * is defined as follows:
+        *      <Preamble><SOF><Op Code><Phy Addr><Offset>
+        * followed by a shift in of 18 bits.  This first two bits shifted in
+        * are TurnAround bits used to avoid contention on the MDIO pin when a
+        * READ operation is performed.  These two bits are thrown away
+        * followed by a shift in of 16 bits which contains the desired data.
+        */
+       mdic = (offset | (hw->phy.addr << 5) |
+               (PHY_OP_READ << 10) | (PHY_SOF << 12));
+
+       e1000_shift_out_mdi_bits_82543(hw, mdic, 14);
+
+       /*
+        * Now that we've shifted out the read command to the MII, we need to
+        * "shift in" the 16-bit value (18 total bits) of the requested PHY
+        * register address.
+        */
+       *data = e1000_shift_in_mdi_bits_82543(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_write_phy_reg_82543 - Write PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be written
+ *  @data: pointer to the data to be written at offset
+ *
+ *  Writes data to the PHY at offset.
+ **/
+static s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       u32 mdic;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_write_phy_reg_82543");
+
+       if (offset > MAX_PHY_REG_ADDRESS) {
+               DEBUGOUT1("PHY Address %d is out of range\n", offset);
+               ret_val = -E1000_ERR_PARAM;
+               goto out;
+       }
+
+       /*
+        * We'll need to use the SW defined pins to shift the write command
+        * out to the PHY. We first send a preamble to the PHY to signal the
+        * beginning of the MII instruction.  This is done by sending 32
+        * consecutive "1" bits.
+        */
+       e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
+
+       /*
+        * Now combine the remaining required fields that will indicate a
+        * write operation. We use this method instead of calling the
+        * e1000_shift_out_mdi_bits routine for each field in the command. The
+        * format of a MII write instruction is as follows:
+        * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
+        */
+       mdic = ((PHY_TURNAROUND) | (offset << 2) | (hw->phy.addr << 7) |
+               (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
+       mdic <<= 16;
+       mdic |= (u32) data;
+
+       e1000_shift_out_mdi_bits_82543(hw, mdic, 32);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_raise_mdi_clk_82543 - Raise Management Data Input clock
+ *  @hw: pointer to the HW structure
+ *  @ctrl: pointer to the control register
+ *
+ *  Raise the management data input clock by setting the MDC bit in the control
+ *  register.
+ **/
+static void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl)
+{
+       /*
+        * Raise the clock input to the Management Data Clock (by setting the
+        * MDC bit), and then delay a sufficient amount of time.
+        */
+       E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl | E1000_CTRL_MDC));
+       E1000_WRITE_FLUSH(hw);
+       usec_delay(10);
+}
+
+/**
+ *  e1000_lower_mdi_clk_82543 - Lower Management Data Input clock
+ *  @hw: pointer to the HW structure
+ *  @ctrl: pointer to the control register
+ *
+ *  Lower the management data input clock by clearing the MDC bit in the
+ *  control register.
+ **/
+static void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl)
+{
+       /*
+        * Lower the clock input to the Management Data Clock (by clearing the
+        * MDC bit), and then delay a sufficient amount of time.
+        */
+       E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl & ~E1000_CTRL_MDC));
+       E1000_WRITE_FLUSH(hw);
+       usec_delay(10);
+}
+
+/**
+ *  e1000_shift_out_mdi_bits_82543 - Shift data bits our to the PHY
+ *  @hw: pointer to the HW structure
+ *  @data: data to send to the PHY
+ *  @count: number of bits to shift out
+ *
+ *  We need to shift 'count' bits out to the PHY.  So, the value in the
+ *  "data" parameter will be shifted out to the PHY one bit at a time.
+ *  In order to do this, "data" must be broken down into bits.
+ **/
+static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
+                                           u16 count)
+{
+       u32 ctrl, mask;
+
+       /*
+        * We need to shift "count" number of bits out to the PHY.  So, the
+        * value in the "data" parameter will be shifted out to the PHY one
+        * bit at a time.  In order to do this, "data" must be broken down
+        * into bits.
+        */
+       mask = 0x01;
+       mask <<= (count -1);
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
+       ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
+
+       while (mask) {
+               /*
+                * A "1" is shifted out to the PHY by setting the MDIO bit to
+                * "1" and then raising and lowering the Management Data Clock.
+                * A "0" is shifted out to the PHY by setting the MDIO bit to
+                * "0" and then raising and lowering the clock.
+                */
+               if (data & mask) ctrl |= E1000_CTRL_MDIO;
+               else ctrl &= ~E1000_CTRL_MDIO;
+
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+               E1000_WRITE_FLUSH(hw);
+
+               usec_delay(10);
+
+               e1000_raise_mdi_clk_82543(hw, &ctrl);
+               e1000_lower_mdi_clk_82543(hw, &ctrl);
+
+               mask >>= 1;
+       }
+}
+
+/**
+ *  e1000_shift_in_mdi_bits_82543 - Shift data bits in from the PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  In order to read a register from the PHY, we need to shift 18 bits
+ *  in from the PHY.  Bits are "shifted in" by raising the clock input to
+ *  the PHY (setting the MDC bit), and then reading the value of the data out
+ *  MDIO bit.
+ **/
+static u16 e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw)
+{
+       u32 ctrl;
+       u16 data = 0;
+       u8 i;
+
+       /*
+        * In order to read a register from the PHY, we need to shift in a
+        * total of 18 bits from the PHY.  The first two bit (turnaround)
+        * times are used to avoid contention on the MDIO pin when a read
+        * operation is performed.  These two bits are ignored by us and
+        * thrown away.  Bits are "shifted in" by raising the input to the
+        * Management Data Clock (setting the MDC bit) and then reading the
+        * value of the MDIO bit.
+        */
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       /*
+        * Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as
+        * input.
+        */
+       ctrl &= ~E1000_CTRL_MDIO_DIR;
+       ctrl &= ~E1000_CTRL_MDIO;
+
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+       E1000_WRITE_FLUSH(hw);
+
+       /*
+        * Raise and lower the clock before reading in the data.  This accounts
+        * for the turnaround bits.  The first clock occurred when we clocked
+        * out the last bit of the Register Address.
+        */
+       e1000_raise_mdi_clk_82543(hw, &ctrl);
+       e1000_lower_mdi_clk_82543(hw, &ctrl);
+
+       for (data = 0, i = 0; i < 16; i++) {
+               data <<= 1;
+               e1000_raise_mdi_clk_82543(hw, &ctrl);
+               ctrl = E1000_READ_REG(hw, E1000_CTRL);
+               /* Check to see if we shifted in a "1". */
+               if (ctrl & E1000_CTRL_MDIO)
+                       data |= 1;
+               e1000_lower_mdi_clk_82543(hw, &ctrl);
+       }
+
+       e1000_raise_mdi_clk_82543(hw, &ctrl);
+       e1000_lower_mdi_clk_82543(hw, &ctrl);
+
+       return data;
+}
+
+#if 0
+/**
+ *  e1000_phy_force_speed_duplex_82543 - Force speed/duplex for PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Calls the function to force speed and duplex for the m88 PHY, and
+ *  if the PHY is not auto-negotiating and the speed is forced to 10Mbit,
+ *  then call the function for polarity reversal workaround.
+ **/
+static s32 e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw)
+{
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_phy_force_speed_duplex_82543");
+
+       ret_val = e1000_phy_force_speed_duplex_m88(hw);
+       if (ret_val)
+               goto out;
+
+       if (!hw->mac.autoneg &&
+           (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED))
+               ret_val = e1000_polarity_reversal_workaround_82543(hw);
+
+out:
+       return ret_val;
+}
+#endif
+
+/**
+ *  e1000_polarity_reversal_workaround_82543 - Workaround polarity reversal
+ *  @hw: pointer to the HW structure
+ *
+ *  When forcing link to 10 Full or 10 Half, the PHY can reverse the polarity
+ *  inadvertently.  To workaround the issue, we disable the transmitter on
+ *  the PHY until we have established the link partner's link parameters.
+ **/
+static s32 e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+       u16 mii_status_reg;
+       u16 i;
+       bool link;
+
+       if (!(hw->phy.ops.write_reg))
+               goto out;
+
+       /* Polarity reversal workaround for forced 10F/10H links. */
+
+       /* Disable the transmitter on the PHY */
+
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+       if (ret_val)
+               goto out;
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
+       if (ret_val)
+               goto out;
+
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
+       if (ret_val)
+               goto out;
+
+       /*
+        * This loop will early-out if the NO link condition has been met.
+        * In other words, DO NOT use e1000_phy_has_link_generic() here.
+        */
+       for (i = PHY_FORCE_TIME; i > 0; i--) {
+               /*
+                * Read the MII Status Register and wait for Link Status bit
+                * to be clear.
+                */
+
+               ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
+               if (ret_val)
+                       goto out;
+
+               ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
+               if (ret_val)
+                       goto out;
+
+               if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0)
+                       break;
+               msec_delay_irq(100);
+       }
+
+       /* Recommended delay time after link has been lost */
+       msec_delay_irq(1000);
+
+       /* Now we will re-enable the transmitter on the PHY */
+
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+       if (ret_val)
+               goto out;
+       msec_delay_irq(50);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
+       if (ret_val)
+               goto out;
+       msec_delay_irq(50);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
+       if (ret_val)
+               goto out;
+       msec_delay_irq(50);
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
+       if (ret_val)
+               goto out;
+
+       ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
+       if (ret_val)
+               goto out;
+
+       /*
+        * Read the MII Status Register and wait for Link Status bit
+        * to be set.
+        */
+       ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_TIME, 100000, &link);
+       if (ret_val)
+               goto out;
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_phy_hw_reset_82543 - PHY hardware reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Sets the PHY_RESET_DIR bit in the extended device control register
+ *  to put the PHY into a reset and waits for completion.  Once the reset
+ *  has been accomplished, clear the PHY_RESET_DIR bit to take the PHY out
+ *  of reset.
+ **/
+static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw)
+{
+       u32 ctrl_ext;
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_phy_hw_reset_82543");
+
+       /*
+        * Read the Extended Device Control Register, assert the PHY_RESET_DIR
+        * bit to put the PHY into reset...
+        */
+       ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+       ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
+       ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+       E1000_WRITE_FLUSH(hw);
+
+       msec_delay(10);
+
+       /* ...then take it out of reset. */
+       ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
+       E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+       E1000_WRITE_FLUSH(hw);
+
+       usec_delay(150);
+
+       if (!(hw->phy.ops.get_cfg_done))
+               return E1000_SUCCESS;
+
+       ret_val = hw->phy.ops.get_cfg_done(hw);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_reset_hw_82543 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+static s32 e1000_reset_hw_82543(struct e1000_hw *hw)
+{
+       u32 ctrl, icr;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_reset_hw_82543");
+
+       DEBUGOUT("Masking off all interrupts\n");
+       E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+
+       E1000_WRITE_REG(hw, E1000_RCTL, 0);
+       E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
+       E1000_WRITE_FLUSH(hw);
+
+       e1000_set_tbi_sbp_82543(hw, false);
+
+       /*
+        * Delay to allow any outstanding PCI transactions to complete before
+        * resetting the device
+        */
+       msec_delay(10);
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       DEBUGOUT("Issuing a global reset to 82543/82544 MAC\n");
+       if (hw->mac.type == e1000_82543) {
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
+       } else {
+               /*
+                * The 82544 can't ACK the 64-bit write when issuing the
+                * reset, so use IO-mapping as a workaround.
+                */
+               E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
+       }
+
+       /*
+        * After MAC reset, force reload of NVM to restore power-on
+        * settings to device.
+        */
+       hw->nvm.ops.reload(hw);
+       msec_delay(2);
+
+       /* Masking off and clearing any pending interrupts */
+       E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+       icr = E1000_READ_REG(hw, E1000_ICR);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_init_hw_82543 - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation.
+ **/
+static s32 e1000_init_hw_82543(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+       u32 ctrl;
+       s32 ret_val;
+       u16 i;
+
+       DEBUGFUNC("e1000_init_hw_82543");
+
+       /* Disabling VLAN filtering */
+       E1000_WRITE_REG(hw, E1000_VET, 0);
+       mac->ops.clear_vfta(hw);
+
+       /* Setup the receive address. */
+       e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
+
+       /* Zero out the Multicast HASH table */
+       DEBUGOUT("Zeroing the MTA\n");
+       for (i = 0; i < mac->mta_reg_count; i++) {
+               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
+               E1000_WRITE_FLUSH(hw);
+       }
+
+       /*
+        * Set the PCI priority bit correctly in the CTRL register.  This
+        * determines if the adapter gives priority to receives, or if it
+        * gives equal priority to transmits and receives.
+        */
+       if (hw->mac.type == e1000_82543 && dev_spec->dma_fairness) {
+               ctrl = E1000_READ_REG(hw, E1000_CTRL);
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PRIOR);
+       }
+
+       e1000_pcix_mmrbc_workaround_generic(hw);
+
+       /* Setup link and flow control */
+       ret_val = mac->ops.setup_link(hw);
+
+       /*
+        * Clear all of the statistics registers (clear on read).  It is
+        * important that we do this after we have tried to establish link
+        * because the symbol error count will increment wildly if there
+        * is no link.
+        */
+       e1000_clear_hw_cntrs_82543(hw);
+
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_link_82543 - Setup flow control and link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Read the EEPROM to determine the initial polarity value and write the
+ *  extended device control register with the information before calling
+ *  the generic setup link function, which does the following:
+ *  Determines which flow control settings to use, then configures flow
+ *  control.  Calls the appropriate media-specific link configuration
+ *  function.  Assuming the adapter has a valid link partner, a valid link
+ *  should be established.  Assumes the hardware has previously been reset
+ *  and the transmitter and receiver are not enabled.
+ **/
+static s32 e1000_setup_link_82543(struct e1000_hw *hw)
+{
+       u32 ctrl_ext;
+       s32  ret_val;
+       u16 data;
+
+       DEBUGFUNC("e1000_setup_link_82543");
+
+       /*
+        * Take the 4 bits from NVM word 0xF that determine the initial
+        * polarity value for the SW controlled pins, and setup the
+        * Extended Device Control reg with that info.
+        * This is needed because one of the SW controlled pins is used for
+        * signal detection.  So this should be done before phy setup.
+        */
+       if (hw->mac.type == e1000_82543) {
+               ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+               if (ret_val) {
+                       DEBUGOUT("NVM Read Error\n");
+                       ret_val = -E1000_ERR_NVM;
+                       goto out;
+               }
+               ctrl_ext = ((data & NVM_WORD0F_SWPDIO_EXT_MASK) <<
+                           NVM_SWDPIO_EXT_SHIFT);
+               E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+       }
+
+       ret_val = e1000_setup_link_generic(hw);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_copper_link_82543 - Configure copper link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures the link for auto-neg or forced speed and duplex.  Then we check
+ *  for link, once link is established calls to configure collision distance
+ *  and flow control are called.
+ **/
+static s32 e1000_setup_copper_link_82543(struct e1000_hw *hw)
+{
+       u32 ctrl;
+       s32 ret_val;
+       bool link;
+
+       DEBUGFUNC("e1000_setup_copper_link_82543");
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL) | E1000_CTRL_SLU;
+       /*
+        * With 82543, we need to force speed and duplex on the MAC
+        * equal to what the PHY speed and duplex configuration is.
+        * In addition, we need to perform a hardware reset on the
+        * PHY to take it out of reset.
+        */
+       if (hw->mac.type == e1000_82543) {
+               ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+               ret_val = hw->phy.ops.reset(hw);
+               if (ret_val)
+                       goto out;
+               hw->phy.reset_disable = false;
+       } else {
+               ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+       }
+
+       /* Set MDI/MDI-X, Polarity Reversal, and downshift settings */
+       ret_val = e1000_copper_link_setup_m88(hw);
+       if (ret_val)
+               goto out;
+
+       if (hw->mac.autoneg) {
+               /*
+                * Setup autoneg and flow control advertisement and perform
+                * autonegotiation.
+                */
+               ret_val = e1000_copper_link_autoneg(hw);
+               if (ret_val)
+                       goto out;
+       } else {
+               /*
+                * PHY will be set to 10H, 10F, 100H or 100F
+                * depending on user settings.
+                */
+#if 0
+               DEBUGOUT("Forcing Speed and Duplex\n");
+               ret_val = e1000_phy_force_speed_duplex_82543(hw);
+               if (ret_val) {
+                       DEBUGOUT("Error Forcing Speed and Duplex\n");
+                       goto out;
+               }
+#endif
+       }
+
+       /*
+        * Check link status. Wait up to 100 microseconds for link to become
+        * valid.
+        */
+       ret_val = e1000_phy_has_link_generic(hw,
+                                            COPPER_LINK_UP_LIMIT,
+                                            10,
+                                            &link);
+       if (ret_val)
+               goto out;
+
+
+       if (link) {
+               DEBUGOUT("Valid link established!!!\n");
+               /* Config the MAC and PHY after link is up */
+               if (hw->mac.type == e1000_82544) {
+                       e1000_config_collision_dist_generic(hw);
+               } else {
+                       ret_val = e1000_config_mac_to_phy_82543(hw);
+                       if (ret_val)
+                               goto out;
+               }
+               ret_val = e1000_config_fc_after_link_up_generic(hw);
+       } else {
+               DEBUGOUT("Unable to establish link!!!\n");
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_fiber_link_82543 - Setup link for fiber
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures collision distance and flow control for fiber links.  Upon
+ *  successful setup, poll for link.
+ **/
+static s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw)
+{
+       u32 ctrl;
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_setup_fiber_link_82543");
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       /* Take the link out of reset */
+       ctrl &= ~E1000_CTRL_LRST;
+
+       e1000_config_collision_dist_generic(hw);
+
+       ret_val = e1000_commit_fc_settings_generic(hw);
+       if (ret_val)
+               goto out;
+
+       DEBUGOUT("Auto-negotiation enabled\n");
+
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+       E1000_WRITE_FLUSH(hw);
+       msec_delay(1);
+
+       /*
+        * For these adapters, the SW definable pin 1 is cleared when the
+        * optics detect a signal.  If we have a signal, then poll for a
+        * "Link-Up" indication.
+        */
+       if (!(E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) {
+               ret_val = e1000_poll_fiber_serdes_link_generic(hw);
+       } else {
+               DEBUGOUT("No signal detected\n");
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_copper_link_82543 - Check for link (Copper)
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks the phy for link, if link exists, do the following:
+ *   - check for downshift
+ *   - do polarity workaround (if necessary)
+ *   - configure collision distance
+ *   - configure flow control after link up
+ *   - configure tbi compatibility
+ **/
+static s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       u32 icr, rctl;
+       s32 ret_val;
+       u16 speed, duplex;
+       bool link;
+
+       DEBUGFUNC("e1000_check_for_copper_link_82543");
+
+       if (!mac->get_link_status) {
+               ret_val = E1000_SUCCESS;
+               goto out;
+       }
+
+       ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
+       if (ret_val)
+               goto out;
+
+       if (!link)
+               goto out; /* No link detected */
+
+       mac->get_link_status = false;
+
+       e1000_check_downshift_generic(hw);
+
+       /*
+        * If we are forcing speed/duplex, then we can return since
+        * we have already determined whether we have link or not.
+        */
+       if (!mac->autoneg) {
+               /*
+                * If speed and duplex are forced to 10H or 10F, then we will
+                * implement the polarity reversal workaround.  We disable
+                * interrupts first, and upon returning, place the devices
+                * interrupt state to its previous value except for the link
+                * status change interrupt which will happened due to the
+                * execution of this workaround.
+                */
+               if (mac->forced_speed_duplex & E1000_ALL_10_SPEED) {
+                       E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
+                       ret_val = e1000_polarity_reversal_workaround_82543(hw);
+                       icr = E1000_READ_REG(hw, E1000_ICR);
+                       E1000_WRITE_REG(hw, E1000_ICS, (icr & ~E1000_ICS_LSC));
+                       E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK);
+               }
+
+               ret_val = -E1000_ERR_CONFIG;
+               goto out;
+       }
+
+       /*
+        * We have a M88E1000 PHY and Auto-Neg is enabled.  If we
+        * have Si on board that is 82544 or newer, Auto
+        * Speed Detection takes care of MAC speed/duplex
+        * configuration.  So we only need to configure Collision
+        * Distance in the MAC.  Otherwise, we need to force
+        * speed/duplex on the MAC to the current PHY speed/duplex
+        * settings.
+        */
+       if (mac->type == e1000_82544)
+               e1000_config_collision_dist_generic(hw);
+       else {
+               ret_val = e1000_config_mac_to_phy_82543(hw);
+               if (ret_val) {
+                       DEBUGOUT("Error configuring MAC to PHY settings\n");
+                       goto out;
+               }
+       }
+
+       /*
+        * Configure Flow Control now that Auto-Neg has completed.
+        * First, we need to restore the desired flow control
+        * settings because we may have had to re-autoneg with a
+        * different link partner.
+        */
+       ret_val = e1000_config_fc_after_link_up_generic(hw);
+       if (ret_val) {
+               DEBUGOUT("Error configuring flow control\n");
+       }
+
+       /*
+        * At this point we know that we are on copper and we have
+        * auto-negotiated link.  These are conditions for checking the link
+        * partner capability register.  We use the link speed to determine if
+        * TBI compatibility needs to be turned on or off.  If the link is not
+        * at gigabit speed, then TBI compatibility is not needed.  If we are
+        * at gigabit speed, we turn on TBI compatibility.
+        */
+       if (e1000_tbi_compatibility_enabled_82543(hw)) {
+               ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex);
+               if (ret_val) {
+                       DEBUGOUT("Error getting link speed and duplex\n");
+                       return ret_val;
+               }
+               if (speed != SPEED_1000) {
+                       /*
+                        * If link speed is not set to gigabit speed,
+                        * we do not need to enable TBI compatibility.
+                        */
+                       if (e1000_tbi_sbp_enabled_82543(hw)) {
+                               /*
+                                * If we previously were in the mode,
+                                * turn it off.
+                                */
+                               e1000_set_tbi_sbp_82543(hw, false);
+                               rctl = E1000_READ_REG(hw, E1000_RCTL);
+                               rctl &= ~E1000_RCTL_SBP;
+                               E1000_WRITE_REG(hw, E1000_RCTL, rctl);
+                       }
+               } else {
+                       /*
+                        * If TBI compatibility is was previously off,
+                        * turn it on. For compatibility with a TBI link
+                        * partner, we will store bad packets. Some
+                        * frames have an additional byte on the end and
+                        * will look like CRC errors to to the hardware.
+                        */
+                       if (!e1000_tbi_sbp_enabled_82543(hw)) {
+                               e1000_set_tbi_sbp_82543(hw, true);
+                               rctl = E1000_READ_REG(hw, E1000_RCTL);
+                               rctl |= E1000_RCTL_SBP;
+                               E1000_WRITE_REG(hw, E1000_RCTL, rctl);
+                       }
+               }
+       }
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_fiber_link_82543 - Check for link (Fiber)
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks for link up on the hardware.  If link is not up and we have
+ *  a signal, then we need to force link up.
+ **/
+static s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       u32 rxcw, ctrl, status;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_check_for_fiber_link_82543");
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+       status = E1000_READ_REG(hw, E1000_STATUS);
+       rxcw = E1000_READ_REG(hw, E1000_RXCW);
+
+       /*
+        * If we don't have link (auto-negotiation failed or link partner
+        * cannot auto-negotiate), the cable is plugged in (we have signal),
+        * and our link partner is not trying to auto-negotiate with us (we
+        * are receiving idles or data), we need to force link up. We also
+        * need to give auto-negotiation time to complete, in case the cable
+        * was just plugged in. The autoneg_failed flag does this.
+        */
+       /* (ctrl & E1000_CTRL_SWDPIN1) == 0 == have signal */
+       if ((!(ctrl & E1000_CTRL_SWDPIN1)) &&
+           (!(status & E1000_STATUS_LU)) &&
+           (!(rxcw & E1000_RXCW_C))) {
+               if (mac->autoneg_failed == 0) {
+                       mac->autoneg_failed = 1;
+                       ret_val = 0;
+                       goto out;
+               }
+               DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
+
+               /* Disable auto-negotiation in the TXCW register */
+               E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));
+
+               /* Force link-up and also force full-duplex. */
+               ctrl = E1000_READ_REG(hw, E1000_CTRL);
+               ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+               /* Configure Flow Control after forcing link up. */
+               ret_val = e1000_config_fc_after_link_up_generic(hw);
+               if (ret_val) {
+                       DEBUGOUT("Error configuring flow control\n");
+                       goto out;
+               }
+       } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
+               /*
+                * If we are forcing link and we are receiving /C/ ordered
+                * sets, re-enable auto-negotiation in the TXCW register
+                * and disable forced link in the Device Control register
+                * in an attempt to auto-negotiate with our link partner.
+                */
+               DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
+               E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
+               E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));
+
+               mac->serdes_has_link = true;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_config_mac_to_phy_82543 - Configure MAC to PHY settings
+ *  @hw: pointer to the HW structure
+ *
+ *  For the 82543 silicon, we need to set the MAC to match the settings
+ *  of the PHY, even if the PHY is auto-negotiating.
+ **/
+static s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw)
+{
+       u32 ctrl;
+       s32 ret_val = E1000_SUCCESS;
+       u16 phy_data;
+
+       DEBUGFUNC("e1000_config_mac_to_phy_82543");
+
+       if (!(hw->phy.ops.read_reg))
+               goto out;
+
+       /* Set the bits to force speed and duplex */
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+       ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+       ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
+
+       /*
+        * Set up duplex in the Device Control and Transmit Control
+        * registers depending on negotiated values.
+        */
+       ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+       if (ret_val)
+               goto out;
+
+       ctrl &= ~E1000_CTRL_FD;
+       if (phy_data & M88E1000_PSSR_DPLX)
+               ctrl |= E1000_CTRL_FD;
+
+       e1000_config_collision_dist_generic(hw);
+
+       /*
+        * Set up speed in the Device Control register depending on
+        * negotiated values.
+        */
+       if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
+               ctrl |= E1000_CTRL_SPD_1000;
+       else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
+               ctrl |= E1000_CTRL_SPD_100;
+
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_write_vfta_82543 - Write value to VLAN filter table
+ *  @hw: pointer to the HW structure
+ *  @offset: the 32-bit offset in which to write the value to.
+ *  @value: the 32-bit value to write at location offset.
+ *
+ *  This writes a 32-bit value to a 32-bit offset in the VLAN filter
+ *  table.
+ **/
+static void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, u32 value)
+{
+       u32 temp;
+
+       DEBUGFUNC("e1000_write_vfta_82543");
+
+       if ((hw->mac.type == e1000_82544) && (offset & 1)) {
+               temp = E1000_READ_REG_ARRAY(hw, E1000_VFTA, offset - 1);
+               E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
+               E1000_WRITE_FLUSH(hw);
+               E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset - 1, temp);
+               E1000_WRITE_FLUSH(hw);
+       } else {
+               e1000_write_vfta_generic(hw, offset, value);
+       }
+}
+
+/**
+ *  e1000_mta_set_82543 - Set multicast filter table address
+ *  @hw: pointer to the HW structure
+ *  @hash_value: determines the MTA register and bit to set
+ *
+ *  The multicast table address is a register array of 32-bit registers.
+ *  The hash_value is used to determine what register the bit is in, the
+ *  current value is read, the new bit is OR'd in and the new value is
+ *  written back into the register.
+ **/
+static void e1000_mta_set_82543(struct e1000_hw *hw, u32 hash_value)
+{
+       u32 hash_bit, hash_reg, mta, temp;
+
+       DEBUGFUNC("e1000_mta_set_82543");
+
+       hash_reg = (hash_value >> 5);
+
+       /*
+        * If we are on an 82544 and we are trying to write an odd offset
+        * in the MTA, save off the previous entry before writing and
+        * restore the old value after writing.
+        */
+       if ((hw->mac.type == e1000_82544) && (hash_reg & 1)) {
+               hash_reg &= (hw->mac.mta_reg_count - 1);
+               hash_bit = hash_value & 0x1F;
+               mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg);
+               mta |= (1 << hash_bit);
+               temp = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg - 1);
+
+               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta);
+               E1000_WRITE_FLUSH(hw);
+               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg - 1, temp);
+               E1000_WRITE_FLUSH(hw);
+       } else {
+               e1000_mta_set_generic(hw, hash_value);
+       }
+}
+
+/**
+ *  e1000_led_on_82543 - Turn on SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED on.
+ **/
+static s32 e1000_led_on_82543(struct e1000_hw *hw __unused)
+{
+#if 0
+       u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       DEBUGFUNC("e1000_led_on_82543");
+
+       if (hw->mac.type == e1000_82544 &&
+           hw->phy.media_type == e1000_media_type_copper) {
+               /* Clear SW-definable Pin 0 to turn on the LED */
+               ctrl &= ~E1000_CTRL_SWDPIN0;
+               ctrl |= E1000_CTRL_SWDPIO0;
+       } else {
+               /* Fiber 82544 and all 82543 use this method */
+               ctrl |= E1000_CTRL_SWDPIN0;
+               ctrl |= E1000_CTRL_SWDPIO0;
+       }
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+       return E1000_SUCCESS;
+#endif
+        return 0;
+}
+
+/**
+ *  e1000_led_off_82543 - Turn off SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED off.
+ **/
+static s32 e1000_led_off_82543(struct e1000_hw *hw __unused)
+{
+#if 0
+       u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       DEBUGFUNC("e1000_led_off_82543");
+
+       if (hw->mac.type == e1000_82544 &&
+           hw->phy.media_type == e1000_media_type_copper) {
+               /* Set SW-definable Pin 0 to turn off the LED */
+               ctrl |= E1000_CTRL_SWDPIN0;
+               ctrl |= E1000_CTRL_SWDPIO0;
+       } else {
+               ctrl &= ~E1000_CTRL_SWDPIN0;
+               ctrl |= E1000_CTRL_SWDPIO0;
+       }
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+       return E1000_SUCCESS;
+#endif
+        return 0;
+}
+
+/**
+ *  e1000_clear_hw_cntrs_82543 - Clear device specific hardware counters
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the hardware counters by reading the counter registers.
+ **/
+static void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_clear_hw_cntrs_82543");
+
+       e1000_clear_hw_cntrs_base_generic(hw);
+
+#if 0
+       E1000_READ_REG(hw, E1000_PRC64);
+       E1000_READ_REG(hw, E1000_PRC127);
+       E1000_READ_REG(hw, E1000_PRC255);
+       E1000_READ_REG(hw, E1000_PRC511);
+       E1000_READ_REG(hw, E1000_PRC1023);
+       E1000_READ_REG(hw, E1000_PRC1522);
+       E1000_READ_REG(hw, E1000_PTC64);
+       E1000_READ_REG(hw, E1000_PTC127);
+       E1000_READ_REG(hw, E1000_PTC255);
+       E1000_READ_REG(hw, E1000_PTC511);
+       E1000_READ_REG(hw, E1000_PTC1023);
+       E1000_READ_REG(hw, E1000_PTC1522);
+
+       E1000_READ_REG(hw, E1000_ALGNERRC);
+       E1000_READ_REG(hw, E1000_RXERRC);
+       E1000_READ_REG(hw, E1000_TNCRS);
+       E1000_READ_REG(hw, E1000_CEXTERR);
+       E1000_READ_REG(hw, E1000_TSCTC);
+       E1000_READ_REG(hw, E1000_TSCTFC);
+#endif
+}
+
+static struct pci_device_id e1000_82543_nics[] = {
+     PCI_ROM(0x8086, 0x1001, "E1000_DEV_ID_82543GC_FIBER", "E1000_DEV_ID_82543GC_FIBER", e1000_82543),
+     PCI_ROM(0x8086, 0x1004, "E1000_DEV_ID_82543GC_COPPER", "E1000_DEV_ID_82543GC_COPPER", e1000_82543),
+     PCI_ROM(0x8086, 0x1008, "E1000_DEV_ID_82544EI_COPPER", "E1000_DEV_ID_82544EI_COPPER", e1000_82544),
+     PCI_ROM(0x8086, 0x1009, "E1000_DEV_ID_82544EI_FIBER", "E1000_DEV_ID_82544EI_FIBER", e1000_82544),
+     PCI_ROM(0x8086, 0x100C, "E1000_DEV_ID_82544GC_COPPER", "E1000_DEV_ID_82544GC_COPPER", e1000_82544),
+     PCI_ROM(0x8086, 0x100D, "E1000_DEV_ID_82544GC_LOM", "E1000_DEV_ID_82544GC_LOM", e1000_82544),
+};
+
+struct pci_driver e1000_82543_driver __pci_driver = {
+       .ids = e1000_82543_nics,
+       .id_count = (sizeof (e1000_82543_nics) / sizeof (e1000_82543_nics[0])),
+       .probe = e1000_probe,
+       .remove = e1000_remove,
+};
diff --git a/kern/drivers/net/e1000/e1000_82543.h b/kern/drivers/net/e1000/e1000_82543.h
new file mode 100644 (file)
index 0000000..30073e8
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+
+  Intel PRO/1000 Linux driver
+  Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef _E1000_82543_H_
+#define _E1000_82543_H_
+
+#define PHY_PREAMBLE      0xFFFFFFFF
+#define PHY_PREAMBLE_SIZE 32
+#define PHY_SOF           0x1
+#define PHY_OP_READ       0x2
+#define PHY_OP_WRITE      0x1
+#define PHY_TURNAROUND    0x2
+
+#define TBI_COMPAT_ENABLED 0x1 /* Global "knob" for the workaround */
+/* If TBI_COMPAT_ENABLED, then this is the current state (on/off) */
+#define TBI_SBP_ENABLED    0x2
+
+#endif
diff --git a/kern/drivers/net/e1000/e1000_api.c b/kern/drivers/net/e1000/e1000_api.c
new file mode 100644 (file)
index 0000000..72aac4c
--- /dev/null
@@ -0,0 +1,1108 @@
+/*******************************************************************************
+
+  Intel PRO/1000 Linux driver
+  Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "e1000_api.h"
+
+/**
+ *  e1000_init_mac_params - Initialize MAC function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  This function initializes the function pointers for the MAC
+ *  set of functions.  Called by drivers or by e1000_setup_init_funcs.
+ **/
+s32 e1000_init_mac_params(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+
+       if (hw->mac.ops.init_params) {
+               ret_val = hw->mac.ops.init_params(hw);
+               if (ret_val) {
+                       DEBUGOUT("MAC Initialization Error\n");
+                       goto out;
+               }
+       } else {
+               DEBUGOUT("mac.init_mac_params was NULL\n");
+               ret_val = -E1000_ERR_CONFIG;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_init_nvm_params - Initialize NVM function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  This function initializes the function pointers for the NVM
+ *  set of functions.  Called by drivers or by e1000_setup_init_funcs.
+ **/
+s32 e1000_init_nvm_params(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+
+       if (hw->nvm.ops.init_params) {
+               ret_val = hw->nvm.ops.init_params(hw);
+               if (ret_val) {
+                       DEBUGOUT("NVM Initialization Error\n");
+                       goto out;
+               }
+       } else {
+               DEBUGOUT("nvm.init_nvm_params was NULL\n");
+               ret_val = -E1000_ERR_CONFIG;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_init_phy_params - Initialize PHY function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  This function initializes the function pointers for the PHY
+ *  set of functions.  Called by drivers or by e1000_setup_init_funcs.
+ **/
+s32 e1000_init_phy_params(struct e1000_hw *hw)
+{
+       s32 ret_val = E1000_SUCCESS;
+
+       if (hw->phy.ops.init_params) {
+               ret_val = hw->phy.ops.init_params(hw);
+               if (ret_val) {
+                       DEBUGOUT("PHY Initialization Error\n");
+                       goto out;
+               }
+       } else {
+               DEBUGOUT("phy.init_phy_params was NULL\n");
+               ret_val =  -E1000_ERR_CONFIG;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_set_mac_type - Sets MAC type
+ *  @hw: pointer to the HW structure
+ *
+ *  This function sets the mac type of the adapter based on the
+ *  device ID stored in the hw structure.
+ *  MUST BE FIRST FUNCTION CALLED (explicitly or through
+ *  e1000_setup_init_funcs()).
+ **/
+s32 e1000_set_mac_type(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_set_mac_type");
+
+       switch (hw->device_id) {
+       case E1000_DEV_ID_82542:
+               mac->type = e1000_82542;
+               break;
+       case E1000_DEV_ID_82543GC_FIBER:
+       case E1000_DEV_ID_82543GC_COPPER:
+               mac->type = e1000_82543;
+               break;
+       case E1000_DEV_ID_82544EI_COPPER:
+       case E1000_DEV_ID_82544EI_FIBER:
+       case E1000_DEV_ID_82544GC_COPPER:
+       case E1000_DEV_ID_82544GC_LOM:
+               mac->type = e1000_82544;
+               break;
+       case E1000_DEV_ID_82540EM:
+       case E1000_DEV_ID_82540EM_LOM:
+       case E1000_DEV_ID_82540EP:
+       case E1000_DEV_ID_82540EP_LOM:
+       case E1000_DEV_ID_82540EP_LP:
+               mac->type = e1000_82540;
+               break;
+       case E1000_DEV_ID_82545EM_COPPER:
+       case E1000_DEV_ID_82545EM_FIBER:
+               mac->type = e1000_82545;
+               break;
+       case E1000_DEV_ID_82545GM_COPPER:
+       case E1000_DEV_ID_82545GM_FIBER:
+       case E1000_DEV_ID_82545GM_SERDES:
+               mac->type = e1000_82545_rev_3;
+               break;
+       case E1000_DEV_ID_82546EB_COPPER:
+       case E1000_DEV_ID_82546EB_FIBER:
+       case E1000_DEV_ID_82546EB_QUAD_COPPER:
+               mac->type = e1000_82546;
+               break;
+       case E1000_DEV_ID_82546GB_COPPER:
+       case E1000_DEV_ID_82546GB_FIBER:
+       case E1000_DEV_ID_82546GB_SERDES:
+       case E1000_DEV_ID_82546GB_PCIE:
+       case E1000_DEV_ID_82546GB_QUAD_COPPER:
+       case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
+               mac->type = e1000_82546_rev_3;
+               break;
+       case E1000_DEV_ID_82541EI:
+       case E1000_DEV_ID_82541EI_MOBILE:
+       case E1000_DEV_ID_82541ER_LOM:
+               mac->type = e1000_82541;
+               break;
+       case E1000_DEV_ID_82541ER:
+       case E1000_DEV_ID_82541GI:
+       case E1000_DEV_ID_82541GI_LF:
+       case E1000_DEV_ID_82541GI_MOBILE:
+               mac->type = e1000_82541_rev_2;
+               break;
+       case E1000_DEV_ID_82547EI:
+       case E1000_DEV_ID_82547EI_MOBILE:
+               mac->type = e1000_82547;
+               break;
+       case E1000_DEV_ID_82547GI:
+               mac->type = e1000_82547_rev_2;
+               break;
+       default:
+               /* Should never have loaded on this device */
+               ret_val = -E1000_ERR_MAC_INIT;
+               break;
+       }
+
+       return ret_val;
+}
+
+/**
+ *  e1000_setup_init_funcs - Initializes function pointers
+ *  @hw: pointer to the HW structure
+ *  @init_device: true will initialize the rest of the function pointers
+ *                 getting the device ready for use.  false will only set
+ *                 MAC type and the function pointers for the other init
+ *                 functions.  Passing false will not generate any hardware
+ *                 reads or writes.
+ *
+ *  This function must be called by a driver in order to use the rest
+ *  of the 'shared' code files. Called by drivers only.
+ **/
+s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
+{
+       s32 ret_val;
+
+       /* Can't do much good without knowing the MAC type. */
+       ret_val = e1000_set_mac_type(hw);
+       if (ret_val) {
+               DEBUGOUT("ERROR: MAC type could not be set properly.\n");
+               goto out;
+       }
+
+       if (!hw->hw_addr) {
+               DEBUGOUT("ERROR: Registers not mapped\n");
+               ret_val = -E1000_ERR_CONFIG;
+               goto out;
+       }
+
+       /*
+        * Init function pointers to generic implementations. We do this first
+        * allowing a driver module to override it afterward.
+        */
+       e1000_init_mac_ops_generic(hw);
+       e1000_init_phy_ops_generic(hw);
+       e1000_init_nvm_ops_generic(hw);
+
+       /*
+        * Set up the init function pointers. These are functions within the
+        * adapter family file that sets up function pointers for the rest of
+        * the functions in that family.
+        */
+       switch (hw->mac.type) {
+       case e1000_82542:
+               e1000_init_function_pointers_82542(hw);
+               break;
+       case e1000_82543:
+       case e1000_82544:
+               e1000_init_function_pointers_82543(hw);
+               break;
+       case e1000_82540:
+       case e1000_82545:
+       case e1000_82545_rev_3:
+       case e1000_82546:
+       case e1000_82546_rev_3:
+               e1000_init_function_pointers_82540(hw);
+               break;
+       case e1000_82541:
+       case e1000_82541_rev_2:
+       case e1000_82547:
+       case e1000_82547_rev_2:
+               e1000_init_function_pointers_82541(hw);
+               break;
+       default:
+               DEBUGOUT("Hardware not supported\n");
+               ret_val = -E1000_ERR_CONFIG;
+               break;
+       }
+
+       /*
+        * Initialize the rest of the function pointers. These require some
+        * register reads/writes in some cases.
+        */
+       if (!(ret_val) && init_device) {
+               ret_val = e1000_init_mac_params(hw);
+               if (ret_val)
+                       goto out;
+
+               ret_val = e1000_init_nvm_params(hw);
+               if (ret_val)
+                       goto out;
+
+               ret_val = e1000_init_phy_params(hw);
+               if (ret_val)
+                       goto out;
+       }
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_get_bus_info - Obtain bus information for adapter
+ *  @hw: pointer to the HW structure
+ *
+ *  This will obtain information about the HW bus for which the
+ *  adapter is attached and stores it in the hw structure. This is a
+ *  function pointer entry point called by drivers.
+ **/
+s32 e1000_get_bus_info(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.get_bus_info)
+               return hw->mac.ops.get_bus_info(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_clear_vfta - Clear VLAN filter table
+ *  @hw: pointer to the HW structure
+ *
+ *  This clears the VLAN filter table on the adapter. This is a function
+ *  pointer entry point called by drivers.
+ **/
+void e1000_clear_vfta(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.clear_vfta)
+               hw->mac.ops.clear_vfta(hw);
+}
+
+/**
+ *  e1000_write_vfta - Write value to VLAN filter table
+ *  @hw: pointer to the HW structure
+ *  @offset: the 32-bit offset in which to write the value to.
+ *  @value: the 32-bit value to write at location offset.
+ *
+ *  This writes a 32-bit value to a 32-bit offset in the VLAN filter
+ *  table. This is a function pointer entry point called by drivers.
+ **/
+void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
+{
+       if (hw->mac.ops.write_vfta)
+               hw->mac.ops.write_vfta(hw, offset, value);
+}
+
+/**
+ *  e1000_update_mc_addr_list - Update Multicast addresses
+ *  @hw: pointer to the HW structure
+ *  @mc_addr_list: array of multicast addresses to program
+ *  @mc_addr_count: number of multicast addresses to program
+ *
+ *  Updates the Multicast Table Array.
+ *  The caller must have a packed mc_addr_list of multicast addresses.
+ **/
+void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list,
+                               u32 mc_addr_count)
+{
+       if (hw->mac.ops.update_mc_addr_list)
+               hw->mac.ops.update_mc_addr_list(hw, mc_addr_list,
+                                               mc_addr_count);
+}
+
+/**
+ *  e1000_force_mac_fc - Force MAC flow control
+ *  @hw: pointer to the HW structure
+ *
+ *  Force the MAC's flow control settings. Currently no func pointer exists
+ *  and all implementations are handled in the generic version of this
+ *  function.
+ **/
+s32 e1000_force_mac_fc(struct e1000_hw *hw)
+{
+       return e1000_force_mac_fc_generic(hw);
+}
+
+/**
+ *  e1000_check_for_link - Check/Store link connection
+ *  @hw: pointer to the HW structure
+ *
+ *  This checks the link condition of the adapter and stores the
+ *  results in the hw->mac structure. This is a function pointer entry
+ *  point called by drivers.
+ **/
+s32 e1000_check_for_link(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.check_for_link)
+               return hw->mac.ops.check_for_link(hw);
+
+       return -E1000_ERR_CONFIG;
+}
+
+#if 0
+/**
+ *  e1000_check_mng_mode - Check management mode
+ *  @hw: pointer to the HW structure
+ *
+ *  This checks if the adapter has manageability enabled.
+ *  This is a function pointer entry point called by drivers.
+ **/
+bool e1000_check_mng_mode(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.check_mng_mode)
+               return hw->mac.ops.check_mng_mode(hw);
+
+       return false;
+}
+
+/**
+ *  e1000_mng_write_dhcp_info - Writes DHCP info to host interface
+ *  @hw: pointer to the HW structure
+ *  @buffer: pointer to the host interface
+ *  @length: size of the buffer
+ *
+ *  Writes the DHCP information to the host interface.
+ **/
+s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
+{
+       return e1000_mng_write_dhcp_info_generic(hw, buffer, length);
+}
+#endif
+
+/**
+ *  e1000_reset_hw - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state. This is a function pointer
+ *  entry point called by drivers.
+ **/
+s32 e1000_reset_hw(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.reset_hw)
+               return hw->mac.ops.reset_hw(hw);
+
+       return -E1000_ERR_CONFIG;
+}
+
+/**
+ *  e1000_init_hw - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation. This is a function
+ *  pointer entry point called by drivers.
+ **/
+s32 e1000_init_hw(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.init_hw)
+               return hw->mac.ops.init_hw(hw);
+
+       return -E1000_ERR_CONFIG;
+}
+
+/**
+ *  e1000_setup_link - Configures link and flow control
+ *  @hw: pointer to the HW structure
+ *
+ *  This configures link and flow control settings for the adapter. This
+ *  is a function pointer entry point called by drivers. While modules can
+ *  also call this, they probably call their own version of this function.
+ **/
+s32 e1000_setup_link(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.setup_link)
+               return hw->mac.ops.setup_link(hw);
+
+       return -E1000_ERR_CONFIG;
+}
+
+/**
+ *  e1000_get_speed_and_duplex - Returns current speed and duplex
+ *  @hw: pointer to the HW structure
+ *  @speed: pointer to a 16-bit value to store the speed
+ *  @duplex: pointer to a 16-bit value to store the duplex.
+ *
+ *  This returns the speed and duplex of the adapter in the two 'out'
+ *  variables passed in. This is a function pointer entry point called
+ *  by drivers.
+ **/
+s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
+{
+       if (hw->mac.ops.get_link_up_info)
+               return hw->mac.ops.get_link_up_info(hw, speed, duplex);
+
+       return -E1000_ERR_CONFIG;
+}
+
+/**
+ *  e1000_setup_led - Configures SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  This prepares the SW controllable LED for use and saves the current state
+ *  of the LED so it can be later restored. This is a function pointer entry
+ *  point called by drivers.
+ **/
+s32 e1000_setup_led(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.setup_led)
+               return hw->mac.ops.setup_led(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_cleanup_led - Restores SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  This restores the SW controllable LED to the value saved off by
+ *  e1000_setup_led. This is a function pointer entry point called by drivers.
+ **/
+s32 e1000_cleanup_led(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.cleanup_led)
+               return hw->mac.ops.cleanup_led(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_blink_led - Blink SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  This starts the adapter LED blinking. Request the LED to be setup first
+ *  and cleaned up after. This is a function pointer entry point called by
+ *  drivers.
+ **/
+s32 e1000_blink_led(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.blink_led)
+               return hw->mac.ops.blink_led(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_id_led_init - store LED configurations in SW
+ *  @hw: pointer to the HW structure
+ *
+ *  Initializes the LED config in SW. This is a function pointer entry point
+ *  called by drivers.
+ **/
+s32 e1000_id_led_init(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.id_led_init)
+               return hw->mac.ops.id_led_init(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_led_on - Turn on SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED on. This is a function pointer entry point
+ *  called by drivers.
+ **/
+s32 e1000_led_on(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.led_on)
+               return hw->mac.ops.led_on(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_led_off - Turn off SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED off. This is a function pointer entry point
+ *  called by drivers.
+ **/
+s32 e1000_led_off(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.led_off)
+               return hw->mac.ops.led_off(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_reset_adaptive - Reset adaptive IFS
+ *  @hw: pointer to the HW structure
+ *
+ *  Resets the adaptive IFS. Currently no func pointer exists and all
+ *  implementations are handled in the generic version of this function.
+ **/
+void e1000_reset_adaptive(struct e1000_hw *hw)
+{
+       e1000_reset_adaptive_generic(hw);
+}
+
+/**
+ *  e1000_update_adaptive - Update adaptive IFS
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates adapter IFS. Currently no func pointer exists and all
+ *  implementations are handled in the generic version of this function.
+ **/
+void e1000_update_adaptive(struct e1000_hw *hw)
+{
+       e1000_update_adaptive_generic(hw);
+}
+
+/**
+ *  e1000_disable_pcie_master - Disable PCI-Express master access
+ *  @hw: pointer to the HW structure
+ *
+ *  Disables PCI-Express master access and verifies there are no pending
+ *  requests. Currently no func pointer exists and all implementations are
+ *  handled in the generic version of this function.
+ **/
+s32 e1000_disable_pcie_master(struct e1000_hw *hw)
+{
+       return e1000_disable_pcie_master_generic(hw);
+}
+
+/**
+ *  e1000_config_collision_dist - Configure collision distance
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures the collision distance to the default value and is used
+ *  during link setup.
+ **/
+void e1000_config_collision_dist(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.config_collision_dist)
+               hw->mac.ops.config_collision_dist(hw);
+}
+
+/**
+ *  e1000_rar_set - Sets a receive address register
+ *  @hw: pointer to the HW structure
+ *  @addr: address to set the RAR to
+ *  @index: the RAR to set
+ *
+ *  Sets a Receive Address Register (RAR) to the specified address.
+ **/
+void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
+{
+       if (hw->mac.ops.rar_set)
+               hw->mac.ops.rar_set(hw, addr, index);
+}
+
+/**
+ *  e1000_validate_mdi_setting - Ensures valid MDI/MDIX SW state
+ *  @hw: pointer to the HW structure
+ *
+ *  Ensures that the MDI/MDIX SW state is valid.
+ **/
+s32 e1000_validate_mdi_setting(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.validate_mdi_setting)
+               return hw->mac.ops.validate_mdi_setting(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_mta_set - Sets multicast table bit
+ *  @hw: pointer to the HW structure
+ *  @hash_value: Multicast hash value.
+ *
+ *  This sets the bit in the multicast table corresponding to the
+ *  hash value.  This is a function pointer entry point called by drivers.
+ **/
+void e1000_mta_set(struct e1000_hw *hw, u32 hash_value)
+{
+       if (hw->mac.ops.mta_set)
+               hw->mac.ops.mta_set(hw, hash_value);
+}
+
+/**
+ *  e1000_hash_mc_addr - Determines address location in multicast table
+ *  @hw: pointer to the HW structure
+ *  @mc_addr: Multicast address to hash.
+ *
+ *  This hashes an address to determine its location in the multicast
+ *  table. Currently no func pointer exists and all implementations
+ *  are handled in the generic version of this function.
+ **/
+u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+{
+       return e1000_hash_mc_addr_generic(hw, mc_addr);
+}
+
+#if 0
+/**
+ *  e1000_enable_tx_pkt_filtering - Enable packet filtering on TX
+ *  @hw: pointer to the HW structure
+ *
+ *  Enables packet filtering on transmit packets if manageability is enabled
+ *  and host interface is enabled.
+ *  Currently no func pointer exists and all implementations are handled in the
+ *  generic version of this function.
+ **/
+bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+{
+       return e1000_enable_tx_pkt_filtering_generic(hw);
+}
+
+/**
+ *  e1000_mng_host_if_write - Writes to the manageability host interface
+ *  @hw: pointer to the HW structure
+ *  @buffer: pointer to the host interface buffer
+ *  @length: size of the buffer
+ *  @offset: location in the buffer to write to
+ *  @sum: sum of the data (not checksum)
+ *
+ *  This function writes the buffer content at the offset given on the host if.
+ *  It also does alignment considerations to do the writes in most efficient
+ *  way.  Also fills up the sum of the buffer in *buffer parameter.
+ **/
+s32 e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer, u16 length,
+                            u16 offset, u8 *sum)
+{
+       if (hw->mac.ops.mng_host_if_write)
+               return hw->mac.ops.mng_host_if_write(hw, buffer, length,
+                                                    offset, sum);
+
+       return E1000_NOT_IMPLEMENTED;
+}
+
+/**
+ *  e1000_mng_write_cmd_header - Writes manageability command header
+ *  @hw: pointer to the HW structure
+ *  @hdr: pointer to the host interface command header
+ *
+ *  Writes the command header after does the checksum calculation.
+ **/
+s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
+                               struct e1000_host_mng_command_header *hdr)
+{
+       if (hw->mac.ops.mng_write_cmd_header)
+               return hw->mac.ops.mng_write_cmd_header(hw, hdr);
+
+       return E1000_NOT_IMPLEMENTED;
+}
+
+/**
+ *  e1000_mng_enable_host_if - Checks host interface is enabled
+ *  @hw: pointer to the HW structure
+ *
+ *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
+ *
+ *  This function checks whether the HOST IF is enabled for command operation
+ *  and also checks whether the previous command is completed.  It busy waits
+ *  in case of previous command is not completed.
+ **/
+s32 e1000_mng_enable_host_if(struct e1000_hw * hw)
+{
+       if (hw->mac.ops.mng_enable_host_if)
+               return hw->mac.ops.mng_enable_host_if(hw);
+
+       return E1000_NOT_IMPLEMENTED;
+}
+#endif
+
+/**
+ *  e1000_wait_autoneg - Waits for autonegotiation completion
+ *  @hw: pointer to the HW structure
+ *
+ *  Waits for autoneg to complete. Currently no func pointer exists and all
+ *  implementations are handled in the generic version of this function.
+ **/
+s32 e1000_wait_autoneg(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.wait_autoneg)
+               return hw->mac.ops.wait_autoneg(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_check_reset_block - Verifies PHY can be reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks if the PHY is in a state that can be reset or if manageability
+ *  has it tied up. This is a function pointer entry point called by drivers.
+ **/
+s32 e1000_check_reset_block(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.check_reset_block)
+               return hw->phy.ops.check_reset_block(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_read_phy_reg - Reads PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: the register to read
+ *  @data: the buffer to store the 16-bit read.
+ *
+ *  Reads the PHY register and returns the value in data.
+ *  This is a function pointer entry point called by drivers.
+ **/
+s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       if (hw->phy.ops.read_reg)
+               return hw->phy.ops.read_reg(hw, offset, data);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_write_phy_reg - Writes PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: the register to write
+ *  @data: the value to write.
+ *
+ *  Writes the PHY register at offset with the value in data.
+ *  This is a function pointer entry point called by drivers.
+ **/
+s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       if (hw->phy.ops.write_reg)
+               return hw->phy.ops.write_reg(hw, offset, data);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_release_phy - Generic release PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Return if silicon family does not require a semaphore when accessing the
+ *  PHY.
+ **/
+void e1000_release_phy(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.release)
+               hw->phy.ops.release(hw);
+}
+
+/**
+ *  e1000_acquire_phy - Generic acquire PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Return success if silicon family does not require a semaphore when
+ *  accessing the PHY.
+ **/
+s32 e1000_acquire_phy(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.acquire)
+               return hw->phy.ops.acquire(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_read_kmrn_reg - Reads register using Kumeran interface
+ *  @hw: pointer to the HW structure
+ *  @offset: the register to read
+ *  @data: the location to store the 16-bit value read.
+ *
+ *  Reads a register out of the Kumeran interface. Currently no func pointer
+ *  exists and all implementations are handled in the generic version of
+ *  this function.
+ **/
+s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       return e1000_read_kmrn_reg_generic(hw, offset, data);
+}
+
+/**
+ *  e1000_write_kmrn_reg - Writes register using Kumeran interface
+ *  @hw: pointer to the HW structure
+ *  @offset: the register to write
+ *  @data: the value to write.
+ *
+ *  Writes a register to the Kumeran interface. Currently no func pointer
+ *  exists and all implementations are handled in the generic version of
+ *  this function.
+ **/
+s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       return e1000_write_kmrn_reg_generic(hw, offset, data);
+}
+
+#if 0
+/**
+ *  e1000_get_cable_length - Retrieves cable length estimation
+ *  @hw: pointer to the HW structure
+ *
+ *  This function estimates the cable length and stores them in
+ *  hw->phy.min_length and hw->phy.max_length. This is a function pointer
+ *  entry point called by drivers.
+ **/
+s32 e1000_get_cable_length(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.get_cable_length)
+               return hw->phy.ops.get_cable_length(hw);
+
+       return E1000_SUCCESS;
+}
+#endif
+
+/**
+ *  e1000_get_phy_info - Retrieves PHY information from registers
+ *  @hw: pointer to the HW structure
+ *
+ *  This function gets some information from various PHY registers and
+ *  populates hw->phy values with it. This is a function pointer entry
+ *  point called by drivers.
+ **/
+s32 e1000_get_phy_info(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.get_info)
+               return hw->phy.ops.get_info(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_phy_hw_reset - Hard PHY reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Performs a hard PHY reset. This is a function pointer entry point called
+ *  by drivers.
+ **/
+s32 e1000_phy_hw_reset(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.reset)
+               return hw->phy.ops.reset(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_phy_commit - Soft PHY reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Performs a soft PHY reset on those that apply. This is a function pointer
+ *  entry point called by drivers.
+ **/
+s32 e1000_phy_commit(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.commit)
+               return hw->phy.ops.commit(hw);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_set_d0_lplu_state - Sets low power link up state for D0
+ *  @hw: pointer to the HW structure
+ *  @active: boolean used to enable/disable lplu
+ *
+ *  Success returns 0, Failure returns 1
+ *
+ *  The low power link up (lplu) state is set to the power management level D0
+ *  and SmartSpeed is disabled when active is true, else clear lplu for D0
+ *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
+ *  is used during Dx states where the power conservation is most important.
+ *  During driver activity, SmartSpeed should be enabled so performance is
+ *  maintained.  This is a function pointer entry point called by drivers.
+ **/
+s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
+{
+       if (hw->phy.ops.set_d0_lplu_state)
+               return hw->phy.ops.set_d0_lplu_state(hw, active);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_set_d3_lplu_state - Sets low power link up state for D3
+ *  @hw: pointer to the HW structure
+ *  @active: boolean used to enable/disable lplu
+ *
+ *  Success returns 0, Failure returns 1
+ *
+ *  The low power link up (lplu) state is set to the power management level D3
+ *  and SmartSpeed is disabled when active is true, else clear lplu for D3
+ *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
+ *  is used during Dx states where the power conservation is most important.
+ *  During driver activity, SmartSpeed should be enabled so performance is
+ *  maintained.  This is a function pointer entry point called by drivers.
+ **/
+s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
+{
+       if (hw->phy.ops.set_d3_lplu_state)
+               return hw->phy.ops.set_d3_lplu_state(hw, active);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_read_mac_addr - Reads MAC address
+ *  @hw: pointer to the HW structure
+ *
+ *  Reads the MAC address out of the adapter and stores it in the HW structure.
+ *  Currently no func pointer exists and all implementations are handled in the
+ *  generic version of this function.
+ **/
+s32 e1000_read_mac_addr(struct e1000_hw *hw)
+{
+       if (hw->mac.ops.read_mac_addr)
+               return hw->mac.ops.read_mac_addr(hw);
+
+       return e1000_read_mac_addr_generic(hw);
+}
+
+/**
+ *  e1000_read_pba_num - Read device part number
+ *  @hw: pointer to the HW structure
+ *  @pba_num: pointer to device part number
+ *
+ *  Reads the product board assembly (PBA) number from the EEPROM and stores
+ *  the value in pba_num.
+ *  Currently no func pointer exists and all implementations are handled in the
+ *  generic version of this function.
+ **/
+s32 e1000_read_pba_num(struct e1000_hw *hw, u32 *pba_num)
+{
+       return e1000_read_pba_num_generic(hw, pba_num);
+}
+
+/**
+ *  e1000_validate_nvm_checksum - Verifies NVM (EEPROM) checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Validates the NVM checksum is correct. This is a function pointer entry
+ *  point called by drivers.
+ **/
+s32 e1000_validate_nvm_checksum(struct e1000_hw *hw)
+{
+       if (hw->nvm.ops.validate)
+               return hw->nvm.ops.validate(hw);
+
+       return -E1000_ERR_CONFIG;
+}
+
+/**
+ *  e1000_update_nvm_checksum - Updates NVM (EEPROM) checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates the NVM checksum. Currently no func pointer exists and all
+ *  implementations are handled in the generic version of this function.
+ **/
+s32 e1000_update_nvm_checksum(struct e1000_hw *hw)
+{
+       if (hw->nvm.ops.update)
+               return hw->nvm.ops.update(hw);
+
+       return -E1000_ERR_CONFIG;
+}
+
+/**
+ *  e1000_reload_nvm - Reloads EEPROM
+ *  @hw: pointer to the HW structure
+ *
+ *  Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
+ *  extended control register.
+ **/
+void e1000_reload_nvm(struct e1000_hw *hw)
+{
+       if (hw->nvm.ops.reload)
+               hw->nvm.ops.reload(hw);
+}
+
+/**
+ *  e1000_read_nvm - Reads NVM (EEPROM)
+ *  @hw: pointer to the HW structure
+ *  @offset: the word offset to read
+ *  @words: number of 16-bit words to read
+ *  @data: pointer to the properly sized buffer for the data.
+ *
+ *  Reads 16-bit chunks of data from the NVM (EEPROM). This is a function
+ *  pointer entry point called by drivers.
+ **/
+s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+{
+       if (hw->nvm.ops.read)
+               return hw->nvm.ops.read(hw, offset, words, data);
+
+       return -E1000_ERR_CONFIG;
+}
+
+/**
+ *  e1000_write_nvm - Writes to NVM (EEPROM)
+ *  @hw: pointer to the HW structure
+ *  @offset: the word offset to read
+ *  @words: number of 16-bit words to write
+ *  @data: pointer to the properly sized buffer for the data.
+ *
+ *  Writes 16-bit chunks of data to the NVM (EEPROM). This is a function
+ *  pointer entry point called by drivers.
+ **/
+s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+{
+       if (hw->nvm.ops.write)
+               return hw->nvm.ops.write(hw, offset, words, data);
+
+       return E1000_SUCCESS;
+}
+
+/**
+ * e1000_power_up_phy - Restores link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * The phy may be powered down to save power, to turn off link when the
+ * driver is unloaded, or wake on lan is not enabled (among others).
+ **/
+void e1000_power_up_phy(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.power_up)
+               hw->phy.ops.power_up(hw);
+
+       e1000_setup_link(hw);
+}
+
+/**
+ * e1000_power_down_phy - Power down PHY
+ * @hw: pointer to the HW structure
+ *
+ * The phy may be powered down to save power, to turn off link when the
+ * driver is unloaded, or wake on lan is not enabled (among others).
+ **/
+void e1000_power_down_phy(struct e1000_hw *hw)
+{
+       if (hw->phy.ops.power_down)
+               hw->phy.ops.power_down(hw);
+}
diff --git a/kern/drivers/net/e1000/e1000_api.h b/kern/drivers/net/e1000/e1000_api.h
new file mode 100644 (file)
index 0000000..d9f13bf
--- /dev/null
@@ -0,0 +1,128 @@
+/*******************************************************************************
+
+  Intel PRO/1000 Linux driver
+  Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef _E1000_API_H_
+#define _E1000_API_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <gpxe/io.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <gpxe/pci.h>
+#include <gpxe/malloc.h>
+#include <gpxe/if_ether.h>
+#include <gpxe/ethernet.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/netdevice.h>
+
+#include "e1000_hw.h"
+
+extern void    e1000_init_function_pointers_82542(struct e1000_hw *hw) __attribute__((weak));
+extern void    e1000_init_function_pointers_82543(struct e1000_hw *hw) __attribute__((weak));
+extern void    e1000_init_function_pointers_82540(struct e1000_hw *hw) __attribute__((weak));
+extern void    e1000_init_function_pointers_82541(struct e1000_hw *hw) __attribute__((weak));
+
+s32  e1000_set_mac_type(struct e1000_hw *hw);
+s32  e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device);
+s32  e1000_init_mac_params(struct e1000_hw *hw);
+s32  e1000_init_nvm_params(struct e1000_hw *hw);
+s32  e1000_init_phy_params(struct e1000_hw *hw);
+s32  e1000_get_bus_info(struct e1000_hw *hw);
+void e1000_clear_vfta(struct e1000_hw *hw);
+void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value);
+s32  e1000_force_mac_fc(struct e1000_hw *hw);
+s32  e1000_check_for_link(struct e1000_hw *hw);
+s32  e1000_reset_hw(struct e1000_hw *hw);
+s32  e1000_init_hw(struct e1000_hw *hw);
+s32  e1000_setup_link(struct e1000_hw *hw);
+s32  e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed,
+                                u16 *duplex);
+s32  e1000_disable_pcie_master(struct e1000_hw *hw);
+void e1000_config_collision_dist(struct e1000_hw *hw);
+void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
+void e1000_mta_set(struct e1000_hw *hw, u32 hash_value);
+u32  e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr);
+void e1000_update_mc_addr_list(struct e1000_hw *hw,
+                               u8 *mc_addr_list, u32 mc_addr_count);
+s32  e1000_setup_led(struct e1000_hw *hw);
+s32  e1000_cleanup_led(struct e1000_hw *hw);
+s32  e1000_check_reset_block(struct e1000_hw *hw);
+s32  e1000_blink_led(struct e1000_hw *hw);
+s32  e1000_led_on(struct e1000_hw *hw);
+s32  e1000_led_off(struct e1000_hw *hw);
+s32 e1000_id_led_init(struct e1000_hw *hw);
+void e1000_reset_adaptive(struct e1000_hw *hw);
+void e1000_update_adaptive(struct e1000_hw *hw);
+#if 0
+s32  e1000_get_cable_length(struct e1000_hw *hw);
+#endif
+s32  e1000_validate_mdi_setting(struct e1000_hw *hw);
+s32  e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_get_phy_info(struct e1000_hw *hw);
+void e1000_release_phy(struct e1000_hw *hw);
+s32  e1000_acquire_phy(struct e1000_hw *hw);
+s32  e1000_phy_hw_reset(struct e1000_hw *hw);
+s32  e1000_phy_commit(struct e1000_hw *hw);
+void e1000_power_up_phy(struct e1000_hw *hw);
+void e1000_power_down_phy(struct e1000_hw *hw);
+s32  e1000_read_mac_addr(struct e1000_hw *hw);
+s32  e1000_read_pba_num(struct e1000_hw *hw, u32 *part_num);
+void e1000_reload_nvm(struct e1000_hw *hw);
+s32  e1000_update_nvm_checksum(struct e1000_hw *hw);
+s32  e1000_validate_nvm_checksum(struct e1000_hw *hw);
+s32  e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+s32  e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words,
+                     u16 *data);
+s32  e1000_wait_autoneg(struct e1000_hw *hw);
+s32  e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
+s32  e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
+bool e1000_check_mng_mode(struct e1000_hw *hw);
+bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
+s32  e1000_mng_enable_host_if(struct e1000_hw *hw);
+s32  e1000_mng_host_if_write(struct e1000_hw *hw,
+                             u8 *buffer, u16 length, u16 offset, u8 *sum);
+s32  e1000_mng_write_cmd_header(struct e1000_hw *hw,
+                                struct e1000_host_mng_command_header *hdr);
+s32  e1000_mng_write_dhcp_info(struct e1000_hw * hw,
+                                    u8 *buffer, u16 length);
+u32  e1000_translate_register_82542(u32 reg) __attribute__((weak));
+
+extern int e1000_probe(struct pci_device *pdev,
+                      const struct pci_device_id *id __unused);
+extern void e1000_remove(struct pci_device *pdev);
+
+#endif
diff --git a/kern/drivers/net/e1000/e1000_defines.h b/kern/drivers/net/e1000/e1000_defines.h
new file mode 100644 (file)
index 0000000..c585f09
--- /dev/null
@@ -0,0 +1,1416 @@
+/*******************************************************************************
+
+  Intel PRO/1000 Linux driver
+  Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef _E1000_DEFINES_H_
+#define _E1000_DEFINES_H_
+
+/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
+#define REQ_TX_DESCRIPTOR_MULTIPLE  8
+#define REQ_RX_DESCRIPTOR_MULTIPLE  8
+
+/* Definitions for power management and wakeup registers */
+/* Wake Up Control */
+#define E1000_WUC_APME       0x00000001 /* APM Enable */
+#define E1000_WUC_PME_EN     0x00000002 /* PME Enable */
+#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */
+#define E1000_WUC_APMPME     0x00000008 /* Assert PME on APM Wakeup */
+#define E1000_WUC_LSCWE      0x00000010 /* Link Status wake up enable */
+#define E1000_WUC_LSCWO      0x00000020 /* Link Status wake up override */
+#define E1000_WUC_SPM        0x80000000 /* Enable SPM */
+#define E1000_WUC_PHY_WAKE   0x00000100 /* if PHY supports wakeup */
+
+/* Wake Up Filter Control */
+#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define E1000_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */
+#define E1000_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
+#define E1000_WUFC_MC   0x00000008 /* Directed Multicast Wakeup Enable */
+#define E1000_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
+#define E1000_WUFC_ARP  0x00000020 /* ARP Request Packet Wakeup Enable */
+#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */
+#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */
+#define E1000_WUFC_IGNORE_TCO   0x00008000 /* Ignore WakeOn TCO packets */
+#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */
+#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */
+#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */
+#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */
+#define E1000_WUFC_ALL_FILTERS  0x000F00FF /* Mask for all wakeup filters */
+#define E1000_WUFC_FLX_OFFSET   16 /* Offset to the Flexible Filters bits */
+#define E1000_WUFC_FLX_FILTERS  0x000F0000 /*Mask for the 4 flexible filters */
+
+/* Wake Up Status */
+#define E1000_WUS_LNKC         E1000_WUFC_LNKC
+#define E1000_WUS_MAG          E1000_WUFC_MAG
+#define E1000_WUS_EX           E1000_WUFC_EX
+#define E1000_WUS_MC           E1000_WUFC_MC
+#define E1000_WUS_BC           E1000_WUFC_BC
+#define E1000_WUS_ARP          E1000_WUFC_ARP
+#define E1000_WUS_IPV4         E1000_WUFC_IPV4
+#define E1000_WUS_IPV6         E1000_WUFC_IPV6
+#define E1000_WUS_FLX0         E1000_WUFC_FLX0
+#define E1000_WUS_FLX1         E1000_WUFC_FLX1
+#define E1000_WUS_FLX2         E1000_WUFC_FLX2
+#define E1000_WUS_FLX3         E1000_WUFC_FLX3
+#define E1000_WUS_FLX_FILTERS  E1000_WUFC_FLX_FILTERS
+
+/* Wake Up Packet Length */
+#define E1000_WUPL_LENGTH_MASK 0x0FFF   /* Only the lower 12 bits are valid */
+
+/* Four Flexible Filters are supported */
+#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4
+
+/* Each Flexible Filter is at most 128 (0x80) bytes in length */
+#define E1000_FLEXIBLE_FILTER_SIZE_MAX  128
+
+#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX
+#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
+#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
+
+/* Extended Device Control */
+#define E1000_CTRL_EXT_GPI0_EN   0x00000001 /* Maps SDP4 to GPI0 */
+#define E1000_CTRL_EXT_GPI1_EN   0x00000002 /* Maps SDP5 to GPI1 */
+#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN
+#define E1000_CTRL_EXT_GPI2_EN   0x00000004 /* Maps SDP6 to GPI2 */
+#define E1000_CTRL_EXT_GPI3_EN   0x00000008 /* Maps SDP7 to GPI3 */
+/* Reserved (bits 4,5) in >= 82575 */
+#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Definable Pin 4 */
+#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Definable Pin 5 */
+#define E1000_CTRL_EXT_PHY_INT   E1000_CTRL_EXT_SDP5_DATA
+#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Definable Pin 6 */
+#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */
+/* SDP 4/5 (bits 8,9) are reserved in >= 82575 */
+#define E1000_CTRL_EXT_SDP4_DIR  0x00000100 /* Direction of SDP4 0=in 1=out */
+#define E1000_CTRL_EXT_SDP5_DIR  0x00000200 /* Direction of SDP5 0=in 1=out */
+#define E1000_CTRL_EXT_SDP6_DIR  0x00000400 /* Direction of SDP6 0=in 1=out */
+#define E1000_CTRL_EXT_SDP7_DIR  0x00000800 /* Direction of SDP7 0=in 1=out */
+#define E1000_CTRL_EXT_ASDCHK    0x00001000 /* Initiate an ASD sequence */
+#define E1000_CTRL_EXT_EE_RST    0x00002000 /* Reinitialize from EEPROM */
+#define E1000_CTRL_EXT_IPS       0x00004000 /* Invert Power State */
+#define E1000_CTRL_EXT_SPD_BYPS  0x00008000 /* Speed Select Bypass */
+#define E1000_CTRL_EXT_RO_DIS    0x00020000 /* Relaxed Ordering disable */
+#define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */
+#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
+#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
+#define E1000_CTRL_EXT_LINK_MODE_TBI  0x00C00000
+#define E1000_CTRL_EXT_LINK_MODE_KMRN    0x00000000
+#define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES  0x00C00000
+#define E1000_CTRL_EXT_LINK_MODE_PCIX_SERDES  0x00800000
+#define E1000_CTRL_EXT_LINK_MODE_SGMII   0x00800000
+#define E1000_CTRL_EXT_EIAME          0x01000000
+#define E1000_CTRL_EXT_IRCA           0x00000001
+#define E1000_CTRL_EXT_WR_WMARK_MASK  0x03000000
+#define E1000_CTRL_EXT_WR_WMARK_256   0x00000000
+#define E1000_CTRL_EXT_WR_WMARK_320   0x01000000
+#define E1000_CTRL_EXT_WR_WMARK_384   0x02000000
+#define E1000_CTRL_EXT_WR_WMARK_448   0x03000000
+#define E1000_CTRL_EXT_CANC           0x04000000 /* Int delay cancellation */
+#define E1000_CTRL_EXT_DRV_LOAD       0x10000000 /* Driver loaded bit for FW */
+/* IAME enable bit (27) was removed in >= 82575 */
+#define E1000_CTRL_EXT_IAME          0x08000000 /* Int acknowledge Auto-mask */
+#define E1000_CRTL_EXT_PB_PAREN       0x01000000 /* packet buffer parity error
+                                                  * detection enabled */
+#define E1000_CTRL_EXT_DF_PAREN       0x02000000 /* descriptor FIFO parity
+                                                  * error detection enable */
+#define E1000_CTRL_EXT_GHOST_PAREN    0x40000000
+#define E1000_CTRL_EXT_PBA_CLR        0x80000000 /* PBA Clear */
+#define E1000_I2CCMD_REG_ADDR_SHIFT   16
+#define E1000_I2CCMD_REG_ADDR         0x00FF0000
+#define E1000_I2CCMD_PHY_ADDR_SHIFT   24
+#define E1000_I2CCMD_PHY_ADDR         0x07000000
+#define E1000_I2CCMD_OPCODE_READ      0x08000000
+#define E1000_I2CCMD_OPCODE_WRITE     0x00000000
+#define E1000_I2CCMD_RESET            0x10000000
+#define E1000_I2CCMD_READY            0x20000000
+#define E1000_I2CCMD_INTERRUPT_ENA    0x40000000
+#define E1000_I2CCMD_ERROR            0x80000000
+#define E1000_MAX_SGMII_PHY_REG_ADDR  255
+#define E1000_I2CCMD_PHY_TIMEOUT      200
+
+/* Receive Descriptor bit definitions */
+#define E1000_RXD_STAT_DD       0x01    /* Descriptor Done */
+#define E1000_RXD_STAT_EOP      0x02    /* End of Packet */
+#define E1000_RXD_STAT_IXSM     0x04    /* Ignore checksum */
+#define E1000_RXD_STAT_VP       0x08    /* IEEE VLAN Packet */
+#define E1000_RXD_STAT_UDPCS    0x10    /* UDP xsum calculated */
+#define E1000_RXD_STAT_TCPCS    0x20    /* TCP xsum calculated */
+#define E1000_RXD_STAT_IPCS     0x40    /* IP xsum calculated */
+#define E1000_RXD_STAT_PIF      0x80    /* passed in-exact filter */
+#define E1000_RXD_STAT_CRCV     0x100   /* Speculative CRC Valid */
+#define E1000_RXD_STAT_IPIDV    0x200   /* IP identification valid */
+#define E1000_RXD_STAT_UDPV     0x400   /* Valid UDP checksum */
+#define E1000_RXD_STAT_DYNINT   0x800   /* Pkt caused INT via DYNINT */
+#define E1000_RXD_STAT_ACK      0x8000  /* ACK Packet indication */
+#define E1000_RXD_ERR_CE        0x01    /* CRC Error */
+#define E1000_RXD_ERR_SE        0x02    /* Symbol Error */
+#define E1000_RXD_ERR_SEQ       0x04    /* Sequence Error */
+#define E1000_RXD_ERR_CXE       0x10    /* Carrier Extension Error */
+#define E1000_RXD_ERR_TCPE      0x20    /* TCP/UDP Checksum Error */
+#define E1000_RXD_ERR_IPE       0x40    /* IP Checksum Error */
+#define E1000_RXD_ERR_RXE       0x80    /* Rx Data Error */
+#define E1000_RXD_SPC_VLAN_MASK 0x0FFF  /* VLAN ID is in lower 12 bits */
+#define E1000_RXD_SPC_PRI_MASK  0xE000  /* Priority is in upper 3 bits */
+#define E1000_RXD_SPC_PRI_SHIFT 13
+#define E1000_RXD_SPC_CFI_MASK  0x1000  /* CFI is bit 12 */
+#define E1000_RXD_SPC_CFI_SHIFT 12
+
+#define E1000_RXDEXT_STATERR_CE    0x01000000
+#define E1000_RXDEXT_STATERR_SE    0x02000000
+#define E1000_RXDEXT_STATERR_SEQ   0x04000000
+#define E1000_RXDEXT_STATERR_CXE   0x10000000
+#define E1000_RXDEXT_STATERR_TCPE  0x20000000
+#define E1000_RXDEXT_STATERR_IPE   0x40000000
+#define E1000_RXDEXT_STATERR_RXE   0x80000000
+
+/* mask to determine if packets should be dropped due to frame errors */
+#define E1000_RXD_ERR_FRAME_ERR_MASK ( \
+    E1000_RXD_ERR_CE  |                \
+    E1000_RXD_ERR_SE  |                \
+    E1000_RXD_ERR_SEQ |                \
+    E1000_RXD_ERR_CXE |                \
+    E1000_RXD_ERR_RXE)
+
+/* Same mask, but for extended and packet split descriptors */
+#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \
+    E1000_RXDEXT_STATERR_CE  |            \
+    E1000_RXDEXT_STATERR_SE  |            \
+    E1000_RXDEXT_STATERR_SEQ |            \
+    E1000_RXDEXT_STATERR_CXE |            \
+    E1000_RXDEXT_STATERR_RXE)
+
+#define E1000_MRQC_ENABLE_MASK                 0x00000007
+#define E1000_MRQC_ENABLE_RSS_2Q               0x00000001
+#define E1000_MRQC_ENABLE_RSS_INT              0x00000004
+#define E1000_MRQC_RSS_FIELD_MASK              0xFFFF0000
+#define E1000_MRQC_RSS_FIELD_IPV4_TCP          0x00010000
+#define E1000_MRQC_RSS_FIELD_IPV4              0x00020000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX       0x00040000
+#define E1000_MRQC_RSS_FIELD_IPV6_EX           0x00080000
+#define E1000_MRQC_RSS_FIELD_IPV6              0x00100000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP          0x00200000
+
+#define E1000_RXDPS_HDRSTAT_HDRSP              0x00008000
+#define E1000_RXDPS_HDRSTAT_HDRLEN_MASK        0x000003FF
+
+/* Management Control */
+#define E1000_MANC_SMBUS_EN      0x00000001 /* SMBus Enabled - RO */
+#define E1000_MANC_ASF_EN        0x00000002 /* ASF Enabled - RO */
+#define E1000_MANC_R_ON_FORCE    0x00000004 /* Reset on Force TCO - RO */
+#define E1000_MANC_RMCP_EN       0x00000100 /* Enable RCMP 026Fh Filtering */
+#define E1000_MANC_0298_EN       0x00000200 /* Enable RCMP 0298h Filtering */
+#define E1000_MANC_IPV4_EN       0x00000400 /* Enable IPv4 */
+#define E1000_MANC_IPV6_EN       0x00000800 /* Enable IPv6 */
+#define E1000_MANC_SNAP_EN       0x00001000 /* Accept LLC/SNAP */
+#define E1000_MANC_ARP_EN        0x00002000 /* Enable ARP Request Filtering */
+/* Enable Neighbor Discovery Filtering */
+#define E1000_MANC_NEIGHBOR_EN   0x00004000
+#define E1000_MANC_ARP_RES_EN    0x00008000 /* Enable ARP response Filtering */
+#define E1000_MANC_TCO_RESET     0x00010000 /* TCO Reset Occurred */
+#define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
+#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
+#define E1000_MANC_RCV_ALL       0x00080000 /* Receive All Enabled */
+#define E1000_MANC_BLK_PHY_RST_ON_IDE   0x00040000 /* Block phy resets */
+/* Enable MAC address filtering */
+#define E1000_MANC_EN_MAC_ADDR_FILTER   0x00100000
+/* Enable MNG packets to host memory */
+#define E1000_MANC_EN_MNG2HOST   0x00200000
+/* Enable IP address filtering */
+#define E1000_MANC_EN_IP_ADDR_FILTER    0x00400000
+#define E1000_MANC_EN_XSUM_FILTER   0x00800000 /* Enable checksum filtering */
+#define E1000_MANC_BR_EN            0x01000000 /* Enable broadcast filtering */
+#define E1000_MANC_SMB_REQ       0x01000000 /* SMBus Request */
+#define E1000_MANC_SMB_GNT       0x02000000 /* SMBus Grant */
+#define E1000_MANC_SMB_CLK_IN    0x04000000 /* SMBus Clock In */
+#define E1000_MANC_SMB_DATA_IN   0x08000000 /* SMBus Data In */
+#define E1000_MANC_SMB_DATA_OUT  0x10000000 /* SMBus Data Out */
+#define E1000_MANC_SMB_CLK_OUT   0x20000000 /* SMBus Clock Out */
+
+#define E1000_MANC_SMB_DATA_OUT_SHIFT  28 /* SMBus Data Out Shift */
+#define E1000_MANC_SMB_CLK_OUT_SHIFT   29 /* SMBus Clock Out Shift */
+
+/* Receive Control */
+#define E1000_RCTL_RST            0x00000001    /* Software reset */
+#define E1000_RCTL_EN             0x00000002    /* enable */
+#define E1000_RCTL_SBP            0x00000004    /* store bad packet */
+#define E1000_RCTL_UPE            0x00000008    /* unicast promisc enable */
+#define E1000_RCTL_MPE            0x00000010    /* multicast promisc enable */
+#define E1000_RCTL_LPE            0x00000020    /* long packet enable */
+#define E1000_RCTL_LBM_NO         0x00000000    /* no loopback mode */
+#define E1000_RCTL_LBM_MAC        0x00000040    /* MAC loopback mode */
+#define E1000_RCTL_LBM_SLP        0x00000080    /* serial link loopback mode */
+#define E1000_RCTL_LBM_TCVR       0x000000C0    /* tcvr loopback mode */
+#define E1000_RCTL_DTYP_MASK      0x00000C00    /* Descriptor type mask */
+#define E1000_RCTL_DTYP_PS        0x00000400    /* Packet Split descriptor */
+#define E1000_RCTL_RDMTS_HALF     0x00000000    /* rx desc min thresh size */
+#define E1000_RCTL_RDMTS_QUAT     0x00000100    /* rx desc min thresh size */
+#define E1000_RCTL_RDMTS_EIGTH    0x00000200    /* rx desc min thresh size */
+#define E1000_RCTL_MO_SHIFT       12            /* multicast offset shift */
+#define E1000_RCTL_MO_0           0x00000000    /* multicast offset 11:0 */
+#define E1000_RCTL_MO_1           0x00001000    /* multicast offset 12:1 */
+#define E1000_RCTL_MO_2           0x00002000    /* multicast offset 13:2 */
+#define E1000_RCTL_MO_3           0x00003000    /* multicast offset 15:4 */
+#define E1000_RCTL_MDR            0x00004000    /* multicast desc ring 0 */
+#define E1000_RCTL_BAM            0x00008000    /* broadcast enable */
+/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
+#define E1000_RCTL_SZ_2048        0x00000000    /* rx buffer size 2048 */
+#define E1000_RCTL_SZ_1024        0x00010000    /* rx buffer size 1024 */
+#define E1000_RCTL_SZ_512         0x00020000    /* rx buffer size 512 */
+#define E1000_RCTL_SZ_256         0x00030000    /* rx buffer size 256 */
+/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
+#define E1000_RCTL_SZ_16384       0x00010000    /* rx buffer size 16384 */
+#define E1000_RCTL_SZ_8192        0x00020000    /* rx buffer size 8192 */
+#define E1000_RCTL_SZ_4096        0x00030000    /* rx buffer size 4096 */
+#define E1000_RCTL_VFE            0x00040000    /* vlan filter enable */
+#define E1000_RCTL_CFIEN          0x00080000    /* canonical form enable */
+#define E1000_RCTL_CFI            0x00100000    /* canonical form indicator */
+#define E1000_RCTL_DPF            0x00400000    /* discard pause frames */
+#define E1000_RCTL_PMCF           0x00800000    /* pass MAC control frames */
+#define E1000_RCTL_BSEX           0x02000000    /* Buffer size extension */
+#define E1000_RCTL_SECRC          0x04000000    /* Strip Ethernet CRC */
+#define E1000_RCTL_FLXBUF_MASK    0x78000000    /* Flexible buffer size */
+#define E1000_RCTL_FLXBUF_SHIFT   27            /* Flexible buffer shift */
+
+/*
+ * Use byte values for the following shift parameters
+ * Usage:
+ *     psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) &
+ *                  E1000_PSRCTL_BSIZE0_MASK) |
+ *                ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) &
+ *                  E1000_PSRCTL_BSIZE1_MASK) |
+ *                ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) &
+ *                  E1000_PSRCTL_BSIZE2_MASK) |
+ *                ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |;
+ *                  E1000_PSRCTL_BSIZE3_MASK))
+ * where value0 = [128..16256],  default=256
+ *       value1 = [1024..64512], default=4096
+ *       value2 = [0..64512],    default=4096
+ *       value3 = [0..64512],    default=0
+ */
+
+#define E1000_PSRCTL_BSIZE0_MASK   0x0000007F
+#define E1000_PSRCTL_BSIZE1_MASK   0x00003F00
+#define E1000_PSRCTL_BSIZE2_MASK   0x003F0000
+#define E1000_PSRCTL_BSIZE3_MASK   0x3F000000
+
+#define E1000_PSRCTL_BSIZE0_SHIFT  7            /* Shift _right_ 7 */
+#define E1000_PSRCTL_BSIZE1_SHIFT  2            /* Shift _right_ 2 */
+#define E1000_PSRCTL_BSIZE2_SHIFT  6            /* Shift _left_ 6 */
+#define E1000_PSRCTL_BSIZE3_SHIFT 14            /* Shift _left_ 14 */
+
+/* SWFW_SYNC Definitions */
+#define E1000_SWFW_EEP_SM   0x01
+#define E1000_SWFW_PHY0_SM  0x02
+#define E1000_SWFW_PHY1_SM  0x04
+#define E1000_SWFW_CSR_SM   0x08
+
+/* FACTPS Definitions */
+#define E1000_FACTPS_LFS    0x40000000  /* LAN Function Select */
+/* Device Control */
+#define E1000_CTRL_FD       0x00000001  /* Full duplex.0=half; 1=full */
+#define E1000_CTRL_BEM      0x00000002  /* Endian Mode.0=little,1=big */
+#define E1000_CTRL_PRIOR    0x00000004  /* Priority on PCI. 0=rx,1=fair */
+#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master reqs */
+#define E1000_CTRL_LRST     0x00000008  /* Link reset. 0=normal,1=reset */
+#define E1000_CTRL_TME      0x00000010  /* Test mode. 0=normal,1=test */
+#define E1000_CTRL_SLE      0x00000020  /* Serial Link on 0=dis,1=en */
+#define E1000_CTRL_ASDE     0x00000020  /* Auto-speed detect enable */
+#define E1000_CTRL_SLU      0x00000040  /* Set link up (Force Link) */
+#define E1000_CTRL_ILOS     0x00000080  /* Invert Loss-Of Signal */
+#define E1000_CTRL_SPD_SEL  0x00000300  /* Speed Select Mask */
+#define E1000_CTRL_SPD_10   0x00000000  /* Force 10Mb */
+#define E1000_CTRL_SPD_100  0x00000100  /* Force 100Mb */
+#define E1000_CTRL_SPD_1000 0x00000200  /* Force 1Gb */
+#define E1000_CTRL_BEM32    0x00000400  /* Big Endian 32 mode */
+#define E1000_CTRL_FRCSPD   0x00000800  /* Force Speed */
+#define E1000_CTRL_FRCDPX   0x00001000  /* Force Duplex */
+#define E1000_CTRL_D_UD_EN  0x00002000  /* Dock/Undock enable */
+#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock
+                                             * indication in SDP[0] */
+#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through
+                                               * PHYRST_N pin */
+#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external
+                                           * LINK_0 and LINK_1 pins */
+#define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
+#define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
+#define E1000_CTRL_SWDPIN2  0x00100000  /* SWDPIN 2 value */
+#define E1000_CTRL_SWDPIN3  0x00200000  /* SWDPIN 3 value */
+#define E1000_CTRL_SWDPIO0  0x00400000  /* SWDPIN 0 Input or output */
+#define E1000_CTRL_SWDPIO1  0x00800000  /* SWDPIN 1 input or output */
+#define E1000_CTRL_SWDPIO2  0x01000000  /* SWDPIN 2 input or output */
+#define E1000_CTRL_SWDPIO3  0x02000000  /* SWDPIN 3 input or output */
+#define E1000_CTRL_RST      0x04000000  /* Global reset */
+#define E1000_CTRL_RFCE     0x08000000  /* Receive Flow Control enable */
+#define E1000_CTRL_TFCE     0x10000000  /* Transmit flow control enable */
+#define E1000_CTRL_RTE      0x20000000  /* Routing tag enable */
+#define E1000_CTRL_VME      0x40000000  /* IEEE VLAN mode enable */
+#define E1000_CTRL_PHY_RST  0x80000000  /* PHY Reset */
+#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to ME */
+#define E1000_CTRL_I2C_ENA  0x02000000  /* I2C enable */
+
+/*
+ * Bit definitions for the Management Data IO (MDIO) and Management Data
+ * Clock (MDC) pins in the Device Control Register.
+ */
+#define E1000_CTRL_PHY_RESET_DIR  E1000_CTRL_SWDPIO0
+#define E1000_CTRL_PHY_RESET      E1000_CTRL_SWDPIN0
+#define E1000_CTRL_MDIO_DIR       E1000_CTRL_SWDPIO2
+#define E1000_CTRL_MDIO           E1000_CTRL_SWDPIN2
+#define E1000_CTRL_MDC_DIR        E1000_CTRL_SWDPIO3
+#define E1000_CTRL_MDC            E1000_CTRL_SWDPIN3
+#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR
+#define E1000_CTRL_PHY_RESET4     E1000_CTRL_EXT_SDP4_DATA
+
+#define E1000_CONNSW_ENRGSRC             0x4
+#define E1000_PCS_CFG_PCS_EN             8
+#define E1000_PCS_LCTL_FLV_LINK_UP       1
+#define E1000_PCS_LCTL_FSV_10            0
+#define E1000_PCS_LCTL_FSV_100           2
+#define E1000_PCS_LCTL_FSV_1000          4
+#define E1000_PCS_LCTL_FDV_FULL          8
+#define E1000_PCS_LCTL_FSD               0x10
+#define E1000_PCS_LCTL_FORCE_LINK        0x20
+#define E1000_PCS_LCTL_LOW_LINK_LATCH    0x40
+#define E1000_PCS_LCTL_FORCE_FCTRL       0x80
+#define E1000_PCS_LCTL_AN_ENABLE         0x10000
+#define E1000_PCS_LCTL_AN_RESTART        0x20000
+#define E1000_PCS_LCTL_AN_TIMEOUT        0x40000
+#define E1000_PCS_LCTL_AN_SGMII_BYPASS   0x80000
+#define E1000_PCS_LCTL_AN_SGMII_TRIGGER  0x100000
+#define E1000_PCS_LCTL_FAST_LINK_TIMER   0x1000000
+#define E1000_PCS_LCTL_LINK_OK_FIX       0x2000000
+#define E1000_PCS_LCTL_CRS_ON_NI         0x4000000
+#define E1000_ENABLE_SERDES_LOOPBACK     0x0410
+
+#define E1000_PCS_LSTS_LINK_OK           1
+#define E1000_PCS_LSTS_SPEED_10          0
+#define E1000_PCS_LSTS_SPEED_100         2
+#define E1000_PCS_LSTS_SPEED_1000        4
+#define E1000_PCS_LSTS_DUPLEX_FULL       8
+#define E1000_PCS_LSTS_SYNK_OK           0x10
+#define E1000_PCS_LSTS_AN_COMPLETE       0x10000
+#define E1000_PCS_LSTS_AN_PAGE_RX        0x20000
+#define E1000_PCS_LSTS_AN_TIMED_OUT      0x40000
+#define E1000_PCS_LSTS_AN_REMOTE_FAULT   0x80000
+#define E1000_PCS_LSTS_AN_ERROR_RWS      0x100000
+
+/* Device Status */
+#define E1000_STATUS_FD         0x00000001      /* Full duplex.0=half,1=full */
+#define E1000_STATUS_LU         0x00000002      /* Link up.0=no,1=link */
+#define E1000_STATUS_FUNC_MASK  0x0000000C      /* PCI Function Mask */
+#define E1000_STATUS_FUNC_SHIFT 2
+#define E1000_STATUS_FUNC_0     0x00000000      /* Function 0 */
+#define E1000_STATUS_FUNC_1     0x00000004      /* Function 1 */
+#define E1000_STATUS_TXOFF      0x00000010      /* transmission paused */
+#define E1000_STATUS_TBIMODE    0x00000020      /* TBI mode */
+#define E1000_STATUS_SPEED_MASK 0x000000C0
+#define E1000_STATUS_SPEED_10   0x00000000      /* Speed 10Mb/s */
+#define E1000_STATUS_SPEED_100  0x00000040      /* Speed 100Mb/s */
+#define E1000_STATUS_SPEED_1000 0x00000080      /* Speed 1000Mb/s */
+#define E1000_STATUS_LAN_INIT_DONE 0x00000200  /* Lan Init Completion by NVM */
+#define E1000_STATUS_ASDV       0x00000300      /* Auto speed detect value */
+#define E1000_STATUS_PHYRA      0x00000400      /* PHY Reset Asserted */
+#define E1000_STATUS_DOCK_CI    0x00000800      /* Change in Dock/Undock state.
+                                                 * Clear on write '0'. */
+#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master request status */
+#define E1000_STATUS_MTXCKOK    0x00000400      /* MTX clock running OK */
+#define E1000_STATUS_PCI66      0x00000800      /* In 66Mhz slot */
+#define E1000_STATUS_BUS64      0x00001000      /* In 64 bit slot */
+#define E1000_STATUS_PCIX_MODE  0x00002000      /* PCI-X mode */
+#define E1000_STATUS_PCIX_SPEED 0x0000C000      /* PCI-X bus speed */
+#define E1000_STATUS_BMC_SKU_0  0x00100000 /* BMC USB redirect disabled */
+#define E1000_STATUS_BMC_SKU_1  0x00200000 /* BMC SRAM disabled */
+#define E1000_STATUS_BMC_SKU_2  0x00400000 /* BMC SDRAM disabled */
+#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */
+#define E1000_STATUS_BMC_LITE   0x01000000 /* BMC external code execution
+                                            * disabled */
+#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */
+#define E1000_STATUS_FUSE_8       0x04000000
+#define E1000_STATUS_FUSE_9       0x08000000
+#define E1000_STATUS_SERDES0_DIS  0x10000000 /* SERDES disabled on port 0 */
+#define E1000_STATUS_SERDES1_DIS  0x20000000 /* SERDES disabled on port 1 */
+
+/* Constants used to interpret the masked PCI-X bus speed. */
+#define E1000_STATUS_PCIX_SPEED_66  0x00000000 /* PCI-X bus speed 50-66 MHz */
+#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */
+#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /*PCI-X bus speed 100-133 MHz*/
+
+#define SPEED_10    10
+#define SPEED_100   100
+#define SPEED_1000  1000
+#define HALF_DUPLEX 1
+#define FULL_DUPLEX 2
+
+#define PHY_FORCE_TIME   20
+
+#define ADVERTISE_10_HALF                 0x0001
+#define ADVERTISE_10_FULL                 0x0002
+#define ADVERTISE_100_HALF                0x0004
+#define ADVERTISE_100_FULL                0x0008
+#define ADVERTISE_1000_HALF               0x0010 /* Not used, just FYI */
+#define ADVERTISE_1000_FULL               0x0020
+
+/* 1000/H is not supported, nor spec-compliant. */
+#define E1000_ALL_SPEED_DUPLEX  (ADVERTISE_10_HALF |   ADVERTISE_10_FULL | \
+                                ADVERTISE_100_HALF |  ADVERTISE_100_FULL | \
+                                                     ADVERTISE_1000_FULL)
+#define E1000_ALL_NOT_GIG       (ADVERTISE_10_HALF |   ADVERTISE_10_FULL | \
+                                ADVERTISE_100_HALF |  ADVERTISE_100_FULL)
+#define E1000_ALL_100_SPEED    (ADVERTISE_100_HALF |  ADVERTISE_100_FULL)
+#define E1000_ALL_10_SPEED      (ADVERTISE_10_HALF |   ADVERTISE_10_FULL)
+#define E1000_ALL_FULL_DUPLEX   (ADVERTISE_10_FULL |  ADVERTISE_100_FULL | \
+                                                     ADVERTISE_1000_FULL)
+#define E1000_ALL_HALF_DUPLEX   (ADVERTISE_10_HALF |  ADVERTISE_100_HALF)
+
+#define AUTONEG_ADVERTISE_SPEED_DEFAULT   E1000_ALL_SPEED_DUPLEX
+
+/* LED Control */
+#define E1000_LEDCTL_LED0_MODE_MASK       0x0000000F
+#define E1000_LEDCTL_LED0_MODE_SHIFT      0
+#define E1000_LEDCTL_LED0_BLINK_RATE      0x00000020
+#define E1000_LEDCTL_LED0_IVRT            0x00000040
+#define E1000_LEDCTL_LED0_BLINK           0x00000080
+#define E1000_LEDCTL_LED1_MODE_MASK       0x00000F00
+#define E1000_LEDCTL_LED1_MODE_SHIFT      8
+#define E1000_LEDCTL_LED1_BLINK_RATE      0x00002000
+#define E1000_LEDCTL_LED1_IVRT            0x00004000
+#define E1000_LEDCTL_LED1_BLINK           0x00008000
+#define E1000_LEDCTL_LED2_MODE_MASK       0x000F0000
+#define E1000_LEDCTL_LED2_MODE_SHIFT      16
+#define E1000_LEDCTL_LED2_BLINK_RATE      0x00200000
+#define E1000_LEDCTL_LED2_IVRT            0x00400000
+#define E1000_LEDCTL_LED2_BLINK           0x00800000
+#define E1000_LEDCTL_LED3_MODE_MASK       0x0F000000
+#define E1000_LEDCTL_LED3_MODE_SHIFT      24
+#define E1000_LEDCTL_LED3_BLINK_RATE      0x20000000
+#define E1000_LEDCTL_LED3_IVRT            0x40000000
+#define E1000_LEDCTL_LED3_BLINK           0x80000000
+
+#define E1000_LEDCTL_MODE_LINK_10_1000  0x0
+#define E1000_LEDCTL_MODE_LINK_100_1000 0x1
+#define E1000_LEDCTL_MODE_LINK_UP       0x2
+#define E1000_LEDCTL_MODE_ACTIVITY      0x3
+#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4
+#define E1000_LEDCTL_MODE_LINK_10       0x5
+#define E1000_LEDCTL_MODE_LINK_100      0x6
+#define E1000_LEDCTL_MODE_LINK_1000     0x7
+#define E1000_LEDCTL_MODE_PCIX_MODE     0x8
+#define E1000_LEDCTL_MODE_FULL_DUPLEX   0x9
+#define E1000_LEDCTL_MODE_COLLISION     0xA
+#define E1000_LEDCTL_MODE_BUS_SPEED     0xB
+#define E1000_LEDCTL_MODE_BUS_SIZE      0xC
+#define E1000_LEDCTL_MODE_PAUSED        0xD
+#define E1000_LEDCTL_MODE_LED_ON        0xE
+#define E1000_LEDCTL_MODE_LED_OFF       0xF
+
+/* Transmit Descriptor bit definitions */
+#define E1000_TXD_DTYP_D     0x00100000 /* Data Descriptor */
+#define E1000_TXD_DTYP_C     0x00000000 /* Context Descriptor */
+#define E1000_TXD_POPTS_SHIFT 8         /* POPTS shift */
+#define E1000_TXD_POPTS_IXSM 0x01       /* Insert IP checksum */
+#define E1000_TXD_POPTS_TXSM 0x02       /* Insert TCP/UDP checksum */
+#define E1000_TXD_CMD_EOP    0x01000000 /* End of Packet */
+#define E1000_TXD_CMD_IFCS   0x02000000 /* Insert FCS (Ethernet CRC) */
+#define E1000_TXD_CMD_IC     0x04000000 /* Insert Checksum */
+#define E1000_TXD_CMD_RS     0x08000000 /* Report Status */
+#define E1000_TXD_CMD_RPS    0x10000000 /* Report Packet Sent */
+#define E1000_TXD_CMD_DEXT   0x20000000 /* Descriptor extension (0 = legacy) */
+#define E1000_TXD_CMD_VLE    0x40000000 /* Add VLAN tag */
+#define E1000_TXD_CMD_IDE    0x80000000 /* Enable Tidv register */
+#define E1000_TXD_STAT_DD    0x00000001 /* Descriptor Done */
+#define E1000_TXD_STAT_EC    0x00000002 /* Excess Collisions */
+#define E1000_TXD_STAT_LC    0x00000004 /* Late Collisions */
+#define E1000_TXD_STAT_TU    0x00000008 /* Transmit underrun */
+#define E1000_TXD_CMD_TCP    0x01000000 /* TCP packet */
+#define E1000_TXD_CMD_IP     0x02000000 /* IP packet */
+#define E1000_TXD_CMD_TSE    0x04000000 /* TCP Seg enable */
+#define E1000_TXD_STAT_TC    0x00000004 /* Tx Underrun */
+/* Extended desc bits for Linksec and timesync */
+
+/* Transmit Control */
+#define E1000_TCTL_RST    0x00000001    /* software reset */
+#define E1000_TCTL_EN     0x00000002    /* enable tx */
+#define E1000_TCTL_BCE    0x00000004    /* busy check enable */
+#define E1000_TCTL_PSP    0x00000008    /* pad short packets */
+#define E1000_TCTL_CT     0x00000ff0    /* collision threshold */
+#define E1000_TCTL_COLD   0x003ff000    /* collision distance */
+#define E1000_TCTL_SWXOFF 0x00400000    /* SW Xoff transmission */
+#define E1000_TCTL_PBE    0x00800000    /* Packet Burst Enable */
+#define E1000_TCTL_RTLC   0x01000000    /* Re-transmit on late collision */
+#define E1000_TCTL_NRTU   0x02000000    /* No Re-transmit on underrun */
+#define E1000_TCTL_MULR   0x10000000    /* Multiple request support */
+
+/* Transmit Arbitration Count */
+#define E1000_TARC0_ENABLE     0x00000400   /* Enable Tx Queue 0 */
+
+/* SerDes Control */
+#define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400
+
+/* Receive Checksum Control */
+#define E1000_RXCSUM_PCSS_MASK 0x000000FF   /* Packet Checksum Start */
+#define E1000_RXCSUM_IPOFL     0x00000100   /* IPv4 checksum offload */
+#define E1000_RXCSUM_TUOFL     0x00000200   /* TCP / UDP checksum offload */
+#define E1000_RXCSUM_IPV6OFL   0x00000400   /* IPv6 checksum offload */
+#define E1000_RXCSUM_CRCOFL    0x00000800   /* CRC32 offload enable */
+#define E1000_RXCSUM_IPPCSE    0x00001000   /* IP payload checksum enable */
+#define E1000_RXCSUM_PCSD      0x00002000   /* packet checksum disabled */
+
+/* Header split receive */
+#define E1000_RFCTL_ISCSI_DIS           0x00000001
+#define E1000_RFCTL_ISCSI_DWC_MASK      0x0000003E
+#define E1000_RFCTL_ISCSI_DWC_SHIFT     1
+#define E1000_RFCTL_NFSW_DIS            0x00000040
+#define E1000_RFCTL_NFSR_DIS            0x00000080
+#define E1000_RFCTL_NFS_VER_MASK        0x00000300
+#define E1000_RFCTL_NFS_VER_SHIFT       8
+#define E1000_RFCTL_IPV6_DIS            0x00000400
+#define E1000_RFCTL_IPV6_XSUM_DIS       0x00000800
+#define E1000_RFCTL_ACK_DIS             0x00001000
+#define E1000_RFCTL_ACKD_DIS            0x00002000
+#define E1000_RFCTL_IPFRSP_DIS          0x00004000
+#define E1000_RFCTL_EXTEN               0x00008000
+#define E1000_RFCTL_IPV6_EX_DIS         0x00010000
+#define E1000_RFCTL_NEW_IPV6_EXT_DIS    0x00020000
+#define E1000_RFCTL_LEF                 0x00040000
+
+/* Collision related configuration parameters */
+#define E1000_COLLISION_THRESHOLD       15
+#define E1000_CT_SHIFT                  4
+#define E1000_COLLISION_DISTANCE        63
+#define E1000_COLD_SHIFT                12
+
+/* Default values for the transmit IPG register */
+#define DEFAULT_82542_TIPG_IPGT        10
+#define DEFAULT_82543_TIPG_IPGT_FIBER  9
+#define DEFAULT_82543_TIPG_IPGT_COPPER 8
+
+#define E1000_TIPG_IPGT_MASK  0x000003FF
+#define E1000_TIPG_IPGR1_MASK 0x000FFC00
+#define E1000_TIPG_IPGR2_MASK 0x3FF00000
+
+#define DEFAULT_82542_TIPG_IPGR1 2
+#define DEFAULT_82543_TIPG_IPGR1 8
+#define E1000_TIPG_IPGR1_SHIFT  10
+
+#define DEFAULT_82542_TIPG_IPGR2 10
+#define DEFAULT_82543_TIPG_IPGR2 6
+#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7
+#define E1000_TIPG_IPGR2_SHIFT  20
+
+/* Ethertype field values */
+#define ETHERNET_IEEE_VLAN_TYPE 0x8100  /* 802.3ac packet */
+
+#define ETHERNET_FCS_SIZE       4
+#define MAX_JUMBO_FRAME_SIZE    0x3F00
+
+/* Extended Configuration Control and Size */
+#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP      0x00000020
+#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE       0x00000001
+#define E1000_EXTCNF_CTRL_SWFLAG                 0x00000020
+#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK   0x00FF0000
+#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT          16
+#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK   0x0FFF0000
+#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT          16
+
+#define E1000_PHY_CTRL_SPD_EN             0x00000001
+#define E1000_PHY_CTRL_D0A_LPLU           0x00000002
+#define E1000_PHY_CTRL_NOND0A_LPLU        0x00000004
+#define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008
+#define E1000_PHY_CTRL_GBE_DISABLE        0x00000040
+
+#define E1000_KABGTXD_BGSQLBIAS           0x00050000
+
+/* PBA constants */
+#define E1000_PBA_6K  0x0006    /* 6KB */
+#define E1000_PBA_8K  0x0008    /* 8KB */
+#define E1000_PBA_10K 0x000A    /* 10KB */
+#define E1000_PBA_12K 0x000C    /* 12KB */
+#define E1000_PBA_14K 0x000E    /* 14KB */
+#define E1000_PBA_16K 0x0010    /* 16KB */
+#define E1000_PBA_18K 0x0012
+#define E1000_PBA_20K 0x0014
+#define E1000_PBA_22K 0x0016
+#define E1000_PBA_24K 0x0018
+#define E1000_PBA_26K 0x001A
+#define E1000_PBA_30K 0x001E
+#define E1000_PBA_32K 0x0020
+#define E1000_PBA_34K 0x0022
+#define E1000_PBA_35K 0x0023
+#define E1000_PBA_38K 0x0026
+#define E1000_PBA_40K 0x0028
+#define E1000_PBA_48K 0x0030    /* 48KB */
+#define E1000_PBA_64K 0x0040    /* 64KB */
+
+#define E1000_PBS_16K E1000_PBA_16K
+#define E1000_PBS_24K E1000_PBA_24K
+
+#define IFS_MAX       80
+#define IFS_MIN       40
+#define IFS_RATIO     4
+#define IFS_STEP      10
+#define MIN_NUM_XMITS 1000
+
+/* SW Semaphore Register */
+#define E1000_SWSM_SMBI         0x00000001 /* Driver Semaphore bit */
+#define E1000_SWSM_SWESMBI      0x00000002 /* FW Semaphore bit */
+#define E1000_SWSM_WMNG         0x00000004 /* Wake MNG Clock */
+#define E1000_SWSM_DRV_LOAD     0x00000008 /* Driver Loaded Bit */
+
+#define E1000_SWSM2_LOCK        0x00000002 /* Secondary driver semaphore bit */
+
+/* Interrupt Cause Read */
+#define E1000_ICR_TXDW          0x00000001 /* Transmit desc written back */
+#define E1000_ICR_TXQE          0x00000002 /* Transmit Queue empty */
+#define E1000_ICR_LSC           0x00000004 /* Link Status Change */
+#define E1000_ICR_RXSEQ         0x00000008 /* rx sequence error */
+#define E1000_ICR_RXDMT0        0x00000010 /* rx desc min. threshold (0) */
+#define E1000_ICR_RXO           0x00000040 /* rx overrun */
+#define E1000_ICR_RXT0          0x00000080 /* rx timer intr (ring 0) */
+#define E1000_ICR_VMMB          0x00000100 /* VM MB event */
+#define E1000_ICR_MDAC          0x00000200 /* MDIO access complete */
+#define E1000_ICR_RXCFG         0x00000400 /* Rx /c/ ordered set */
+#define E1000_ICR_GPI_EN0       0x00000800 /* GP Int 0 */
+#define E1000_ICR_GPI_EN1       0x00001000 /* GP Int 1 */
+#define E1000_ICR_GPI_EN2       0x00002000 /* GP Int 2 */
+#define E1000_ICR_GPI_EN3       0x00004000 /* GP Int 3 */
+#define E1000_ICR_TXD_LOW       0x00008000
+#define E1000_ICR_SRPD          0x00010000
+#define E1000_ICR_ACK           0x00020000 /* Receive Ack frame */
+#define E1000_ICR_MNG           0x00040000 /* Manageability event */
+#define E1000_ICR_DOCK          0x00080000 /* Dock/Undock */
+#define E1000_ICR_INT_ASSERTED  0x80000000 /* If this bit asserted, the driver
+                                            * should claim the interrupt */
+#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* Q0 Rx desc FIFO parity error */
+#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* Q0 Tx desc FIFO parity error */
+#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity err */
+#define E1000_ICR_PB_PAR        0x00800000 /* packet buffer parity error */
+#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* Q1 Rx desc FIFO parity error */
+#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* Q1 Tx desc FIFO parity error */
+#define E1000_ICR_ALL_PARITY    0x03F00000 /* all parity error bits */
+#define E1000_ICR_DSW           0x00000020 /* FW changed the status of DISSW
+                                            * bit in the FWSM */
+#define E1000_ICR_PHYINT        0x00001000 /* LAN connected device generates
+                                            * an interrupt */
+#define E1000_ICR_DOUTSYNC      0x10000000 /* NIC DMA out of sync */
+#define E1000_ICR_EPRST         0x00100000 /* ME hardware reset occurs */
+
+
+/*
+ * This defines the bits that are set in the Interrupt Mask
+ * Set/Read Register.  Each bit is documented below:
+ *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
+ *   o RXSEQ  = Receive Sequence Error
+ */
+#define POLL_IMS_ENABLE_MASK ( \
+    E1000_IMS_RXDMT0 |    \
+    E1000_IMS_RXSEQ)
+
+/*
+ * This defines the bits that are set in the Interrupt Mask
+ * Set/Read Register.  Each bit is documented below:
+ *   o RXT0   = Receiver Timer Interrupt (ring 0)
+ *   o TXDW   = Transmit Descriptor Written Back
+ *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
+ *   o RXSEQ  = Receive Sequence Error
+ *   o LSC    = Link Status Change
+ */
+#define IMS_ENABLE_MASK ( \
+    E1000_IMS_RXT0   |    \
+    E1000_IMS_TXDW   |    \
+    E1000_IMS_RXDMT0 |    \
+    E1000_IMS_RXSEQ  |    \
+    E1000_IMS_LSC)
+
+/* Interrupt Mask Set */
+#define E1000_IMS_TXDW      E1000_ICR_TXDW      /* Tx desc written back */
+#define E1000_IMS_TXQE      E1000_ICR_TXQE      /* Transmit Queue empty */
+#define E1000_IMS_LSC       E1000_ICR_LSC       /* Link Status Change */
+#define E1000_IMS_VMMB      E1000_ICR_VMMB      /* Mail box activity */
+#define E1000_IMS_RXSEQ     E1000_ICR_RXSEQ     /* rx sequence error */
+#define E1000_IMS_RXDMT0    E1000_ICR_RXDMT0    /* rx desc min. threshold */
+#define E1000_IMS_RXO       E1000_ICR_RXO       /* rx overrun */
+#define E1000_IMS_RXT0      E1000_ICR_RXT0      /* rx timer intr */
+#define E1000_IMS_MDAC      E1000_ICR_MDAC      /* MDIO access complete */
+#define E1000_IMS_RXCFG     E1000_ICR_RXCFG     /* Rx /c/ ordered set */
+#define E1000_IMS_GPI_EN0   E1000_ICR_GPI_EN0   /* GP Int 0 */
+#define E1000_IMS_GPI_EN1   E1000_ICR_GPI_EN1   /* GP Int 1 */
+#define E1000_IMS_GPI_EN2   E1000_ICR_GPI_EN2   /* GP Int 2 */
+#define E1000_IMS_GPI_EN3   E1000_ICR_GPI_EN3   /* GP Int 3 */
+#define E1000_IMS_TXD_LOW   E1000_ICR_TXD_LOW
+#define E1000_IMS_SRPD      E1000_ICR_SRPD
+#define E1000_IMS_ACK       E1000_ICR_ACK       /* Receive Ack frame */
+#define E1000_IMS_MNG       E1000_ICR_MNG       /* Manageability event */
+#define E1000_IMS_DOCK      E1000_ICR_DOCK      /* Dock/Undock */
+#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* Q0 Rx desc FIFO
+                                                         * parity error */
+#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* Q0 Tx desc FIFO
+                                                         * parity error */
+#define E1000_IMS_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR  /* host arb read buffer
+                                                         * parity error */
+#define E1000_IMS_PB_PAR        E1000_ICR_PB_PAR        /* packet buffer parity
+                                                         * error */
+#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* Q1 Rx desc FIFO
+                                                         * parity error */
+#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* Q1 Tx desc FIFO
+                                                         * parity error */
+#define E1000_IMS_DSW       E1000_ICR_DSW
+#define E1000_IMS_PHYINT    E1000_ICR_PHYINT
+#define E1000_IMS_DOUTSYNC  E1000_ICR_DOUTSYNC /* NIC DMA out of sync */
+#define E1000_IMS_EPRST     E1000_ICR_EPRST
+
+/* Interrupt Cause Set */
+#define E1000_ICS_TXDW      E1000_ICR_TXDW      /* Tx desc written back */
+#define E1000_ICS_TXQE      E1000_ICR_TXQE      /* Transmit Queue empty */
+#define E1000_ICS_LSC       E1000_ICR_LSC       /* Link Status Change */
+#define E1000_ICS_RXSEQ     E1000_ICR_RXSEQ     /* rx sequence error */
+#define E1000_ICS_RXDMT0    E1000_ICR_RXDMT0    /* rx desc min. threshold */
+#define E1000_ICS_RXO       E1000_ICR_RXO       /* rx overrun */
+#define E1000_ICS_RXT0      E1000_ICR_RXT0      /* rx timer intr */
+#define E1000_ICS_MDAC      E1000_ICR_MDAC      /* MDIO access complete */
+#define E1000_ICS_RXCFG     E1000_ICR_RXCFG     /* Rx /c/ ordered set */
+#define E1000_ICS_GPI_EN0   E1000_ICR_GPI_EN0   /* GP Int 0 */
+#define E1000_ICS_GPI_EN1   E1000_ICR_GPI_EN1   /* GP Int 1 */
+#define E1000_ICS_GPI_EN2   E1000_ICR_GPI_EN2   /* GP Int 2 */
+#define E1000_ICS_GPI_EN3   E1000_ICR_GPI_EN3   /* GP Int 3 */
+#define E1000_ICS_TXD_LOW   E1000_ICR_TXD_LOW
+#define E1000_ICS_SRPD      E1000_ICR_SRPD
+#define E1000_ICS_ACK       E1000_ICR_ACK       /* Receive Ack frame */
+#define E1000_ICS_MNG       E1000_ICR_MNG       /* Manageability event */
+#define E1000_ICS_DOCK      E1000_ICR_DOCK      /* Dock/Undock */
+#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* Q0 Rx desc FIFO
+                                                         * parity error */
+#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* Q0 Tx desc FIFO
+                                                         * parity error */
+#define E1000_ICS_HOST_ARB_PAR  E1000_ICR_HOST_ARB_PAR  /* host arb read buffer
+                                                         * parity error */
+#define E1000_ICS_PB_PAR        E1000_ICR_PB_PAR        /* packet buffer parity
+                                                         * error */
+#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* Q1 Rx desc FIFO
+                                                         * parity error */
+#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* Q1 Tx desc FIFO
+                                                         * parity error */
+#define E1000_ICS_DSW       E1000_ICR_DSW
+#define E1000_ICS_DOUTSYNC  E1000_ICR_DOUTSYNC /* NIC DMA out of sync */
+#define E1000_ICS_PHYINT    E1000_ICR_PHYINT
+#define E1000_ICS_EPRST     E1000_ICR_EPRST
+
+/* Transmit Descriptor Control */
+#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
+#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */
+#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
+#define E1000_TXDCTL_GRAN    0x01000000 /* TXDCTL Granularity */
+#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
+#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
+#define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */
+/* Enable the counting of descriptors still to be processed. */
+#define E1000_TXDCTL_COUNT_DESC 0x00400000
+
+/* Flow Control Constants */
+#define FLOW_CONTROL_ADDRESS_LOW  0x00C28001
+#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
+#define FLOW_CONTROL_TYPE         0x8808
+
+/* 802.1q VLAN Packet Size */
+#define VLAN_TAG_SIZE              4    /* 802.3ac tag (not DMA'd) */
+#define E1000_VLAN_FILTER_TBL_SIZE 128  /* VLAN Filter Table (4096 bits) */
+
+/* Receive Address */
+/*
+ * Number of high/low register pairs in the RAR. The RAR (Receive Address
+ * Registers) holds the directed and multicast addresses that we monitor.
+ * Technically, we have 16 spots.  However, we reserve one of these spots
+ * (RAR[15]) for our directed address used by controllers with
+ * manageability enabled, allowing us room for 15 multicast addresses.
+ */
+#define E1000_RAR_ENTRIES     15
+#define E1000_RAH_AV  0x80000000        /* Receive descriptor valid */
+#define E1000_RAL_MAC_ADDR_LEN 4
+#define E1000_RAH_MAC_ADDR_LEN 2
+#define E1000_RAH_POOL_MASK 0x03FC0000
+#define E1000_RAH_POOL_1 0x00040000
+
+/* Error Codes */
+#define E1000_SUCCESS      0
+#define E1000_ERR_NVM      1
+#define E1000_ERR_PHY      2
+#define E1000_ERR_CONFIG   3
+#define E1000_ERR_PARAM    4
+#define E1000_ERR_MAC_INIT 5
+#define E1000_ERR_PHY_TYPE 6
+#define E1000_ERR_RESET   9
+#define E1000_ERR_MASTER_REQUESTS_PENDING 10
+#define E1000_ERR_HOST_INTERFACE_COMMAND 11
+#define E1000_BLK_PHY_RESET   12
+#define E1000_ERR_SWFW_SYNC 13
+#define E1000_NOT_IMPLEMENTED 14
+#define E1000_ERR_MBX      15
+
+/* Loop limit on how long we wait for auto-negotiation to complete */
+#define FIBER_LINK_UP_LIMIT               50
+#define COPPER_LINK_UP_LIMIT              10
+#define PHY_AUTO_NEG_LIMIT                45
+#define PHY_FORCE_LIMIT                   20
+/* Number of 100 microseconds we wait for PCI Express master disable */
+#define MASTER_DISABLE_TIMEOUT      800
+/* Number of milliseconds we wait for PHY configuration done after MAC reset */
+#define PHY_CFG_TIMEOUT             100
+/* Number of 2 milliseconds we wait for acquiring MDIO ownership. */
+#define MDIO_OWNERSHIP_TIMEOUT      10
+/* Number of milliseconds for NVM auto read done after MAC reset. */
+#define AUTO_READ_DONE_TIMEOUT      10
+
+/* Flow Control */
+#define E1000_FCRTH_RTH  0x0000FFF8     /* Mask Bits[15:3] for RTH */
+#define E1000_FCRTH_XFCE 0x80000000     /* External Flow Control Enable */
+#define E1000_FCRTL_RTL  0x0000FFF8     /* Mask Bits[15:3] for RTL */
+#define E1000_FCRTL_XONE 0x80000000     /* Enable XON frame transmission */
+
+/* Transmit Configuration Word */
+#define E1000_TXCW_FD         0x00000020        /* TXCW full duplex */
+#define E1000_TXCW_HD         0x00000040        /* TXCW half duplex */
+#define E1000_TXCW_PAUSE      0x00000080        /* TXCW sym pause request */
+#define E1000_TXCW_ASM_DIR    0x00000100        /* TXCW astm pause direction */
+#define E1000_TXCW_PAUSE_MASK 0x00000180        /* TXCW pause request mask */
+#define E1000_TXCW_RF         0x00003000        /* TXCW remote fault */
+#define E1000_TXCW_NP         0x00008000        /* TXCW next page */
+#define E1000_TXCW_CW         0x0000ffff        /* TxConfigWord mask */
+#define E1000_TXCW_TXC        0x40000000        /* Transmit Config control */
+#define E1000_TXCW_ANE        0x80000000        /* Auto-neg enable */
+
+/* Receive Configuration Word */
+#define E1000_RXCW_CW         0x0000ffff        /* RxConfigWord mask */
+#define E1000_RXCW_NC         0x04000000        /* Receive config no carrier */
+#define E1000_RXCW_IV         0x08000000        /* Receive config invalid */
+#define E1000_RXCW_CC         0x10000000        /* Receive config change */
+#define E1000_RXCW_C          0x20000000        /* Receive config */
+#define E1000_RXCW_SYNCH      0x40000000        /* Receive config synch */
+#define E1000_RXCW_ANC        0x80000000        /* Auto-neg complete */
+
+
+/* PCI Express Control */
+#define E1000_GCR_RXD_NO_SNOOP          0x00000001
+#define E1000_GCR_RXDSCW_NO_SNOOP       0x00000002
+#define E1000_GCR_RXDSCR_NO_SNOOP       0x00000004
+#define E1000_GCR_TXD_NO_SNOOP          0x00000008
+#define E1000_GCR_TXDSCW_NO_SNOOP       0x00000010
+#define E1000_GCR_TXDSCR_NO_SNOOP       0x00000020
+#define E1000_GCR_CMPL_TMOUT_MASK       0x0000F000
+#define E1000_GCR_CMPL_TMOUT_10ms       0x00001000
+#define E1000_GCR_CMPL_TMOUT_RESEND     0x00010000
+#define E1000_GCR_CAP_VER2              0x00040000
+
+#define PCIE_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP         | \
+                           E1000_GCR_RXDSCW_NO_SNOOP      | \
+                           E1000_GCR_RXDSCR_NO_SNOOP      | \
+                           E1000_GCR_TXD_NO_SNOOP         | \
+                           E1000_GCR_TXDSCW_NO_SNOOP      | \
+                           E1000_GCR_TXDSCR_NO_SNOOP)
+
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB 0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080  /* Collision test enable */
+#define MII_CR_FULL_DUPLEX      0x0100  /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200  /* Restart auto negotiation */
+#define MII_CR_ISOLATE          0x0400  /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN       0x0800  /* Power down */
+#define MII_CR_AUTO_NEG_EN      0x1000  /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK         0x4000  /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET            0x8000  /* 0 = normal, 1 = PHY reset */
+#define MII_CR_SPEED_1000       0x0040
+#define MII_CR_SPEED_100        0x2000
+#define MII_CR_SPEED_10         0x0000
+
+/* PHY Status Register */
+#define MII_SR_EXTENDED_CAPS     0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT     0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS       0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS      0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT      0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE  0x0020 /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS   0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS     0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS     0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS       0x0800 /* 10T   Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS       0x1000 /* 10T   Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS      0x2000 /* 100X  Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS      0x4000 /* 100X  Full Duplex Capable */
+#define MII_SR_100T4_CAPS        0x8000 /* 100T4 Capable */
+
+/* Autoneg Advertisement Register */
+#define NWAY_AR_SELECTOR_FIELD   0x0001   /* indicates IEEE 802.3 CSMA/CD */
+#define NWAY_AR_10T_HD_CAPS      0x0020   /* 10T   Half Duplex Capable */
+#define NWAY_AR_10T_FD_CAPS      0x0040   /* 10T   Full Duplex Capable */
+#define NWAY_AR_100TX_HD_CAPS    0x0080   /* 100TX Half Duplex Capable */
+#define NWAY_AR_100TX_FD_CAPS    0x0100   /* 100TX Full Duplex Capable */
+#define NWAY_AR_100T4_CAPS       0x0200   /* 100T4 Capable */
+#define NWAY_AR_PAUSE            0x0400   /* Pause operation desired */
+#define NWAY_AR_ASM_DIR          0x0800   /* Asymmetric Pause Direction bit */
+#define NWAY_AR_REMOTE_FAULT     0x2000   /* Remote Fault detected */
+#define NWAY_AR_NEXT_PAGE        0x8000   /* Next Page ability supported */
+
+/* Link Partner Ability Register (Base Page) */
+#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */
+#define NWAY_LPAR_10T_HD_CAPS    0x0020 /* LP is 10T   Half Duplex Capable */
+#define NWAY_LPAR_10T_FD_CAPS    0x0040 /* LP is 10T   Full Duplex Capable */
+#define NWAY_LPAR_100TX_HD_CAPS  0x0080 /* LP is 100TX Half Duplex Capable */
+#define NWAY_LPAR_100TX_FD_CAPS  0x0100 /* LP is 100TX Full Duplex Capable */
+#define NWAY_LPAR_100T4_CAPS     0x0200 /* LP is 100T4 Capable */
+#define NWAY_LPAR_PAUSE          0x0400 /* LP Pause operation desired */
+#define NWAY_LPAR_ASM_DIR        0x0800 /* LP Asymmetric Pause Direction bit */
+#define NWAY_LPAR_REMOTE_FAULT   0x2000 /* LP has detected Remote Fault */
+#define NWAY_LPAR_ACKNOWLEDGE    0x4000 /* LP has rx'd link code word */
+#define NWAY_LPAR_NEXT_PAGE      0x8000 /* Next Page ability supported */
+
+/* Autoneg Expansion Register */
+#define NWAY_ER_LP_NWAY_CAPS      0x0001 /* LP has Auto Neg Capability */
+#define NWAY_ER_PAGE_RXD          0x0002 /* LP is 10T   Half Duplex Capable */
+#define NWAY_ER_NEXT_PAGE_CAPS    0x0004 /* LP is 10T   Full Duplex Capable */
+#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */
+#define NWAY_ER_PAR_DETECT_FAULT  0x0010 /* LP is 100TX Full Duplex Capable */
+
+/* 1000BASE-T Control Register */
+#define CR_1000T_ASYM_PAUSE      0x0080 /* Advertise asymmetric pause bit */
+#define CR_1000T_HD_CAPS         0x0100 /* Advertise 1000T HD capability */
+#define CR_1000T_FD_CAPS         0x0200 /* Advertise 1000T FD capability  */
+#define CR_1000T_REPEATER_DTE    0x0400 /* 1=Repeater/switch device port */
+                                        /* 0=DTE device */
+#define CR_1000T_MS_VALUE        0x0800 /* 1=Configure PHY as Master */
+                                        /* 0=Configure PHY as Slave */
+#define CR_1000T_MS_ENABLE      0x1000 /* 1=Master/Slave manual config value */
+                                        /* 0=Automatic Master/Slave config */
+#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
+#define CR_1000T_TEST_MODE_1     0x2000 /* Transmit Waveform test */
+#define CR_1000T_TEST_MODE_2     0x4000 /* Master Transmit Jitter test */
+#define CR_1000T_TEST_MODE_3     0x6000 /* Slave Transmit Jitter test */
+#define CR_1000T_TEST_MODE_4     0x8000 /* Transmitter Distortion test */
+
+/* 1000BASE-T Status Register */
+#define SR_1000T_IDLE_ERROR_CNT   0x00FF /* Num idle errors since last read */
+#define SR_1000T_ASYM_PAUSE_DIR  0x0100 /* LP asymmetric pause direction bit */
+#define SR_1000T_LP_HD_CAPS       0x0400 /* LP is 1000T HD capable */
+#define SR_1000T_LP_FD_CAPS       0x0800 /* LP is 1000T FD capable */
+#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
+#define SR_1000T_LOCAL_RX_STATUS  0x2000 /* Local receiver OK */
+#define SR_1000T_MS_CONFIG_RES    0x4000 /* 1=Local Tx is Master, 0=Slave */
+#define SR_1000T_MS_CONFIG_FAULT  0x8000 /* Master/Slave config fault */
+
+#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5
+
+/* PHY 1000 MII Register/Bit Definitions */
+/* PHY Registers defined by IEEE */
+#define PHY_CONTROL      0x00 /* Control Register */
+#define PHY_STATUS       0x01 /* Status Register */
+#define PHY_ID1          0x02 /* Phy Id Reg (word 1) */
+#define PHY_ID2          0x03 /* Phy Id Reg (word 2) */
+#define PHY_AUTONEG_ADV  0x04 /* Autoneg Advertisement */
+#define PHY_LP_ABILITY   0x05 /* Link Partner Ability (Base Page) */
+#define PHY_AUTONEG_EXP  0x06 /* Autoneg Expansion Reg */
+#define PHY_NEXT_PAGE_TX 0x07 /* Next Page Tx */
+#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
+#define PHY_1000T_CTRL   0x09 /* 1000Base-T Control Reg */
+#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
+#define PHY_EXT_STATUS   0x0F /* Extended Status Reg */
+
+#define PHY_CONTROL_LB   0x4000 /* PHY Loopback bit */
+
+/* NVM Control */
+#define E1000_EECD_SK        0x00000001 /* NVM Clock */
+#define E1000_EECD_CS        0x00000002 /* NVM Chip Select */
+#define E1000_EECD_DI        0x00000004 /* NVM Data In */
+#define E1000_EECD_DO        0x00000008 /* NVM Data Out */
+#define E1000_EECD_FWE_MASK  0x00000030
+#define E1000_EECD_FWE_DIS   0x00000010 /* Disable FLASH writes */
+#define E1000_EECD_FWE_EN    0x00000020 /* Enable FLASH writes */
+#define E1000_EECD_FWE_SHIFT 4
+#define E1000_EECD_REQ       0x00000040 /* NVM Access Request */
+#define E1000_EECD_GNT       0x00000080 /* NVM Access Grant */
+#define E1000_EECD_PRES      0x00000100 /* NVM Present */
+#define E1000_EECD_SIZE      0x00000200 /* NVM Size (0=64 word 1=256 word) */
+/* NVM Addressing bits based on type 0=small, 1=large */
+#define E1000_EECD_ADDR_BITS 0x00000400
+#define E1000_EECD_TYPE      0x00002000 /* NVM Type (1-SPI, 0-Microwire) */
+#define E1000_NVM_GRANT_ATTEMPTS   1000 /* NVM # attempts to gain grant */
+#define E1000_EECD_AUTO_RD          0x00000200  /* NVM Auto Read done */
+#define E1000_EECD_SIZE_EX_MASK     0x00007800  /* NVM Size */
+#define E1000_EECD_SIZE_EX_SHIFT     11
+#define E1000_EECD_NVADDS    0x00018000 /* NVM Address Size */
+#define E1000_EECD_SELSHAD   0x00020000 /* Select Shadow RAM */
+#define E1000_EECD_INITSRAM  0x00040000 /* Initialize Shadow RAM */
+#define E1000_EECD_FLUPD     0x00080000 /* Update FLASH */
+#define E1000_EECD_AUPDEN    0x00100000 /* Enable Autonomous FLASH update */
+#define E1000_EECD_SHADV     0x00200000 /* Shadow RAM Data Valid */
+#define E1000_EECD_SEC1VAL   0x00400000 /* Sector One Valid */
+#define E1000_EECD_SECVAL_SHIFT      22
+#define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES)
+
+#define E1000_NVM_SWDPIN0   0x0001   /* SWDPIN 0 NVM Value */
+#define E1000_NVM_LED_LOGIC 0x0020   /* Led Logic Word */
+#define E1000_NVM_RW_REG_DATA   16  /* Offset to data in NVM read/write regs */
+#define E1000_NVM_RW_REG_DONE   2    /* Offset to READ/WRITE done bit */
+#define E1000_NVM_RW_REG_START  1    /* Start operation */
+#define E1000_NVM_RW_ADDR_SHIFT 2    /* Shift to the address bits */
+#define E1000_NVM_POLL_WRITE    1    /* Flag for polling for write complete */
+#define E1000_NVM_POLL_READ     0    /* Flag for polling for read complete */
+#define E1000_FLASH_UPDATES  2000
+
+/* NVM Word Offsets */
+#define NVM_COMPAT                 0x0003
+#define NVM_ID_LED_SETTINGS        0x0004
+#define NVM_VERSION                0x0005
+#define NVM_SERDES_AMPLITUDE       0x0006 /* SERDES output amplitude */
+#define NVM_PHY_CLASS_WORD         0x0007
+#define NVM_INIT_CONTROL1_REG      0x000A
+#define NVM_INIT_CONTROL2_REG      0x000F
+#define NVM_SWDEF_PINS_CTRL_PORT_1 0x0010
+#define NVM_INIT_CONTROL3_PORT_B   0x0014
+#define NVM_INIT_3GIO_3            0x001A
+#define NVM_SWDEF_PINS_CTRL_PORT_0 0x0020
+#define NVM_INIT_CONTROL3_PORT_A   0x0024
+#define NVM_CFG                    0x0012
+#define NVM_FLASH_VERSION          0x0032
+#define NVM_ALT_MAC_ADDR_PTR       0x0037
+#define NVM_CHECKSUM_REG           0x003F
+
+#define E1000_NVM_CFG_DONE_PORT_0  0x040000 /* MNG config cycle done */
+#define E1000_NVM_CFG_DONE_PORT_1  0x080000 /* ...for second port */
+
+/* Mask bits for fields in Word 0x0f of the NVM */
+#define NVM_WORD0F_PAUSE_MASK       0x3000
+#define NVM_WORD0F_PAUSE            0x1000
+#define NVM_WORD0F_ASM_DIR          0x2000
+#define NVM_WORD0F_ANE              0x0800
+#define NVM_WORD0F_SWPDIO_EXT_MASK  0x00F0
+#define NVM_WORD0F_LPLU             0x0001
+
+/* Mask bits for fields in Word 0x1a of the NVM */
+#define NVM_WORD1A_ASPM_MASK  0x000C
+
+/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
+#define NVM_SUM                    0xBABA
+
+#define NVM_MAC_ADDR_OFFSET        0
+#define NVM_PBA_OFFSET_0           8
+#define NVM_PBA_OFFSET_1           9
+#define NVM_RESERVED_WORD          0xFFFF
+#define NVM_PHY_CLASS_A            0x8000
+#define NVM_SERDES_AMPLITUDE_MASK  0x000F
+#define NVM_SIZE_MASK              0x1C00
+#define NVM_SIZE_SHIFT             10
+#define NVM_WORD_SIZE_BASE_SHIFT   6
+#define NVM_SWDPIO_EXT_SHIFT       4
+
+/* NVM Commands - Microwire */
+#define NVM_READ_OPCODE_MICROWIRE  0x6  /* NVM read opcode */
+#define NVM_WRITE_OPCODE_MICROWIRE 0x5  /* NVM write opcode */
+#define NVM_ERASE_OPCODE_MICROWIRE 0x7  /* NVM erase opcode */
+#define NVM_EWEN_OPCODE_MICROWIRE  0x13 /* NVM erase/write enable */
+#define NVM_EWDS_OPCODE_MICROWIRE  0x10 /* NVM erase/write disable */
+
+/* NVM Commands - SPI */
+#define NVM_MAX_RETRY_SPI          5000 /* Max wait of 5ms, for RDY signal */
+#define NVM_READ_OPCODE_SPI        0x03 /* NVM read opcode */
+#define NVM_WRITE_OPCODE_SPI       0x02 /* NVM write opcode */
+#define NVM_A8_OPCODE_SPI          0x08 /* opcode bit-3 = address bit-8 */
+#define NVM_WREN_OPCODE_SPI        0x06 /* NVM set Write Enable latch */
+#define NVM_WRDI_OPCODE_SPI        0x04 /* NVM reset Write Enable latch */
+#define NVM_RDSR_OPCODE_SPI        0x05 /* NVM read Status register */
+#define NVM_WRSR_OPCODE_SPI        0x01 /* NVM write Status register */
+
+/* SPI NVM Status Register */
+#define NVM_STATUS_RDY_SPI         0x01
+#define NVM_STATUS_WEN_SPI         0x02
+#define NVM_STATUS_BP0_SPI         0x04
+#define NVM_STATUS_BP1_SPI         0x08
+#define NVM_STATUS_WPEN_SPI        0x80
+
+/* Word definitions for ID LED Settings */
+#define ID_LED_RESERVED_0000 0x0000
+#define ID_LED_RESERVED_FFFF 0xFFFF
+#define ID_LED_DEFAULT       ((ID_LED_OFF1_ON2  << 12) | \
+                              (ID_LED_OFF1_OFF2 <<  8) | \
+                              (ID_LED_DEF1_DEF2 <<  4) | \
+                              (ID_LED_DEF1_DEF2))
+#define ID_LED_DEF1_DEF2     0x1
+#define ID_LED_DEF1_ON2      0x2
+#define ID_LED_DEF1_OFF2     0x3
+#define ID_LED_ON1_DEF2      0x4
+#define ID_LED_ON1_ON2       0x5
+#define ID_LED_ON1_OFF2      0x6
+#define ID_LED_OFF1_DEF2     0x7
+#define ID_LED_OFF1_ON2      0x8
+#define ID_LED_OFF1_OFF2     0x9
+
+#define IGP_ACTIVITY_LED_MASK   0xFFFFF0FF
+#define IGP_ACTIVITY_LED_ENABLE 0x0300
+#define IGP_LED3_MODE           0x07000000
+
+/* PCI/PCI-X/PCI-EX Config space */
+#define PCIX_COMMAND_REGISTER        0xE6
+#define PCIX_STATUS_REGISTER_LO      0xE8
+#define PCIX_STATUS_REGISTER_HI      0xEA
+#define PCI_HEADER_TYPE_REGISTER     0x0E
+#define PCIE_LINK_STATUS             0x12
+#define PCIE_DEVICE_CONTROL2         0x28
+
+#define PCIX_COMMAND_MMRBC_MASK      0x000C
+#define PCIX_COMMAND_MMRBC_SHIFT     0x2
+#define PCIX_STATUS_HI_MMRBC_MASK    0x0060
+#define PCIX_STATUS_HI_MMRBC_SHIFT   0x5
+#define PCIX_STATUS_HI_MMRBC_4K      0x3
+#define PCIX_STATUS_HI_MMRBC_2K      0x2
+#define PCIX_STATUS_LO_FUNC_MASK     0x7
+#define PCI_HEADER_TYPE_MULTIFUNC    0x80
+#define PCIE_LINK_WIDTH_MASK         0x3F0
+#define PCIE_LINK_WIDTH_SHIFT        4
+#define PCIE_DEVICE_CONTROL2_16ms    0x0005
+
+#ifndef ETH_ADDR_LEN
+#define ETH_ADDR_LEN                 6
+#endif
+
+#define PHY_REVISION_MASK      0xFFFFFFF0
+#define MAX_PHY_REG_ADDRESS    0x1F  /* 5 bit address bus (0-0x1F) */
+#define MAX_PHY_MULTI_PAGE_REG 0xF
+
+/* Bit definitions for valid PHY IDs. */
+/*
+ * I = Integrated
+ * E = External
+ */
+#define M88E1000_E_PHY_ID    0x01410C50
+#define M88E1000_I_PHY_ID    0x01410C30
+#define M88E1011_I_PHY_ID    0x01410C20
+#define IGP01E1000_I_PHY_ID  0x02A80380
+#define M88E1011_I_REV_4     0x04
+#define M88E1111_I_PHY_ID    0x01410CC0
+#define GG82563_E_PHY_ID     0x01410CA0
+#define IGP03E1000_E_PHY_ID  0x02A80390
+#define IFE_E_PHY_ID         0x02A80330
+#define IFE_PLUS_E_PHY_ID    0x02A80320
+#define IFE_C_E_PHY_ID       0x02A80310
+#define M88_VENDOR           0x0141
+
+/* M88E1000 Specific Registers */
+#define M88E1000_PHY_SPEC_CTRL     0x10  /* PHY Specific Control Register */
+#define M88E1000_PHY_SPEC_STATUS   0x11  /* PHY Specific Status Register */
+#define M88E1000_INT_ENABLE        0x12  /* Interrupt Enable Register */
+#define M88E1000_INT_STATUS        0x13  /* Interrupt Status Register */
+#define M88E1000_EXT_PHY_SPEC_CTRL 0x14  /* Extended PHY Specific Control */
+#define M88E1000_RX_ERR_CNTR       0x15  /* Receive Error Counter */
+
+#define M88E1000_PHY_EXT_CTRL      0x1A  /* PHY extend control register */
+#define M88E1000_PHY_PAGE_SELECT   0x1D  /* Reg 29 for page number setting */
+#define M88E1000_PHY_GEN_CONTROL   0x1E  /* Its meaning depends on reg 29 */
+#define M88E1000_PHY_VCO_REG_BIT8  0x100 /* Bits 8 & 11 are adjusted for */
+#define M88E1000_PHY_VCO_REG_BIT11 0x800    /* improved BER performance */
+
+/* M88E1000 PHY Specific Control Register */
+#define M88E1000_PSCR_JABBER_DISABLE    0x0001 /* 1=Jabber Function disabled */
+#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reverse enabled */
+#define M88E1000_PSCR_SQE_TEST          0x0004 /* 1=SQE Test enabled */
+/* 1=CLK125 low, 0=CLK125 toggling */
+#define M88E1000_PSCR_CLK125_DISABLE    0x0010
+#define M88E1000_PSCR_MDI_MANUAL_MODE  0x0000 /* MDI Crossover Mode bits 6:5 */
+                                               /* Manual MDI configuration */
+#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020  /* Manual MDIX configuration */
+/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
+#define M88E1000_PSCR_AUTO_X_1000T     0x0040
+/* Auto crossover enabled all speeds */
+#define M88E1000_PSCR_AUTO_X_MODE      0x0060
+/*
+ * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold
+ * 0=Normal 10BASE-T Rx Threshold
+ */
+#define M88E1000_PSCR_EN_10BT_EXT_DIST 0x0080
+/* 1=5-bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */
+#define M88E1000_PSCR_MII_5BIT_ENABLE      0x0100
+#define M88E1000_PSCR_SCRAMBLER_DISABLE    0x0200 /* 1=Scrambler disable */
+#define M88E1000_PSCR_FORCE_LINK_GOOD      0x0400 /* 1=Force link good */
+#define M88E1000_PSCR_ASSERT_CRS_ON_TX     0x0800 /* 1=Assert CRS on Tx */
+
+/* M88E1000 PHY Specific Status Register */
+#define M88E1000_PSSR_JABBER             0x0001 /* 1=Jabber */
+#define M88E1000_PSSR_REV_POLARITY       0x0002 /* 1=Polarity reversed */
+#define M88E1000_PSSR_DOWNSHIFT          0x0020 /* 1=Downshifted */
+#define M88E1000_PSSR_MDIX               0x0040 /* 1=MDIX; 0=MDI */
+/*
+ * 0 = <50M
+ * 1 = 50-80M
+ * 2 = 80-110M
+ * 3 = 110-140M
+ * 4 = >140M
+ */
+#define M88E1000_PSSR_CABLE_LENGTH       0x0380
+#define M88E1000_PSSR_LINK               0x0400 /* 1=Link up, 0=Link down */
+#define M88E1000_PSSR_SPD_DPLX_RESOLVED  0x0800 /* 1=Speed & Duplex resolved */
+#define M88E1000_PSSR_PAGE_RCVD          0x1000 /* 1=Page received */
+#define M88E1000_PSSR_DPLX               0x2000 /* 1=Duplex 0=Half Duplex */
+#define M88E1000_PSSR_SPEED              0xC000 /* Speed, bits 14:15 */
+#define M88E1000_PSSR_10MBS              0x0000 /* 00=10Mbs */
+#define M88E1000_PSSR_100MBS             0x4000 /* 01=100Mbs */
+#define M88E1000_PSSR_1000MBS            0x8000 /* 10=1000Mbs */
+
+#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
+
+/* M88E1000 Extended PHY Specific Control Register */
+#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */
+/*
+ * 1 = Lost lock detect enabled.
+ * Will assert lost lock and bring
+ * link down if idle not seen
+ * within 1ms in 1000BASE-T
+ */
+#define M88E1000_EPSCR_DOWN_NO_IDLE   0x8000
+/*
+ * Number of times we will attempt to autonegotiate before downshifting if we
+ * are the master
+ */
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X   0x0000
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X   0x0400
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X   0x0800
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X   0x0C00
+/*
+ * Number of times we will attempt to autonegotiate before downshifting if we
+ * are the slave
+ */
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK  0x0300
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_DIS   0x0000
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X    0x0100
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X    0x0200
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X    0x0300
+#define M88E1000_EPSCR_TX_CLK_2_5     0x0060 /* 2.5 MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_25      0x0070 /* 25  MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_0       0x0000 /* NO  TX_CLK */
+
+/* M88EC018 Rev 2 specific DownShift settings */
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK  0x0E00
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_1X    0x0000
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_2X    0x0200
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_3X    0x0400
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_4X    0x0600
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X    0x0800
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_6X    0x0A00
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X    0x0C00
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X    0x0E00
+
+/*
+ * Bits...
+ * 15-5: page
+ * 4-0: register offset
+ */
+#define GG82563_PAGE_SHIFT        5
+#define GG82563_REG(page, reg)    \
+        (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
+#define GG82563_MIN_ALT_REG       30
+
+/* GG82563 Specific Registers */
+#define GG82563_PHY_SPEC_CTRL           \
+        GG82563_REG(0, 16) /* PHY Specific Control */
+#define GG82563_PHY_SPEC_STATUS         \
+        GG82563_REG(0, 17) /* PHY Specific Status */
+#define GG82563_PHY_INT_ENABLE          \
+        GG82563_REG(0, 18) /* Interrupt Enable */
+#define GG82563_PHY_SPEC_STATUS_2       \
+        GG82563_REG(0, 19) /* PHY Specific Status 2 */
+#define GG82563_PHY_RX_ERR_CNTR         \
+        GG82563_REG(0, 21) /* Receive Error Counter */
+#define GG82563_PHY_PAGE_SELECT         \
+        GG82563_REG(0, 22) /* Page Select */
+#define GG82563_PHY_SPEC_CTRL_2         \
+        GG82563_REG(0, 26) /* PHY Specific Control 2 */
+#define GG82563_PHY_PAGE_SELECT_ALT     \
+        GG82563_REG(0, 29) /* Alternate Page Select */
+#define GG82563_PHY_TEST_CLK_CTRL       \
+        GG82563_REG(0, 30) /* Test Clock Control (use reg. 29 to select) */
+
+#define GG82563_PHY_MAC_SPEC_CTRL       \
+        GG82563_REG(2, 21) /* MAC Specific Control Register */
+#define GG82563_PHY_MAC_SPEC_CTRL_2     \
+        GG82563_REG(2, 26) /* MAC Specific Control 2 */
+
+#define GG82563_PHY_DSP_DISTANCE    \
+        GG82563_REG(5, 26) /* DSP Distance */
+
+/* Page 193 - Port Control Registers */
+#define GG82563_PHY_KMRN_MODE_CTRL   \
+        GG82563_REG(193, 16) /* Kumeran Mode Control */
+#define GG82563_PHY_PORT_RESET          \
+        GG82563_REG(193, 17) /* Port Reset */
+#define GG82563_PHY_REVISION_ID         \
+        GG82563_REG(193, 18) /* Revision ID */
+#define GG82563_PHY_DEVICE_ID           \
+        GG82563_REG(193, 19) /* Device ID */
+#define GG82563_PHY_PWR_MGMT_CTRL       \
+        GG82563_REG(193, 20) /* Power Management Control */
+#define GG82563_PHY_RATE_ADAPT_CTRL     \
+        GG82563_REG(193, 25) /* Rate Adaptation Control */
+
+/* Page 194 - KMRN Registers */
+#define GG82563_PHY_KMRN_FIFO_CTRL_STAT \
+        GG82563_REG(194, 16) /* FIFO's Control/Status */
+#define GG82563_PHY_KMRN_CTRL           \
+        GG82563_REG(194, 17) /* Control */
+#define GG82563_PHY_INBAND_CTRL         \
+        GG82563_REG(194, 18) /* Inband Control */
+#define GG82563_PHY_KMRN_DIAGNOSTIC     \
+        GG82563_REG(194, 19) /* Diagnostic */
+#define GG82563_PHY_ACK_TIMEOUTS        \
+        GG82563_REG(194, 20) /* Acknowledge Timeouts */
+#define GG82563_PHY_ADV_ABILITY         \
+        GG82563_REG(194, 21) /* Advertised Ability */
+#define GG82563_PHY_LINK_PARTNER_ADV_ABILITY \
+        GG82563_REG(194, 23) /* Link Partner Advertised Ability */
+#define GG82563_PHY_ADV_NEXT_PAGE       \
+        GG82563_REG(194, 24) /* Advertised Next Page */
+#define GG82563_PHY_LINK_PARTNER_ADV_NEXT_PAGE \
+        GG82563_REG(194, 25) /* Link Partner Advertised Next page */
+#define GG82563_PHY_KMRN_MISC           \
+        GG82563_REG(194, 26) /* Misc. */
+
+/* MDI Control */
+#define E1000_MDIC_DATA_MASK 0x0000FFFF
+#define E1000_MDIC_REG_MASK  0x001F0000
+#define E1000_MDIC_REG_SHIFT 16
+#define E1000_MDIC_PHY_MASK  0x03E00000
+#define E1000_MDIC_PHY_SHIFT 21
+#define E1000_MDIC_OP_WRITE  0x04000000
+#define E1000_MDIC_OP_READ   0x08000000
+#define E1000_MDIC_READY     0x10000000
+#define E1000_MDIC_INT_EN    0x20000000
+#define E1000_MDIC_ERROR     0x40000000
+
+/* SerDes Control */
+#define E1000_GEN_CTL_READY             0x80000000
+#define E1000_GEN_CTL_ADDRESS_SHIFT     8
+#define E1000_GEN_POLL_TIMEOUT          640
+
+
+
+#endif /* _E1000_DEFINES_H_ */
diff --git a/kern/drivers/net/e1000/e1000_hw.h b/kern/drivers/net/e1000/e1000_hw.h
new file mode 100644 (file)
index 0000000..753f75e
--- /dev/null
@@ -0,0 +1,728 @@
+/*******************************************************************************
+
+  Intel PRO/1000 Linux driver
+  Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#ifndef _E1000_HW_H_
+#define _E1000_HW_H_
+
+#include "e1000_osdep.h"
+#include "e1000_regs.h"
+#include "e1000_defines.h"
+
+struct e1000_hw;
+
+#define E1000_DEV_ID_82542                    0x1000
+#define E1000_DEV_ID_82543GC_FIBER            0x1001
+#define E1000_DEV_ID_82543GC_COPPER           0x1004
+#define E1000_DEV_ID_82544EI_COPPER           0x1008
+#define E1000_DEV_ID_82544EI_FIBER            0x1009
+#define E1000_DEV_ID_82544GC_COPPER           0x100C
+#define E1000_DEV_ID_82544GC_LOM              0x100D
+#define E1000_DEV_ID_82540EM                  0x100E
+#define E1000_DEV_ID_82540EM_LOM              0x1015
+#define E1000_DEV_ID_82540EP_LOM              0x1016
+#define E1000_DEV_ID_82540EP                  0x1017
+#define E1000_DEV_ID_82540EP_LP               0x101E
+#define E1000_DEV_ID_82545EM_COPPER           0x100F
+#define E1000_DEV_ID_82545EM_FIBER            0x1011
+#define E1000_DEV_ID_82545GM_COPPER           0x1026
+#define E1000_DEV_ID_82545GM_FIBER            0x1027
+#define E1000_DEV_ID_82545GM_SERDES           0x1028
+#define E1000_DEV_ID_82546EB_COPPER           0x1010
+#define E1000_DEV_ID_82546EB_FIBER            0x1012
+#define E1000_DEV_ID_82546EB_QUAD_COPPER      0x101D
+#define E1000_DEV_ID_82546GB_COPPER           0x1079
+#define E1000_DEV_ID_82546GB_FIBER            0x107A
+#define E1000_DEV_ID_82546GB_SERDES           0x107B
+#define E1000_DEV_ID_82546GB_PCIE             0x108A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER      0x1099
+#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
+#define E1000_DEV_ID_82541EI                  0x1013
+#define E1000_DEV_ID_82541EI_MOBILE           0x1018
+#define E1000_DEV_ID_82541ER_LOM              0x1014
+#define E1000_DEV_ID_82541ER                  0x1078
+#define E1000_DEV_ID_82541GI                  0x1076
+#define E1000_DEV_ID_82541GI_LF               0x107C
+#define E1000_DEV_ID_82541GI_MOBILE           0x1077
+#define E1000_DEV_ID_82547EI                  0x1019
+#define E1000_DEV_ID_82547EI_MOBILE           0x101A
+#define E1000_DEV_ID_82547GI                  0x1075
+#define E1000_REVISION_0 0
+#define E1000_REVISION_1 1
+#define E1000_REVISION_2 2
+#define E1000_REVISION_3 3
+#define E1000_REVISION_4 4
+
+#define E1000_FUNC_0     0
+#define E1000_FUNC_1     1
+
+#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0   0
+#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1   3
+
+enum e1000_mac_type {
+       e1000_undefined = 0,
+       e1000_82542,
+       e1000_82543,
+       e1000_82544,
+       e1000_82540,
+       e1000_82545,
+       e1000_82545_rev_3,
+       e1000_82546,
+       e1000_82546_rev_3,
+       e1000_82541,
+       e1000_82541_rev_2,
+       e1000_82547,
+       e1000_82547_rev_2,
+       e1000_num_macs  /* List is 1-based, so subtract 1 for true count. */
+};
+
+enum e1000_media_type {
+       e1000_media_type_unknown = 0,
+       e1000_media_type_copper = 1,
+       e1000_media_type_fiber = 2,
+       e1000_media_type_internal_serdes = 3,
+       e1000_num_media_types
+};
+
+enum e1000_nvm_type {
+       e1000_nvm_unknown = 0,
+       e1000_nvm_none,
+       e1000_nvm_eeprom_spi,
+       e1000_nvm_eeprom_microwire,
+       e1000_nvm_flash_hw,
+       e1000_nvm_flash_sw
+};
+
+enum e1000_nvm_override {
+       e1000_nvm_override_none = 0,
+       e1000_nvm_override_spi_small,
+       e1000_nvm_override_spi_large,
+       e1000_nvm_override_microwire_small,
+       e1000_nvm_override_microwire_large
+};
+
+enum e1000_phy_type {
+       e1000_phy_unknown = 0,
+       e1000_phy_none,
+       e1000_phy_m88,
+       e1000_phy_igp,
+       e1000_phy_igp_2,
+       e1000_phy_gg82563,
+       e1000_phy_igp_3,
+       e1000_phy_ife,
+};
+
+enum e1000_bus_type {
+       e1000_bus_type_unknown = 0,
+       e1000_bus_type_pci,
+       e1000_bus_type_pcix,
+       e1000_bus_type_pci_express,
+       e1000_bus_type_reserved
+};
+
+enum e1000_bus_speed {
+       e1000_bus_speed_unknown = 0,
+       e1000_bus_speed_33,
+       e1000_bus_speed_66,
+       e1000_bus_speed_100,
+       e1000_bus_speed_120,
+       e1000_bus_speed_133,
+       e1000_bus_speed_2500,
+       e1000_bus_speed_5000,
+       e1000_bus_speed_reserved
+};
+
+enum e1000_bus_width {
+       e1000_bus_width_unknown = 0,
+       e1000_bus_width_pcie_x1,
+       e1000_bus_width_pcie_x2,
+       e1000_bus_width_pcie_x4 = 4,
+       e1000_bus_width_pcie_x8 = 8,
+       e1000_bus_width_32,
+       e1000_bus_width_64,
+       e1000_bus_width_reserved
+};
+
+enum e1000_1000t_rx_status {
+       e1000_1000t_rx_status_not_ok = 0,
+       e1000_1000t_rx_status_ok,
+       e1000_1000t_rx_status_undefined = 0xFF
+};
+
+enum e1000_rev_polarity {
+       e1000_rev_polarity_normal = 0,
+       e1000_rev_polarity_reversed,
+       e1000_rev_polarity_undefined = 0xFF
+};
+
+enum e1000_fc_mode {
+       e1000_fc_none = 0,
+       e1000_fc_rx_pause,
+       e1000_fc_tx_pause,
+       e1000_fc_full,
+       e1000_fc_default = 0xFF
+};
+
+enum e1000_ffe_config {
+       e1000_ffe_config_enabled = 0,
+       e1000_ffe_config_active,
+       e1000_ffe_config_blocked
+};
+
+enum e1000_dsp_config {
+       e1000_dsp_config_disabled = 0,
+       e1000_dsp_config_enabled,
+       e1000_dsp_config_activated,
+       e1000_dsp_config_undefined = 0xFF
+};
+
+enum e1000_ms_type {
+       e1000_ms_hw_default = 0,
+       e1000_ms_force_master,
+       e1000_ms_force_slave,
+       e1000_ms_auto
+};
+
+enum e1000_smart_speed {
+       e1000_smart_speed_default = 0,
+       e1000_smart_speed_on,
+       e1000_smart_speed_off
+};
+
+enum e1000_serdes_link_state {
+       e1000_serdes_link_down = 0,
+       e1000_serdes_link_autoneg_progress,
+       e1000_serdes_link_autoneg_complete,
+       e1000_serdes_link_forced_up
+};
+
+/* Receive Descriptor */
+struct e1000_rx_desc {
+       __le64 buffer_addr; /* Address of the descriptor's data buffer */
+       __le16 length;      /* Length of data DMAed into data buffer */
+       __le16 csum;        /* Packet checksum */
+       u8  status;         /* Descriptor status */
+       u8  errors;         /* Descriptor Errors */
+       __le16 special;
+};
+
+/* Receive Descriptor - Extended */
+union e1000_rx_desc_extended {
+       struct {
+               __le64 buffer_addr;
+               __le64 reserved;
+       } read;
+       struct {
+               struct {
+                       __le32 mrq;           /* Multiple Rx Queues */
+                       union {
+                               __le32 rss;         /* RSS Hash */
+                               struct {
+                                       __le16 ip_id;  /* IP id */
+                                       __le16 csum;   /* Packet Checksum */
+                               } csum_ip;
+                       } hi_dword;
+               } lower;
+               struct {
+                       __le32 status_error;  /* ext status/error */
+                       __le16 length;
+                       __le16 vlan;          /* VLAN tag */
+               } upper;
+       } wb;  /* writeback */
+};
+
+#define MAX_PS_BUFFERS 4
+/* Receive Descriptor - Packet Split */
+union e1000_rx_desc_packet_split {
+       struct {
+               /* one buffer for protocol header(s), three data buffers */
+               __le64 buffer_addr[MAX_PS_BUFFERS];
+       } read;
+       struct {
+               struct {
+                       __le32 mrq;           /* Multiple Rx Queues */
+                       union {
+                               __le32 rss;           /* RSS Hash */
+                               struct {
+                                       __le16 ip_id;    /* IP id */
+                                       __le16 csum;     /* Packet Checksum */
+                               } csum_ip;
+                       } hi_dword;
+               } lower;
+               struct {
+                       __le32 status_error;  /* ext status/error */
+                       __le16 length0;       /* length of buffer 0 */
+                       __le16 vlan;          /* VLAN tag */
+               } middle;
+               struct {
+                       __le16 header_status;
+                       __le16 length[3];     /* length of buffers 1-3 */
+               } upper;
+               __le64 reserved;
+       } wb; /* writeback */
+};
+
+/* Transmit Descriptor */
+struct e1000_tx_desc {
+       __le64 buffer_addr;   /* Address of the descriptor's data buffer */
+       union {
+               __le32 data;
+               struct {
+                       __le16 length;    /* Data buffer length */
+                       u8 cso;           /* Checksum offset */
+                       u8 cmd;           /* Descriptor control */
+               } flags;
+       } lower;
+       union {
+               __le32 data;
+               struct {
+                       u8 status;        /* Descriptor status */
+                       u8 css;           /* Checksum start */
+                       __le16 special;
+               } fields;
+       } upper;
+};
+
+/* Offload Context Descriptor */
+struct e1000_context_desc {
+       union {
+               __le32 ip_config;
+               struct {
+                       u8 ipcss;         /* IP checksum start */
+                       u8 ipcso;         /* IP checksum offset */
+                       __le16 ipcse;     /* IP checksum end */
+               } ip_fields;
+       } lower_setup;
+       union {
+               __le32 tcp_config;
+               struct {
+                       u8 tucss;         /* TCP checksum start */
+                       u8 tucso;         /* TCP checksum offset */
+                       __le16 tucse;     /* TCP checksum end */
+               } tcp_fields;
+       } upper_setup;
+       __le32 cmd_and_length;
+       union {
+               __le32 data;
+               struct {
+                       u8 status;        /* Descriptor status */
+                       u8 hdr_len;       /* Header length */
+                       __le16 mss;       /* Maximum segment size */
+               } fields;
+       } tcp_seg_setup;
+};
+
+/* Offload data descriptor */
+struct e1000_data_desc {
+       __le64 buffer_addr;   /* Address of the descriptor's buffer address */
+       union {
+               __le32 data;
+               struct {
+                       __le16 length;    /* Data buffer length */
+                       u8 typ_len_ext;
+                       u8 cmd;
+               } flags;
+       } lower;
+       union {
+               __le32 data;
+               struct {
+                       u8 status;        /* Descriptor status */
+                       u8 popts;         /* Packet Options */
+                       __le16 special;
+               } fields;
+       } upper;
+};
+
+/* Statistics counters collected by the MAC */
+struct e1000_hw_stats {
+       u64 crcerrs;
+       u64 algnerrc;
+       u64 symerrs;
+       u64 rxerrc;
+       u64 mpc;
+       u64 scc;
+       u64 ecol;
+       u64 mcc;
+       u64 latecol;
+       u64 colc;
+       u64 dc;
+       u64 tncrs;
+       u64 sec;
+       u64 cexterr;
+       u64 rlec;
+       u64 xonrxc;
+       u64 xontxc;
+       u64 xoffrxc;
+       u64 xofftxc;
+       u64 fcruc;
+       u64 prc64;
+       u64 prc127;
+       u64 prc255;
+       u64 prc511;
+       u64 prc1023;
+       u64 prc1522;
+       u64 gprc;
+       u64 bprc;
+       u64 mprc;
+       u64 gptc;
+       u64 gorc;
+       u64 gotc;
+       u64 rnbc;
+       u64 ruc;
+       u64 rfc;
+       u64 roc;
+       u64 rjc;
+       u64 mgprc;
+       u64 mgpdc;
+       u64 mgptc;
+       u64 tor;
+       u64 tot;
+       u64 tpr;
+       u64 tpt;
+       u64 ptc64;
+       u64 ptc127;
+       u64 ptc255;
+       u64 ptc511;
+       u64 ptc1023;
+       u64 ptc1522;
+       u64 mptc;
+       u64 bptc;
+       u64 tsctc;
+       u64 tsctfc;
+       u64 iac;
+       u64 icrxptc;
+       u64 icrxatc;
+       u64 ictxptc;
+       u64 ictxatc;
+       u64 ictxqec;
+       u64 ictxqmtc;
+       u64 icrxdmtc;
+       u64 icrxoc;
+       u64 cbtmpc;
+       u64 htdpmc;
+       u64 cbrdpc;
+       u64 cbrmpc;
+       u64 rpthc;
+       u64 hgptc;
+       u64 htcbdpc;
+       u64 hgorc;
+       u64 hgotc;
+       u64 lenerrs;
+       u64 scvpc;
+       u64 hrmpc;
+       u64 doosync;
+};
+
+
+struct e1000_phy_stats {
+       u32 idle_errors;
+       u32 receive_errors;
+};
+
+struct e1000_host_mng_dhcp_cookie {
+       u32 signature;
+       u8  status;
+       u8  reserved0;
+       u16 vlan_id;
+       u32 reserved1;
+       u16 reserved2;
+       u8  reserved3;
+       u8  checksum;
+};
+
+/* Host Interface "Rev 1" */
+struct e1000_host_command_header {
+       u8 command_id;
+       u8 command_length;
+       u8 command_options;
+       u8 checksum;
+};
+
+#define E1000_HI_MAX_DATA_LENGTH     252
+struct e1000_host_command_info {
+       struct e1000_host_command_header command_header;
+       u8 command_data[E1000_HI_MAX_DATA_LENGTH];
+};
+
+/* Host Interface "Rev 2" */
+struct e1000_host_mng_command_header {
+       u8  command_id;
+       u8  checksum;
+       u16 reserved1;
+       u16 reserved2;
+       u16 command_length;
+};
+
+#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8
+struct e1000_host_mng_command_info {
+       struct e1000_host_mng_command_header command_header;
+       u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH];
+};
+
+#include "e1000_mac.h"
+#include "e1000_phy.h"
+#include "e1000_nvm.h"
+#include "e1000_manage.h"
+
+struct e1000_mac_operations {
+       /* Function pointers for the MAC. */
+       s32  (*init_params)(struct e1000_hw *);
+       s32  (*id_led_init)(struct e1000_hw *);
+       s32  (*blink_led)(struct e1000_hw *);
+       s32  (*check_for_link)(struct e1000_hw *);
+       bool (*check_mng_mode)(struct e1000_hw *hw);
+       s32  (*cleanup_led)(struct e1000_hw *);
+       void (*clear_hw_cntrs)(struct e1000_hw *);
+       void (*clear_vfta)(struct e1000_hw *);
+       s32  (*get_bus_info)(struct e1000_hw *);
+       void (*set_lan_id)(struct e1000_hw *);
+       s32  (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
+       s32  (*led_on)(struct e1000_hw *);
+       s32  (*led_off)(struct e1000_hw *);
+       void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32);
+       s32  (*reset_hw)(struct e1000_hw *);
+       s32  (*init_hw)(struct e1000_hw *);
+       s32  (*setup_link)(struct e1000_hw *);
+       s32  (*setup_physical_interface)(struct e1000_hw *);
+       s32  (*setup_led)(struct e1000_hw *);
+       void (*write_vfta)(struct e1000_hw *, u32, u32);
+       void (*mta_set)(struct e1000_hw *, u32);
+       void (*config_collision_dist)(struct e1000_hw *);
+       void (*rar_set)(struct e1000_hw *, u8*, u32);
+       s32  (*read_mac_addr)(struct e1000_hw *);
+       s32  (*validate_mdi_setting)(struct e1000_hw *);
+       s32  (*mng_host_if_write)(struct e1000_hw *, u8*, u16, u16, u8*);
+       s32  (*mng_write_cmd_header)(struct e1000_hw *hw,
+                      struct e1000_host_mng_command_header*);
+       s32  (*mng_enable_host_if)(struct e1000_hw *);
+       s32  (*wait_autoneg)(struct e1000_hw *);
+};
+
+struct e1000_phy_operations {
+       s32  (*init_params)(struct e1000_hw *);
+       s32  (*acquire)(struct e1000_hw *);
+       s32  (*check_polarity)(struct e1000_hw *);
+       s32  (*check_reset_block)(struct e1000_hw *);
+       s32  (*commit)(struct e1000_hw *);
+#if 0
+       s32  (*force_speed_duplex)(struct e1000_hw *);
+#endif
+       s32  (*get_cfg_done)(struct e1000_hw *hw);
+#if 0
+       s32  (*get_cable_length)(struct e1000_hw *);
+#endif
+       s32  (*get_info)(struct e1000_hw *);
+       s32  (*read_reg)(struct e1000_hw *, u32, u16 *);
+       void (*release)(struct e1000_hw *);
+       s32  (*reset)(struct e1000_hw *);
+       s32  (*set_d0_lplu_state)(struct e1000_hw *, bool);
+       s32  (*set_d3_lplu_state)(struct e1000_hw *, bool);
+       s32  (*write_reg)(struct e1000_hw *, u32, u16);
+       void (*power_up)(struct e1000_hw *);
+       void (*power_down)(struct e1000_hw *);
+};
+
+struct e1000_nvm_operations {
+       s32  (*init_params)(struct e1000_hw *);
+       s32  (*acquire)(struct e1000_hw *);
+       s32  (*read)(struct e1000_hw *, u16, u16, u16 *);
+       void (*release)(struct e1000_hw *);
+       void (*reload)(struct e1000_hw *);
+       s32  (*update)(struct e1000_hw *);
+       s32  (*valid_led_default)(struct e1000_hw *, u16 *);
+       s32  (*validate)(struct e1000_hw *);
+       s32  (*write)(struct e1000_hw *, u16, u16, u16 *);
+};
+
+struct e1000_mac_info {
+       struct e1000_mac_operations ops;
+       u8 addr[6];
+       u8 perm_addr[6];
+
+       enum e1000_mac_type type;
+
+       u32 collision_delta;
+       u32 ledctl_default;
+       u32 ledctl_mode1;
+       u32 ledctl_mode2;
+       u32 mc_filter_type;
+       u32 tx_packet_delta;
+       u32 txcw;
+
+       u16 current_ifs_val;
+       u16 ifs_max_val;
+       u16 ifs_min_val;
+       u16 ifs_ratio;
+       u16 ifs_step_size;
+       u16 mta_reg_count;
+
+       /* Maximum size of the MTA register table in all supported adapters */
+       #define MAX_MTA_REG 128
+       u32 mta_shadow[MAX_MTA_REG];
+       u16 rar_entry_count;
+
+       u8  forced_speed_duplex;
+
+       bool adaptive_ifs;
+       bool arc_subsystem_valid;
+       bool asf_firmware_present;
+       bool autoneg;
+       bool autoneg_failed;
+       bool get_link_status;
+       bool in_ifs_mode;
+       bool report_tx_early;
+       enum e1000_serdes_link_state serdes_link_state;
+       bool serdes_has_link;
+       bool tx_pkt_filtering;
+};
+
+struct e1000_phy_info {
+       struct e1000_phy_operations ops;
+       enum e1000_phy_type type;
+
+       enum e1000_1000t_rx_status local_rx;
+       enum e1000_1000t_rx_status remote_rx;
+       enum e1000_ms_type ms_type;
+       enum e1000_ms_type original_ms_type;
+       enum e1000_rev_polarity cable_polarity;
+       enum e1000_smart_speed smart_speed;
+
+       u32 addr;
+       u32 id;
+       u32 reset_delay_us; /* in usec */
+       u32 revision;
+
+       enum e1000_media_type media_type;
+
+       u16 autoneg_advertised;
+       u16 autoneg_mask;
+       u16 cable_length;
+       u16 max_cable_length;
+       u16 min_cable_length;
+
+       u8 mdix;
+
+       bool disable_polarity_correction;
+       bool is_mdix;
+       bool polarity_correction;
+       bool reset_disable;
+       bool speed_downgraded;
+       bool autoneg_wait_to_complete;
+};
+
+struct e1000_nvm_info {
+       struct e1000_nvm_operations ops;
+       enum e1000_nvm_type type;
+       enum e1000_nvm_override override;
+
+       u32 flash_bank_size;
+       u32 flash_base_addr;
+
+       u16 word_size;
+       u16 delay_usec;
+       u16 address_bits;
+       u16 opcode_bits;
+       u16 page_size;
+};
+
+struct e1000_bus_info {
+       enum e1000_bus_type type;
+       enum e1000_bus_speed speed;
+       enum e1000_bus_width width;
+
+       u16 func;
+       u16 pci_cmd_word;
+};
+
+struct e1000_fc_info {
+       u32 high_water;          /* Flow control high-water mark */
+       u32 low_water;           /* Flow control low-water mark */
+       u16 pause_time;          /* Flow control pause timer */
+       bool send_xon;           /* Flow control send XON */
+       bool strict_ieee;        /* Strict IEEE mode */
+       enum e1000_fc_mode current_mode; /* FC mode in effect */
+       enum e1000_fc_mode requested_mode; /* FC mode requested by caller */
+};
+
+struct e1000_dev_spec_82541 {
+       enum e1000_dsp_config dsp_config;
+       enum e1000_ffe_config ffe_config;
+       u16 spd_default;
+       bool phy_init_script;
+};
+
+struct e1000_dev_spec_82542 {
+       bool dma_fairness;
+};
+
+struct e1000_dev_spec_82543 {
+       u32  tbi_compatibility;
+       bool dma_fairness;
+       bool init_phy_disabled;
+};
+
+struct e1000_hw {
+       void *back;
+
+       u8 __iomem *hw_addr;
+       u8 __iomem *flash_address;
+       unsigned long io_base;
+
+       struct e1000_mac_info  mac;
+       struct e1000_fc_info   fc;
+       struct e1000_phy_info  phy;
+       struct e1000_nvm_info  nvm;
+       struct e1000_bus_info  bus;
+       struct e1000_host_mng_dhcp_cookie mng_cookie;
+
+       union {
+               struct e1000_dev_spec_82541     _82541;
+               struct e1000_dev_spec_82542     _82542;
+               struct e1000_dev_spec_82543     _82543;
+       } dev_spec;
+
+       u16 device_id;
+       u16 subsystem_vendor_id;
+       u16 subsystem_device_id;
+       u16 vendor_id;
+
+       u8  revision_id;
+};
+
+#include "e1000_82541.h"
+#include "e1000_82543.h"
+
+/* These functions must be implemented by drivers */
+void e1000_pci_clear_mwi(struct e1000_hw *hw);
+void e1000_pci_set_mwi(struct e1000_hw *hw);
+s32  e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
+void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
+void e1000_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
+
+#endif
diff --git a/kern/drivers/net/e1000/e1000_mac.c b/kern/drivers/net/e1000/e1000_mac.c
new file mode 100644 (file)
index 0000000..2351387
--- /dev/null
@@ -0,0 +1,2196 @@
+/*******************************************************************************
+
+  Intel PRO/1000 Linux driver
+  Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "e1000_api.h"
+
+static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw);
+static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw);
+
+/**
+ *  e1000_init_mac_ops_generic - Initialize MAC function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  Setups up the function pointers to no-op functions
+ **/
+void e1000_init_mac_ops_generic(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       DEBUGFUNC("e1000_init_mac_ops_generic");
+
+       /* General Setup */
+       mac->ops.init_params = e1000_null_ops_generic;
+       mac->ops.init_hw = e1000_null_ops_generic;
+       mac->ops.reset_hw = e1000_null_ops_generic;
+       mac->ops.setup_physical_interface = e1000_null_ops_generic;
+       mac->ops.get_bus_info = e1000_null_ops_generic;
+       mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pcie;
+       mac->ops.read_mac_addr = e1000_read_mac_addr_generic;
+       mac->ops.config_collision_dist = e1000_config_collision_dist_generic;
+       mac->ops.clear_hw_cntrs = e1000_null_mac_generic;
+       /* LED */
+       mac->ops.cleanup_led = e1000_null_ops_generic;
+       mac->ops.setup_led = e1000_null_ops_generic;
+       mac->ops.blink_led = e1000_null_ops_generic;
+       mac->ops.led_on = e1000_null_ops_generic;
+       mac->ops.led_off = e1000_null_ops_generic;
+       /* LINK */
+       mac->ops.setup_link = e1000_null_ops_generic;
+       mac->ops.get_link_up_info = e1000_null_link_info;
+       mac->ops.check_for_link = e1000_null_ops_generic;
+       mac->ops.wait_autoneg = e1000_wait_autoneg_generic;
+#if 0
+       /* Management */
+       mac->ops.check_mng_mode = e1000_null_mng_mode;
+       mac->ops.mng_host_if_write = e1000_mng_host_if_write_generic;
+       mac->ops.mng_write_cmd_header = e1000_mng_write_cmd_header_generic;
+       mac->ops.mng_enable_host_if = e1000_mng_enable_host_if_generic;
+#endif
+       /* VLAN, MC, etc. */
+       mac->ops.update_mc_addr_list = e1000_null_update_mc;
+       mac->ops.clear_vfta = e1000_null_mac_generic;
+       mac->ops.write_vfta = e1000_null_write_vfta;
+       mac->ops.mta_set = e1000_null_mta_set;
+       mac->ops.rar_set = e1000_rar_set_generic;
+       mac->ops.validate_mdi_setting = e1000_validate_mdi_setting_generic;
+}
+
+/**
+ *  e1000_null_ops_generic - No-op function, returns 0
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_null_ops_generic(struct e1000_hw *hw __unused)
+{
+       DEBUGFUNC("e1000_null_ops_generic");
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_null_mac_generic - No-op function, return void
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_null_mac_generic(struct e1000_hw *hw __unused)
+{
+       DEBUGFUNC("e1000_null_mac_generic");
+       return;
+}
+
+/**
+ *  e1000_null_link_info - No-op function, return 0
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_null_link_info(struct e1000_hw *hw __unused,
+                         u16 *s __unused, u16 *d __unused)
+{
+       DEBUGFUNC("e1000_null_link_info");
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_null_mng_mode - No-op function, return false
+ *  @hw: pointer to the HW structure
+ **/
+bool e1000_null_mng_mode(struct e1000_hw *hw __unused)
+{
+       DEBUGFUNC("e1000_null_mng_mode");
+       return false;
+}
+
+/**
+ *  e1000_null_update_mc - No-op function, return void
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_null_update_mc(struct e1000_hw *hw __unused,
+                          u8 *h __unused, u32 a __unused)
+{
+       DEBUGFUNC("e1000_null_update_mc");
+       return;
+}
+
+/**
+ *  e1000_null_write_vfta - No-op function, return void
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_null_write_vfta(struct e1000_hw *hw __unused,
+                           u32 a __unused, u32 b __unused)
+{
+       DEBUGFUNC("e1000_null_write_vfta");
+       return;
+}
+
+/**
+ *  e1000_null_set_mta - No-op function, return void
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_null_mta_set(struct e1000_hw *hw __unused, u32 a __unused)
+{
+       DEBUGFUNC("e1000_null_mta_set");
+       return;
+}
+
+/**
+ *  e1000_null_rar_set - No-op function, return void
+ *  @hw: pointer to the HW structure
+ **/
+void e1000_null_rar_set(struct e1000_hw *hw __unused, u8 *h __unused,
+                        u32 a __unused)
+{
+       DEBUGFUNC("e1000_null_rar_set");
+       return;
+}
+
+/**
+ *  e1000_get_bus_info_pci_generic - Get PCI(x) bus information
+ *  @hw: pointer to the HW structure
+ *
+ *  Determines and stores the system bus information for a particular
+ *  network interface.  The following bus information is determined and stored:
+ *  bus speed, bus width, type (PCI/PCIx), and PCI(-x) function.
+ **/
+s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw __unused)
+{
+#if 0
+       struct e1000_mac_info *mac = &hw->mac;
+       struct e1000_bus_info *bus = &hw->bus;
+       u32 status = E1000_READ_REG(hw, E1000_STATUS);
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_get_bus_info_pci_generic");
+
+       /* PCI or PCI-X? */
+       bus->type = (status & E1000_STATUS_PCIX_MODE)
+                       ? e1000_bus_type_pcix
+                       : e1000_bus_type_pci;
+
+       /* Bus speed */
+       if (bus->type == e1000_bus_type_pci) {
+               bus->speed = (status & E1000_STATUS_PCI66)
+                            ? e1000_bus_speed_66
+                            : e1000_bus_speed_33;
+       } else {
+               switch (status & E1000_STATUS_PCIX_SPEED) {
+               case E1000_STATUS_PCIX_SPEED_66:
+                       bus->speed = e1000_bus_speed_66;
+                       break;
+               case E1000_STATUS_PCIX_SPEED_100:
+                       bus->speed = e1000_bus_speed_100;
+                       break;
+               case E1000_STATUS_PCIX_SPEED_133:
+                       bus->speed = e1000_bus_speed_133;
+                       break;
+               default:
+                       bus->speed = e1000_bus_speed_reserved;
+                       break;
+               }
+       }
+
+       /* Bus width */
+       bus->width = (status & E1000_STATUS_BUS64)
+                    ? e1000_bus_width_64
+                    : e1000_bus_width_32;
+
+       /* Which PCI(-X) function? */
+       mac->ops.set_lan_id(hw);
+
+       return ret_val;
+#endif
+       return 0;
+}
+
+/**
+ *  e1000_get_bus_info_pcie_generic - Get PCIe bus information
+ *  @hw: pointer to the HW structure
+ *
+ *  Determines and stores the system bus information for a particular
+ *  network interface.  The following bus information is determined and stored:
+ *  bus speed, bus width, type (PCIe), and PCIe function.
+ **/
+s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw __unused)
+{
+#if 0
+       struct e1000_mac_info *mac = &hw->mac;
+       struct e1000_bus_info *bus = &hw->bus;
+
+       s32 ret_val;
+       u16 pcie_link_status;
+
+       DEBUGFUNC("e1000_get_bus_info_pcie_generic");
+
+       bus->type = e1000_bus_type_pci_express;
+       bus->speed = e1000_bus_speed_2500;
+
+       ret_val = e1000_read_pcie_cap_reg(hw,
+                                         PCIE_LINK_STATUS,
+                                         &pcie_link_status);
+       if (ret_val)
+               bus->width = e1000_bus_width_unknown;
+       else
+               bus->width = (enum e1000_bus_width)((pcie_link_status &
+                                               PCIE_LINK_WIDTH_MASK) >>
+                                              PCIE_LINK_WIDTH_SHIFT);
+
+       mac->ops.set_lan_id(hw);
+
+       return E1000_SUCCESS;
+#endif
+       return 0;
+}
+
+/**
+ *  e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
+ *
+ *  @hw: pointer to the HW structure
+ *
+ *  Determines the LAN function id by reading memory-mapped registers
+ *  and swaps the port value if requested.
+ **/
+static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw)
+{
+       struct e1000_bus_info *bus = &hw->bus;
+       u32 reg;
+
+       /*
+        * The status register reports the correct function number
+        * for the device regardless of function swap state.
+        */
+       reg = E1000_READ_REG(hw, E1000_STATUS);
+       bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT;
+}
+
+/**
+ *  e1000_set_lan_id_multi_port_pci - Set LAN id for PCI multiple port devices
+ *  @hw: pointer to the HW structure
+ *
+ *  Determines the LAN function id by reading PCI config space.
+ **/
+void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw)
+{
+       struct e1000_bus_info *bus = &hw->bus;
+       u16 pci_header_type;
+       u32 status;
+
+       e1000_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type);
+       if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) {
+               status = E1000_READ_REG(hw, E1000_STATUS);
+               bus->func = (status & E1000_STATUS_FUNC_MASK)
+                           >> E1000_STATUS_FUNC_SHIFT;
+       } else {
+               bus->func = 0;
+       }
+}
+
+/**
+ *  e1000_set_lan_id_single_port - Set LAN id for a single port device
+ *  @hw: pointer to the HW structure
+ *
+ *  Sets the LAN function id to zero for a single port device.
+ **/
+void e1000_set_lan_id_single_port(struct e1000_hw *hw)
+{
+       struct e1000_bus_info *bus = &hw->bus;
+
+       bus->func = 0;
+}
+
+/**
+ *  e1000_clear_vfta_generic - Clear VLAN filter table
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the register array which contains the VLAN filter table by
+ *  setting all the values to 0.
+ **/
+void e1000_clear_vfta_generic(struct e1000_hw *hw)
+{
+       u32 offset;
+
+       DEBUGFUNC("e1000_clear_vfta_generic");
+
+       for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
+               E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0);
+               E1000_WRITE_FLUSH(hw);
+       }
+}
+
+/**
+ *  e1000_write_vfta_generic - Write value to VLAN filter table
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset in VLAN filter table
+ *  @value: register value written to VLAN filter table
+ *
+ *  Writes value at the given offset in the register array which stores
+ *  the VLAN filter table.
+ **/
+void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value)
+{
+       DEBUGFUNC("e1000_write_vfta_generic");
+
+       E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
+       E1000_WRITE_FLUSH(hw);
+}
+
+/**
+ *  e1000_init_rx_addrs_generic - Initialize receive address's
+ *  @hw: pointer to the HW structure
+ *  @rar_count: receive address registers
+ *
+ *  Setups the receive address registers by setting the base receive address
+ *  register to the devices MAC address and clearing all the other receive
+ *  address registers to 0.
+ **/
+void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count)
+{
+       u32 i;
+       u8 mac_addr[ETH_ADDR_LEN] = {0};
+
+       DEBUGFUNC("e1000_init_rx_addrs_generic");
+
+       /* Setup the receive address */
+       DEBUGOUT("Programming MAC Address into RAR[0]\n");
+
+       hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
+
+       /* Zero out the other (rar_entry_count - 1) receive addresses */
+       DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1);
+       for (i = 1; i < rar_count; i++)
+               hw->mac.ops.rar_set(hw, mac_addr, i);
+}
+
+/**
+ *  e1000_check_alt_mac_addr_generic - Check for alternate MAC addr
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks the nvm for an alternate MAC address.  An alternate MAC address
+ *  can be setup by pre-boot software and must be treated like a permanent
+ *  address and must override the actual permanent MAC address. If an
+ *  alternate MAC address is found it is programmed into RAR0, replacing
+ *  the permanent address that was installed into RAR0 by the Si on reset.
+ *  This function will return SUCCESS unless it encounters an error while
+ *  reading the EEPROM.
+ **/
+s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
+{
+       u32 i;
+       s32 ret_val = E1000_SUCCESS;
+       u16 offset, nvm_alt_mac_addr_offset, nvm_data;
+       u8 alt_mac_addr[ETH_ADDR_LEN];
+
+       DEBUGFUNC("e1000_check_alt_mac_addr_generic");
+
+       ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1,
+                                &nvm_alt_mac_addr_offset);
+       if (ret_val) {
+               DEBUGOUT("NVM Read Error\n");
+               goto out;
+       }
+
+       if (nvm_alt_mac_addr_offset == 0xFFFF) {
+               /* There is no Alternate MAC Address */
+               goto out;
+       }
+
+       if (hw->bus.func == E1000_FUNC_1)
+               nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
+       for (i = 0; i < ETH_ADDR_LEN; i += 2) {
+               offset = nvm_alt_mac_addr_offset + (i >> 1);
+               ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
+               if (ret_val) {
+                       DEBUGOUT("NVM Read Error\n");
+                       goto out;
+               }
+
+               alt_mac_addr[i] = (u8)(nvm_data & 0xFF);
+               alt_mac_addr[i + 1] = (u8)(nvm_data >> 8);
+       }
+
+       /* if multicast bit is set, the alternate address will not be used */
+       if (alt_mac_addr[0] & 0x01) {
+               DEBUGOUT("Ignoring Alternate Mac Address with MC bit set\n");
+               goto out;
+       }
+
+       /*
+        * We have a valid alternate MAC address, and we want to treat it the
+        * same as the normal permanent MAC address stored by the HW into the
+        * RAR. Do this by mapping this address into RAR0.
+        */
+       hw->mac.ops.rar_set(hw, alt_mac_addr, 0);
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_rar_set_generic - Set receive address register
+ *  @hw: pointer to the HW structure
+ *  @addr: pointer to the receive address
+ *  @index: receive address array register
+ *
+ *  Sets the receive address array register at index to the address passed
+ *  in by addr.
+ **/
+void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
+{
+       u32 rar_low, rar_high;
+
+       DEBUGFUNC("e1000_rar_set_generic");
+
+       /*
+        * HW expects these in little endian so we reverse the byte order
+        * from network order (big endian) to little endian
+        */
+       rar_low = ((u32) addr[0] |
+                  ((u32) addr[1] << 8) |
+                  ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+
+       rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+
+       /* If MAC address zero, no need to set the AV bit */
+       if (rar_low || rar_high)
+               rar_high |= E1000_RAH_AV;
+
+       /*
+        * Some bridges will combine consecutive 32-bit writes into
+        * a single burst write, which will malfunction on some parts.
+        * The flushes avoid this.
+        */
+       E1000_WRITE_REG(hw, E1000_RAL(index), rar_low);
+       E1000_WRITE_FLUSH(hw);
+       E1000_WRITE_REG(hw, E1000_RAH(index), rar_high);
+       E1000_WRITE_FLUSH(hw);
+}
+
+/**
+ *  e1000_mta_set_generic - Set multicast filter table address
+ *  @hw: pointer to the HW structure
+ *  @hash_value: determines the MTA register and bit to set
+ *
+ *  The multicast table address is a register array of 32-bit registers.
+ *  The hash_value is used to determine what register the bit is in, the
+ *  current value is read, the new bit is OR'd in and the new value is
+ *  written back into the register.
+ **/
+void e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value)
+{
+       u32 hash_bit, hash_reg, mta;
+
+       DEBUGFUNC("e1000_mta_set_generic");
+       /*
+        * The MTA is a register array of 32-bit registers. It is
+        * treated like an array of (32*mta_reg_count) bits.  We want to
+        * set bit BitArray[hash_value]. So we figure out what register
+        * the bit is in, read it, OR in the new bit, then write
+        * back the new value.  The (hw->mac.mta_reg_count - 1) serves as a
+        * mask to bits 31:5 of the hash value which gives us the
+        * register we're modifying.  The hash bit within that register
+        * is determined by the lower 5 bits of the hash value.
+        */
+       hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
+       hash_bit = hash_value & 0x1F;
+
+       mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg);
+
+       mta |= (1 << hash_bit);
+
+       E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta);
+       E1000_WRITE_FLUSH(hw);
+}
+
+/**
+ *  e1000_update_mc_addr_list_generic - Update Multicast addresses
+ *  @hw: pointer to the HW structure
+ *  @mc_addr_list: array of multicast addresses to program
+ *  @mc_addr_count: number of multicast addresses to program
+ *
+ *  Updates entire Multicast Table Array.
+ *  The caller must have a packed mc_addr_list of multicast addresses.
+ **/
+void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
+                                       u8 *mc_addr_list, u32 mc_addr_count)
+{
+       u32 hash_value, hash_bit, hash_reg;
+       int i;
+
+       DEBUGFUNC("e1000_update_mc_addr_list_generic");
+
+       /* clear mta_shadow */
+       memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
+
+       /* update mta_shadow from mc_addr_list */
+       for (i = 0; (u32) i < mc_addr_count; i++) {
+               hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list);
+
+               hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
+               hash_bit = hash_value & 0x1F;
+
+               hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
+               mc_addr_list += (ETH_ADDR_LEN);
+       }
+
+       /* replace the entire MTA table */
+       for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
+               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]);
+       E1000_WRITE_FLUSH(hw);
+}
+
+/**
+ *  e1000_hash_mc_addr_generic - Generate a multicast hash value
+ *  @hw: pointer to the HW structure
+ *  @mc_addr: pointer to a multicast address
+ *
+ *  Generates a multicast address hash value which is used to determine
+ *  the multicast filter table array address and new table value.  See
+ *  e1000_mta_set_generic()
+ **/
+u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr)
+{
+       u32 hash_value, hash_mask;
+       u8 bit_shift = 0;
+
+       DEBUGFUNC("e1000_hash_mc_addr_generic");
+
+       /* Register count multiplied by bits per register */
+       hash_mask = (hw->mac.mta_reg_count * 32) - 1;
+
+       /*
+        * For a mc_filter_type of 0, bit_shift is the number of left-shifts
+        * where 0xFF would still fall within the hash mask.
+        */
+       while (hash_mask >> bit_shift != 0xFF)
+               bit_shift++;
+
+       /*
+        * The portion of the address that is used for the hash table
+        * is determined by the mc_filter_type setting.
+        * The algorithm is such that there is a total of 8 bits of shifting.
+        * The bit_shift for a mc_filter_type of 0 represents the number of
+        * left-shifts where the MSB of mc_addr[5] would still fall within
+        * the hash_mask.  Case 0 does this exactly.  Since there are a total
+        * of 8 bits of shifting, then mc_addr[4] will shift right the
+        * remaining number of bits. Thus 8 - bit_shift.  The rest of the
+        * cases are a variation of this algorithm...essentially raising the
+        * number of bits to shift mc_addr[5] left, while still keeping the
+        * 8-bit shifting total.
+        *
+        * For example, given the following Destination MAC Address and an
+        * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask),
+        * we can see that the bit_shift for case 0 is 4.  These are the hash
+        * values resulting from each mc_filter_type...
+        * [0] [1] [2] [3] [4] [5]
+        * 01  AA  00  12  34  56
+        * LSB                 MSB
+        *
+        * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563
+        * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6
+        * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163
+        * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634
+        */
+       switch (hw->mac.mc_filter_type) {
+       default:
+       case 0:
+               break;
+       case 1:
+               bit_shift += 1;
+               break;
+       case 2:
+               bit_shift += 2;
+               break;
+       case 3:
+               bit_shift += 4;
+               break;
+       }
+
+       hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
+                                 (((u16) mc_addr[5]) << bit_shift)));
+
+       return hash_value;
+}
+
+/**
+ *  e1000_pcix_mmrbc_workaround_generic - Fix incorrect MMRBC value
+ *  @hw: pointer to the HW structure
+ *
+ *  In certain situations, a system BIOS may report that the PCIx maximum
+ *  memory read byte count (MMRBC) value is higher than than the actual
+ *  value. We check the PCIx command register with the current PCIx status
+ *  register.
+ **/
+void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw)
+{
+       u16 cmd_mmrbc;
+       u16 pcix_cmd;
+       u16 pcix_stat_hi_word;
+       u16 stat_mmrbc;
+
+       DEBUGFUNC("e1000_pcix_mmrbc_workaround_generic");
+
+       /* Workaround for PCI-X issue when BIOS sets MMRBC incorrectly */
+       if (hw->bus.type != e1000_bus_type_pcix)
+               return;
+
+       e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd);
+       e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word);
+       cmd_mmrbc = (pcix_cmd & PCIX_COMMAND_MMRBC_MASK) >>
+                    PCIX_COMMAND_MMRBC_SHIFT;
+       stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >>
+                     PCIX_STATUS_HI_MMRBC_SHIFT;
+       if (stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K)
+               stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K;
+       if (cmd_mmrbc > stat_mmrbc) {
+               pcix_cmd &= ~PCIX_COMMAND_MMRBC_MASK;
+               pcix_cmd |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT;
+               e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd);
+       }
+}
+
+/**
+ *  e1000_clear_hw_cntrs_base_generic - Clear base hardware counters
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the base hardware counters by reading the counter registers.
+ **/
+void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw __unused)
+{
+       DEBUGFUNC("e1000_clear_hw_cntrs_base_generic");
+
+#if 0
+       E1000_READ_REG(hw, E1000_CRCERRS);
+       E1000_READ_REG(hw, E1000_SYMERRS);
+       E1000_READ_REG(hw, E1000_MPC);
+       E1000_READ_REG(hw, E1000_SCC);
+       E1000_READ_REG(hw, E1000_ECOL);
+       E1000_READ_REG(hw, E1000_MCC);
+       E1000_READ_REG(hw, E1000_LATECOL);
+       E1000_READ_REG(hw, E1000_COLC);
+       E1000_READ_REG(hw, E1000_DC);
+       E1000_READ_REG(hw, E1000_SEC);
+       E1000_READ_REG(hw, E1000_RLEC);
+       E1000_READ_REG(hw, E1000_XONRXC);
+       E1000_READ_REG(hw, E1000_XONTXC);
+       E1000_READ_REG(hw, E1000_XOFFRXC);
+       E1000_READ_REG(hw, E1000_XOFFTXC);
+       E1000_READ_REG(hw, E1000_FCRUC);
+       E1000_READ_REG(hw, E1000_GPRC);
+       E1000_READ_REG(hw, E1000_BPRC);
+       E1000_READ_REG(hw, E1000_MPRC);
+       E1000_READ_REG(hw, E1000_GPTC);
+       E1000_READ_REG(hw, E1000_GORCL);
+       E1000_READ_REG(hw, E1000_GORCH);
+       E1000_READ_REG(hw, E1000_GOTCL);
+       E1000_READ_REG(hw, E1000_GOTCH);
+       E1000_READ_REG(hw, E1000_RNBC);
+       E1000_READ_REG(hw, E1000_RUC);
+       E1000_READ_REG(hw, E1000_RFC);
+       E1000_READ_REG(hw, E1000_ROC);
+       E1000_READ_REG(hw, E1000_RJC);
+       E1000_READ_REG(hw, E1000_TORL);
+       E1000_READ_REG(hw, E1000_TORH);
+       E1000_READ_REG(hw, E1000_TOTL);
+       E1000_READ_REG(hw, E1000_TOTH);
+       E1000_READ_REG(hw, E1000_TPR);
+       E1000_READ_REG(hw, E1000_TPT);
+       E1000_READ_REG(hw, E1000_MPTC);
+       E1000_READ_REG(hw, E1000_BPTC);
+#endif
+}
+
+/**
+ *  e1000_check_for_copper_link_generic - Check for link (Copper)
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks to see of the link status of the hardware has changed.  If a
+ *  change in link status has been detected, then we read the PHY registers
+ *  to get the current speed/duplex if link exists.
+ **/
+s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       s32 ret_val;
+       bool link;
+
+       DEBUGFUNC("e1000_check_for_copper_link");
+
+       /*
+        * We only want to go out to the PHY registers to see if Auto-Neg
+        * has completed and/or if our link status has changed.  The
+        * get_link_status flag is set upon receiving a Link Status
+        * Change or Rx Sequence Error interrupt.
+        */
+       if (!mac->get_link_status) {
+               ret_val = E1000_SUCCESS;
+               goto out;
+       }
+
+       /*
+        * First we want to see if the MII Status Register reports
+        * link.  If so, then we want to get the current speed/duplex
+        * of the PHY.
+        */
+       ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
+       if (ret_val)
+               goto out;
+
+       if (!link)
+               goto out; /* No link detected */
+
+       mac->get_link_status = false;
+
+       /*
+        * Check if there was DownShift, must be checked
+        * immediately after link-up
+        */
+       e1000_check_downshift_generic(hw);
+
+       /*
+        * If we are forcing speed/duplex, then we simply return since
+        * we have already determined whether we have link or not.
+        */
+       if (!mac->autoneg) {
+               ret_val = -E1000_ERR_CONFIG;
+               goto out;
+       }
+
+       /*
+        * Auto-Neg is enabled.  Auto Speed Detection takes care
+        * of MAC speed/duplex configuration.  So we only need to
+        * configure Collision Distance in the MAC.
+        */
+       e1000_config_collision_dist_generic(hw);
+
+       /*
+        * Configure Flow Control now that Auto-Neg has completed.
+        * First, we need to restore the desired flow control
+        * settings because we may have had to re-autoneg with a
+        * different link partner.
+        */
+       ret_val = e1000_config_fc_after_link_up_generic(hw);
+       if (ret_val)
+               DEBUGOUT("Error configuring flow control\n");
+
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_check_for_fiber_link_generic - Check for link (Fiber)
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks for link up on the hardware.  If link is not up and we have
+ *  a signal, then we need to force link up.
+ **/
+s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       u32 rxcw;
+       u32 ctrl;
+       u32 status;
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_check_for_fiber_link_generic");
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+       status = E1000_READ_REG(hw, E1000_STATUS);
+       rxcw = E1000_READ_REG(hw, E1000_RXCW);
+
+       /*
+        * If we don't have link (auto-negotiation failed or link partner
+        * cannot auto-negotiate), the cable is plugged in (we have signal),
+        * and our link partner is not trying to auto-negotiate with us (we
+        * are receiving idles or data), we need to force link up. We also
+        * need to give auto-negotiation time to complete, in case the cable
+        * was just plugged in. The autoneg_failed flag does this.
+        */
+       /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
+       if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) &&
+           (!(rxcw & E1000_RXCW_C))) {
+               if (mac->autoneg_failed == 0) {
+                       mac->autoneg_failed = 1;
+                       goto out;
+               }
+               DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
+
+               /* Disable auto-negotiation in the TXCW register */
+               E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));
+
+               /* Force link-up and also force full-duplex. */
+               ctrl = E1000_READ_REG(hw, E1000_CTRL);
+               ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
+               E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+               /* Configure Flow Control after forcing link up. */
+               ret_val = e1000_config_fc_after_link_up_generic(hw);
+               if (ret_val) {
+                       DEBUGOUT("Error configuring flow control\n");
+                       goto out;
+               }
+       } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
+               /*
+                * If we are forcing link and we are receiving /C/ ordered
+                * sets, re-enable auto-negotiation in the TXCW register
+                * and disable forced link in the Device Control register
+                * in an attempt to auto-negotiate with our li