diff -Ncr linux-2.4.22-old/drivers/net/e1000/e1000.h linux-2.4.22/drivers/net/e1000/e1000.h
*** linux-2.4.22-old/drivers/net/e1000/e1000.h	2003-11-18 17:22:41.000000000 +0900
--- linux-2.4.22/drivers/net/e1000/e1000.h	2003-08-25 20:44:42.000000000 +0900
***************
*** 63,68 ****
--- 63,71 ----
  #include <net/pkt_sched.h>
  #include <linux/list.h>
  #include <linux/reboot.h>
+ #ifdef NETIF_F_TSO
+ #include <net/checksum.h>
+ #endif
  #include <linux/tqueue.h>
  #include <linux/mii.h>
  #include <linux/ethtool.h>
***************
*** 131,136 ****
--- 134,140 ----
  	uint64_t dma;
  	unsigned long length;
  	unsigned long time_stamp;
+ 	unsigned int next_to_watch;
  };
  
  struct e1000_desc_ring {
***************
*** 166,172 ****
  	struct timer_list watchdog_timer;
  	struct timer_list phy_info_timer;
  	struct vlan_group *vlgrp;
- 	char *id_string;
  	uint32_t bd_number;
  	uint32_t rx_buffer_len;
  	uint32_t part_num;
--- 170,175 ----
***************
*** 215,223 ****
  	struct e1000_phy_info phy_info;
  	struct e1000_phy_stats phy_stats;
  
  
  
  	uint32_t pci_state[16];
- 	char ifname[IFNAMSIZ];
  };
  #endif /* _E1000_H_ */
--- 218,228 ----
  	struct e1000_phy_info phy_info;
  	struct e1000_phy_stats phy_stats;
  
+ 	uint32_t test_icr;
+ 	struct e1000_desc_ring test_tx_ring;
+ 	struct e1000_desc_ring test_rx_ring;
  
  
  	uint32_t pci_state[16];
  };
  #endif /* _E1000_H_ */
diff -Ncr linux-2.4.22-old/drivers/net/e1000/e1000_ethtool.c linux-2.4.22/drivers/net/e1000/e1000_ethtool.c
*** linux-2.4.22-old/drivers/net/e1000/e1000_ethtool.c	2003-11-18 17:02:21.000000000 +0900
--- linux-2.4.22/drivers/net/e1000/e1000_ethtool.c	2003-08-25 20:44:42.000000000 +0900
***************
*** 40,54 ****
  extern void e1000_reset(struct e1000_adapter *adapter);
  extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
  
! static char e1000_gstrings_stats[][ETH_GSTRING_LEN] = {
! 	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
! 	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
! 	"rx_length_errors", "rx_over_errors", "rx_crc_errors",
! 	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
! 	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
! 	"tx_heartbeat_errors", "tx_window_errors",
  };
! #define E1000_STATS_LEN	sizeof(e1000_gstrings_stats) / ETH_GSTRING_LEN
  
  static void
  e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
--- 40,99 ----
  extern void e1000_reset(struct e1000_adapter *adapter);
  extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
  
! 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 struct e1000_stats e1000_gstrings_stats[] = {
! 	{ "rx_packets", E1000_STAT(net_stats.rx_packets) },
! 	{ "tx_packets", E1000_STAT(net_stats.tx_packets) },
! 	{ "rx_bytes", E1000_STAT(net_stats.rx_bytes) },
! 	{ "tx_bytes", E1000_STAT(net_stats.tx_bytes) },
! 	{ "rx_errors", E1000_STAT(net_stats.rx_errors) },
! 	{ "tx_errors", E1000_STAT(net_stats.tx_errors) },
! 	{ "rx_dropped", E1000_STAT(net_stats.rx_dropped) },
! 	{ "tx_dropped", E1000_STAT(net_stats.tx_dropped) },
! 	{ "multicast", E1000_STAT(net_stats.multicast) },
! 	{ "collisions", E1000_STAT(net_stats.collisions) },
! 	{ "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(net_stats.rx_crc_errors) },
! 	{ "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) },
! 	{ "rx_fifo_errors", E1000_STAT(net_stats.rx_fifo_errors) },
! 	{ "rx_missed_errors", E1000_STAT(net_stats.rx_missed_errors) },
! 	{ "tx_aborted_errors", E1000_STAT(net_stats.tx_aborted_errors) },
! 	{ "tx_carrier_errors", E1000_STAT(net_stats.tx_carrier_errors) },
! 	{ "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(net_stats.tx_window_errors) },
! 	{ "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) },
! 	{ "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_csum_offload_good", E1000_STAT(hw_csum_good) },
! 	{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }
! };
! #define E1000_STATS_LEN	\
! 	sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
! static 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 sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN
  
  static void
  e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
***************
*** 154,159 ****
--- 199,205 ----
  	strncpy(drvinfo->fw_version, "N/A", 32);
  	strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32);
  	drvinfo->n_stats = E1000_STATS_LEN;
+ 	drvinfo->testinfo_len = E1000_TEST_LEN;
  #define E1000_REGS_LEN 32
  	drvinfo->regdump_len  = E1000_REGS_LEN * sizeof(uint32_t);
  	drvinfo->eedump_len = adapter->hw.eeprom.word_size * 2;
***************
*** 164,169 ****
--- 210,216 ----
                      struct ethtool_regs *regs, uint32_t *regs_buff)
  {
  	struct e1000_hw *hw = &adapter->hw;
+ 	uint16_t phy_data;
  
  	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
  
***************
*** 182,187 ****
--- 229,290 ----
  	regs_buff[10] = E1000_READ_REG(hw, TDT);
  	regs_buff[11] = E1000_READ_REG(hw, TIDV);
  
+ 	regs_buff[12] = adapter->hw.phy_type;  /* PHY type (IGP=1, M88=0) */
+ 	if(hw->phy_type == e1000_phy_igp) {
+ 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ 				    IGP01E1000_PHY_AGC_A);
+ 		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A &
+ 				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+ 		regs_buff[13] = (uint32_t)phy_data; /* cable length */
+ 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ 				    IGP01E1000_PHY_AGC_B);
+ 		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_B &
+ 				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+ 		regs_buff[14] = (uint32_t)phy_data; /* cable length */
+ 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ 				    IGP01E1000_PHY_AGC_C);
+ 		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_C &
+ 				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+ 		regs_buff[15] = (uint32_t)phy_data; /* cable length */
+ 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ 				    IGP01E1000_PHY_AGC_D);
+ 		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_D &
+ 				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+ 		regs_buff[16] = (uint32_t)phy_data; /* cable length */
+ 		regs_buff[17] = 0; /* extended 10bt distance (not needed) */
+ 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
+ 		e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS &
+ 				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+ 		regs_buff[18] = (uint32_t)phy_data; /* cable polarity */
+ 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ 				    IGP01E1000_PHY_PCS_INIT_REG);
+ 		e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG &
+ 				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+ 		regs_buff[19] = (uint32_t)phy_data; /* cable polarity */
+ 		regs_buff[20] = 0; /* polarity correction enabled (always) */
+ 		regs_buff[22] = 0; /* phy receive errors (unavailable) */
+ 		regs_buff[23] = regs_buff[18]; /* mdix mode */
+ 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
+ 	} else {
+         	e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+ 		regs_buff[13] = (uint32_t)phy_data; /* cable length */
+ 		regs_buff[14] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
+ 		regs_buff[15] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
+ 		regs_buff[16] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
+         	e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ 		regs_buff[17] = (uint32_t)phy_data; /* extended 10bt distance */
+ 		regs_buff[18] = regs_buff[13]; /* cable polarity */
+ 		regs_buff[19] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
+ 		regs_buff[20] = regs_buff[17]; /* polarity correction */
+ 		/* phy receive errors */
+ 		regs_buff[22] = adapter->phy_stats.receive_errors;
+ 		regs_buff[23] = regs_buff[13]; /* mdix mode */
+ 	}
+ 	regs_buff[21] = adapter->phy_stats.idle_errors;  /* phy idle errors */
+ 	e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
+ 	regs_buff[24] = (uint32_t)phy_data;  /* phy local receiver status */
+ 	regs_buff[25] = regs_buff[24];  /* phy remote receiver status */
+ 
  	return;
  }
  
***************
*** 219,225 ****
  		uint16_t i;
  		for (i = 0; i < last_word - first_word + 1; i++)
  			if((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
! 						       &eeprom_buff[i])))
  				break;
  	}
  geeprom_error:
--- 322,328 ----
  		uint16_t i;
  		for (i = 0; i < last_word - first_word + 1; i++)
  			if((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
! 							&eeprom_buff[i])))
  				break;
  	}
  geeprom_error:
***************
*** 249,255 ****
  	first_word = eeprom->offset >> 1;
  	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
  	eeprom_buff = kmalloc(max_len, GFP_KERNEL);
! 	if(eeprom_buff == NULL)
  		return -ENOMEM;
  
  	ptr = (void *)eeprom_buff;
--- 352,358 ----
  	first_word = eeprom->offset >> 1;
  	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
  	eeprom_buff = kmalloc(max_len, GFP_KERNEL);
! 	if(!eeprom_buff)
  		return -ENOMEM;
  
  	ptr = (void *)eeprom_buff;
***************
*** 284,289 ****
--- 387,1152 ----
  	return ret_val;
  }
  
