++#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */
++#define E1000_MDPHYA 0x0003C /* PHY address - RW */
++#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */
++#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
++#define E1000_CCMCTL 0x05B48 /* CCM Control Register */
++#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */
++#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */
++#define E1000_GCR 0x05B00 /* PCI-Ex Control */
++#define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */
++#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */
++#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */
++#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */
++#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */
++#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
++#define E1000_SWSM 0x05B50 /* SW Semaphore */
++#define E1000_FWSM 0x05B54 /* FW Semaphore */
++#define E1000_SWSM2 0x05B58 /* Driver-only SW semaphore (not used by BOOT agents) */
++#define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */
++#define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */
++#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
++#define E1000_HICR 0x08F00 /* Host Interface Control */
++
++/* RSS registers */
++#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
++#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
++#define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */
++#define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate Interrupt Ext*/
++#define E1000_IMIRVP 0x05AC0 /* Immediate Interrupt Rx VLAN Priority - RW */
++#define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Allocation Register
++ * (_i) - RW */
++#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10)) /* MSI-X Table entry addr
++ * low reg - RW */
++#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) /* MSI-X Table entry addr
++ * upper reg - RW */
++#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10)) /* MSI-X Table entry
++ * message reg - RW */
++#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) /* MSI-X Table entry
++ * vector ctrl reg - RW */
++#define E1000_MSIXPBA 0x0E000 /* MSI-X Pending bit array */
++#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */
++#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */
++#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
++#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
++#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */
++#define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */
++
++#endif
+diff -Nurp linux-2.6.22-0/drivers/net/e1000e/ethtool.c linux-2.6.22-10/drivers/net/e1000e/ethtool.c
+--- linux-2.6.22-0/drivers/net/e1000e/ethtool.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22-10/drivers/net/e1000e/ethtool.c 2009-06-24 00:32:20.000000000 +0200
+@@ -0,0 +1,2033 @@
++/*******************************************************************************
++
++ Intel PRO/1000 Linux driver
++ Copyright(c) 1999 - 2009 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
++
++*******************************************************************************/
++
++/* ethtool support for e1000 */
++
++#include <linux/netdevice.h>
++#ifdef SIOCETHTOOL
++#include <linux/ethtool.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++
++#include "e1000.h"
++#ifdef NETIF_F_HW_VLAN_TX
++#include <linux/if_vlan.h>
++#endif
++#ifdef ETHTOOL_OPS_COMPAT
++#include "kcompat_ethtool.c"
++#endif
++
++struct e1000_stats {
++ char stat_string[ETH_GSTRING_LEN];
++ int sizeof_stat;
++ int stat_offset;
++};
++
++#define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \
++ offsetof(struct e1000_adapter, m)
++static const struct e1000_stats e1000_gstrings_stats[] = {
++ { "rx_packets", E1000_STAT(stats.gprc) },
++ { "tx_packets", E1000_STAT(stats.gptc) },
++ { "rx_bytes", E1000_STAT(stats.gorc) },
++ { "tx_bytes", E1000_STAT(stats.gotc) },
++ { "rx_broadcast", E1000_STAT(stats.bprc) },
++ { "tx_broadcast", E1000_STAT(stats.bptc) },
++ { "rx_multicast", E1000_STAT(stats.mprc) },
++ { "tx_multicast", E1000_STAT(stats.mptc) },
++ { "rx_errors", E1000_STAT(net_stats.rx_errors) },
++ { "tx_errors", E1000_STAT(net_stats.tx_errors) },
++#ifndef CONFIG_E1000E_NAPI
++ { "rx_dropped_backlog", E1000_STAT(rx_dropped_backlog) },
++#endif
++ { "tx_dropped", E1000_STAT(net_stats.tx_dropped) },
++ { "multicast", E1000_STAT(stats.mprc) },
++ { "collisions", E1000_STAT(stats.colc) },
++ { "rx_length_errors", E1000_STAT(net_stats.rx_length_errors) },
++ { "rx_over_errors", E1000_STAT(net_stats.rx_over_errors) },
++ { "rx_crc_errors", E1000_STAT(stats.crcerrs) },
++ { "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) },
++ { "rx_no_buffer_count", E1000_STAT(stats.rnbc) },
++ { "rx_missed_errors", E1000_STAT(stats.mpc) },
++ { "tx_aborted_errors", E1000_STAT(stats.ecol) },
++ { "tx_carrier_errors", E1000_STAT(stats.tncrs) },
++ { "tx_fifo_errors", E1000_STAT(net_stats.tx_fifo_errors) },
++ { "tx_heartbeat_errors", E1000_STAT(net_stats.tx_heartbeat_errors) },
++ { "tx_window_errors", E1000_STAT(stats.latecol) },
++ { "tx_abort_late_coll", E1000_STAT(stats.latecol) },
++ { "tx_deferred_ok", E1000_STAT(stats.dc) },
++ { "tx_single_coll_ok", E1000_STAT(stats.scc) },
++ { "tx_multi_coll_ok", E1000_STAT(stats.mcc) },
++ { "tx_timeout_count", E1000_STAT(tx_timeout_count) },
++ { "tx_restart_queue", E1000_STAT(restart_queue) },
++ { "rx_long_length_errors", E1000_STAT(stats.roc) },
++ { "rx_short_length_errors", E1000_STAT(stats.ruc) },
++ { "rx_align_errors", E1000_STAT(stats.algnerrc) },
++ { "tx_tcp_seg_good", E1000_STAT(stats.tsctc) },
++ { "tx_tcp_seg_failed", E1000_STAT(stats.tsctfc) },
++ { "rx_flow_control_xon", E1000_STAT(stats.xonrxc) },
++ { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) },
++ { "tx_flow_control_xon", E1000_STAT(stats.xontxc) },
++ { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
++ { "rx_long_byte_count", E1000_STAT(stats.gorc) },
++ { "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
++ { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
++ { "rx_header_split", E1000_STAT(rx_hdr_split) },
++ { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) },
++ { "tx_smbus", E1000_STAT(stats.mgptc) },
++ { "rx_smbus", E1000_STAT(stats.mgprc) },
++ { "dropped_smbus", E1000_STAT(stats.mgpdc) },
++ { "rx_dma_failed", E1000_STAT(rx_dma_failed) },
++ { "tx_dma_failed", E1000_STAT(tx_dma_failed) },
++};
++
++#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats)
++#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN)
++static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
++ "Register test (offline)", "Eeprom test (offline)",
++ "Interrupt test (offline)", "Loopback test (offline)",
++ "Link test (on/offline)"
++};
++#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test)
++
++static int e1000_get_settings(struct net_device *netdev,
++ struct ethtool_cmd *ecmd)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ u32 status;
++
++ if (hw->phy.media_type == e1000_media_type_copper) {
++
++ ecmd->supported = (SUPPORTED_10baseT_Half |
++ SUPPORTED_10baseT_Full |
++ SUPPORTED_100baseT_Half |
++ SUPPORTED_100baseT_Full |
++ SUPPORTED_1000baseT_Full |
++ SUPPORTED_Autoneg |
++ SUPPORTED_TP);
++ if (hw->phy.type == e1000_phy_ife)
++ ecmd->supported &= ~SUPPORTED_1000baseT_Full;
++ ecmd->advertising = ADVERTISED_TP;
++
++ if (hw->mac.autoneg == 1) {
++ ecmd->advertising |= ADVERTISED_Autoneg;
++ /* the e1000 autoneg seems to match ethtool nicely */
++ ecmd->advertising |= hw->phy.autoneg_advertised;
++ }
++
++ ecmd->port = PORT_TP;
++ ecmd->phy_address = hw->phy.addr;
++ ecmd->transceiver = XCVR_INTERNAL;
++
++ } else {
++ ecmd->supported = (SUPPORTED_1000baseT_Full |
++ SUPPORTED_FIBRE |
++ SUPPORTED_Autoneg);
++
++ ecmd->advertising = (ADVERTISED_1000baseT_Full |
++ ADVERTISED_FIBRE |
++ ADVERTISED_Autoneg);
++
++ ecmd->port = PORT_FIBRE;
++ ecmd->transceiver = XCVR_EXTERNAL;
++ }
++
++ status = er32(STATUS);
++ if (status & E1000_STATUS_LU) {
++ if (status & E1000_STATUS_SPEED_1000)
++ ecmd->speed = 1000;
++ else if (status & E1000_STATUS_SPEED_100)
++ ecmd->speed = 100;
++ else
++ ecmd->speed = 10;
++
++ if (status & E1000_STATUS_FD)
++ ecmd->duplex = DUPLEX_FULL;
++ else
++ ecmd->duplex = DUPLEX_HALF;
++ } else {
++ ecmd->speed = -1;
++ ecmd->duplex = -1;
++ }
++
++ ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) ||
++ hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
++ return 0;
++}
++
++static u32 e1000_get_link(struct net_device *netdev)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++
++ return e1000_has_link(adapter);
++}
++
++static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
++{
++ struct e1000_mac_info *mac = &adapter->hw.mac;
++
++ mac->autoneg = 0;
++
++ /* Fiber NICs only allow 1000 gbps Full duplex */
++ if ((adapter->hw.phy.media_type == e1000_media_type_fiber) &&
++ spddplx != (SPEED_1000 + DUPLEX_FULL)) {
++ e_err("Unsupported Speed/Duplex configuration\n");
++ return -EINVAL;
++ }
++
++ switch (spddplx) {
++ case SPEED_10 + DUPLEX_HALF:
++ mac->forced_speed_duplex = ADVERTISE_10_HALF;
++ break;
++ case SPEED_10 + DUPLEX_FULL:
++ mac->forced_speed_duplex = ADVERTISE_10_FULL;
++ break;
++ case SPEED_100 + DUPLEX_HALF:
++ mac->forced_speed_duplex = ADVERTISE_100_HALF;
++ break;
++ case SPEED_100 + DUPLEX_FULL:
++ mac->forced_speed_duplex = ADVERTISE_100_FULL;
++ break;
++ case SPEED_1000 + DUPLEX_FULL:
++ mac->autoneg = 1;
++ adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL;
++ break;
++ case SPEED_1000 + DUPLEX_HALF: /* not supported */
++ default:
++ e_err("Unsupported Speed/Duplex configuration\n");
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int e1000_set_settings(struct net_device *netdev,
++ struct ethtool_cmd *ecmd)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++
++ /*
++ * When SoL/IDER sessions are active, autoneg/speed/duplex
++ * cannot be changed
++ */
++ if (e1000_check_reset_block(hw)) {
++ e_err("Cannot change link characteristics when SoL/IDER is "
++ "active.\n");
++ return -EINVAL;
++ }
++
++ while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
++ msleep(1);
++
++ if (ecmd->autoneg == AUTONEG_ENABLE) {
++ hw->mac.autoneg = 1;
++ if (hw->phy.media_type == e1000_media_type_fiber)
++ hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full |
++ ADVERTISED_FIBRE |
++ ADVERTISED_Autoneg;
++ else
++ hw->phy.autoneg_advertised = ecmd->advertising |
++ ADVERTISED_TP |
++ ADVERTISED_Autoneg;
++ ecmd->advertising = hw->phy.autoneg_advertised;
++ if (adapter->fc_autoneg) {
++ if (hw->mac.type == e1000_pchlan) {
++ /* Workaround h/w hang when Tx flow control
++ * enabled */
++ hw->fc.requested_mode = e1000_fc_rx_pause;
++ } else {
++ hw->fc.requested_mode = e1000_fc_default;
++ }
++ }
++ } else {
++ if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) {
++ clear_bit(__E1000_RESETTING, &adapter->state);
++ return -EINVAL;
++ }
++ }
++
++ /* reset the link */
++
++ if (netif_running(adapter->netdev)) {
++ e1000e_down(adapter);
++ e1000e_up(adapter);
++ } else {
++ e1000e_reset(adapter);
++ }
++
++ clear_bit(__E1000_RESETTING, &adapter->state);
++ return 0;
++}
++
++static void e1000_get_pauseparam(struct net_device *netdev,
++ struct ethtool_pauseparam *pause)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;