+ #define REG_PATTERN_TEST(R, M, W)                                              \
+ {                                                                              \
+ 	uint32_t pat, value;                                                   \
+ 	uint32_t test[] =                                                      \
+ 		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};              \
+ 	for(pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) {              \
+ 		E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W));             \
+ 		value = E1000_READ_REG(&adapter->hw, R);                       \
+ 		if(value != (test[pat] & W & M)) {                             \
+ 			*data = (adapter->hw.mac_type < e1000_82543) ?         \
+ 				E1000_82542_##R : E1000_##R;                   \
+ 			return 1;                                              \
+ 		}                                                              \
+ 	}                                                                      \
+ }
+ 
+ #define REG_SET_AND_CHECK(R, M, W)                                             \
+ {                                                                              \
+ 	uint32_t value;                                                        \
+ 	E1000_WRITE_REG(&adapter->hw, R, W & M);                               \
+ 	value = E1000_READ_REG(&adapter->hw, R);                               \
+ 	if ((W & M) != (value & M)) {                                          \
+ 		*data = (adapter->hw.mac_type < e1000_82543) ?                 \
+ 			E1000_82542_##R : E1000_##R;                           \
+ 		return 1;                                                      \
+ 	}                                                                      \
+ }
+ 
+ static int
+ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
+ {
+ 	uint32_t value;
+ 	uint32_t i;
+ 
+ 	/* The status register is Read Only, so a write should fail.
+ 	 * Some bits that get toggled are ignored.
+ 	 */
+ 	value = (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833));
+ 	E1000_WRITE_REG(&adapter->hw, STATUS, (0xFFFFFFFF));
+ 	if(value != (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833))) {
+ 		*data = 1;
+ 		return 1;
+ 	}
+ 
+ 	REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
+ 	REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
+ 	REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
+ 	REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);
+ 	REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF);
+ 	REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
+ 	REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF);
+ 	REG_PATTERN_TEST(RDH, 0x0000FFFF, 0x0000FFFF);
+ 	REG_PATTERN_TEST(RDT, 0x0000FFFF, 0x0000FFFF);
+ 	REG_PATTERN_TEST(FCRTH, 0x0000FFF8, 0x0000FFF8);
+ 	REG_PATTERN_TEST(FCTTV, 0x0000FFFF, 0x0000FFFF);
+ 	REG_PATTERN_TEST(TIPG, 0x3FFFFFFF, 0x3FFFFFFF);
+ 	REG_PATTERN_TEST(TDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
+ 	REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF);
+ 
+ 	REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);
+ 	REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0x003FFFFB);
+ 	REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
+ 
+ 	if(adapter->hw.mac_type >= e1000_82543) {
+ 
+ 		REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0xFFFFFFFF);
+ 		REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
+ 		REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
+ 		REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
+ 		REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
+ 
+ 		for(i = 0; i < E1000_RAR_ENTRIES; i++) {
+ 			REG_PATTERN_TEST(RA + ((i << 1) << 2), 0xFFFFFFFF,
+ 					 0xFFFFFFFF);
+ 			REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
+ 					 0xFFFFFFFF);
+ 		}
+ 
+ 	} else {
+ 
+ 		REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x01FFFFFF);
+ 		REG_PATTERN_TEST(RDBAL, 0xFFFFF000, 0xFFFFFFFF);
+ 		REG_PATTERN_TEST(TXCW, 0x0000FFFF, 0x0000FFFF);
+ 		REG_PATTERN_TEST(TDBAL, 0xFFFFF000, 0xFFFFFFFF);
+ 
+ 	}
+ 
+ 	for(i = 0; i < E1000_MC_TBL_SIZE; i++)
+ 		REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
+ 
+ 	return 0;
+ }
+ 
+ static int
+ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
+ {
+ 	uint16_t temp;
+ 	uint16_t checksum = 0;
+ 	uint16_t i;
+ 
+ 	*data = 0;
+ 	/* Read and add up the contents of the EEPROM */
+ 	for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
+ 		if((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
+ 			*data = 1;
+ 			break;
+ 		}
+ 		checksum += temp;
+ 	}
+ 
+ 	/* If Checksum is not Correct return error else test passed */
+ 	if((checksum != (uint16_t) EEPROM_SUM) && !(*data))
+ 		*data = 2;
+ 
+ 	return *data;
+ }
+ 
+ static void
+ e1000_test_intr(int irq,
+ 		void *data,
+ 		struct pt_regs *regs)
+ {
+ 	struct net_device *netdev = (struct net_device *) data;
+ 	struct e1000_adapter *adapter = netdev->priv;
+ 
+ 	adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR);
+ 
+ 	return;
+ }
+ 
+ static int
+ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+ 	uint32_t icr, mask, i=0;
+ 
+ 	*data = 0;
+ 
+ 	/* Hook up test interrupt handler just for this test */
+ 	if(request_irq
+ 	   (netdev->irq, &e1000_test_intr, SA_SHIRQ, netdev->name, netdev)) {
+ 		*data = 1;
+ 		return -1;
+ 	}
+ 
+ 	/* Disable all the interrupts */
+ 	E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
+ 	msec_delay(10);
+ 
+ 	/* Interrupts are disabled, so read interrupt cause
+ 	 * register (icr) twice to verify that there are no interrupts
+ 	 * pending.  icr is clear on read.
+ 	 */
+ 	icr = E1000_READ_REG(&adapter->hw, ICR);
+ 	icr = E1000_READ_REG(&adapter->hw, ICR);
+ 
+ 	if(icr != 0) {
+ 		/* if icr is non-zero, there is no point
+ 		 * running other interrupt tests.
+ 		 */
+ 		*data = 2;
+ 		i = 10;
+ 	}
+ 
+ 	/* Test each interrupt */
+ 	for(; i < 10; i++) {
+ 
+ 		/* Interrupt to test */
+ 		mask = 1 << i;
+ 
+ 		/* Disable the interrupt to be reported in
+ 		 * the cause register and then force the same
+ 		 * interrupt and see if one gets posted.  If
+ 		 * an interrupt was posted to the bus, the
+ 		 * test failed.
+ 		 */
+ 		adapter->test_icr = 0;
+ 		E1000_WRITE_REG(&adapter->hw, IMC, mask);
+ 		E1000_WRITE_REG(&adapter->hw, ICS, mask);
+ 		msec_delay(10);
+ 
+ 		if(adapter->test_icr & mask) {
+ 			*data = 3;
+ 			break;
+ 		}
+ 
+ 		/* Enable the interrupt to be reported in
+ 		 * the cause register and then force the same
+ 		 * interrupt and see if one gets posted.  If
+ 		 * an interrupt was not posted to the bus, the
+ 		 * test failed.
+ 		 */
+ 		adapter->test_icr = 0;
+ 		E1000_WRITE_REG(&adapter->hw, IMS, mask);
+ 		E1000_WRITE_REG(&adapter->hw, ICS, mask);
+ 		msec_delay(10);
+ 
+ 		if(!(adapter->test_icr & mask)) {
+ 			*data = 4;
+ 			break;
+ 		}
+ 
+ 		/* Disable the other interrupts to be reported in
+ 		 * the cause register and then force the other
+ 		 * interrupts and see if any get posted.  If
+ 		 * an interrupt was posted to the bus, the
+ 		 * test failed.
+ 		 */
+ 		adapter->test_icr = 0;
+ 		E1000_WRITE_REG(&adapter->hw, IMC, ~mask);
+ 		E1000_WRITE_REG(&adapter->hw, ICS, ~mask);
+ 		msec_delay(10);
+ 
+ 		if(adapter->test_icr) {
+ 			*data = 5;
+ 			break;
+ 		}
+ 	}
+ 
+ 	/* Disable all the interrupts */
+ 	E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
+ 	msec_delay(10);
+ 
+ 	/* Unhook test interrupt handler */
+ 	free_irq(netdev->irq, netdev);
+ 
+ 	return *data;
+ }
+ 
+ static void
+ e1000_free_desc_rings(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
+ 	struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+ 	struct pci_dev *pdev = adapter->pdev;
+ 	int i;
+ 
+ 	if(txdr->desc && txdr->buffer_info) {
+ 		for(i = 0; i < txdr->count; i++) {
+ 			if(txdr->buffer_info[i].dma)
+ 				pci_unmap_single(pdev, txdr->buffer_info[i].dma,
+ 						 txdr->buffer_info[i].length,
+ 						 PCI_DMA_TODEVICE);
+ 			if(txdr->buffer_info[i].skb)
+ 				dev_kfree_skb(txdr->buffer_info[i].skb);
+ 		}
+ 	}
+ 
+ 	if(rxdr->desc && rxdr->buffer_info) {
+ 		for(i = 0; i < rxdr->count; i++) {
+ 			if(rxdr->buffer_info[i].dma)
+ 				pci_unmap_single(pdev, rxdr->buffer_info[i].dma,
+ 						 rxdr->buffer_info[i].length,
+ 						 PCI_DMA_FROMDEVICE);
+ 			if(rxdr->buffer_info[i].skb)
+ 				dev_kfree_skb(rxdr->buffer_info[i].skb);
+ 		}
+ 	}
+ 
+ 	if(txdr->desc)
+ 		pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma);
+ 	if(rxdr->desc)
+ 		pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
+ 
+ 	if(txdr->buffer_info)
+ 		kfree(txdr->buffer_info);
+ 	if(rxdr->buffer_info)
+ 		kfree(rxdr->buffer_info);
+ 
+ 	return;
+ }
+ 
+ static int
+ e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
+ 	struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+ 	struct pci_dev *pdev = adapter->pdev;
+ 	uint32_t rctl;
+ 	int size, i, ret_val;
+ 
+ 	/* Setup Tx descriptor ring and Tx buffers */
+ 
+ 	txdr->count = 80;
+ 
+ 	size = txdr->count * sizeof(struct e1000_buffer);
+ 	if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
+ 		ret_val = 1;
+ 		goto err_nomem;
+ 	}
+ 	memset(txdr->buffer_info, 0, size);
+ 
+ 	txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
+ 	E1000_ROUNDUP(txdr->size, 4096);
+ 	if(!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) {
+ 		ret_val = 2;
+ 		goto err_nomem;
+ 	}
+ 	memset(txdr->desc, 0, txdr->size);
+ 	txdr->next_to_use = txdr->next_to_clean = 0;
+ 
+ 	E1000_WRITE_REG(&adapter->hw, TDBAL,
+ 			((uint64_t) txdr->dma & 0x00000000FFFFFFFF));
+ 	E1000_WRITE_REG(&adapter->hw, TDBAH, ((uint64_t) txdr->dma >> 32));
+ 	E1000_WRITE_REG(&adapter->hw, TDLEN,
+ 			txdr->count * sizeof(struct e1000_tx_desc));
+ 	E1000_WRITE_REG(&adapter->hw, TDH, 0);
+ 	E1000_WRITE_REG(&adapter->hw, TDT, 0);
+ 	E1000_WRITE_REG(&adapter->hw, TCTL,
+ 			E1000_TCTL_PSP | E1000_TCTL_EN |
+ 			E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
+ 			E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
+ 
+ 	for(i = 0; i < txdr->count; i++) {
+ 		struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i);
+ 		struct sk_buff *skb;
+ 		unsigned int size = 1024;
+ 
+ 		if(!(skb = alloc_skb(size, GFP_KERNEL))) {
+ 			ret_val = 3;
+ 			goto err_nomem;
+ 		}
+ 		skb_put(skb, size);
+ 		txdr->buffer_info[i].skb = skb;
+ 		txdr->buffer_info[i].length = skb->len;
+ 		txdr->buffer_info[i].dma =
+ 			pci_map_single(pdev, skb->data, skb->len,
+ 				       PCI_DMA_TODEVICE);
+ 		tx_desc->buffer_addr = cpu_to_le64(txdr->buffer_info[i].dma);
+ 		tx_desc->lower.data = cpu_to_le32(skb->len);
+ 		tx_desc->lower.data |= E1000_TXD_CMD_EOP;
+ 		tx_desc->lower.data |= E1000_TXD_CMD_IFCS;
+ 		tx_desc->lower.data |= E1000_TXD_CMD_RPS;
+ 		tx_desc->upper.data = 0;
+ 	}
+ 
+ 	/* Setup Rx descriptor ring and Rx buffers */
+ 
+ 	rxdr->count = 80;
+ 
+ 	size = rxdr->count * sizeof(struct e1000_buffer);
+ 	if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
+ 		ret_val = 4;
+ 		goto err_nomem;
+ 	}
+ 	memset(rxdr->buffer_info, 0, size);
+ 
+ 	rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
+ 	if(!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
+ 		ret_val = 5;
+ 		goto err_nomem;
+ 	}
+ 	memset(rxdr->desc, 0, rxdr->size);
+ 	rxdr->next_to_use = rxdr->next_to_clean = 0;
+ 
+ 	rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ 	E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
+ 	E1000_WRITE_REG(&adapter->hw, RDBAL,
+ 			((uint64_t) rxdr->dma & 0xFFFFFFFF));
+ 	E1000_WRITE_REG(&adapter->hw, RDBAH, ((uint64_t) rxdr->dma >> 32));
+ 	E1000_WRITE_REG(&adapter->hw, RDLEN, rxdr->size);
+ 	E1000_WRITE_REG(&adapter->hw, RDH, 0);
+ 	E1000_WRITE_REG(&adapter->hw, RDT, 0);
+ 	rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
+ 		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
+ 		(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
+ 	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ 
+ 	for(i = 0; i < rxdr->count; i++) {
+ 		struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
+ 		struct sk_buff *skb;
+ 
+ 		if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + 2, GFP_KERNEL))) {
+ 			ret_val = 6;
+ 			goto err_nomem;
+ 		}
+ 		skb_reserve(skb, 2);
+ 		rxdr->buffer_info[i].skb = skb;
+ 		rxdr->buffer_info[i].length = E1000_RXBUFFER_2048;
+ 		rxdr->buffer_info[i].dma =
+ 			pci_map_single(pdev, skb->data, E1000_RXBUFFER_2048,
+ 				       PCI_DMA_FROMDEVICE);
+ 		rx_desc->buffer_addr = cpu_to_le64(rxdr->buffer_info[i].dma);
+ 		memset(skb->data, 0x00, skb->len);
+ 	}
+ 
+ 	return 0;
+ 
+       err_nomem:
+ 	e1000_free_desc_rings(adapter);
+ 	return ret_val;
+ }
+ 
+ static void
+ e1000_phy_disable_receiver(struct e1000_adapter *adapter)
+ {
+ 	/* Write out to PHY registers 29 and 30 to disable the Receiver. */
+ 	e1000_write_phy_reg(&adapter->hw, 29, 0x001F);
+ 	e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC);
+ 	e1000_write_phy_reg(&adapter->hw, 29, 0x001A);
+ 	e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0);
+ 
+ 	return;
+ }
+ 
+ static void
+ e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
+ {
+ 	uint16_t phy_reg;
+ 
+ 	/* Because we reset the PHY above, we need to re-force TX_CLK in the
+ 	 * Extended PHY Specific Control Register to 25MHz clock.  This
+ 	 * value defaults back to a 2.5MHz clock when the PHY is reset.
+ 	 */
+ 	e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
+ 	phy_reg |= M88E1000_EPSCR_TX_CLK_25;
+ 	e1000_write_phy_reg(&adapter->hw,
+ 		M88E1000_EXT_PHY_SPEC_CTRL, phy_reg);
+ 
+ 	/* In addition, because of the s/w reset above, we need to enable
+ 	 * CRS on TX.  This must be set for both full and half duplex
+ 	 * operation.
+ 	 */
+ 	e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
+ 	phy_reg |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+ 	e1000_write_phy_reg(&adapter->hw,
+ 		M88E1000_PHY_SPEC_CTRL, phy_reg);
+ }
+ 
+ static int
+ e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
+ {
+ 	uint32_t ctrl_reg;
+ 	uint16_t phy_reg;
+ 
+ 	/* Setup the Device Control Register for PHY loopback test. */
+ 
+ 	ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+ 	ctrl_reg |= (E1000_CTRL_ILOS |		/* Invert Loss-Of-Signal */
+ 		     E1000_CTRL_FRCSPD |	/* Set the Force Speed Bit */
+ 		     E1000_CTRL_FRCDPX |	/* Set the Force Duplex Bit */
+ 		     E1000_CTRL_SPD_1000 |	/* Force Speed to 1000 */
+ 		     E1000_CTRL_FD);		/* Force Duplex to FULL */
+ 
+ 	E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);
+ 
+ 	/* Read the PHY Specific Control Register (0x10) */
+ 	e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
+ 
+ 	/* Clear Auto-Crossover bits in PHY Specific Control Register
+ 	 * (bits 6:5).
+ 	 */
+ 	phy_reg &= ~M88E1000_PSCR_AUTO_X_MODE;
+ 	e1000_write_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, phy_reg);
+ 
+ 	/* Perform software reset on the PHY */
+ 	e1000_phy_reset(&adapter->hw);
+ 
+ 	/* Have to setup TX_CLK and TX_CRS after software reset */
+ 	e1000_phy_reset_clk_and_crs(adapter);
+ 
+ 	e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8100);
+ 
+ 	/* Wait for reset to complete. */
+ 	udelay(500);
+ 
+ 	/* Have to setup TX_CLK and TX_CRS after software reset */
+ 	e1000_phy_reset_clk_and_crs(adapter);
+ 
+ 	/* Write out to PHY registers 29 and 30 to disable the Receiver. */
+ 	e1000_phy_disable_receiver(adapter);
+ 
+ 	/* Set the loopback bit in the PHY control register. */
+ 	e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+ 	phy_reg |= MII_CR_LOOPBACK;
+ 	e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
+ 
+ 	/* Setup TX_CLK and TX_CRS one more time. */
+ 	e1000_phy_reset_clk_and_crs(adapter);
+ 
+ 	/* Check Phy Configuration */
+ 	e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+ 	if(phy_reg != 0x4100)
+ 		 return 9;
+ 
+ 	e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
+ 	if(phy_reg != 0x0070)
+ 		return 10;
+ 
+ 	e1000_read_phy_reg(&adapter->hw, 29, &phy_reg);
+ 	if(phy_reg != 0x001A)
+ 		return 11;
+ 
+ 	return 0;
+ }
+ 
+ static int
+ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ {
+ 	uint32_t ctrl_reg = 0;
+ 	uint32_t stat_reg = 0;
+ 
+ 	adapter->hw.autoneg = FALSE;
+ 
+ 	if(adapter->hw.phy_type == e1000_phy_m88) {
+ 		/* Auto-MDI/MDIX Off */
+ 		e1000_write_phy_reg(&adapter->hw,
+ 				    M88E1000_PHY_SPEC_CTRL, 0x0808);
+ 		/* reset to update Auto-MDI/MDIX */
+ 		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x9140);
+ 		/* autoneg off */
+ 		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8140);
+ 	}
+ 	/* force 1000, set loopback */
+ 	e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140);
+ 
+ 	/* Now set up the MAC to the same speed/duplex as the PHY. */
+ 	ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+ 	ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
+ 	ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
+ 		     E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
+ 		     E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
+ 		     E1000_CTRL_FD);	 /* Force Duplex to FULL */
+ 
+ 	if(adapter->hw.media_type == e1000_media_type_copper &&
+ 	   adapter->hw.phy_type == e1000_phy_m88) {
+ 		ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
+ 	} else {
+ 		/* Set the ILOS bit on the fiber Nic is half
+ 		 * duplex link is detected. */
+ 		stat_reg = E1000_READ_REG(&adapter->hw, STATUS);
+ 		if((stat_reg & E1000_STATUS_FD) == 0)
+ 			ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
+ 	}
+ 
+ 	E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);
+ 
+ 	/* Disable the receiver on the PHY so when a cable is plugged in, the
+ 	 * PHY does not begin to autoneg when a cable is reconnected to the NIC.
+ 	 */
+ 	if(adapter->hw.phy_type == e1000_phy_m88)
+ 		e1000_phy_disable_receiver(adapter);
+ 
+ 	udelay(500);
+ 
+ 	return 0;
+ }
+ 
+ static int
+ e1000_set_phy_loopback(struct e1000_adapter *adapter)
+ {
+ 	uint16_t phy_reg = 0;
+ 	uint16_t count = 0;
+ 
+ 	switch (adapter->hw.mac_type) {
+ 	case e1000_82543:
+ 		if(adapter->hw.media_type == e1000_media_type_copper) {
+ 			/* Attempt to setup Loopback mode on Non-integrated PHY.
+ 			 * Some PHY registers get corrupted at random, so
+ 			 * attempt this 10 times.
+ 			 */
+ 			while(e1000_nonintegrated_phy_loopback(adapter) &&
+ 			      count++ < 10);
+ 			if(count < 11)
+ 				return 0;
+ 		}
+ 		break;
+ 
+ 	case e1000_82544:
+ 	case e1000_82540:
+ 	case e1000_82545:
+ 	case e1000_82546:
+ 	case e1000_82541:
+ 	case e1000_82547:
+ 		return e1000_integrated_phy_loopback(adapter);
+ 		break;
+ 
+ 	default:
+ 		/* Default PHY loopback work is to read the MII
+ 		 * control register and assert bit 14 (loopback mode).
+ 		 */
+ 		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+ 		phy_reg |= MII_CR_LOOPBACK;
+ 		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
+ 		return 0;
+ 		break;
+ 	}
+ 
+ 	return 8;
+ }
+ 
+ static int
+ e1000_setup_loopback_test(struct e1000_adapter *adapter)
+ {
+ 	uint32_t rctl;
+ 
+ 	if(adapter->hw.media_type == e1000_media_type_fiber) {
+ 		if(adapter->hw.mac_type == e1000_82545 ||
+ 		   adapter->hw.mac_type == e1000_82546)
+ 			return e1000_set_phy_loopback(adapter);
+ 		else {
+ 			rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ 			rctl |= E1000_RCTL_LBM_TCVR;
+ 			E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ 			return 0;
+ 		}
+ 	} else if(adapter->hw.media_type == e1000_media_type_copper)
+ 		return e1000_set_phy_loopback(adapter);
+ 
+ 	return 7;
+ }
+ 
+ static void
+ e1000_loopback_cleanup(struct e1000_adapter *adapter)
+ {
+ 	uint32_t rctl;
+ 	uint16_t phy_reg;
+ 
+ 	rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ 	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
+ 	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ 
+ 	if(adapter->hw.media_type == e1000_media_type_copper ||
+ 	   (adapter->hw.media_type == e1000_media_type_fiber &&
+ 	    (adapter->hw.mac_type == e1000_82545 ||
+ 	     adapter->hw.mac_type == e1000_82546))) {
+ 		adapter->hw.autoneg = TRUE;
+ 		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+ 		if(phy_reg & MII_CR_LOOPBACK) {
+ 			phy_reg &= ~MII_CR_LOOPBACK;
+ 			e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
+ 			e1000_phy_reset(&adapter->hw);
+ 		}
+ 	}
+ }
+ 
+ static void
+ e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+ {
+ 	memset(skb->data, 0xFF, frame_size);
+ 	frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
+ 	memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
+ 	memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);
+ 	memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
+ }
+ 
+ static int
+ e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+ {
+ 	frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
+ 	if(*(skb->data + 3) == 0xFF) {
+ 		if((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
+ 		   (*(skb->data + frame_size / 2 + 12) == 0xAF)) {
+ 			return 0;
+ 		}
+ 	}
+ 	return 13;
+ }
+ 
+ static int
+ e1000_run_loopback_test(struct e1000_adapter *adapter)
+ {
+ 	struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
+ 	struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+ 	struct pci_dev *pdev = adapter->pdev;
+ 	int i;
+ 
+ 	E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
+ 
+ 	for(i = 0; i < 64; i++) {
+ 		e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024);
+ 		pci_dma_sync_single(pdev, txdr->buffer_info[i].dma,
+ 				    txdr->buffer_info[i].length,
+ 				    PCI_DMA_TODEVICE);
+ 	}
+ 	E1000_WRITE_REG(&adapter->hw, TDT, i);
+ 
+ 	msec_delay(200);
+ 
+ 	pci_dma_sync_single(pdev, rxdr->buffer_info[0].dma,
+ 			    rxdr->buffer_info[0].length, PCI_DMA_FROMDEVICE);
+ 
+ 	return e1000_check_lbtest_frame(rxdr->buffer_info[0].skb, 1024);
+ }
+ 
+ static int
+ e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
+ {
+ 	if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback;
+ 	if((*data = e1000_setup_loopback_test(adapter))) goto err_loopback;
+ 	*data = e1000_run_loopback_test(adapter);
+ 	e1000_loopback_cleanup(adapter);
+ 	e1000_free_desc_rings(adapter);
+ err_loopback:
+ 	return *data;
+ }
+ 
+ static int
+ e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
+ {
+ 	*data = 0;
+ 	e1000_check_for_link(&adapter->hw);
+ 
+ 	if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
+ 		*data = 1;
+ 	}
+ 	return *data;
+ }
+ 
+ static int
+ e1000_ethtool_test(struct e1000_adapter *adapter,
+ 		   struct ethtool_test *eth_test, uint64_t *data)
+ {
+ 	boolean_t if_running = netif_running(adapter->netdev);
+ 
+ 	if(eth_test->flags == ETH_TEST_FL_OFFLINE) {
+ 		/* Offline tests */
+ 
+ 		/* Link test performed before hardware reset so autoneg doesn't
+ 		 * interfere with test result */
+ 		if(e1000_link_test(adapter, &data[4]))
+ 			eth_test->flags |= ETH_TEST_FL_FAILED;
+ 
+ 		if(if_running)
+ 			e1000_down(adapter);
+ 		else
+ 			e1000_reset(adapter);
+ 		
+ 		if(e1000_reg_test(adapter, &data[0]))
+ 			eth_test->flags |= ETH_TEST_FL_FAILED;
+ 
+ 		e1000_reset(adapter);
+ 		if(e1000_eeprom_test(adapter, &data[1]))
+ 			eth_test->flags |= ETH_TEST_FL_FAILED;
+ 
+ 		e1000_reset(adapter);
+ 		if(e1000_intr_test(adapter, &data[2]))
+ 			eth_test->flags |= ETH_TEST_FL_FAILED;
+ 
+ 		e1000_reset(adapter);
+ 		if(e1000_loopback_test(adapter, &data[3]))
+ 			eth_test->flags |= ETH_TEST_FL_FAILED;
+ 
+ 		e1000_reset(adapter);
+ 		if(if_running)
+ 			e1000_up(adapter);
+ 	} else {
+ 		/* Online tests */
+ 		if(e1000_link_test(adapter, &data[4]))
+ 			eth_test->flags |= ETH_TEST_FL_FAILED;
+ 
+ 		/* Offline tests aren't run; pass by default */
+ 		data[0] = 0;
+ 		data[1] = 0;
+ 		data[2] = 0;
+ 		data[3] = 0;
+ 	}
+ 	return 0;
+ }
+ 
  static void
  e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
  {
***************
*** 427,434 ****
  	}
  	case ETHTOOL_SSET: {
  		struct ethtool_cmd ecmd;
- 		if(!capable(CAP_NET_ADMIN))
- 			return -EPERM;
  		if(copy_from_user(&ecmd, addr, sizeof(ecmd)))
  			return -EFAULT;
  		return e1000_ethtool_sset(adapter, &ecmd);
--- 1290,1295 ----
***************
*** 443,466 ****
  	case ETHTOOL_GSTRINGS: {
  		struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS };
  		char *strings = NULL;
  
  		if(copy_from_user(&gstrings, addr, sizeof(gstrings)))
  			return -EFAULT;
  		switch(gstrings.string_set) {
! 		case ETH_SS_STATS:
  			gstrings.len = E1000_STATS_LEN;
! 			strings = *e1000_gstrings_stats;
  			break;
  		default:
  			return -EOPNOTSUPP;
  		}
  		if(copy_to_user(addr, &gstrings, sizeof(gstrings)))
! 			return -EFAULT;
  		addr += offsetof(struct ethtool_gstrings, data);
! 		if(copy_to_user(addr, strings,
  		   gstrings.len * ETH_GSTRING_LEN))
! 			return -EFAULT;
! 		return 0;
  	}
  	case ETHTOOL_GREGS: {
  		struct ethtool_regs regs = {ETHTOOL_GREGS};
--- 1304,1349 ----
  	case ETHTOOL_GSTRINGS: {
  		struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS };
  		char *strings = NULL;
+ 		int err = 0;
  
  		if(copy_from_user(&gstrings, addr, sizeof(gstrings)))
  			return -EFAULT;
  		switch(gstrings.string_set) {
! 		case ETH_SS_TEST:
! 			gstrings.len = E1000_TEST_LEN;
! 			strings = kmalloc(E1000_TEST_LEN * ETH_GSTRING_LEN,
! 					  GFP_KERNEL);
! 			if(!strings)
! 				return -ENOMEM;
! 			memcpy(strings, e1000_gstrings_test, E1000_TEST_LEN *
! 			       ETH_GSTRING_LEN);
! 			break;
! 		case ETH_SS_STATS: {
! 			int i;
  			gstrings.len = E1000_STATS_LEN;
! 			strings = kmalloc(E1000_STATS_LEN * ETH_GSTRING_LEN,
! 					  GFP_KERNEL);
! 			if(!strings)
! 				return -ENOMEM;
! 			for(i=0; i < E1000_STATS_LEN; i++) {
! 				memcpy(&strings[i * ETH_GSTRING_LEN],
! 				       e1000_gstrings_stats[i].stat_string,
! 				       ETH_GSTRING_LEN);
! 			}
  			break;
+ 		}
  		default:
  			return -EOPNOTSUPP;
  		}
  		if(copy_to_user(addr, &gstrings, sizeof(gstrings)))
! 			err = -EFAULT;
  		addr += offsetof(struct ethtool_gstrings, data);
! 		if(!err && copy_to_user(addr, strings,
  		   gstrings.len * ETH_GSTRING_LEN))
! 			err = -EFAULT;
! 
! 		kfree(strings);
! 		return err;
  	}
  	case ETHTOOL_GREGS: {
  		struct ethtool_regs regs = {ETHTOOL_GREGS};
***************
*** 479,486 ****
  		return 0;
  	}
  	case ETHTOOL_NWAY_RST: {
- 		if(!capable(CAP_NET_ADMIN))
- 			return -EPERM;
  		if(netif_running(netdev)) {
  			e1000_down(adapter);
  			e1000_up(adapter);
--- 1362,1367 ----
***************
*** 509,516 ****
  	}
  	case ETHTOOL_SWOL: {
  		struct ethtool_wolinfo wol;
- 		if(!capable(CAP_NET_ADMIN))
- 			return -EPERM;
  		if(copy_from_user(&wol, addr, sizeof(wol)) != 0)
  			return -EFAULT;
  		return e1000_ethtool_swol(adapter, &wol);
--- 1390,1395 ----
***************
*** 522,537 ****
  		void *ptr;
  		int err = 0;
  
  		eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL);
  
! 		if(eeprom_buff == NULL)
  			return -ENOMEM;
  
- 		if(copy_from_user(&eeprom, addr, sizeof(eeprom))) {
- 			err = -EFAULT;
- 			goto err_geeprom_ioctl;
- 		}
- 
  		if((err = e1000_ethtool_geeprom(adapter, &eeprom,
  						eeprom_buff)))
  			goto err_geeprom_ioctl;
--- 1401,1414 ----
  		void *ptr;
  		int err = 0;
  
+ 		if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
+ 			return -EFAULT;
+ 
  		eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL);
  
! 		if(!eeprom_buff)
  			return -ENOMEM;
  
  		if((err = e1000_ethtool_geeprom(adapter, &eeprom,
  						eeprom_buff)))
  			goto err_geeprom_ioctl;
***************
*** 554,562 ****
  	case ETHTOOL_SEEPROM: {
  		struct ethtool_eeprom eeprom;
  
- 		if(!capable(CAP_NET_ADMIN))
- 			return -EPERM;
- 
  		if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
  			return -EFAULT;
  
--- 1431,1436 ----
***************
*** 565,582 ****
  	}
  	case ETHTOOL_GSTATS: {
  		struct {
! 			struct ethtool_stats cmd;
  			uint64_t data[E1000_STATS_LEN];
  		} stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} };
  		int i;
  
  		for(i = 0; i < E1000_STATS_LEN; i++)
! 			stats.data[i] =
! 				((unsigned long *)&adapter->net_stats)[i];
  		if(copy_to_user(addr, &stats, sizeof(stats)))
  			return -EFAULT;
  		return 0;
  	}
  	default:
  		return -EOPNOTSUPP;
  	}
--- 1439,1480 ----
  	}
  	case ETHTOOL_GSTATS: {
  		struct {
! 			struct ethtool_stats eth_stats;
  			uint64_t data[E1000_STATS_LEN];
  		} stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} };
  		int i;
  
  		for(i = 0; i < E1000_STATS_LEN; i++)
! 			stats.data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
! 					sizeof(uint64_t)) ?
! 				*(uint64_t *)((char *)adapter +
! 					e1000_gstrings_stats[i].stat_offset) :
! 				*(uint32_t *)((char *)adapter +
! 					e1000_gstrings_stats[i].stat_offset);
  		if(copy_to_user(addr, &stats, sizeof(stats)))
  			return -EFAULT;
  		return 0;
  	}
+ 	case ETHTOOL_TEST: {
+ 		struct {
+ 			struct ethtool_test eth_test;
+ 			uint64_t data[E1000_TEST_LEN];
+ 		} test = { {ETHTOOL_TEST} };
+ 		int err;
+ 
+ 		if(copy_from_user(&test.eth_test, addr, sizeof(test.eth_test)))
+ 			return -EFAULT;
+ 
+ 		test.eth_test.len = E1000_TEST_LEN;
+ 
+ 		if((err = e1000_ethtool_test(adapter, &test.eth_test,
+ 					     test.data)))
+ 			return err;
+ 
+ 		if(copy_to_user(addr, &test, sizeof(test)) != 0)
+ 			return -EFAULT;
+ 		return 0;
+ 	}
  	default:
  		return -EOPNOTSUPP;
  	}
diff -Ncr linux-2.4.22-old/drivers/net/e1000/e1000_hw.c linux-2.4.22/drivers/net/e1000/e1000_hw.c
*** linux-2.4.22-old/drivers/net/e1000/e1000_hw.c	2003-11-18 17:02:21.000000000 +0900
--- linux-2.4.22/drivers/net/e1000/e1000_hw.c	2003-08-25 20:44:42.000000000 +0900
***************
*** 135,140 ****
--- 135,175 ----
  
          e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000);
          e1000_write_phy_reg(hw,0x0000,0x3300);
+ 
+ 
+         if(hw->mac_type == e1000_82547) {
+             uint16_t fused, fine, coarse;
+ 
+             /* Move to analog registers page */
+             e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 
+                                 IGP01E1000_ANALOG_REGS_PAGE);
+ 
+             e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused);
+ 
+             if(!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
+                 e1000_read_phy_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);
+ 
+                 e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_CONTROL, fused);
+                 e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS, 
+                                     IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
+             }
+             /* Return to first page of registers */
+             e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+                                 IGP01E1000_IEEE_REGS_PAGE);
+         }
      }
  }
  
***************
*** 185,190 ****
--- 220,226 ----
          break;
      case E1000_DEV_ID_82546EB_COPPER:
      case E1000_DEV_ID_82546EB_FIBER:
+     case E1000_DEV_ID_82546EB_QUAD_COPPER:
          hw->mac_type = e1000_82546;
          break;
      case E1000_DEV_ID_82541EI:
***************
*** 258,267 ****
  	msec_delay(5);
      }
  
!     if(hw->mac_type > e1000_82543)
!         E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
!     else
!         E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
  
      /* Force a reload from the EEPROM if necessary */
      if(hw->mac_type < e1000_82540) {
--- 294,313 ----
  	msec_delay(5);
      }
  
!     switch(hw->mac_type) {
!         case e1000_82544:
!         case e1000_82540:
!         case e1000_82545:
!         case e1000_82546:
!         case e1000_82541:
!             /* These controllers can't ack the 64-bit write when issuing the
!              * reset, so use IO-mapping as a workaround to issue the reset */
!             E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
!             break;
!         default:
!             E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
!             break;
!     }
  
      /* Force a reload from the EEPROM if necessary */
      if(hw->mac_type < e1000_82540) {
***************
*** 288,296 ****
          /* Configure activity LED after PHY reset */
          led_ctrl = E1000_READ_REG(hw, LEDCTL);
          led_ctrl &= IGP_ACTIVITY_LED_MASK;
!         led_ctrl |= IGP_ACTIVITY_LED_ENABLE;
!         if(hw->mac_type == e1000_82547)
!             led_ctrl |= IGP_LED3_MODE;
          E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
      }
  
--- 334,340 ----
          /* Configure activity LED after PHY reset */
          led_ctrl = E1000_READ_REG(hw, LEDCTL);
          led_ctrl &= IGP_ACTIVITY_LED_MASK;
!         led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
          E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
      }
  
***************
*** 688,694 ****
  static int32_t
  e1000_setup_copper_link(struct e1000_hw *hw)
  {
!     uint32_t ctrl, led_ctrl;
      int32_t ret_val;
      uint16_t i;
      uint16_t phy_data;
--- 732,739 ----
  static int32_t
  e1000_setup_copper_link(struct e1000_hw *hw)
  {
!     uint32_t ctrl;
!     uint32_t led_ctrl;
      int32_t ret_val;
      uint16_t i;
      uint16_t phy_data;
***************
*** 737,745 ****
          /* Configure activity LED after PHY reset */
          led_ctrl = E1000_READ_REG(hw, LEDCTL);
          led_ctrl &= IGP_ACTIVITY_LED_MASK;
!         led_ctrl |= IGP_ACTIVITY_LED_ENABLE;
!         if(hw->mac_type == e1000_82547)
!             led_ctrl |= IGP_LED3_MODE;
          E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
  
          if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {
--- 782,788 ----
          /* Configure activity LED after PHY reset */
          led_ctrl = E1000_READ_REG(hw, LEDCTL);
          led_ctrl &= IGP_ACTIVITY_LED_MASK;
!         led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
          E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
  
          if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {
***************
*** 2252,2258 ****
  void
  e1000_phy_hw_reset(struct e1000_hw *hw)
  {
!     uint32_t ctrl, ctrl_ext, led_ctrl;
  
      DEBUGFUNC("e1000_phy_hw_reset");
  
--- 2295,2302 ----
  void
  e1000_phy_hw_reset(struct e1000_hw *hw)
  {
!     uint32_t ctrl, ctrl_ext;
!     uint32_t led_ctrl;
  
      DEBUGFUNC("e1000_phy_hw_reset");
  
***************
*** 2293,2301 ****
          /* Configure activity LED after PHY reset */
          led_ctrl = E1000_READ_REG(hw, LEDCTL);
          led_ctrl &= IGP_ACTIVITY_LED_MASK;
!         led_ctrl |= IGP_ACTIVITY_LED_ENABLE;
!         if(hw->mac_type == e1000_82547)
!             led_ctrl |= IGP_LED3_MODE;
          E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
      }
  }
--- 2337,2343 ----
          /* Configure activity LED after PHY reset */
          led_ctrl = E1000_READ_REG(hw, LEDCTL);
          led_ctrl &= IGP_ACTIVITY_LED_MASK;
!         led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
          E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
      }
  }
***************
*** 3801,3806 ****
--- 3843,3849 ----
      case E1000_DEV_ID_82540EM_LOM:
      case E1000_DEV_ID_82545EM_COPPER:
      case E1000_DEV_ID_82546EB_COPPER:
+     case E1000_DEV_ID_82546EB_QUAD_COPPER:
      case E1000_DEV_ID_82541EI:
      case E1000_DEV_ID_82541EP:
      case E1000_DEV_ID_82547EI:
***************
*** 3842,3847 ****
--- 3885,3891 ----
      case E1000_DEV_ID_82545EM_FIBER:
      case E1000_DEV_ID_82546EB_COPPER:
      case E1000_DEV_ID_82546EB_FIBER:
+     case E1000_DEV_ID_82546EB_QUAD_COPPER:
      case E1000_DEV_ID_82541EI:
      case E1000_DEV_ID_82541EP:
      case E1000_DEV_ID_82547EI:
***************
*** 3896,3901 ****
--- 3940,3946 ----
      case E1000_DEV_ID_82540EM_LOM:
      case E1000_DEV_ID_82545EM_COPPER:
      case E1000_DEV_ID_82546EB_COPPER:
+     case E1000_DEV_ID_82546EB_QUAD_COPPER:
      case E1000_DEV_ID_82541EI:
      case E1000_DEV_ID_82541EP:
      case E1000_DEV_ID_82547EI:
***************
*** 3949,3954 ****
--- 3994,4000 ----
      case E1000_DEV_ID_82540EM_LOM:
      case E1000_DEV_ID_82545EM_COPPER:
      case E1000_DEV_ID_82546EB_COPPER:
+     case E1000_DEV_ID_82546EB_QUAD_COPPER:
      case E1000_DEV_ID_82541EI:
      case E1000_DEV_ID_82541EP:
      case E1000_DEV_ID_82547EI:
***************
*** 4206,4212 ****
      status = E1000_READ_REG(hw, STATUS);
      hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
                     e1000_bus_type_pcix : e1000_bus_type_pci;
!     if(hw->bus_type == e1000_bus_type_pci) {
          hw->bus_speed = (status & E1000_STATUS_PCI66) ?
                          e1000_bus_speed_66 : e1000_bus_speed_33;
      } else {
--- 4252,4262 ----
      status = E1000_READ_REG(hw, STATUS);
      hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
                     e1000_bus_type_pcix : e1000_bus_type_pci;
! 
!     if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
!         hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
!                         e1000_bus_speed_66 : e1000_bus_speed_120;
!     } else if(hw->bus_type == e1000_bus_type_pci) {
          hw->bus_speed = (status & E1000_STATUS_PCI66) ?
                          e1000_bus_speed_66 : e1000_bus_speed_33;
      } else {
diff -Ncr linux-2.4.22-old/drivers/net/e1000/e1000_hw.h linux-2.4.22/drivers/net/e1000/e1000_hw.h
*** linux-2.4.22-old/drivers/net/e1000/e1000_hw.h	2003-11-18 17:22:41.000000000 +0900
--- linux-2.4.22/drivers/net/e1000/e1000_hw.h	2003-08-25 20:44:42.000000000 +0900
***************
*** 99,104 ****
--- 99,105 ----
      e1000_bus_speed_33,
      e1000_bus_speed_66,
      e1000_bus_speed_100,
+     e1000_bus_speed_120,
      e1000_bus_speed_133,
      e1000_bus_speed_reserved
  } e1000_bus_speed;
***************
*** 314,323 ****
  #define E1000_DEV_ID_82545EM_FIBER       0x1011
  #define E1000_DEV_ID_82546EB_COPPER      0x1010
  #define E1000_DEV_ID_82546EB_FIBER       0x1012
  #define E1000_DEV_ID_82541EI             0x1013
  #define E1000_DEV_ID_82541EP             0x1018
  #define E1000_DEV_ID_82547EI             0x1019
! #define NUM_DEV_IDS 19
  
  #define NODE_ADDRESS_SIZE 6
  #define ETH_LENGTH_OF_ADDRESS 6
--- 315,325 ----
  #define E1000_DEV_ID_82545EM_FIBER       0x1011
  #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_82541EI             0x1013
  #define E1000_DEV_ID_82541EP             0x1018
  #define E1000_DEV_ID_82547EI             0x1019
! #define NUM_DEV_IDS 20
  
  #define NODE_ADDRESS_SIZE 6
  #define ETH_LENGTH_OF_ADDRESS 6
***************
*** 601,607 ****
  #define E1000_EECD     0x00010  /* EEPROM/Flash Control - RW */
  #define E1000_EERD     0x00014  /* EEPROM Read - RW */
  #define E1000_CTRL_EXT 0x00018  /* Extended Device Control - RW */
! #define E1000_FLA      0x0001C  /* Flash Access Register - RW */
  #define E1000_MDIC     0x00020  /* MDI Control - RW */
  #define E1000_FCAL     0x00028  /* Flow Control Address Low - RW */
  #define E1000_FCAH     0x0002C  /* Flow Control Address High -RW */
--- 603,609 ----
  #define E1000_EECD     0x00010  /* EEPROM/Flash Control - RW */
  #define E1000_EERD     0x00014  /* EEPROM Read - RW */
  #define E1000_CTRL_EXT 0x00018  /* Extended Device Control - RW */
! #define E1000_FLA      0x0001C  /* Flash Access - RW */
  #define E1000_MDIC     0x00020  /* MDI Control - RW */
  #define E1000_FCAL     0x00028  /* Flow Control Address Low - RW */
  #define E1000_FCAH     0x0002C  /* Flow Control Address High -RW */
***************
*** 730,735 ****
--- 732,738 ----
   * the registers function in the same manner.
   */
  #define E1000_82542_CTRL     E1000_CTRL
+ #define E1000_82542_CTRL_DUP E1000_CTRL_DUP
  #define E1000_82542_STATUS   E1000_STATUS
  #define E1000_82542_EECD     E1000_EECD
  #define E1000_82542_EERD     E1000_EERD
***************
*** 1485,1491 ****
  #define E1000_COLLISION_DISTANCE        64
  #define E1000_FDX_COLLISION_DISTANCE    E1000_COLLISION_DISTANCE
  #define E1000_HDX_COLLISION_DISTANCE    E1000_COLLISION_DISTANCE
- #define E1000_GB_HDX_COLLISION_DISTANCE 512
  #define E1000_COLD_SHIFT                12
  
  /* The number of Transmit and Receive Descriptors must be a multiple of 8 */
--- 1488,1493 ----
***************
*** 1666,1671 ****
--- 1668,1674 ----
  #define M88E1000_EXT_PHY_SPEC_CTRL 0x14  /* Extended PHY Specific Control */
  #define M88E1000_RX_ERR_CNTR       0x15  /* Receive Error Counter */
  
+ #define IGP01E1000_IEEE_REGS_PAGE  0x0000
  /* IGP01E1000 Specific Registers */
  #define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */
  #define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */
***************
*** 1688,1693 ****
--- 1691,1697 ----
   * speed = 1000 Mbps. */
  #define IGP01E1000_PHY_PCS_INIT_REG  0x00B4
  
+ #define IGP01E1000_ANALOG_REGS_PAGE  0x20C0
  
  #define MAX_PHY_REG_ADDRESS 0x1F        /* 5 bit address bus (0-0x1F) */
  
***************
*** 1978,1983 ****
--- 1982,2003 ----
  #define IGP01E1000_GMII_FLEX_SPD               0x10 /* Enable flexible speed
                                                       * on Link-Up */
  #define IGP01E1000_GMII_SPD                    0x20 /* Enable SPD */
+ /* IGP01E1000 Analog Register */
+ #define IGP01E1000_ANALOG_SPARE_FUSE_STATUS         0x0011
+ #define IGP01E1000_ANALOG_FUSE_STATUS               0x0010
+ #define IGP01E1000_ANALOG_FUSE_CONTROL              0x001C
+ #define IGP01E1000_ANALOG_FUSE_BYPASS               0x001E
+ 
+ #define IGP01E1000_ANALOG_FUSE_POLY_MASK            0xF000
+ #define IGP01E1000_ANALOG_FUSE_FINE_MASK            0x0F80
+ #define IGP01E1000_ANALOG_FUSE_COARSE_MASK          0x0070
+ #define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED        0x0100
+ #define IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL    0x0002
+ 
+ #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
  
  /* Bit definitions for valid PHY IDs. */
  #define M88E1000_E_PHY_ID  0x01410C50
diff -Ncr linux-2.4.22-old/drivers/net/e1000/e1000_main.c linux-2.4.22/drivers/net/e1000/e1000_main.c
*** linux-2.4.22-old/drivers/net/e1000/e1000_main.c	2003-11-18 17:02:24.000000000 +0900
--- linux-2.4.22/drivers/net/e1000/e1000_main.c	2003-08-25 20:44:42.000000000 +0900
***************
*** 30,96 ****
  
  /* Change Log
   *
!  * 5.0.43	3/5/03
!  *   o Feature: Added support for 82541 and 82547 hardware.
!  *   o Feature: Added support for Intel Gigabit PHY (IGP) and a variety of
!  *   eeproms.
!  *   o Feature: Added support for TCP Segmentation Offload (TSO).
!  *   o Feature: Added MII ioctl.
!  *   o Feature: Added support for statistics reporting through ethtool.
!  *   o Cleanup: Removed proprietary hooks for ANS.
!  *   o Cleanup: Miscellaneous code changes to improve CPU utilization.
!  *   	- Replaced "%" with conditionals and "+-" operators.
!  *   	- Implemented dynamic Interrupt Throttle Rate (ITR).
!  *   	- Reduced expensive PCI reads of ICR in interrupt.
!  *   o Bug fix: Request IRQ after descriptor ring setup to avoid panic in
!  *   shared interrupt instances.
!  *
!  * 4.4.18       11/27/02
!  *   o Feature: Added user-settable knob for interrupt throttle rate (ITR).
!  *   o Cleanup: removed large static array allocations.
!  *   o Cleanup: C99 struct initializer format.
!  *   o Bug fix: restore VLAN settings when interface is brought up.
!  *   o Bug fix: return cleanly in probe if error in detecting MAC type.
!  *   o Bug fix: Wake up on magic packet by default only if enabled in eeprom.
!  *   o Bug fix: Validate MAC address in set_mac.
!  *   o Bug fix: Throw away zero-length Tx skbs.
!  *   o Bug fix: Make ethtool EEPROM acceses work on older versions of ethtool.
!  * 
!  * 4.4.12       10/15/02
   */
  
  char e1000_driver_name[] = "e1000";
  char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
! char e1000_driver_version[] = "5.0.43-k1";
  char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation.";
  
  /* e1000_pci_tbl - PCI Device ID Table
   *
-  * Private driver_data field (last one) stores an index into e1000_strings
   * Wildcard entries (PCI_ANY_ID) should come last
   * Last entry must be all 0s
   *
   * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
!  *   Class, Class Mask, String Index }
   */
  static struct pci_device_id e1000_pci_tbl[] __devinitdata = {
- 	/* Intel(R) PRO/1000 Network Connection */
- 	{0x8086, 0x1000, 0x8086, 0x1000, 0, 0, 0},
- 	{0x8086, 0x1001, 0x8086, 0x1003, 0, 0, 0},
- 	{0x8086, 0x1004, 0x8086, 0x1004, 0, 0, 0},
- 	{0x8086, 0x1008, 0x8086, 0x1107, 0, 0, 0},
- 	{0x8086, 0x1009, 0x8086, 0x1109, 0, 0, 0},
- 	{0x8086, 0x100C, 0x8086, 0x1112, 0, 0, 0},
- 	{0x8086, 0x100E, 0x8086, 0x001E, 0, 0, 0},
- 	/* Compaq Gigabit Ethernet Server Adapter */
- 	{0x8086, 0x1000, 0x0E11, PCI_ANY_ID, 0, 0, 1},
- 	{0x8086, 0x1001, 0x0E11, PCI_ANY_ID, 0, 0, 1},
- 	{0x8086, 0x1004, 0x0E11, PCI_ANY_ID, 0, 0, 1},
- 	/* IBM Mobile, Desktop & Server Adapters */
- 	{0x8086, 0x1000, 0x1014, PCI_ANY_ID, 0, 0, 2},
- 	{0x8086, 0x1001, 0x1014, PCI_ANY_ID, 0, 0, 2},
- 	{0x8086, 0x1004, 0x1014, PCI_ANY_ID, 0, 0, 2},
- 	/* Generic */
  	{0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
  	{0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
  	{0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
--- 30,67 ----
  
  /* Change Log
   *
!  * 5.1.13	5/28/03
!  *   o Bug fix: request_irq() failure resulted in freeing resources twice!
!  *     [Don Fry (brazilnut@us.ibm.com)]
!  *   o Bug fix: fix VLAN support on ppc64 [Mark Rakes (mrakes@vivato.net)]
!  *   o Bug fix: missing Tx cleanup opportunities during interrupt handling.
!  *   o Bug fix: alloc_etherdev failure didn't cleanup regions in probe.
!  *   o Cleanup: s/int/unsigned int/ for descriptor ring indexes.
!  *   
!  * 5.1.11	5/6/03
!  *   o Feature: Added support for 82546EB (Quad-port) hardware.
!  *   o Feature: Added support for Diagnostics through Ethtool.
!  *   o Cleanup: Removed /proc support.
!  *   o Cleanup: Removed proprietary IDIAG interface.
!  *   o Bug fix: TSO bug fixes.
!  *
!  * 5.0.42	3/5/03
   */
  
  char e1000_driver_name[] = "e1000";
  char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
! char e1000_driver_version[] = "5.1.13-k1";
  char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation.";
  
  /* e1000_pci_tbl - PCI Device ID Table
   *
   * Wildcard entries (PCI_ANY_ID) should come last
   * Last entry must be all 0s
   *
   * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
!  *   Class, Class Mask, private data (not used) }
   */
  static struct pci_device_id e1000_pci_tbl[] __devinitdata = {
  	{0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
  	{0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
  	{0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
***************
*** 106,111 ****
--- 77,83 ----
  	{0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
  	{0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
  	{0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ 	{0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
  	{0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
  	{0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
  	/* required last entry */
***************
*** 114,125 ****
  
  MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
  
- static char *e1000_strings[] = {
- 	"Intel(R) PRO/1000 Network Connection",
- 	"HP Gigabit Ethernet Server Adapter",
- 	"IBM Mobile, Desktop & Server Adapters"
- };
- 
  /* Local Function Prototypes */
  
  int e1000_up(struct e1000_adapter *adapter);
--- 86,91 ----
***************
*** 130,136 ****
  static int e1000_init_module(void);
  static void e1000_exit_module(void);
  static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
! static void e1000_remove(struct pci_dev *pdev);
  static int e1000_sw_init(struct e1000_adapter *adapter);
  static int e1000_open(struct net_device *netdev);
  static int e1000_close(struct net_device *netdev);
--- 96,102 ----
  static int e1000_init_module(void);
  static void e1000_exit_module(void);
  static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
! static void __devexit e1000_remove(struct pci_dev *pdev);
  static int e1000_sw_init(struct e1000_adapter *adapter);
  static int e1000_open(struct net_device *netdev);
  static int e1000_close(struct net_device *netdev);
***************
*** 156,162 ****
--- 122,134 ----
  static inline void e1000_irq_enable(struct e1000_adapter *adapter);
  static void e1000_intr(int irq, void *data, struct pt_regs *regs);
  static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter);
+ #ifdef CONFIG_E1000_NAPI
+ static int e1000_clean(struct net_device *netdev, int *budget);
+ static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+                                     int *work_done, int work_to_do);
+ #else
  static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter);
+ #endif
  static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
  static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
  static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
***************
*** 183,198 ****
  static int e1000_resume(struct pci_dev *pdev);
  #endif
  
- /* for netdump / net console */
- static void e1000_netpoll (struct net_device *dev);
- 
  struct notifier_block e1000_notifier_reboot = {
  	.notifier_call	= e1000_notify_reboot,
  	.next		= NULL,
  	.priority	= 0
  };
  
- 
  /* Exported from other modules */
  
  extern void e1000_check_options(struct e1000_adapter *adapter);
--- 155,166 ----
***************
*** 231,238 ****
  	printk(KERN_INFO "%s\n", e1000_copyright);
  
  	ret = pci_module_init(&e1000_driver);
! 	if(ret >= 0)
  		register_reboot_notifier(&e1000_notifier_reboot);
  	return ret;
  }
  
--- 199,207 ----
  	printk(KERN_INFO "%s\n", e1000_copyright);
  
  	ret = pci_module_init(&e1000_driver);
! 	if(ret >= 0) {
  		register_reboot_notifier(&e1000_notifier_reboot);
+ 	}
  	return ret;
  }
  
***************
*** 272,283 ****
  	e1000_alloc_rx_buffers(adapter);
  
  	if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM,
! 		       netdev->name, netdev)) {
! 		e1000_reset_hw(&adapter->hw);
! 		e1000_free_tx_resources(adapter);
! 		e1000_free_rx_resources(adapter);
  		return -1;
- 	}
  
  	mod_timer(&adapter->watchdog_timer, jiffies);
  	e1000_irq_enable(adapter);
--- 241,248 ----
  	e1000_alloc_rx_buffers(adapter);
  
  	if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM,
! 		       netdev->name, netdev))
  		return -1;
  
  	mod_timer(&adapter->watchdog_timer, jiffies);
  	e1000_irq_enable(adapter);
***************
*** 421,441 ****
  	netdev->do_ioctl = &e1000_ioctl;
  	netdev->tx_timeout = &e1000_tx_timeout;
  	netdev->watchdog_timeo = 5 * HZ;
  	netdev->vlan_rx_register = e1000_vlan_rx_register;
  	netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid;
  	netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid;
  
- #ifdef HAVE_POLL_CONTROLLER
- 	netdev->poll_controller = e1000_netpoll;
- #endif
- 
  	netdev->irq = pdev->irq;
  	netdev->mem_start = mmio_start;
  	netdev->mem_end = mmio_start + mmio_len;
  	netdev->base_addr = adapter->hw.io_base;
  
  	adapter->bd_number = cards_found;
- 	adapter->id_string = e1000_strings[ent->driver_data];
  
  	/* setup the private structure */
  
--- 386,405 ----
  	netdev->do_ioctl = &e1000_ioctl;
  	netdev->tx_timeout = &e1000_tx_timeout;
  	netdev->watchdog_timeo = 5 * HZ;
+ #ifdef CONFIG_E1000_NAPI
+ 	netdev->poll = &e1000_clean;
+ 	netdev->weight = 64;
+ #endif
  	netdev->vlan_rx_register = e1000_vlan_rx_register;
  	netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid;
  	netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid;
  
  	netdev->irq = pdev->irq;
  	netdev->mem_start = mmio_start;
  	netdev->mem_end = mmio_start + mmio_len;
  	netdev->base_addr = adapter->hw.io_base;
  
  	adapter->bd_number = cards_found;
  
  	/* setup the private structure */
  
***************
*** 452,457 ****
--- 416,427 ----
  		netdev->features = NETIF_F_SG;
  	}
  
+ #ifdef NETIF_F_TSO
+ 	if((adapter->hw.mac_type >= e1000_82544) &&
+ 	   (adapter->hw.mac_type != e1000_82547))
+ 		netdev->features |= NETIF_F_TSO;
+ #endif
+ 
  	if(pci_using_dac)
  		netdev->features |= NETIF_F_HIGHDMA;
  
***************
*** 490,504 ****
  		(void (*)(void *))e1000_tx_timeout_task, netdev);
  
  	register_netdev(netdev);
- 	memcpy(adapter->ifname, netdev->name, IFNAMSIZ);
- 	adapter->ifname[IFNAMSIZ-1] = 0;
  
  	/* we're going to reset, so assume we have no link for now */
  
  	netif_carrier_off(netdev);
  	netif_stop_queue(netdev);
  
! 	printk(KERN_INFO "%s: %s\n", netdev->name, adapter->id_string);
  	e1000_check_options(adapter);
  
  	/* Initial Wake on LAN setting
--- 460,473 ----
  		(void (*)(void *))e1000_tx_timeout_task, netdev);
  
  	register_netdev(netdev);
  
  	/* we're going to reset, so assume we have no link for now */
  
  	netif_carrier_off(netdev);
  	netif_stop_queue(netdev);
  
! 	printk(KERN_INFO "%s: Intel(R) PRO/1000 Network Connection\n",
! 	       netdev->name);
  	e1000_check_options(adapter);
  
  	/* Initial Wake on LAN setting
***************
*** 523,531 ****
  err_eeprom:
  	iounmap(adapter->hw.hw_addr);
  err_ioremap:
- 	pci_release_regions(pdev);
  	kfree(netdev);
  err_alloc_etherdev:
  	return -ENOMEM;
  }
  
--- 492,500 ----
  err_eeprom:
  	iounmap(adapter->hw.hw_addr);
  err_ioremap:
  	kfree(netdev);
  err_alloc_etherdev:
+ 	pci_release_regions(pdev);
  	return -ENOMEM;
  }
  
***************
*** 558,564 ****
  
  	e1000_phy_hw_reset(&adapter->hw);
  
- 
  	iounmap(adapter->hw.hw_addr);
  	pci_release_regions(pdev);
  
--- 527,532 ----
***************
*** 821,828 ****
  
  	e1000_config_collision_dist(&adapter->hw);
  
! 	/* Setup Transmit Descriptor Settings for this adapter */
! 	adapter->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_IDE;
  
  	if(adapter->hw.report_tx_early == 1)
  		adapter->txd_cmd |= E1000_TXD_CMD_RS;
--- 789,797 ----
  
  	e1000_config_collision_dist(&adapter->hw);
  
! 	/* Setup Transmit Descriptor Settings for eop descriptor */
! 	adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP |
! 		E1000_TXD_CMD_IFCS;
  
  	if(adapter->hw.report_tx_early == 1)
  		adapter->txd_cmd |= E1000_TXD_CMD_RS;
***************
*** 1000,1034 ****
  static void
  e1000_clean_tx_ring(struct e1000_adapter *adapter)
  {
  	struct pci_dev *pdev = adapter->pdev;
  	unsigned long size;
! 	int i;
  
  	/* Free all the Tx ring sk_buffs */
  
! 	for(i = 0; i < adapter->tx_ring.count; i++) {
! 		if(adapter->tx_ring.buffer_info[i].skb) {
  
  			pci_unmap_page(pdev,
! 			               adapter->tx_ring.buffer_info[i].dma,
! 			               adapter->tx_ring.buffer_info[i].length,
  			               PCI_DMA_TODEVICE);
  
! 			dev_kfree_skb(adapter->tx_ring.buffer_info[i].skb);
  
! 			adapter->tx_ring.buffer_info[i].skb = NULL;
  		}
  	}
  
! 	size = sizeof(struct e1000_buffer) * adapter->tx_ring.count;
! 	memset(adapter->tx_ring.buffer_info, 0, size);
  
  	/* Zero out the descriptor ring */
  
! 	memset(adapter->tx_ring.desc, 0, adapter->tx_ring.size);
  
! 	adapter->tx_ring.next_to_use = 0;
! 	adapter->tx_ring.next_to_clean = 0;
  
  	E1000_WRITE_REG(&adapter->hw, TDH, 0);
  	E1000_WRITE_REG(&adapter->hw, TDT, 0);
--- 969,1006 ----
  static void
  e1000_clean_tx_ring(struct e1000_adapter *adapter)
  {
+ 	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
+ 	struct e1000_buffer *buffer_info;
  	struct pci_dev *pdev = adapter->pdev;
  	unsigned long size;
! 	unsigned int i;
  
  	/* Free all the Tx ring sk_buffs */
  
! 	for(i = 0; i < tx_ring->count; i++) {
! 		buffer_info = &tx_ring->buffer_info[i];
! 		if(buffer_info->skb) {
  
  			pci_unmap_page(pdev,
! 			               buffer_info->dma,
! 			               buffer_info->length,
  			               PCI_DMA_TODEVICE);
  
! 			dev_kfree_skb(buffer_info->skb);
  
! 			buffer_info->skb = NULL;
  		}
  	}
  
! 	size = sizeof(struct e1000_buffer) * tx_ring->count;
! 	memset(tx_ring->buffer_info, 0, size);
  
  	/* Zero out the descriptor ring */
  
! 	memset(tx_ring->desc, 0, tx_ring->size);
  
! 	tx_ring->next_to_use = 0;
! 	tx_ring->next_to_clean = 0;
  
  	E1000_WRITE_REG(&adapter->hw, TDH, 0);
  	E1000_WRITE_REG(&adapter->hw, TDT, 0);
***************
*** 1044,1060 ****
  static void
  e1000_free_rx_resources(struct e1000_adapter *adapter)
  {
  	struct pci_dev *pdev = adapter->pdev;
  
  	e1000_clean_rx_ring(adapter);
  
! 	kfree(adapter->rx_ring.buffer_info);
! 	adapter->rx_ring.buffer_info = NULL;
  
! 	pci_free_consistent(pdev, adapter->rx_ring.size,
! 	                    adapter->rx_ring.desc, adapter->rx_ring.dma);
  
! 	adapter->rx_ring.desc = NULL;
  }
  
  /**
--- 1016,1032 ----
  static void
  e1000_free_rx_resources(struct e1000_adapter *adapter)
  {
+ 	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
  	struct pci_dev *pdev = adapter->pdev;
  
  	e1000_clean_rx_ring(adapter);
  
! 	kfree(rx_ring->buffer_info);
! 	rx_ring->buffer_info = NULL;
  
! 	pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
  
! 	rx_ring->desc = NULL;
  }
  
  /**
***************
*** 1065,1099 ****
  static void
  e1000_clean_rx_ring(struct e1000_adapter *adapter)
  {
  	struct pci_dev *pdev = adapter->pdev;
  	unsigned long size;
! 	int i;
  
  	/* Free all the Rx ring sk_buffs */
  
! 	for(i = 0; i < adapter->rx_ring.count; i++) {
! 		if(adapter->rx_ring.buffer_info[i].skb) {
  
  			pci_unmap_single(pdev,
! 			                 adapter->rx_ring.buffer_info[i].dma,
! 			                 adapter->rx_ring.buffer_info[i].length,
  			                 PCI_DMA_FROMDEVICE);
  
! 			dev_kfree_skb(adapter->rx_ring.buffer_info[i].skb);
  
! 			adapter->rx_ring.buffer_info[i].skb = NULL;
  		}
  	}
  
! 	size = sizeof(struct e1000_buffer) * adapter->rx_ring.count;
! 	memset(adapter->rx_ring.buffer_info, 0, size);
  
  	/* Zero out the descriptor ring */
  
! 	memset(adapter->rx_ring.desc, 0, adapter->rx_ring.size);
  
! 	adapter->rx_ring.next_to_clean = 0;
! 	adapter->rx_ring.next_to_use = 0;
  
  	E1000_WRITE_REG(&adapter->hw, RDH, 0);
  	E1000_WRITE_REG(&adapter->hw, RDT, 0);
--- 1037,1074 ----
  static void
  e1000_clean_rx_ring(struct e1000_adapter *adapter)
  {
+ 	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
+ 	struct e1000_buffer *buffer_info;
  	struct pci_dev *pdev = adapter->pdev;
  	unsigned long size;
! 	unsigned int i;
  
  	/* Free all the Rx ring sk_buffs */
  
! 	for(i = 0; i < rx_ring->count; i++) {
! 		buffer_info = &rx_ring->buffer_info[i];
! 		if(buffer_info->skb) {
  
  			pci_unmap_single(pdev,
! 			                 buffer_info->dma,
! 			                 buffer_info->length,
  			                 PCI_DMA_FROMDEVICE);
  
! 			dev_kfree_skb(buffer_info->skb);
  
! 			buffer_info->skb = NULL;
  		}
  	}
  
! 	size = sizeof(struct e1000_buffer) * rx_ring->count;
! 	memset(rx_ring->buffer_info, 0, size);
  
  	/* Zero out the descriptor ring */
  
! 	memset(rx_ring->desc, 0, rx_ring->size);
  
! 	rx_ring->next_to_clean = 0;
! 	rx_ring->next_to_use = 0;
  
  	E1000_WRITE_REG(&adapter->hw, RDH, 0);
  	E1000_WRITE_REG(&adapter->hw, RDT, 0);
***************
*** 1343,1349 ****
  	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
  	struct net_device *netdev = adapter->netdev;
  	struct e1000_desc_ring *txdr = &adapter->tx_ring;
! 	int i;
  
  	e1000_check_for_link(&adapter->hw);
  
--- 1318,1324 ----
  	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
  	struct net_device *netdev = adapter->netdev;
  	struct e1000_desc_ring *txdr = &adapter->tx_ring;
! 	unsigned int i;
  
  	e1000_check_for_link(&adapter->hw);
  
***************
*** 1420,1433 ****
  
  #define E1000_TX_FLAGS_CSUM		0x00000001
  #define E1000_TX_FLAGS_VLAN		0x00000002
  #define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
  #define E1000_TX_FLAGS_VLAN_SHIFT	16
  
  static inline boolean_t
  e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
  {
  	struct e1000_context_desc *context_desc;
! 	int i;
  	uint8_t css, cso;
  
  	if(skb->ip_summed == CHECKSUM_HW) {
--- 1395,1461 ----
  
  #define E1000_TX_FLAGS_CSUM		0x00000001
  #define E1000_TX_FLAGS_VLAN		0x00000002
+ #define E1000_TX_FLAGS_TSO		0x00000004
  #define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
  #define E1000_TX_FLAGS_VLAN_SHIFT	16
  
  static inline boolean_t
+ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
+ {
+ #ifdef NETIF_F_TSO
+ 	struct e1000_context_desc *context_desc;
+ 	unsigned int i;
+ 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
+ 	uint16_t ipcse, tucse, mss;
+ 
+ 	if(skb_shinfo(skb)->tso_size) {
+ 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+ 		mss = skb_shinfo(skb)->tso_size;
+ 		skb->nh.iph->tot_len = 0;
+ 		skb->nh.iph->check = 0;
+ 		skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
+ 		                                      skb->nh.iph->daddr,
+ 		                                      0,
+ 		                                      IPPROTO_TCP,
+ 		                                      0);
+ 		ipcss = skb->nh.raw - skb->data;
+ 		ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data;
+ 		ipcse = skb->h.raw - skb->data - 1;
+ 		tucss = skb->h.raw - skb->data;
+ 		tucso = (void *)&(skb->h.th->check) - (void *)skb->data;
+ 		tucse = 0;
+ 
+ 		i = adapter->tx_ring.next_to_use;
+ 		context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
+ 
+ 		context_desc->lower_setup.ip_fields.ipcss  = ipcss;
+ 		context_desc->lower_setup.ip_fields.ipcso  = ipcso;
+ 		context_desc->lower_setup.ip_fields.ipcse  = cpu_to_le16(ipcse);
+ 		context_desc->upper_setup.tcp_fields.tucss = tucss;
+ 		context_desc->upper_setup.tcp_fields.tucso = tucso;
+ 		context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);
+ 		context_desc->tcp_seg_setup.fields.mss     = cpu_to_le16(mss);
+ 		context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
+ 		context_desc->cmd_and_length = cpu_to_le32(
+ 			E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
+ 			E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP |
+ 			(skb->len - (hdr_len)));
+ 
+ 		if(++i == adapter->tx_ring.count) i = 0;
+ 		adapter->tx_ring.next_to_use = i;
+ 
+ 		return TRUE;
+ 	}
+ #endif
+ 
+ 	return FALSE;
+ }
+ 
+ static inline boolean_t
  e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
  {
  	struct e1000_context_desc *context_desc;
! 	unsigned int i;
  	uint8_t css, cso;
  
  	if(skb->ip_summed == CHECKSUM_HW) {
***************
*** 1441,1448 ****
  		context_desc->upper_setup.tcp_fields.tucso = cso;
  		context_desc->upper_setup.tcp_fields.tucse = 0;
  		context_desc->tcp_seg_setup.data = 0;
! 		context_desc->cmd_and_length =
! 			cpu_to_le32(adapter->txd_cmd | E1000_TXD_CMD_DEXT);
  
  		if(++i == adapter->tx_ring.count) i = 0;
  		adapter->tx_ring.next_to_use = i;
--- 1469,1475 ----
  		context_desc->upper_setup.tcp_fields.tucso = cso;
  		context_desc->upper_setup.tcp_fields.tucse = 0;
  		context_desc->tcp_seg_setup.data = 0;
! 		context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
  
  		if(++i == adapter->tx_ring.count) i = 0;
  		adapter->tx_ring.next_to_use = i;
***************
*** 1457,1481 ****
  #define E1000_MAX_DATA_PER_TXD	(1<<E1000_MAX_TXD_PWR)
  
  static inline int
! e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb)
  {
  	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
! 	int len = skb->len, offset = 0, size, count = 0, i;
  
! 	int f;
  	len -= skb->data_len;
  
  	i = tx_ring->next_to_use;
  
  	while(len) {
  		size = min(len, E1000_MAX_DATA_PER_TXD);
! 		tx_ring->buffer_info[i].length = size;
! 		tx_ring->buffer_info[i].dma =
  			pci_map_single(adapter->pdev,
  				skb->data + offset,
  				size,
  				PCI_DMA_TODEVICE);
! 		tx_ring->buffer_info[i].time_stamp = jiffies;
  
  		len -= size;
  		offset += size;
--- 1484,1522 ----
  #define E1000_MAX_DATA_PER_TXD	(1<<E1000_MAX_TXD_PWR)
  
  static inline int
! e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
! 	unsigned int first)
  {
  	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
! 	struct e1000_buffer *buffer_info;
! 	int len = skb->len;
! 	unsigned int offset = 0, size, count = 0, i;
  
! #ifdef NETIF_F_TSO
! 	unsigned int tso = skb_shinfo(skb)->tso_size;
! #endif
! 	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
! 	unsigned int f;
  	len -= skb->data_len;
  
  	i = tx_ring->next_to_use;
  
  	while(len) {
+ 		buffer_info = &tx_ring->buffer_info[i];
  		size = min(len, E1000_MAX_DATA_PER_TXD);
! #ifdef NETIF_F_TSO
! 		/* Workaround for premature desc write-backs
! 		 * in TSO mode.  Append 4-byte sentinel desc */
! 		if(tso && !nr_frags && size == len && size > 4)
! 			size -= 4;
! #endif
! 		buffer_info->length = size;
! 		buffer_info->dma =
  			pci_map_single(adapter->pdev,
  				skb->data + offset,
  				size,
  				PCI_DMA_TODEVICE);
! 		buffer_info->time_stamp = jiffies;
  
  		len -= size;
  		offset += size;
***************
*** 1483,1489 ****
  		if(++i == tx_ring->count) i = 0;
  	}
  
! 	for(f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
  		struct skb_frag_struct *frag;
  
  		frag = &skb_shinfo(skb)->frags[f];
--- 1524,1530 ----
  		if(++i == tx_ring->count) i = 0;
  	}
  
! 	for(f = 0; f < nr_frags; f++) {
  		struct skb_frag_struct *frag;
  
  		frag = &skb_shinfo(skb)->frags[f];
***************
*** 1491,1505 ****
  		offset = 0;
  
  		while(len) {
  			size = min(len, E1000_MAX_DATA_PER_TXD);
! 			tx_ring->buffer_info[i].length = size;
! 			tx_ring->buffer_info[i].dma =
  				pci_map_page(adapter->pdev,
  					frag->page,
  					frag->page_offset + offset,
  					size,
  					PCI_DMA_TODEVICE);
! 			tx_ring->buffer_info[i].time_stamp = jiffies;
  
  			len -= size;
  			offset += size;
--- 1532,1553 ----
  		offset = 0;
  
  		while(len) {
+ 			buffer_info = &tx_ring->buffer_info[i];
  			size = min(len, E1000_MAX_DATA_PER_TXD);
! #ifdef NETIF_F_TSO
! 			/* Workaround for premature desc write-backs
! 			 * in TSO mode.  Append 4-byte sentinel desc */
! 			if(tso && f == (nr_frags-1) && size == len && size > 4)
! 				size -= 4;
! #endif
! 			buffer_info->length = size;
! 			buffer_info->dma =
  				pci_map_page(adapter->pdev,
  					frag->page,
  					frag->page_offset + offset,
  					size,
  					PCI_DMA_TODEVICE);
! 			buffer_info->time_stamp = jiffies;
  
  			len -= size;
  			offset += size;
***************
*** 1507,1514 ****
  			if(++i == tx_ring->count) i = 0;
  		}
  	}
! 	if(--i < 0) i = tx_ring->count - 1;
  	tx_ring->buffer_info[i].skb = skb;
  
  	return count;
  }
--- 1555,1563 ----
  			if(++i == tx_ring->count) i = 0;
  		}
  	}
! 	i = (i == 0) ? tx_ring->count - 1 : i - 1;
  	tx_ring->buffer_info[i].skb = skb;
+ 	tx_ring->buffer_info[first].next_to_watch = i;
  
  	return count;
  }
***************
*** 1518,1528 ****
  {
  	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
  	struct e1000_tx_desc *tx_desc = NULL;
! 	uint32_t txd_upper, txd_lower;
! 	int i;
! 
! 	txd_upper = 0;
! 	txd_lower = adapter->txd_cmd;
  
  	if(tx_flags & E1000_TX_FLAGS_CSUM) {
  		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
--- 1567,1581 ----
  {
  	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
  	struct e1000_tx_desc *tx_desc = NULL;
! 	struct e1000_buffer *buffer_info;
! 	uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
! 	unsigned int i;
! 
! 	if(tx_flags & E1000_TX_FLAGS_TSO) {
! 		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
! 		             E1000_TXD_CMD_TSE;
! 		txd_upper |= (E1000_TXD_POPTS_IXSM | E1000_TXD_POPTS_TXSM) << 8;
! 	}
  
  	if(tx_flags & E1000_TX_FLAGS_CSUM) {
  		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
***************
*** 1537,1551 ****
  	i = tx_ring->next_to_use;
  
  	while(count--) {
  		tx_desc = E1000_TX_DESC(*tx_ring, i);
! 		tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma);
  		tx_desc->lower.data =
! 			cpu_to_le32(txd_lower | tx_ring->buffer_info[i].length);
  		tx_desc->upper.data = cpu_to_le32(txd_upper);
  		if(++i == tx_ring->count) i = 0;
  	}
  
! 	tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP);
  
  	/* Force memory writes to complete before letting h/w
  	 * know there are new descriptors to fetch.  (Only
--- 1590,1605 ----
  	i = tx_ring->next_to_use;
  
  	while(count--) {
+ 		buffer_info = &tx_ring->buffer_info[i];
  		tx_desc = E1000_TX_DESC(*tx_ring, i);
! 		tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
  		tx_desc->lower.data =
! 			cpu_to_le32(txd_lower | buffer_info->length);
  		tx_desc->upper.data = cpu_to_le32(txd_upper);
  		if(++i == tx_ring->count) i = 0;
  	}
  
! 	tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
  
  	/* Force memory writes to complete before letting h/w
  	 * know there are new descriptors to fetch.  (Only
***************
*** 1605,1611 ****
  e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
  {
  	struct e1000_adapter *adapter = netdev->priv;
! 	int tx_flags = 0;
  
  	if(skb->len <= 0) {
  		dev_kfree_skb_any(skb);
--- 1659,1666 ----
  e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
  {
  	struct e1000_adapter *adapter = netdev->priv;
! 	unsigned int first;
! 	unsigned int tx_flags = 0;
  
  	if(skb->len <= 0) {
  		dev_kfree_skb_any(skb);
***************
*** 1630,1639 ****
  		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
  	}
  
! 	if(e1000_tx_csum(adapter, skb))
  		tx_flags |= E1000_TX_FLAGS_CSUM;
  
! 	e1000_tx_queue(adapter, e1000_tx_map(adapter, skb), tx_flags);
  
  	netdev->trans_start = jiffies;
  
--- 1685,1698 ----
  		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
  	}
  
! 	first = adapter->tx_ring.next_to_use;
! 	
! 	if(e1000_tso(adapter, skb))
! 		tx_flags |= E1000_TX_FLAGS_TSO;
! 	else if(e1000_tx_csum(adapter, skb))
  		tx_flags |= E1000_TX_FLAGS_CSUM;
  
! 	e1000_tx_queue(adapter, e1000_tx_map(adapter, skb, first), tx_flags);
  
  	netdev->trans_start = jiffies;
  
***************
*** 1865,1870 ****
--- 1924,1930 ----
  		}
  
  		if((hw->mac_type <= e1000_82546) &&
+ 		   (hw->phy_type == e1000_phy_m88) &&
  		   !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
  			adapter->phy_stats.receive_errors += phy_tmp;
  	}
***************
*** 1911,1917 ****
  	struct net_device *netdev = data;
  	struct e1000_adapter *adapter = netdev->priv;
  	uint32_t icr = E1000_READ_REG(&adapter->hw, ICR);
! 	int i;
  
  	if(!icr)
  		return;  /* Not our interrupt */
--- 1971,1979 ----
  	struct net_device *netdev = data;
  	struct e1000_adapter *adapter = netdev->priv;
  	uint32_t icr = E1000_READ_REG(&adapter->hw, ICR);
! #ifndef CONFIG_E1000_NAPI
! 	unsigned int i;
! #endif
  
  	if(!icr)
  		return;  /* Not our interrupt */
***************
*** 1921,1932 ****
  		mod_timer(&adapter->watchdog_timer, jiffies);
  	}
  
  	for(i = 0; i < E1000_MAX_INTR; i++)
! 		if(!e1000_clean_rx_irq(adapter) &&
  		   !e1000_clean_tx_irq(adapter))
  			break;
  
  }
  
  /**
   * e1000_clean_tx_irq - Reclaim resources after transmit completes
--- 1983,2034 ----
  		mod_timer(&adapter->watchdog_timer, jiffies);
  	}
  
+ #ifdef CONFIG_E1000_NAPI
+ 	if(netif_rx_schedule_prep(netdev)) {
+ 
+ 		/* Disable interrupts and register for poll. The flush 
+ 		  of the posted write is intentionally left out.
+ 		*/
+ 
+ 		atomic_inc(&adapter->irq_sem);
+ 		E1000_WRITE_REG(&adapter->hw, IMC, ~0);
+ 		__netif_rx_schedule(netdev);
+ 	}
+ #else
  	for(i = 0; i < E1000_MAX_INTR; i++)
! 		if(!e1000_clean_rx_irq(adapter) &
  		   !e1000_clean_tx_irq(adapter))
  			break;
+ #endif
+ }
+ 
+ #ifdef CONFIG_E1000_NAPI
+ /**
+  * e1000_clean - NAPI Rx polling callback
+  * @adapter: board private structure
+  **/
  
+ static int
+ e1000_clean(struct net_device *netdev, int *budget)
+ {
+ 	struct e1000_adapter *adapter = netdev->priv;
+ 	int work_to_do = min(*budget, netdev->quota);
+ 	int work_done = 0;
+ 	
+ 	e1000_clean_tx_irq(adapter);
+ 	e1000_clean_rx_irq(adapter, &work_done, work_to_do);
+ 
+ 	*budget -= work_done;
+ 	netdev->quota -= work_done;
+ 	
+ 	if(work_done < work_to_do) {
+ 		netif_rx_complete(netdev);
+ 		e1000_irq_enable(adapter);
+ 	}
+ 
+ 	return (work_done >= work_to_do);
  }
+ #endif
  
  /**
   * e1000_clean_tx_irq - Reclaim resources after transmit completes
***************
*** 1939,1977 ****
  	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
  	struct net_device *netdev = adapter->netdev;
  	struct pci_dev *pdev = adapter->pdev;
! 	struct e1000_tx_desc *tx_desc;
! 	int i, cleaned = FALSE;
  
  	i = tx_ring->next_to_clean;
! 	tx_desc = E1000_TX_DESC(*tx_ring, i);
  
! 	while(tx_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
  
! 		cleaned = TRUE;
  
! 		if(tx_ring->buffer_info[i].dma) {
  
! 			pci_unmap_page(pdev,
! 			               tx_ring->buffer_info[i].dma,
! 			               tx_ring->buffer_info[i].length,
! 			               PCI_DMA_TODEVICE);
  
! 			tx_ring->buffer_info[i].dma = 0;
! 		}
  
! 		if(tx_ring->buffer_info[i].skb) {
  
! 			dev_kfree_skb_any(tx_ring->buffer_info[i].skb);
  
! 			tx_ring->buffer_info[i].skb = NULL;
! 		}
  
! 		tx_desc->buffer_addr = 0;
! 		tx_desc->lower.data = 0;
! 		tx_desc->upper.data = 0;
  
! 		if(++i == tx_ring->count) i = 0;
! 		tx_desc = E1000_TX_DESC(*tx_ring, i);
  	}
  
  	tx_ring->next_to_clean = i;
--- 2041,2088 ----
  	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
  	struct net_device *netdev = adapter->netdev;
  	struct pci_dev *pdev = adapter->pdev;
! 	struct e1000_tx_desc *tx_desc, *eop_desc;
! 	struct e1000_buffer *buffer_info;
! 	unsigned int i, eop;
! 	boolean_t cleaned = FALSE;
  
  	i = tx_ring->next_to_clean;
! 	eop = tx_ring->buffer_info[i].next_to_watch;
! 	eop_desc = E1000_TX_DESC(*tx_ring, eop);
  
! 	while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
  
! 		for(cleaned = FALSE; !cleaned; ) {
! 			tx_desc = E1000_TX_DESC(*tx_ring, i);
! 			buffer_info = &tx_ring->buffer_info[i];
  
! 			if(buffer_info->dma) {
  
! 				pci_unmap_page(pdev,
! 					       buffer_info->dma,
! 					       buffer_info->length,
! 					       PCI_DMA_TODEVICE);
  
! 				buffer_info->dma = 0;
! 			}
  
! 			if(buffer_info->skb) {
  
! 				dev_kfree_skb_any(buffer_info->skb);
  
! 				buffer_info->skb = NULL;
! 			}
  
! 			tx_desc->buffer_addr = 0;
! 			tx_desc->lower.data = 0;
! 			tx_desc->upper.data = 0;
  
! 			cleaned = (i == eop);
! 			if(++i == tx_ring->count) i = 0;
! 		}
! 		
! 		eop = tx_ring->buffer_info[i].next_to_watch;
! 		eop_desc = E1000_TX_DESC(*tx_ring, eop);
  	}
  
  	tx_ring->next_to_clean = i;
***************
*** 1988,2018 ****
   **/
  
  static boolean_t
  e1000_clean_rx_irq(struct e1000_adapter *adapter)
  {
  	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
  	struct net_device *netdev = adapter->netdev;
  	struct pci_dev *pdev = adapter->pdev;
  	struct e1000_rx_desc *rx_desc;
  	struct sk_buff *skb;
  	unsigned long flags;
  	uint32_t length;
  	uint8_t last_byte;
! 	int i, cleaned = FALSE;
  
  	i = rx_ring->next_to_clean;
  	rx_desc = E1000_RX_DESC(*rx_ring, i);
  
  	while(rx_desc->status & E1000_RXD_STAT_DD) {
  
  		cleaned = TRUE;
  
  		pci_unmap_single(pdev,
! 		                 rx_ring->buffer_info[i].dma,
! 		                 rx_ring->buffer_info[i].length,
  		                 PCI_DMA_FROMDEVICE);
  
! 		skb = rx_ring->buffer_info[i].skb;
  		length = le16_to_cpu(rx_desc->length);
  
  		if(!(rx_desc->status & E1000_RXD_STAT_EOP)) {
--- 2099,2144 ----
   **/
  
  static boolean_t
+ #ifdef CONFIG_E1000_NAPI
+ e1000_clean_rx_irq(struct e1000_adapter *adapter, int *work_done,
+                    int work_to_do)
+ #else
  e1000_clean_rx_irq(struct e1000_adapter *adapter)
+ #endif
  {
  	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
  	struct net_device *netdev = adapter->netdev;
  	struct pci_dev *pdev = adapter->pdev;
  	struct e1000_rx_desc *rx_desc;
+ 	struct e1000_buffer *buffer_info;
  	struct sk_buff *skb;
  	unsigned long flags;
  	uint32_t length;
  	uint8_t last_byte;
! 	unsigned int i;
! 	boolean_t cleaned = FALSE;
  
  	i = rx_ring->next_to_clean;
  	rx_desc = E1000_RX_DESC(*rx_ring, i);
  
  	while(rx_desc->status & E1000_RXD_STAT_DD) {
+ 		buffer_info = &rx_ring->buffer_info[i];
+ 
+ #ifdef CONFIG_E1000_NAPI
+ 		if(*work_done >= work_to_do)
+ 			break;
+ 
+ 		(*work_done)++;
+ #endif
  
  		cleaned = TRUE;
  
  		pci_unmap_single(pdev,
! 		                 buffer_info->dma,
! 		                 buffer_info->length,
  		                 PCI_DMA_FROMDEVICE);
  
! 		skb = buffer_info->skb;
  		length = le16_to_cpu(rx_desc->length);
  
  		if(!(rx_desc->status & E1000_RXD_STAT_EOP)) {
***************
*** 2023,2029 ****
  
  			dev_kfree_skb_irq(skb);
  			rx_desc->status = 0;
! 			rx_ring->buffer_info[i].skb = NULL;
  
  			if(++i == rx_ring->count) i = 0;
  
--- 2149,2155 ----
  
  			dev_kfree_skb_irq(skb);
  			rx_desc->status = 0;
! 			buffer_info->skb = NULL;
  
  			if(++i == rx_ring->count) i = 0;
  
***************
*** 2051,2057 ****
  
  				dev_kfree_skb_irq(skb);
  				rx_desc->status = 0;
! 				rx_ring->buffer_info[i].skb = NULL;
  
  				if(++i == rx_ring->count) i = 0;
  
--- 2177,2183 ----
  
  				dev_kfree_skb_irq(skb);
  				rx_desc->status = 0;
! 				buffer_info->skb = NULL;
  
  				if(++i == rx_ring->count) i = 0;
  
***************
*** 2067,2082 ****
  		e1000_rx_checksum(adapter, rx_desc, skb);
  
  		skb->protocol = eth_type_trans(skb, netdev);
  		if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
  			vlan_hwaccel_rx(skb, adapter->vlgrp,
! 				(rx_desc->special & E1000_RXD_SPC_VLAN_MASK));
  		} else {
  			netif_rx(skb);
  		}
  		netdev->last_rx = jiffies;
  
  		rx_desc->status = 0;
! 		rx_ring->buffer_info[i].skb = NULL;
  
  		if(++i == rx_ring->count) i = 0;
  
--- 2193,2219 ----
  		e1000_rx_checksum(adapter, rx_desc, skb);
  
  		skb->protocol = eth_type_trans(skb, netdev);
+ #ifdef CONFIG_E1000_NAPI
+ 		if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
+ 			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
+ 				le16_to_cpu(rx_desc->special &
+ 					E1000_RXD_SPC_VLAN_MASK));
+ 		} else {
+ 			netif_receive_skb(skb);
+ 		}
+ #else /* CONFIG_E1000_NAPI */
  		if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
  			vlan_hwaccel_rx(skb, adapter->vlgrp,
! 				le16_to_cpu(rx_desc->special &
! 					E1000_RXD_SPC_VLAN_MASK));
  		} else {
  			netif_rx(skb);
  		}
+ #endif /* CONFIG_E1000_NAPI */
  		netdev->last_rx = jiffies;
  
  		rx_desc->status = 0;
! 		buffer_info->skb = NULL;
  
  		if(++i == rx_ring->count) i = 0;
  
***************
*** 2102,2114 ****
  	struct net_device *netdev = adapter->netdev;
  	struct pci_dev *pdev = adapter->pdev;
  	struct e1000_rx_desc *rx_desc;
  	struct sk_buff *skb;
  	int reserve_len = 2;
! 	int i;
  
  	i = rx_ring->next_to_use;
  
! 	while(!rx_ring->buffer_info[i].skb) {
  		rx_desc = E1000_RX_DESC(*rx_ring, i);
  
  		skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len);
--- 2239,2253 ----
  	struct net_device *netdev = adapter->netdev;
  	struct pci_dev *pdev = adapter->pdev;
  	struct e1000_rx_desc *rx_desc;
+ 	struct e1000_buffer *buffer_info;
  	struct sk_buff *skb;
  	int reserve_len = 2;
! 	unsigned int i;
  
  	i = rx_ring->next_to_use;
+ 	buffer_info = &rx_ring->buffer_info[i];
  
! 	while(!buffer_info->skb) {
  		rx_desc = E1000_RX_DESC(*rx_ring, i);
  
  		skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len);
***************
*** 2126,2140 ****
  
  		skb->dev = netdev;
  
! 		rx_ring->buffer_info[i].skb = skb;
! 		rx_ring->buffer_info[i].length = adapter->rx_buffer_len;
! 		rx_ring->buffer_info[i].dma =
  			pci_map_single(pdev,
  			               skb->data,
  			               adapter->rx_buffer_len,
  			               PCI_DMA_FROMDEVICE);
  
! 		rx_desc->buffer_addr = cpu_to_le64(rx_ring->buffer_info[i].dma);
  
  		if((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i) {
  			/* Force memory writes to complete before letting h/w
--- 2265,2279 ----
  
  		skb->dev = netdev;
  
! 		buffer_info->skb = skb;
! 		buffer_info->length = adapter->rx_buffer_len;
! 		buffer_info->dma =
  			pci_map_single(pdev,
  			               skb->data,
  			               adapter->rx_buffer_len,
  			               PCI_DMA_FROMDEVICE);
  
! 		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
  
  		if((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i) {
  			/* Force memory writes to complete before letting h/w
***************
*** 2147,2152 ****
--- 2286,2292 ----
  		}
  
  		if(++i == rx_ring->count) i = 0;
+ 		buffer_info = &rx_ring->buffer_info[i];
  	}
  
  	rx_ring->next_to_use = i;
***************
*** 2525,2531 ****
  	return NOTIFY_DONE;
  }
  
- 
  static int
  e1000_suspend(struct pci_dev *pdev, uint32_t state)
  {
--- 2665,2670 ----
***************
*** 2633,2652 ****
  }
  #endif
  
- #ifdef HAVE_POLL_CONTROLLER
- /*
-  * Polling 'interrupt' - used by things like netconsole to send skbs
-  * without having to re-enable interrupts. It's not called while
-  * the interrupt routine is executing.
-  */
- 
- static void e1000_netpoll (struct net_device *dev)
- {
- 	if (!netdump_mode) disable_irq(dev->irq);
- 	e1000_intr (dev->irq, dev, NULL);
- 	if (!netdump_mode) enable_irq(dev->irq);
- }
- 
- #endif
- 
  /* e1000_main.c */
--- 2772,2775 ----
diff -Ncr linux-2.4.22-old/drivers/net/e1000/e1000_osdep.h linux-2.4.22/drivers/net/e1000/e1000_osdep.h
*** linux-2.4.22-old/drivers/net/e1000/e1000_osdep.h	2003-11-18 17:22:41.000000000 +0900
--- linux-2.4.22/drivers/net/e1000/e1000_osdep.h	2003-08-25 20:44:42.000000000 +0900
***************
*** 27,33 ****
  *******************************************************************************/
  
  
! /* glue for the OS independant part of e1000
   * includes register access macros
   */
  
--- 27,33 ----
  *******************************************************************************/
  
  
! /* glue for the OS independent part of e1000
   * includes register access macros
   */
  
