Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/drivers/net/ixgb/Makefile b/drivers/net/ixgb/Makefile
new file mode 100644
index 0000000..7c7aff1
--- /dev/null
+++ b/drivers/net/ixgb/Makefile
@@ -0,0 +1,35 @@
+################################################################################
+#
+# 
+# Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it 
+# under the terms of the GNU General Public License as published by the Free 
+# Software Foundation; either version 2 of the License, or (at your option) 
+# any later version.
+# 
+# This program is distributed in the hope that it will be useful, but WITHOUT 
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+# more details.
+# 
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 
+# Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+# 
+# The full GNU General Public License is included in this distribution in the
+# file called LICENSE.
+# 
+# Contact Information:
+# Linux NICS <linux.nics@intel.com>
+# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+#
+################################################################################
+
+#
+# Makefile for the Intel(R) PRO/10GbE driver
+#
+
+obj-$(CONFIG_IXGB) += ixgb.o
+
+ixgb-objs := ixgb_main.o ixgb_hw.o ixgb_ee.o ixgb_ethtool.o ixgb_param.o
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
new file mode 100644
index 0000000..26c4f15
--- /dev/null
+++ b/drivers/net/ixgb/ixgb.h
@@ -0,0 +1,200 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of the GNU General Public License as published by the Free 
+  Software Foundation; either version 2 of the License, or (at your option) 
+  any later version.
+  
+  This program is distributed in the hope that it will be useful, but WITHOUT 
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+  more details.
+  
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#ifndef _IXGB_H_
+#define _IXGB_H_
+
+#include <linux/stddef.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/pagemap.h>
+#include <linux/dma-mapping.h>
+#include <linux/bitops.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/capability.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <net/pkt_sched.h>
+#include <linux/list.h>
+#include <linux/reboot.h>
+#ifdef NETIF_F_TSO
+#include <net/checksum.h>
+#endif
+
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+
+#define BAR_0		0
+#define BAR_1		1
+#define BAR_5		5
+
+struct ixgb_adapter;
+#include "ixgb_hw.h"
+#include "ixgb_ee.h"
+#include "ixgb_ids.h"
+
+#ifdef _DEBUG_DRIVER_
+#define IXGB_DBG(args...) printk(KERN_DEBUG "ixgb: " args)
+#else
+#define IXGB_DBG(args...)
+#endif
+
+#define IXGB_ERR(args...) printk(KERN_ERR "ixgb: " args)
+
+/* TX/RX descriptor defines */
+#define DEFAULT_TXD	 256
+#define MAX_TXD   	4096
+#define MIN_TXD	  64
+
+/* hardware cannot reliably support more than 512 descriptors owned by
+ * hardware descrioptor cache otherwise an unreliable ring under heavy 
+ * recieve load may result */
+/* #define DEFAULT_RXD	   1024 */
+/* #define MAX_RXD	   4096 */
+#define DEFAULT_RXD	512
+#define MAX_RXD	512
+#define MIN_RXD	 64
+
+/* Supported Rx Buffer Sizes */
+#define IXGB_RXBUFFER_2048  2048
+#define IXGB_RXBUFFER_4096  4096
+#define IXGB_RXBUFFER_8192  8192
+#define IXGB_RXBUFFER_16384 16384
+
+/* How many Tx Descriptors do we need to call netif_wake_queue? */
+#define IXGB_TX_QUEUE_WAKE 16
+
+/* How many Rx Buffers do we bundle into one write to the hardware ? */
+#define IXGB_RX_BUFFER_WRITE	16	/* Must be power of 2 */
+
+/* only works for sizes that are powers of 2 */
+#define IXGB_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1)))
+
+/* wrapper around a pointer to a socket buffer,
+ * so a DMA handle can be stored along with the buffer */
+struct ixgb_buffer {
+	struct sk_buff *skb;
+	uint64_t dma;
+	unsigned long time_stamp;
+	uint16_t length;
+	uint16_t next_to_watch;
+};
+
+struct ixgb_desc_ring {
+	/* pointer to the descriptor ring memory */
+	void *desc;
+	/* physical address of the descriptor ring */
+	dma_addr_t dma;
+	/* length of descriptor ring in bytes */
+	unsigned int size;
+	/* number of descriptors in the ring */
+	unsigned int count;
+	/* next descriptor to associate a buffer with */
+	unsigned int next_to_use;
+	/* next descriptor to check for DD status bit */
+	unsigned int next_to_clean;
+	/* array of buffer information structs */
+	struct ixgb_buffer *buffer_info;
+};
+
+#define IXGB_DESC_UNUSED(R) \
+	((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
+	(R)->next_to_clean - (R)->next_to_use - 1)
+
+#define IXGB_GET_DESC(R, i, type)	(&(((struct type *)((R).desc))[i]))
+#define IXGB_RX_DESC(R, i)		IXGB_GET_DESC(R, i, ixgb_rx_desc)
+#define IXGB_TX_DESC(R, i)		IXGB_GET_DESC(R, i, ixgb_tx_desc)
+#define IXGB_CONTEXT_DESC(R, i)	IXGB_GET_DESC(R, i, ixgb_context_desc)
+
+/* board specific private data structure */
+
+struct ixgb_adapter {
+	struct timer_list watchdog_timer;
+	struct vlan_group *vlgrp;
+	uint32_t bd_number;
+	uint32_t rx_buffer_len;
+	uint32_t part_num;
+	uint16_t link_speed;
+	uint16_t link_duplex;
+	spinlock_t tx_lock;
+	atomic_t irq_sem;
+	struct work_struct tx_timeout_task;
+
+	struct timer_list blink_timer;
+	unsigned long led_status;
+
+	/* TX */
+	struct ixgb_desc_ring tx_ring;
+	unsigned long timeo_start;
+	uint32_t tx_cmd_type;
+	uint64_t hw_csum_tx_good;
+	uint64_t hw_csum_tx_error;
+	uint32_t tx_int_delay;
+	boolean_t tx_int_delay_enable;
+	boolean_t detect_tx_hung;
+
+	/* RX */
+	struct ixgb_desc_ring rx_ring;
+	uint64_t hw_csum_rx_error;
+	uint64_t hw_csum_rx_good;
+	uint32_t rx_int_delay;
+	boolean_t rx_csum;
+
+	/* OS defined structs */
+	struct net_device *netdev;
+	struct pci_dev *pdev;
+	struct net_device_stats net_stats;
+
+	/* structs defined in ixgb_hw.h */
+	struct ixgb_hw hw;
+	struct ixgb_hw_stats stats;
+#ifdef CONFIG_PCI_MSI
+	boolean_t have_msi;
+#endif
+};
+#endif /* _IXGB_H_ */
diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
new file mode 100644
index 0000000..653e99f
--- /dev/null
+++ b/drivers/net/ixgb/ixgb_ee.c
@@ -0,0 +1,774 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of the GNU General Public License as published by the Free 
+  Software Foundation; either version 2 of the License, or (at your option) 
+  any later version.
+  
+  This program is distributed in the hope that it will be useful, but WITHOUT 
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+  more details.
+  
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include "ixgb_hw.h"
+#include "ixgb_ee.h"
+/* Local prototypes */
+static uint16_t ixgb_shift_in_bits(struct ixgb_hw *hw);
+
+static void ixgb_shift_out_bits(struct ixgb_hw *hw,
+				uint16_t data,
+				uint16_t count);
+static void ixgb_standby_eeprom(struct ixgb_hw *hw);
+
+static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw);
+
+static void ixgb_cleanup_eeprom(struct ixgb_hw *hw);
+
+/******************************************************************************
+ * Raises the EEPROM's clock input.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * eecd_reg - EECD's current value
+ *****************************************************************************/
+static void
+ixgb_raise_clock(struct ixgb_hw *hw,
+		  uint32_t *eecd_reg)
+{
+	/* Raise the clock input to the EEPROM (by setting the SK bit), and then
+	 *  wait 50 microseconds.
+	 */
+	*eecd_reg = *eecd_reg | IXGB_EECD_SK;
+	IXGB_WRITE_REG(hw, EECD, *eecd_reg);
+	udelay(50);
+	return;
+}
+
+/******************************************************************************
+ * Lowers the EEPROM's clock input.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * eecd_reg - EECD's current value
+ *****************************************************************************/
+static void
+ixgb_lower_clock(struct ixgb_hw *hw,
+		  uint32_t *eecd_reg)
+{
+	/* Lower the clock input to the EEPROM (by clearing the SK bit), and then
+	 * wait 50 microseconds.
+	 */
+	*eecd_reg = *eecd_reg & ~IXGB_EECD_SK;
+	IXGB_WRITE_REG(hw, EECD, *eecd_reg);
+	udelay(50);
+	return;
+}
+
+/******************************************************************************
+ * Shift data bits out to the EEPROM.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * data - data to send to the EEPROM
+ * count - number of bits to shift out
+ *****************************************************************************/
+static void
+ixgb_shift_out_bits(struct ixgb_hw *hw,
+					 uint16_t data,
+					 uint16_t count)
+{
+	uint32_t eecd_reg;
+	uint32_t mask;
+
+	/* We need to shift "count" bits out to the EEPROM. So, value in the
+	 * "data" parameter will be shifted out to the EEPROM one bit at a time.
+	 * In order to do this, "data" must be broken down into bits.
+	 */
+	mask = 0x01 << (count - 1);
+	eecd_reg = IXGB_READ_REG(hw, EECD);
+	eecd_reg &= ~(IXGB_EECD_DO | IXGB_EECD_DI);
+	do {
+		/* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1",
+		 * and then raising and then lowering the clock (the SK bit controls
+		 * the clock input to the EEPROM).  A "0" is shifted out to the EEPROM
+		 * by setting "DI" to "0" and then raising and then lowering the clock.
+		 */
+		eecd_reg &= ~IXGB_EECD_DI;
+
+		if(data & mask)
+			eecd_reg |= IXGB_EECD_DI;
+
+		IXGB_WRITE_REG(hw, EECD, eecd_reg);
+
+		udelay(50);
+
+		ixgb_raise_clock(hw, &eecd_reg);
+		ixgb_lower_clock(hw, &eecd_reg);
+
+		mask = mask >> 1;
+
+	} while(mask);
+
+	/* We leave the "DI" bit set to "0" when we leave this routine. */
+	eecd_reg &= ~IXGB_EECD_DI;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	return;
+}
+
+/******************************************************************************
+ * Shift data bits in from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static uint16_t
+ixgb_shift_in_bits(struct ixgb_hw *hw)
+{
+	uint32_t eecd_reg;
+	uint32_t i;
+	uint16_t data;
+
+	/* In order to read a register from the EEPROM, we need to shift 16 bits
+	 * in from the EEPROM. Bits are "shifted in" by raising the clock input to
+	 * the EEPROM (setting the SK bit), and then reading the value of the "DO"
+	 * bit.  During this "shifting in" process the "DI" bit should always be
+	 * clear..
+	 */
+
+	eecd_reg = IXGB_READ_REG(hw, EECD);
+
+	eecd_reg &= ~(IXGB_EECD_DO | IXGB_EECD_DI);
+	data = 0;
+
+	for(i = 0; i < 16; i++) {
+		data = data << 1;
+		ixgb_raise_clock(hw, &eecd_reg);
+
+		eecd_reg = IXGB_READ_REG(hw, EECD);
+
+		eecd_reg &= ~(IXGB_EECD_DI);
+		if(eecd_reg & IXGB_EECD_DO)
+			data |= 1;
+
+		ixgb_lower_clock(hw, &eecd_reg);
+	}
+
+	return data;
+}
+
+/******************************************************************************
+ * Prepares EEPROM for access
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
+ * function should be called before issuing a command to the EEPROM.
+ *****************************************************************************/
+static void
+ixgb_setup_eeprom(struct ixgb_hw *hw)
+{
+	uint32_t eecd_reg;
+
+	eecd_reg = IXGB_READ_REG(hw, EECD);
+
+	/*  Clear SK and DI  */
+	eecd_reg &= ~(IXGB_EECD_SK | IXGB_EECD_DI);
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+
+	/*  Set CS  */
+	eecd_reg |= IXGB_EECD_CS;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	return;
+}
+
+/******************************************************************************
+ * Returns EEPROM to a "standby" state
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static void
+ixgb_standby_eeprom(struct ixgb_hw *hw)
+{
+	uint32_t eecd_reg;
+
+	eecd_reg = IXGB_READ_REG(hw, EECD);
+
+	/*  Deselct EEPROM  */
+	eecd_reg &= ~(IXGB_EECD_CS | IXGB_EECD_SK);
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	udelay(50);
+
+	/*  Clock high  */
+	eecd_reg |= IXGB_EECD_SK;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	udelay(50);
+
+	/*  Select EEPROM  */
+	eecd_reg |= IXGB_EECD_CS;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	udelay(50);
+
+	/*  Clock low  */
+	eecd_reg &= ~IXGB_EECD_SK;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	udelay(50);
+	return;
+}
+
+/******************************************************************************
+ * Raises then lowers the EEPROM's clock pin
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static void
+ixgb_clock_eeprom(struct ixgb_hw *hw)
+{
+	uint32_t eecd_reg;
+
+	eecd_reg = IXGB_READ_REG(hw, EECD);
+
+	/*  Rising edge of clock  */
+	eecd_reg |= IXGB_EECD_SK;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	udelay(50);
+
+	/*  Falling edge of clock  */
+	eecd_reg &= ~IXGB_EECD_SK;
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+	udelay(50);
+	return;
+}
+
+/******************************************************************************
+ * Terminates a command by lowering the EEPROM's chip select pin
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static void
+ixgb_cleanup_eeprom(struct ixgb_hw *hw)
+{
+	uint32_t eecd_reg;
+
+	eecd_reg = IXGB_READ_REG(hw, EECD);
+
+	eecd_reg &= ~(IXGB_EECD_CS | IXGB_EECD_DI);
+
+	IXGB_WRITE_REG(hw, EECD, eecd_reg);
+
+	ixgb_clock_eeprom(hw);
+	return;
+}
+
+/******************************************************************************
+ * Waits for the EEPROM to finish the current command.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * The command is done when the EEPROM's data out pin goes high.
+ *
+ * Returns:
+ *      TRUE: EEPROM data pin is high before timeout.
+ *      FALSE:  Time expired.
+ *****************************************************************************/
+static boolean_t
+ixgb_wait_eeprom_command(struct ixgb_hw *hw)
+{
+	uint32_t eecd_reg;
+	uint32_t i;
+
+	/* Toggle the CS line.  This in effect tells to EEPROM to actually execute
+	 * the command in question.
+	 */
+	ixgb_standby_eeprom(hw);
+
+	/* Now read DO repeatedly until is high (equal to '1').  The EEEPROM will
+	 * signal that the command has been completed by raising the DO signal.
+	 * If DO does not go high in 10 milliseconds, then error out.
+	 */
+	for(i = 0; i < 200; i++) {
+		eecd_reg = IXGB_READ_REG(hw, EECD);
+
+		if(eecd_reg & IXGB_EECD_DO)
+			return (TRUE);
+
+		udelay(50);
+	}
+	ASSERT(0);
+	return (FALSE);
+}
+
+/******************************************************************************
+ * Verifies that the EEPROM has a valid checksum
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Reads the first 64 16 bit words of the EEPROM and sums the values read.
+ * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
+ * valid.
+ *
+ * Returns:
+ *  TRUE: Checksum is valid
+ *  FALSE: Checksum is not valid.
+ *****************************************************************************/
+boolean_t
+ixgb_validate_eeprom_checksum(struct ixgb_hw *hw)
+{
+	uint16_t checksum = 0;
+	uint16_t i;
+
+	for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++)
+		checksum += ixgb_read_eeprom(hw, i);
+
+	if(checksum == (uint16_t) EEPROM_SUM)
+		return (TRUE);
+	else
+		return (FALSE);
+}
+
+/******************************************************************************
+ * Calculates the EEPROM checksum and writes it to the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
+ * Writes the difference to word offset 63 of the EEPROM.
+ *****************************************************************************/
+void
+ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
+{
+	uint16_t checksum = 0;
+	uint16_t i;
+
+	for(i = 0; i < EEPROM_CHECKSUM_REG; i++)
+		checksum += ixgb_read_eeprom(hw, i);
+
+	checksum = (uint16_t) EEPROM_SUM - checksum;
+
+	ixgb_write_eeprom(hw, EEPROM_CHECKSUM_REG, checksum);
+	return;
+}
+
+/******************************************************************************
+ * Writes a 16 bit word to a given offset in the EEPROM.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * reg - offset within the EEPROM to be written to
+ * data - 16 bit word to be writen to the EEPROM
+ *
+ * If ixgb_update_eeprom_checksum is not called after this function, the
+ * EEPROM will most likely contain an invalid checksum.
+ *
+ *****************************************************************************/
+void
+ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t offset, uint16_t data)
+{
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	/* Prepare the EEPROM for writing */
+	ixgb_setup_eeprom(hw);
+
+	/*  Send the 9-bit EWEN (write enable) command to the EEPROM (5-bit opcode
+	 *  plus 4-bit dummy).  This puts the EEPROM into write/erase mode.
+	 */
+	ixgb_shift_out_bits(hw, EEPROM_EWEN_OPCODE, 5);
+	ixgb_shift_out_bits(hw, 0, 4);
+
+	/*  Prepare the EEPROM  */
+	ixgb_standby_eeprom(hw);
+
+	/*  Send the Write command (3-bit opcode + 6-bit addr)  */
+	ixgb_shift_out_bits(hw, EEPROM_WRITE_OPCODE, 3);
+	ixgb_shift_out_bits(hw, offset, 6);
+
+	/*  Send the data  */
+	ixgb_shift_out_bits(hw, data, 16);
+
+	ixgb_wait_eeprom_command(hw);
+
+	/*  Recover from write  */
+	ixgb_standby_eeprom(hw);
+
+	/* Send the 9-bit EWDS (write disable) command to the EEPROM (5-bit
+	 * opcode plus 4-bit dummy).  This takes the EEPROM out of write/erase
+	 * mode.
+	 */
+	ixgb_shift_out_bits(hw, EEPROM_EWDS_OPCODE, 5);
+	ixgb_shift_out_bits(hw, 0, 4);
+
+	/*  Done with writing  */
+	ixgb_cleanup_eeprom(hw);
+
+	/* clear the init_ctrl_reg_1 to signify that the cache is invalidated */
+	ee_map->init_ctrl_reg_1 = EEPROM_ICW1_SIGNATURE_CLEAR;
+
+	return;
+}
+
+/******************************************************************************
+ * Reads a 16 bit word from the EEPROM.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - offset of 16 bit word in the EEPROM to read
+ *
+ * Returns:
+ *  The 16-bit value read from the eeprom
+ *****************************************************************************/
+uint16_t
+ixgb_read_eeprom(struct ixgb_hw *hw,
+		  uint16_t offset)
+{
+	uint16_t data;
+
+	/*  Prepare the EEPROM for reading  */
+	ixgb_setup_eeprom(hw);
+
+	/*  Send the READ command (opcode + addr)  */
+	ixgb_shift_out_bits(hw, EEPROM_READ_OPCODE, 3);
+	/*
+	 * We have a 64 word EEPROM, there are 6 address bits
+	 */
+	ixgb_shift_out_bits(hw, offset, 6);
+
+	/*  Read the data  */
+	data = ixgb_shift_in_bits(hw);
+
+	/*  End this read operation  */
+	ixgb_standby_eeprom(hw);
+
+	return (data);
+}
+
+/******************************************************************************
+ * Reads eeprom and stores data in shared structure.
+ * Validates eeprom checksum and eeprom signature.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *      TRUE: if eeprom read is successful
+ *      FALSE: otherwise.
+ *****************************************************************************/
+boolean_t
+ixgb_get_eeprom_data(struct ixgb_hw *hw)
+{
+	uint16_t i;
+	uint16_t checksum = 0;
+	struct ixgb_ee_map_type *ee_map;
+
+	DEBUGFUNC("ixgb_get_eeprom_data");
+
+	ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	DEBUGOUT("ixgb_ee: Reading eeprom data\n");
+	for(i = 0; i < IXGB_EEPROM_SIZE ; i++) {
+		uint16_t ee_data;
+		ee_data = ixgb_read_eeprom(hw, i);
+		checksum += ee_data;
+		hw->eeprom[i] = le16_to_cpu(ee_data);
+	}
+
+	if (checksum != (uint16_t) EEPROM_SUM) {
+		DEBUGOUT("ixgb_ee: Checksum invalid.\n");
+		/* clear the init_ctrl_reg_1 to signify that the cache is
+		 * invalidated */
+		ee_map->init_ctrl_reg_1 = EEPROM_ICW1_SIGNATURE_CLEAR;
+		return (FALSE);
+	}
+
+	if ((ee_map->init_ctrl_reg_1 & le16_to_cpu(EEPROM_ICW1_SIGNATURE_MASK))
+		 != le16_to_cpu(EEPROM_ICW1_SIGNATURE_VALID)) {
+		DEBUGOUT("ixgb_ee: Signature invalid.\n");
+		return(FALSE);
+	}
+
+	return(TRUE);
+}
+
+/******************************************************************************
+ * Local function to check if the eeprom signature is good
+ * If the eeprom signature is good, calls ixgb)get_eeprom_data.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *      TRUE: eeprom signature was good and the eeprom read was successful
+ *      FALSE: otherwise.
+ ******************************************************************************/
+static boolean_t
+ixgb_check_and_get_eeprom_data (struct ixgb_hw* hw)
+{
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	if ((ee_map->init_ctrl_reg_1 & le16_to_cpu(EEPROM_ICW1_SIGNATURE_MASK))
+	    == le16_to_cpu(EEPROM_ICW1_SIGNATURE_VALID)) {
+		return (TRUE);
+	} else {
+		return ixgb_get_eeprom_data(hw);
+	}
+}
+
+/******************************************************************************
+ * return a word from the eeprom
+ *
+ * hw - Struct containing variables accessed by shared code
+ * index - Offset of eeprom word
+ *
+ * Returns:
+ *          Word at indexed offset in eeprom, if valid, 0 otherwise.
+ ******************************************************************************/
+uint16_t
+ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index)
+{
+
+	if ((index < IXGB_EEPROM_SIZE) &&
+		(ixgb_check_and_get_eeprom_data(hw) == TRUE)) {
+	   return(hw->eeprom[index]);
+	}
+
+	return(0);
+}
+
+/******************************************************************************
+ * return the mac address from EEPROM
+ *
+ * hw       - Struct containing variables accessed by shared code
+ * mac_addr - Ethernet Address if EEPROM contents are valid, 0 otherwise
+ *
+ * Returns: None.
+ ******************************************************************************/
+void
+ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
+			uint8_t *mac_addr)
+{
+	int i;
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	DEBUGFUNC("ixgb_get_ee_mac_addr");
+
+	if (ixgb_check_and_get_eeprom_data(hw) == TRUE) {
+		for (i = 0; i < IXGB_ETH_LENGTH_OF_ADDRESS; i++) {
+			mac_addr[i] = ee_map->mac_addr[i];
+			DEBUGOUT2("mac(%d) = %.2X\n", i, mac_addr[i]);
+		}
+	}
+}
+
+/******************************************************************************
+ * return the compatibility flags from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *          compatibility flags if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+uint16_t
+ixgb_get_ee_compatibility(struct ixgb_hw *hw)
+{
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return(ee_map->compatibility);
+
+	return(0);
+}
+
+/******************************************************************************
+ * return the Printed Board Assembly number from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *          PBA number if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+uint32_t
+ixgb_get_ee_pba_number(struct ixgb_hw *hw)
+{
+	if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return (le16_to_cpu(hw->eeprom[EEPROM_PBA_1_2_REG])
+			| (le16_to_cpu(hw->eeprom[EEPROM_PBA_3_4_REG])<<16));
+
+	return(0);
+}
+
+/******************************************************************************
+ * return the Initialization Control Word 1 from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *          Initialization Control Word 1 if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+uint16_t
+ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw)
+{
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return(ee_map->init_ctrl_reg_1);
+
+	return(0);
+}
+
+/******************************************************************************
+ * return the Initialization Control Word 2 from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *          Initialization Control Word 2 if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+uint16_t
+ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw)
+{
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return(ee_map->init_ctrl_reg_2);
+
+	return(0);
+}
+
+/******************************************************************************
+ * return the Subsystem Id from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *          Subsystem Id if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+uint16_t
+ixgb_get_ee_subsystem_id(struct ixgb_hw *hw)
+{
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+	   return(ee_map->subsystem_id);
+
+	return(0);
+}
+
+/******************************************************************************
+ * return the Sub Vendor Id from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *          Sub Vendor Id if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+uint16_t
+ixgb_get_ee_subvendor_id(struct ixgb_hw *hw)
+{
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return(ee_map->subvendor_id);
+
+	return(0);
+}
+
+/******************************************************************************
+ * return the Device Id from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *          Device Id if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+uint16_t
+ixgb_get_ee_device_id(struct ixgb_hw *hw)
+{
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return(ee_map->device_id);
+
+	return(0);
+}
+
+/******************************************************************************
+ * return the Vendor Id from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *          Device Id if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+uint16_t
+ixgb_get_ee_vendor_id(struct ixgb_hw *hw)
+{
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return(ee_map->vendor_id);
+
+	return(0);
+}
+
+/******************************************************************************
+ * return the Software Defined Pins Register from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *          SDP Register if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+uint16_t
+ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw)
+{
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return(ee_map->swdpins_reg);
+
+	return(0);
+}
+
+/******************************************************************************
+ * return the D3 Power Management Bits from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *          D3 Power Management Bits if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+uint8_t
+ixgb_get_ee_d3_power(struct ixgb_hw *hw)
+{
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return(ee_map->d3_power);
+
+	return(0);
+}
+
+/******************************************************************************
+ * return the D0 Power Management Bits from EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+ *          D0 Power Management Bits if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+uint8_t
+ixgb_get_ee_d0_power(struct ixgb_hw *hw)
+{
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+		return(ee_map->d0_power);
+
+	return(0);
+}
diff --git a/drivers/net/ixgb/ixgb_ee.h b/drivers/net/ixgb/ixgb_ee.h
new file mode 100644
index 0000000..5190aa8
--- /dev/null
+++ b/drivers/net/ixgb/ixgb_ee.h
@@ -0,0 +1,106 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of the GNU General Public License as published by the Free 
+  Software Foundation; either version 2 of the License, or (at your option) 
+  any later version.
+  
+  This program is distributed in the hope that it will be useful, but WITHOUT 
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+  more details.
+  
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#ifndef _IXGB_EE_H_
+#define _IXGB_EE_H_
+
+#define IXGB_EEPROM_SIZE    64	/* Size in words */
+
+#define IXGB_ETH_LENGTH_OF_ADDRESS   6
+
+/* EEPROM Commands */
+#define EEPROM_READ_OPCODE  0x6	/* EERPOM read opcode */
+#define EEPROM_WRITE_OPCODE 0x5	/* EERPOM write opcode */
+#define EEPROM_ERASE_OPCODE 0x7	/* EERPOM erase opcode */
+#define EEPROM_EWEN_OPCODE  0x13	/* EERPOM erase/write enable */
+#define EEPROM_EWDS_OPCODE  0x10	/* EERPOM erast/write disable */
+
+/* EEPROM MAP (Word Offsets) */
+#define EEPROM_IA_1_2_REG        0x0000
+#define EEPROM_IA_3_4_REG        0x0001
+#define EEPROM_IA_5_6_REG        0x0002
+#define EEPROM_COMPATIBILITY_REG 0x0003
+#define EEPROM_PBA_1_2_REG       0x0008
+#define EEPROM_PBA_3_4_REG       0x0009
+#define EEPROM_INIT_CONTROL1_REG 0x000A
+#define EEPROM_SUBSYS_ID_REG     0x000B
+#define EEPROM_SUBVEND_ID_REG    0x000C
+#define EEPROM_DEVICE_ID_REG     0x000D
+#define EEPROM_VENDOR_ID_REG     0x000E
+#define EEPROM_INIT_CONTROL2_REG 0x000F
+#define EEPROM_SWDPINS_REG       0x0020
+#define EEPROM_CIRCUIT_CTRL_REG  0x0021
+#define EEPROM_D0_D3_POWER_REG   0x0022
+#define EEPROM_FLASH_VERSION     0x0032
+#define EEPROM_CHECKSUM_REG      0x003F
+
+/* Mask bits for fields in Word 0x0a of the EEPROM */
+
+#define EEPROM_ICW1_SIGNATURE_MASK  0xC000
+#define EEPROM_ICW1_SIGNATURE_VALID 0x4000
+#define EEPROM_ICW1_SIGNATURE_CLEAR 0x0000
+
+/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */
+#define EEPROM_SUM 0xBABA
+
+/* EEPROM Map Sizes (Byte Counts) */
+#define PBA_SIZE 4
+
+/* EEPROM Map defines (WORD OFFSETS)*/
+
+/* EEPROM structure */
+struct ixgb_ee_map_type {
+	uint8_t mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS];
+	uint16_t compatibility;
+	uint16_t reserved1[4];
+	uint32_t pba_number;
+	uint16_t init_ctrl_reg_1;
+	uint16_t subsystem_id;
+	uint16_t subvendor_id;
+	uint16_t device_id;
+	uint16_t vendor_id;
+	uint16_t init_ctrl_reg_2;
+	uint16_t oem_reserved[16];
+	uint16_t swdpins_reg;
+	uint16_t circuit_ctrl_reg;
+	uint8_t d3_power;
+	uint8_t d0_power;
+	uint16_t reserved2[28];
+	uint16_t checksum;
+};
+
+/* EEPROM Functions */
+uint16_t ixgb_read_eeprom(struct ixgb_hw *hw, uint16_t reg);
+
+boolean_t ixgb_validate_eeprom_checksum(struct ixgb_hw *hw);
+
+void ixgb_update_eeprom_checksum(struct ixgb_hw *hw);
+
+void ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t reg, uint16_t data);
+
+#endif				/* IXGB_EE_H */
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
new file mode 100644
index 0000000..aea10e8
--- /dev/null
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -0,0 +1,704 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of the GNU General Public License as published by the Free 
+  Software Foundation; either version 2 of the License, or (at your option) 
+  any later version.
+  
+  This program is distributed in the hope that it will be useful, but WITHOUT 
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+  more details.
+  
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+/* ethtool support for ixgb */
+
+#include "ixgb.h"
+
+#include <asm/uaccess.h>
+
+extern char ixgb_driver_name[];
+extern char ixgb_driver_version[];
+
+extern int ixgb_up(struct ixgb_adapter *adapter);
+extern void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
+extern void ixgb_reset(struct ixgb_adapter *adapter);
+extern int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
+extern int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
+extern void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
+extern void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
+extern void ixgb_update_stats(struct ixgb_adapter *adapter);
+
+struct ixgb_stats {
+	char stat_string[ETH_GSTRING_LEN];
+	int sizeof_stat;
+	int stat_offset;
+};
+
+#define IXGB_STAT(m) sizeof(((struct ixgb_adapter *)0)->m), \
+		      offsetof(struct ixgb_adapter, m)
+static struct ixgb_stats ixgb_gstrings_stats[] = {
+	{"rx_packets", IXGB_STAT(net_stats.rx_packets)},
+	{"tx_packets", IXGB_STAT(net_stats.tx_packets)},
+	{"rx_bytes", IXGB_STAT(net_stats.rx_bytes)},
+	{"tx_bytes", IXGB_STAT(net_stats.tx_bytes)},
+	{"rx_errors", IXGB_STAT(net_stats.rx_errors)},
+	{"tx_errors", IXGB_STAT(net_stats.tx_errors)},
+	{"rx_dropped", IXGB_STAT(net_stats.rx_dropped)},
+	{"tx_dropped", IXGB_STAT(net_stats.tx_dropped)},
+	{"multicast", IXGB_STAT(net_stats.multicast)},
+	{"collisions", IXGB_STAT(net_stats.collisions)},
+
+/*	{ "rx_length_errors", IXGB_STAT(net_stats.rx_length_errors) },	*/
+	{"rx_over_errors", IXGB_STAT(net_stats.rx_over_errors)},
+	{"rx_crc_errors", IXGB_STAT(net_stats.rx_crc_errors)},
+	{"rx_frame_errors", IXGB_STAT(net_stats.rx_frame_errors)},
+	{"rx_fifo_errors", IXGB_STAT(net_stats.rx_fifo_errors)},
+	{"rx_missed_errors", IXGB_STAT(net_stats.rx_missed_errors)},
+	{"tx_aborted_errors", IXGB_STAT(net_stats.tx_aborted_errors)},
+	{"tx_carrier_errors", IXGB_STAT(net_stats.tx_carrier_errors)},
+	{"tx_fifo_errors", IXGB_STAT(net_stats.tx_fifo_errors)},
+	{"tx_heartbeat_errors", IXGB_STAT(net_stats.tx_heartbeat_errors)},
+	{"tx_window_errors", IXGB_STAT(net_stats.tx_window_errors)},
+	{"tx_deferred_ok", IXGB_STAT(stats.dc)},
+	{"rx_long_length_errors", IXGB_STAT(stats.roc)},
+	{"rx_short_length_errors", IXGB_STAT(stats.ruc)},
+#ifdef NETIF_F_TSO
+	{"tx_tcp_seg_good", IXGB_STAT(stats.tsctc)},
+	{"tx_tcp_seg_failed", IXGB_STAT(stats.tsctfc)},
+#endif
+	{"rx_flow_control_xon", IXGB_STAT(stats.xonrxc)},
+	{"rx_flow_control_xoff", IXGB_STAT(stats.xoffrxc)},
+	{"tx_flow_control_xon", IXGB_STAT(stats.xontxc)},
+	{"tx_flow_control_xoff", IXGB_STAT(stats.xofftxc)},
+	{"rx_csum_offload_good", IXGB_STAT(hw_csum_rx_good)},
+	{"rx_csum_offload_errors", IXGB_STAT(hw_csum_rx_error)},
+	{"tx_csum_offload_good", IXGB_STAT(hw_csum_tx_good)},
+	{"tx_csum_offload_errors", IXGB_STAT(hw_csum_tx_error)}
+};
+
+#define IXGB_STATS_LEN	\
+	sizeof(ixgb_gstrings_stats) / sizeof(struct ixgb_stats)
+
+static int
+ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+	ecmd->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+	ecmd->port = PORT_FIBRE;
+	ecmd->transceiver = XCVR_EXTERNAL;
+
+	if(netif_carrier_ok(adapter->netdev)) {
+		ecmd->speed = SPEED_10000;
+		ecmd->duplex = DUPLEX_FULL;
+	} else {
+		ecmd->speed = -1;
+		ecmd->duplex = -1;
+	}
+
+	ecmd->autoneg = AUTONEG_DISABLE;
+	return 0;
+}
+
+static int
+ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	if(ecmd->autoneg == AUTONEG_ENABLE ||
+	   ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
+		return -EINVAL;
+	
+	if(netif_running(adapter->netdev)) {
+		ixgb_down(adapter, TRUE);
+		ixgb_reset(adapter);
+		ixgb_up(adapter);
+	} else
+		ixgb_reset(adapter);
+
+	return 0;
+}
+
+static void
+ixgb_get_pauseparam(struct net_device *netdev,
+			 struct ethtool_pauseparam *pause)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	struct ixgb_hw *hw = &adapter->hw;
+	
+	pause->autoneg = AUTONEG_DISABLE;
+		
+	if(hw->fc.type == ixgb_fc_rx_pause)
+		pause->rx_pause = 1;
+	else if(hw->fc.type == ixgb_fc_tx_pause)
+		pause->tx_pause = 1;
+	else if(hw->fc.type == ixgb_fc_full) {
+		pause->rx_pause = 1;
+		pause->tx_pause = 1;
+	}
+}
+
+static int
+ixgb_set_pauseparam(struct net_device *netdev,
+			 struct ethtool_pauseparam *pause)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	struct ixgb_hw *hw = &adapter->hw;
+	
+	if(pause->autoneg == AUTONEG_ENABLE)
+		return -EINVAL;
+
+	if(pause->rx_pause && pause->tx_pause)
+		hw->fc.type = ixgb_fc_full;
+	else if(pause->rx_pause && !pause->tx_pause)
+		hw->fc.type = ixgb_fc_rx_pause;
+	else if(!pause->rx_pause && pause->tx_pause)
+		hw->fc.type = ixgb_fc_tx_pause;
+	else if(!pause->rx_pause && !pause->tx_pause)
+		hw->fc.type = ixgb_fc_none;
+
+	if(netif_running(adapter->netdev)) {
+		ixgb_down(adapter, TRUE);
+		ixgb_up(adapter);
+	} else
+		ixgb_reset(adapter);
+		
+	return 0;
+}
+
+static uint32_t
+ixgb_get_rx_csum(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	return adapter->rx_csum;
+}
+
+static int
+ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	adapter->rx_csum = data;
+
+	if(netif_running(netdev)) {
+		ixgb_down(adapter,TRUE);
+		ixgb_up(adapter);
+	} else
+		ixgb_reset(adapter);
+	return 0;
+}
+	
+static uint32_t
+ixgb_get_tx_csum(struct net_device *netdev)
+{
+	return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static int
+ixgb_set_tx_csum(struct net_device *netdev, uint32_t data)
+{
+	if (data)
+		netdev->features |= NETIF_F_HW_CSUM;
+	else
+		netdev->features &= ~NETIF_F_HW_CSUM;
+
+	return 0;
+}
+
+#ifdef NETIF_F_TSO
+static int
+ixgb_set_tso(struct net_device *netdev, uint32_t data)
+{
+	if(data)
+		netdev->features |= NETIF_F_TSO;
+	else
+		netdev->features &= ~NETIF_F_TSO;
+	return 0;
+} 
+#endif /* NETIF_F_TSO */
+
+#define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_
+
+static int 
+ixgb_get_regs_len(struct net_device *netdev)
+{
+#define IXGB_REG_DUMP_LEN  136*sizeof(uint32_t)
+	return IXGB_REG_DUMP_LEN;
+}
+
+static void
+ixgb_get_regs(struct net_device *netdev,
+		   struct ethtool_regs *regs, void *p)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	struct ixgb_hw *hw = &adapter->hw;
+	uint32_t *reg = p;
+	uint32_t *reg_start = reg;
+	uint8_t i;
+
+	regs->version = (adapter->hw.device_id << 16) | adapter->hw.subsystem_id;
+
+	/* General Registers */
+	*reg++ = IXGB_READ_REG(hw, CTRL0);	/*   0 */
+	*reg++ = IXGB_READ_REG(hw, CTRL1);	/*   1 */
+	*reg++ = IXGB_READ_REG(hw, STATUS);	/*   2 */
+	*reg++ = IXGB_READ_REG(hw, EECD);	/*   3 */
+	*reg++ = IXGB_READ_REG(hw, MFS);	/*   4 */
+
+	/* Interrupt */
+	*reg++ = IXGB_READ_REG(hw, ICR);	/*   5 */
+	*reg++ = IXGB_READ_REG(hw, ICS);	/*   6 */
+	*reg++ = IXGB_READ_REG(hw, IMS);	/*   7 */
+	*reg++ = IXGB_READ_REG(hw, IMC);	/*   8 */
+
+	/* Receive */
+	*reg++ = IXGB_READ_REG(hw, RCTL);	/*   9 */
+	*reg++ = IXGB_READ_REG(hw, FCRTL);	/*  10 */
+	*reg++ = IXGB_READ_REG(hw, FCRTH);	/*  11 */
+	*reg++ = IXGB_READ_REG(hw, RDBAL);	/*  12 */
+	*reg++ = IXGB_READ_REG(hw, RDBAH);	/*  13 */
+	*reg++ = IXGB_READ_REG(hw, RDLEN);	/*  14 */
+	*reg++ = IXGB_READ_REG(hw, RDH);	/*  15 */
+	*reg++ = IXGB_READ_REG(hw, RDT);	/*  16 */
+	*reg++ = IXGB_READ_REG(hw, RDTR);	/*  17 */
+	*reg++ = IXGB_READ_REG(hw, RXDCTL);	/*  18 */
+	*reg++ = IXGB_READ_REG(hw, RAIDC);	/*  19 */
+	*reg++ = IXGB_READ_REG(hw, RXCSUM);	/*  20 */
+
+	for (i = 0; i < IXGB_RAR_ENTRIES; i++) {
+		*reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
+		*reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
+	}
+
+	/* Transmit */
+	*reg++ = IXGB_READ_REG(hw, TCTL);	/*  53 */
+	*reg++ = IXGB_READ_REG(hw, TDBAL);	/*  54 */
+	*reg++ = IXGB_READ_REG(hw, TDBAH);	/*  55 */
+	*reg++ = IXGB_READ_REG(hw, TDLEN);	/*  56 */
+	*reg++ = IXGB_READ_REG(hw, TDH);	/*  57 */
+	*reg++ = IXGB_READ_REG(hw, TDT);	/*  58 */
+	*reg++ = IXGB_READ_REG(hw, TIDV);	/*  59 */
+	*reg++ = IXGB_READ_REG(hw, TXDCTL);	/*  60 */
+	*reg++ = IXGB_READ_REG(hw, TSPMT);	/*  61 */
+	*reg++ = IXGB_READ_REG(hw, PAP);	/*  62 */
+
+	/* Physical */
+	*reg++ = IXGB_READ_REG(hw, PCSC1);	/*  63 */
+	*reg++ = IXGB_READ_REG(hw, PCSC2);	/*  64 */
+	*reg++ = IXGB_READ_REG(hw, PCSS1);	/*  65 */
+	*reg++ = IXGB_READ_REG(hw, PCSS2);	/*  66 */
+	*reg++ = IXGB_READ_REG(hw, XPCSS);	/*  67 */
+	*reg++ = IXGB_READ_REG(hw, UCCR);	/*  68 */
+	*reg++ = IXGB_READ_REG(hw, XPCSTC);	/*  69 */
+	*reg++ = IXGB_READ_REG(hw, MACA);	/*  70 */
+	*reg++ = IXGB_READ_REG(hw, APAE);	/*  71 */
+	*reg++ = IXGB_READ_REG(hw, ARD);	/*  72 */
+	*reg++ = IXGB_READ_REG(hw, AIS);	/*  73 */
+	*reg++ = IXGB_READ_REG(hw, MSCA);	/*  74 */
+	*reg++ = IXGB_READ_REG(hw, MSRWD);	/*  75 */
+
+	/* Statistics */
+	*reg++ = IXGB_GET_STAT(adapter, tprl);	/*  76 */
+	*reg++ = IXGB_GET_STAT(adapter, tprh);	/*  77 */
+	*reg++ = IXGB_GET_STAT(adapter, gprcl);	/*  78 */
+	*reg++ = IXGB_GET_STAT(adapter, gprch);	/*  79 */
+	*reg++ = IXGB_GET_STAT(adapter, bprcl);	/*  80 */
+	*reg++ = IXGB_GET_STAT(adapter, bprch);	/*  81 */
+	*reg++ = IXGB_GET_STAT(adapter, mprcl);	/*  82 */
+	*reg++ = IXGB_GET_STAT(adapter, mprch);	/*  83 */
+	*reg++ = IXGB_GET_STAT(adapter, uprcl);	/*  84 */
+	*reg++ = IXGB_GET_STAT(adapter, uprch);	/*  85 */
+	*reg++ = IXGB_GET_STAT(adapter, vprcl);	/*  86 */
+	*reg++ = IXGB_GET_STAT(adapter, vprch);	/*  87 */
+	*reg++ = IXGB_GET_STAT(adapter, jprcl);	/*  88 */
+	*reg++ = IXGB_GET_STAT(adapter, jprch);	/*  89 */
+	*reg++ = IXGB_GET_STAT(adapter, gorcl);	/*  90 */
+	*reg++ = IXGB_GET_STAT(adapter, gorch);	/*  91 */
+	*reg++ = IXGB_GET_STAT(adapter, torl);	/*  92 */
+	*reg++ = IXGB_GET_STAT(adapter, torh);	/*  93 */
+	*reg++ = IXGB_GET_STAT(adapter, rnbc);	/*  94 */
+	*reg++ = IXGB_GET_STAT(adapter, ruc);	/*  95 */
+	*reg++ = IXGB_GET_STAT(adapter, roc);	/*  96 */
+	*reg++ = IXGB_GET_STAT(adapter, rlec);	/*  97 */
+	*reg++ = IXGB_GET_STAT(adapter, crcerrs);	/*  98 */
+	*reg++ = IXGB_GET_STAT(adapter, icbc);	/*  99 */
+	*reg++ = IXGB_GET_STAT(adapter, ecbc);	/* 100 */
+	*reg++ = IXGB_GET_STAT(adapter, mpc);	/* 101 */
+	*reg++ = IXGB_GET_STAT(adapter, tptl);	/* 102 */
+	*reg++ = IXGB_GET_STAT(adapter, tpth);	/* 103 */
+	*reg++ = IXGB_GET_STAT(adapter, gptcl);	/* 104 */
+	*reg++ = IXGB_GET_STAT(adapter, gptch);	/* 105 */
+	*reg++ = IXGB_GET_STAT(adapter, bptcl);	/* 106 */
+	*reg++ = IXGB_GET_STAT(adapter, bptch);	/* 107 */
+	*reg++ = IXGB_GET_STAT(adapter, mptcl);	/* 108 */
+	*reg++ = IXGB_GET_STAT(adapter, mptch);	/* 109 */
+	*reg++ = IXGB_GET_STAT(adapter, uptcl);	/* 110 */
+	*reg++ = IXGB_GET_STAT(adapter, uptch);	/* 111 */
+	*reg++ = IXGB_GET_STAT(adapter, vptcl);	/* 112 */
+	*reg++ = IXGB_GET_STAT(adapter, vptch);	/* 113 */
+	*reg++ = IXGB_GET_STAT(adapter, jptcl);	/* 114 */
+	*reg++ = IXGB_GET_STAT(adapter, jptch);	/* 115 */
+	*reg++ = IXGB_GET_STAT(adapter, gotcl);	/* 116 */
+	*reg++ = IXGB_GET_STAT(adapter, gotch);	/* 117 */
+	*reg++ = IXGB_GET_STAT(adapter, totl);	/* 118 */
+	*reg++ = IXGB_GET_STAT(adapter, toth);	/* 119 */
+	*reg++ = IXGB_GET_STAT(adapter, dc);	/* 120 */
+	*reg++ = IXGB_GET_STAT(adapter, plt64c);	/* 121 */
+	*reg++ = IXGB_GET_STAT(adapter, tsctc);	/* 122 */
+	*reg++ = IXGB_GET_STAT(adapter, tsctfc);	/* 123 */
+	*reg++ = IXGB_GET_STAT(adapter, ibic);	/* 124 */
+	*reg++ = IXGB_GET_STAT(adapter, rfc);	/* 125 */
+	*reg++ = IXGB_GET_STAT(adapter, lfc);	/* 126 */
+	*reg++ = IXGB_GET_STAT(adapter, pfrc);	/* 127 */
+	*reg++ = IXGB_GET_STAT(adapter, pftc);	/* 128 */
+	*reg++ = IXGB_GET_STAT(adapter, mcfrc);	/* 129 */
+	*reg++ = IXGB_GET_STAT(adapter, mcftc);	/* 130 */
+	*reg++ = IXGB_GET_STAT(adapter, xonrxc);	/* 131 */
+	*reg++ = IXGB_GET_STAT(adapter, xontxc);	/* 132 */
+	*reg++ = IXGB_GET_STAT(adapter, xoffrxc);	/* 133 */
+	*reg++ = IXGB_GET_STAT(adapter, xofftxc);	/* 134 */
+	*reg++ = IXGB_GET_STAT(adapter, rjc);	/* 135 */
+
+	regs->len = (reg - reg_start) * sizeof(uint32_t);
+}
+
+static int
+ixgb_get_eeprom_len(struct net_device *netdev)
+{
+	/* return size in bytes */
+	return (IXGB_EEPROM_SIZE << 1);
+}
+
+static int
+ixgb_get_eeprom(struct net_device *netdev,
+		  struct ethtool_eeprom *eeprom, uint8_t *bytes)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	struct ixgb_hw *hw = &adapter->hw;
+	uint16_t *eeprom_buff;
+	int i, max_len, first_word, last_word;
+	int ret_val = 0;
+
+	if(eeprom->len == 0) {
+		ret_val = -EINVAL;
+		goto geeprom_error;
+	}
+
+	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
+
+	max_len = ixgb_get_eeprom_len(netdev);
+
+	if(eeprom->offset > eeprom->offset + eeprom->len) {
+		ret_val = -EINVAL;
+		goto geeprom_error;
+	}
+
+	if((eeprom->offset + eeprom->len) > max_len)
+		eeprom->len = (max_len - eeprom->offset);
+
+	first_word = eeprom->offset >> 1;
+	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+
+	eeprom_buff = kmalloc(sizeof(uint16_t) *
+			(last_word - first_word + 1), GFP_KERNEL);
+	if(!eeprom_buff)
+		return -ENOMEM;
+
+	/* note the eeprom was good because the driver loaded */
+	for(i = 0; i <= (last_word - first_word); i++) {
+		eeprom_buff[i] = ixgb_get_eeprom_word(hw, (first_word + i));
+	}
+
+	memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
+			eeprom->len);
+	kfree(eeprom_buff);
+
+geeprom_error:
+	return ret_val;
+}
+
+static int
+ixgb_set_eeprom(struct net_device *netdev,
+		  struct ethtool_eeprom *eeprom, uint8_t *bytes)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	struct ixgb_hw *hw = &adapter->hw;
+	uint16_t *eeprom_buff;
+	void *ptr;
+	int max_len, first_word, last_word;
+	uint16_t i;
+
+	if(eeprom->len == 0)
+		return -EINVAL;
+
+	if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+		return -EFAULT;
+
+	max_len = ixgb_get_eeprom_len(netdev);
+
+	if(eeprom->offset > eeprom->offset + eeprom->len)
+		return -EINVAL;
+
+	if((eeprom->offset + eeprom->len) > max_len)
+		eeprom->len = (max_len - eeprom->offset);
+
+	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;
+
+	if(eeprom->offset & 1) {
+		/* need read/modify/write of first changed EEPROM word */
+		/* only the second byte of the word is being modified */
+		eeprom_buff[0] = ixgb_read_eeprom(hw, first_word);
+		ptr++;
+	}
+	if((eeprom->offset + eeprom->len) & 1) {
+		/* need read/modify/write of last changed EEPROM word */
+		/* only the first byte of the word is being modified */
+		eeprom_buff[last_word - first_word] 
+			= ixgb_read_eeprom(hw, last_word);
+	}
+
+	memcpy(ptr, bytes, eeprom->len);
+	for(i = 0; i <= (last_word - first_word); i++)
+		ixgb_write_eeprom(hw, first_word + i, eeprom_buff[i]);
+
+	/* Update the checksum over the first part of the EEPROM if needed */
+	if(first_word <= EEPROM_CHECKSUM_REG)
+		ixgb_update_eeprom_checksum(hw);
+
+	kfree(eeprom_buff);
+	return 0;
+}
+
+static void
+ixgb_get_drvinfo(struct net_device *netdev,
+		   struct ethtool_drvinfo *drvinfo)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	strncpy(drvinfo->driver,  ixgb_driver_name, 32);
+	strncpy(drvinfo->version, ixgb_driver_version, 32);
+	strncpy(drvinfo->fw_version, "N/A", 32);
+	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+	drvinfo->n_stats = IXGB_STATS_LEN;
+	drvinfo->regdump_len = ixgb_get_regs_len(netdev);
+	drvinfo->eedump_len = ixgb_get_eeprom_len(netdev);
+}
+
+static void
+ixgb_get_ringparam(struct net_device *netdev,
+		struct ethtool_ringparam *ring)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	struct ixgb_desc_ring *txdr = &adapter->tx_ring;
+	struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
+
+	ring->rx_max_pending = MAX_RXD; 
+	ring->tx_max_pending = MAX_TXD;
+	ring->rx_mini_max_pending = 0;
+	ring->rx_jumbo_max_pending = 0;
+	ring->rx_pending = rxdr->count;
+	ring->tx_pending = txdr->count;
+	ring->rx_mini_pending = 0;
+	ring->rx_jumbo_pending = 0;
+}
+
+static int 
+ixgb_set_ringparam(struct net_device *netdev,
+		struct ethtool_ringparam *ring)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	struct ixgb_desc_ring *txdr = &adapter->tx_ring;
+	struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
+	struct ixgb_desc_ring tx_old, tx_new, rx_old, rx_new;
+	int err;
+
+	tx_old = adapter->tx_ring;
+	rx_old = adapter->rx_ring;
+
+	if((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) 
+		return -EINVAL;
+
+	if(netif_running(adapter->netdev))
+		ixgb_down(adapter,TRUE);
+
+	rxdr->count = max(ring->rx_pending,(uint32_t)MIN_RXD);
+	rxdr->count = min(rxdr->count,(uint32_t)MAX_RXD);
+	IXGB_ROUNDUP(rxdr->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE); 
+
+	txdr->count = max(ring->tx_pending,(uint32_t)MIN_TXD);
+	txdr->count = min(txdr->count,(uint32_t)MAX_TXD);
+	IXGB_ROUNDUP(txdr->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE); 
+
+	if(netif_running(adapter->netdev)) {
+		/* Try to get new resources before deleting old */
+		if((err = ixgb_setup_rx_resources(adapter)))
+			goto err_setup_rx;
+		if((err = ixgb_setup_tx_resources(adapter)))
+			goto err_setup_tx;
+
+		/* save the new, restore the old in order to free it,
+		 * then restore the new back again */
+
+		rx_new = adapter->rx_ring;
+		tx_new = adapter->tx_ring;
+		adapter->rx_ring = rx_old;
+		adapter->tx_ring = tx_old;
+		ixgb_free_rx_resources(adapter);
+		ixgb_free_tx_resources(adapter);
+		adapter->rx_ring = rx_new;
+		adapter->tx_ring = tx_new;
+		if((err = ixgb_up(adapter)))
+			return err;
+	}
+
+	return 0;
+err_setup_tx:
+	ixgb_free_rx_resources(adapter);
+err_setup_rx:
+	adapter->rx_ring = rx_old;
+	adapter->tx_ring = tx_old;
+	ixgb_up(adapter);
+	return err;
+}
+
+/* toggle LED 4 times per second = 2 "blinks" per second */
+#define IXGB_ID_INTERVAL	(HZ/4)
+
+/* bit defines for adapter->led_status */
+#define IXGB_LED_ON		0
+
+static void
+ixgb_led_blink_callback(unsigned long data)
+{
+	struct ixgb_adapter *adapter = (struct ixgb_adapter *)data;
+
+	if(test_and_change_bit(IXGB_LED_ON, &adapter->led_status))
+		ixgb_led_off(&adapter->hw);
+	else
+		ixgb_led_on(&adapter->hw);
+
+	mod_timer(&adapter->blink_timer, jiffies + IXGB_ID_INTERVAL);
+}
+
+static int
+ixgb_phys_id(struct net_device *netdev, uint32_t data)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
+		data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
+
+	if(!adapter->blink_timer.function) {
+		init_timer(&adapter->blink_timer);
+		adapter->blink_timer.function = ixgb_led_blink_callback;
+		adapter->blink_timer.data = (unsigned long)adapter;
+	}
+
+	mod_timer(&adapter->blink_timer, jiffies);
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	if(data)
+		schedule_timeout(data * HZ);
+	else
+		schedule_timeout(MAX_SCHEDULE_TIMEOUT);
+
+	del_timer_sync(&adapter->blink_timer);
+	ixgb_led_off(&adapter->hw);
+	clear_bit(IXGB_LED_ON, &adapter->led_status);
+
+	return 0;
+}
+
+static int 
+ixgb_get_stats_count(struct net_device *netdev)
+{
+	return IXGB_STATS_LEN;
+}
+
+static void 
+ixgb_get_ethtool_stats(struct net_device *netdev, 
+		struct ethtool_stats *stats, uint64_t *data)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	int i;
+
+	ixgb_update_stats(adapter);
+	for(i = 0; i < IXGB_STATS_LEN; i++) {
+		char *p = (char *)adapter+ixgb_gstrings_stats[i].stat_offset;	
+		data[i] = (ixgb_gstrings_stats[i].sizeof_stat == 
+			sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
+	}
+}
+
+static void 
+ixgb_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
+{
+	int i;
+
+	switch(stringset) {
+	case ETH_SS_STATS:
+		for(i=0; i < IXGB_STATS_LEN; i++) {
+			memcpy(data + i * ETH_GSTRING_LEN, 
+			ixgb_gstrings_stats[i].stat_string,
+			ETH_GSTRING_LEN);
+		}
+		break;
+	}
+}
+
+struct ethtool_ops ixgb_ethtool_ops = {
+	.get_settings = ixgb_get_settings,
+	.set_settings = ixgb_set_settings,
+	.get_drvinfo = ixgb_get_drvinfo,
+	.get_regs_len = ixgb_get_regs_len,
+	.get_regs = ixgb_get_regs,
+	.get_link = ethtool_op_get_link,
+	.get_eeprom_len = ixgb_get_eeprom_len,
+	.get_eeprom = ixgb_get_eeprom,
+	.set_eeprom = ixgb_set_eeprom,
+	.get_ringparam = ixgb_get_ringparam,
+	.set_ringparam = ixgb_set_ringparam,
+	.get_pauseparam	= ixgb_get_pauseparam,
+	.set_pauseparam	= ixgb_set_pauseparam,
+	.get_rx_csum = ixgb_get_rx_csum,
+	.set_rx_csum = ixgb_set_rx_csum,
+	.get_tx_csum = ixgb_get_tx_csum,
+	.set_tx_csum = ixgb_set_tx_csum,
+	.get_sg	= ethtool_op_get_sg,
+	.set_sg	= ethtool_op_set_sg,
+#ifdef NETIF_F_TSO
+	.get_tso = ethtool_op_get_tso,
+	.set_tso = ixgb_set_tso,
+#endif
+	.get_strings = ixgb_get_strings,
+	.phys_id = ixgb_phys_id,
+	.get_stats_count = ixgb_get_stats_count,
+	.get_ethtool_stats = ixgb_get_ethtool_stats,
+};
+
+void ixgb_set_ethtool_ops(struct net_device *netdev)
+{
+	SET_ETHTOOL_OPS(netdev, &ixgb_ethtool_ops);
+}
diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
new file mode 100644
index 0000000..69329c7
--- /dev/null
+++ b/drivers/net/ixgb/ixgb_hw.c
@@ -0,0 +1,1202 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of the GNU General Public License as published by the Free 
+  Software Foundation; either version 2 of the License, or (at your option) 
+  any later version.
+  
+  This program is distributed in the hope that it will be useful, but WITHOUT 
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+  more details.
+  
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+/* ixgb_hw.c
+ * Shared functions for accessing and configuring the adapter
+ */
+
+#include "ixgb_hw.h"
+#include "ixgb_ids.h"
+
+/*  Local function prototypes */
+
+static uint32_t ixgb_hash_mc_addr(struct ixgb_hw *hw, uint8_t * mc_addr);
+
+static void ixgb_mta_set(struct ixgb_hw *hw, uint32_t hash_value);
+
+static void ixgb_get_bus_info(struct ixgb_hw *hw);
+
+static boolean_t ixgb_link_reset(struct ixgb_hw *hw);
+
+static void ixgb_optics_reset(struct ixgb_hw *hw);
+
+static ixgb_phy_type ixgb_identify_phy(struct ixgb_hw *hw);
+
+uint32_t ixgb_mac_reset(struct ixgb_hw *hw);
+
+uint32_t ixgb_mac_reset(struct ixgb_hw *hw)
+{
+	uint32_t ctrl_reg;
+
+	ctrl_reg =  IXGB_CTRL0_RST |
+				IXGB_CTRL0_SDP3_DIR |   /* All pins are Output=1 */
+				IXGB_CTRL0_SDP2_DIR |
+				IXGB_CTRL0_SDP1_DIR |
+				IXGB_CTRL0_SDP0_DIR |
+				IXGB_CTRL0_SDP3	 |   /* Initial value 1101   */
+				IXGB_CTRL0_SDP2	 |
+				IXGB_CTRL0_SDP0;
+
+#ifdef HP_ZX1
+	/* Workaround for 82597EX reset errata */
+	IXGB_WRITE_REG_IO(hw, CTRL0, ctrl_reg);
+#else
+	IXGB_WRITE_REG(hw, CTRL0, ctrl_reg);
+#endif
+
+	/* Delay a few ms just to allow the reset to complete */
+	msec_delay(IXGB_DELAY_AFTER_RESET);
+	ctrl_reg = IXGB_READ_REG(hw, CTRL0);
+#ifdef DBG
+	/* Make sure the self-clearing global reset bit did self clear */
+	ASSERT(!(ctrl_reg & IXGB_CTRL0_RST));
+#endif
+
+	if (hw->phy_type == ixgb_phy_type_txn17401) {
+		ixgb_optics_reset(hw);
+	}
+
+	return ctrl_reg;
+}
+
+/******************************************************************************
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+boolean_t
+ixgb_adapter_stop(struct ixgb_hw *hw)
+{
+	uint32_t ctrl_reg;
+	uint32_t icr_reg;
+
+	DEBUGFUNC("ixgb_adapter_stop");
+
+	/* If we are stopped or resetting exit gracefully and wait to be
+	 * started again before accessing the hardware.
+	 */
+	if(hw->adapter_stopped) {
+		DEBUGOUT("Exiting because the adapter is already stopped!!!\n");
+		return FALSE;
+	}
+
+	/* Set the Adapter Stopped flag so other driver functions stop
+	 * touching the Hardware.
+	 */
+	hw->adapter_stopped = TRUE;
+
+	/* Clear interrupt mask to stop board from generating interrupts */
+	DEBUGOUT("Masking off all interrupts\n");
+	IXGB_WRITE_REG(hw, IMC, 0xFFFFFFFF);
+
+	/* Disable the Transmit and Receive units.  Then delay to allow
+	 * any pending transactions to complete before we hit the MAC with
+	 * the global reset.
+	 */
+	IXGB_WRITE_REG(hw, RCTL, IXGB_READ_REG(hw, RCTL) & ~IXGB_RCTL_RXEN);
+	IXGB_WRITE_REG(hw, TCTL, IXGB_READ_REG(hw, TCTL) & ~IXGB_TCTL_TXEN);
+	msec_delay(IXGB_DELAY_BEFORE_RESET);
+
+	/* Issue a global reset to the MAC.  This will reset the chip's
+	 * transmit, receive, DMA, and link units.  It will not effect
+	 * the current PCI configuration.  The global reset bit is self-
+	 * clearing, and should clear within a microsecond.
+	 */
+	DEBUGOUT("Issuing a global reset to MAC\n");
+
+	ctrl_reg = ixgb_mac_reset(hw);
+
+	/* Clear interrupt mask to stop board from generating interrupts */
+	DEBUGOUT("Masking off all interrupts\n");
+	IXGB_WRITE_REG(hw, IMC, 0xffffffff);
+
+	/* Clear any pending interrupt events. */
+	icr_reg = IXGB_READ_REG(hw, ICR);
+
+	return (ctrl_reg & IXGB_CTRL0_RST);
+}
+
+
+/******************************************************************************
+ * Identifies the vendor of the optics module on the adapter.  The SR adapters
+ * support two different types of XPAK optics, so it is necessary to determine
+ * which optics are present before applying any optics-specific workarounds.
+ *
+ * hw - Struct containing variables accessed by shared code.
+ *
+ * Returns: the vendor of the XPAK optics module.
+ *****************************************************************************/
+static ixgb_xpak_vendor
+ixgb_identify_xpak_vendor(struct ixgb_hw *hw)
+{
+	uint32_t i;
+	uint16_t vendor_name[5];
+	ixgb_xpak_vendor xpak_vendor;
+
+	DEBUGFUNC("ixgb_identify_xpak_vendor");
+
+	/* Read the first few bytes of the vendor string from the XPAK NVR
+	 * registers.  These are standard XENPAK/XPAK registers, so all XPAK
+	 * devices should implement them. */
+	for (i = 0; i < 5; i++) {
+		vendor_name[i] = ixgb_read_phy_reg(hw,
+						   MDIO_PMA_PMD_XPAK_VENDOR_NAME
+						   + i, IXGB_PHY_ADDRESS,
+						   MDIO_PMA_PMD_DID);
+	}
+
+	/* Determine the actual vendor */
+	if (vendor_name[0] == 'I' &&
+	    vendor_name[1] == 'N' &&
+	    vendor_name[2] == 'T' &&
+	    vendor_name[3] == 'E' && vendor_name[4] == 'L') {
+		xpak_vendor = ixgb_xpak_vendor_intel;
+	} else {
+		xpak_vendor = ixgb_xpak_vendor_infineon;
+	}
+
+	return (xpak_vendor);
+}
+
+/******************************************************************************
+ * Determine the physical layer module on the adapter.
+ *
+ * hw - Struct containing variables accessed by shared code.  The device_id
+ *      field must be (correctly) populated before calling this routine.
+ *
+ * Returns: the phy type of the adapter.
+ *****************************************************************************/
+static ixgb_phy_type
+ixgb_identify_phy(struct ixgb_hw *hw)
+{
+	ixgb_phy_type phy_type;
+	ixgb_xpak_vendor xpak_vendor;
+
+	DEBUGFUNC("ixgb_identify_phy");
+
+	/* Infer the transceiver/phy type from the device id */
+	switch (hw->device_id) {
+	case IXGB_DEVICE_ID_82597EX:
+		DEBUGOUT("Identified TXN17401 optics\n");
+		phy_type = ixgb_phy_type_txn17401;
+		break;
+
+	case IXGB_DEVICE_ID_82597EX_SR:
+		/* The SR adapters carry two different types of XPAK optics
+		 * modules; read the vendor identifier to determine the exact
+		 * type of optics. */
+		xpak_vendor = ixgb_identify_xpak_vendor(hw);
+		if (xpak_vendor == ixgb_xpak_vendor_intel) {
+			DEBUGOUT("Identified TXN17201 optics\n");
+			phy_type = ixgb_phy_type_txn17201;
+		} else {
+			DEBUGOUT("Identified G6005 optics\n");
+			phy_type = ixgb_phy_type_g6005;
+		}
+		break;
+	case IXGB_DEVICE_ID_82597EX_LR:
+		DEBUGOUT("Identified G6104 optics\n");
+		phy_type = ixgb_phy_type_g6104;
+		break;
+	default:
+		DEBUGOUT("Unknown physical layer module\n");
+		phy_type = ixgb_phy_type_unknown;
+		break;
+	}
+
+	return (phy_type);
+}
+
+/******************************************************************************
+ * Performs basic configuration of the adapter.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Resets the controller.
+ * Reads and validates the EEPROM.
+ * Initializes the receive address registers.
+ * Initializes the multicast table.
+ * Clears all on-chip counters.
+ * Calls routine to setup flow control settings.
+ * Leaves the transmit and receive units disabled and uninitialized.
+ *
+ * Returns:
+ *      TRUE if successful,
+ *      FALSE if unrecoverable problems were encountered.
+ *****************************************************************************/
+boolean_t
+ixgb_init_hw(struct ixgb_hw *hw)
+{
+	uint32_t i;
+	uint32_t ctrl_reg;
+	boolean_t status;
+
+	DEBUGFUNC("ixgb_init_hw");
+
+	/* Issue a global reset to the MAC.  This will reset the chip's
+	 * transmit, receive, DMA, and link units.  It will not effect
+	 * the current PCI configuration.  The global reset bit is self-
+	 * clearing, and should clear within a microsecond.
+	 */
+	DEBUGOUT("Issuing a global reset to MAC\n");
+
+	ctrl_reg = ixgb_mac_reset(hw);
+
+	DEBUGOUT("Issuing an EE reset to MAC\n");
+#ifdef HP_ZX1
+	/* Workaround for 82597EX reset errata */
+	IXGB_WRITE_REG_IO(hw, CTRL1, IXGB_CTRL1_EE_RST);
+#else
+	IXGB_WRITE_REG(hw, CTRL1, IXGB_CTRL1_EE_RST);
+#endif
+
+	/* Delay a few ms just to allow the reset to complete */
+	msec_delay(IXGB_DELAY_AFTER_EE_RESET);
+
+	if (ixgb_get_eeprom_data(hw) == FALSE) {
+		return(FALSE);
+	}
+
+	/* Use the device id to determine the type of phy/transceiver. */
+	hw->device_id = ixgb_get_ee_device_id(hw);
+	hw->phy_type = ixgb_identify_phy(hw);
+
+	/* Setup the receive addresses.
+	 * Receive Address Registers (RARs 0 - 15).
+	 */
+	ixgb_init_rx_addrs(hw);
+
+	/*
+	 * Check that a valid MAC address has been set.
+	 * If it is not valid, we fail hardware init.
+	 */
+	if (!mac_addr_valid(hw->curr_mac_addr)) {
+		DEBUGOUT("MAC address invalid after ixgb_init_rx_addrs\n");
+		return(FALSE);
+	}
+
+	/* tell the routines in this file they can access hardware again */
+	hw->adapter_stopped = FALSE;
+
+	/* Fill in the bus_info structure */
+	ixgb_get_bus_info(hw);
+
+	/* Zero out the Multicast HASH table */
+	DEBUGOUT("Zeroing the MTA\n");
+	for(i = 0; i < IXGB_MC_TBL_SIZE; i++)
+		IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0);
+
+	/* Zero out the VLAN Filter Table Array */
+	ixgb_clear_vfta(hw);
+
+	/* Zero all of the hardware counters */
+	ixgb_clear_hw_cntrs(hw);
+
+	/* Call a subroutine to setup flow control. */
+	status = ixgb_setup_fc(hw);
+
+	/* 82597EX errata: Call check-for-link in case lane deskew is locked */
+	ixgb_check_for_link(hw);
+
+	return (status);
+}
+
+/******************************************************************************
+ * Initializes receive address filters.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Places the MAC address in receive address register 0 and clears the rest
+ * of the receive addresss registers. Clears the multicast table. Assumes
+ * the receiver is in reset when the routine is called.
+ *****************************************************************************/
+void
+ixgb_init_rx_addrs(struct ixgb_hw *hw)
+{
+	uint32_t i;
+
+	DEBUGFUNC("ixgb_init_rx_addrs");
+
+	/*
+	 * If the current mac address is valid, assume it is a software override
+	 * to the permanent address.
+	 * Otherwise, use the permanent address from the eeprom.
+	 */
+	if (!mac_addr_valid(hw->curr_mac_addr)) {
+
+		/* Get the MAC address from the eeprom for later reference */
+		ixgb_get_ee_mac_addr(hw, hw->curr_mac_addr);
+
+		DEBUGOUT3(" Keeping Permanent MAC Addr =%.2X %.2X %.2X ",
+			  hw->curr_mac_addr[0],
+			  hw->curr_mac_addr[1], hw->curr_mac_addr[2]);
+		DEBUGOUT3("%.2X %.2X %.2X\n",
+			  hw->curr_mac_addr[3],
+			  hw->curr_mac_addr[4], hw->curr_mac_addr[5]);
+	} else {
+
+		/* Setup the receive address. */
+		DEBUGOUT("Overriding MAC Address in RAR[0]\n");
+		DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ",
+			  hw->curr_mac_addr[0],
+			  hw->curr_mac_addr[1], hw->curr_mac_addr[2]);
+		DEBUGOUT3("%.2X %.2X %.2X\n",
+			  hw->curr_mac_addr[3],
+			  hw->curr_mac_addr[4], hw->curr_mac_addr[5]);
+
+		ixgb_rar_set(hw, hw->curr_mac_addr, 0);
+	}
+
+	/* Zero out the other 15 receive addresses. */
+	DEBUGOUT("Clearing RAR[1-15]\n");
+	for(i = 1; i < IXGB_RAR_ENTRIES; i++) {
+		IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
+		IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
+	}
+
+	return;
+}
+
+/******************************************************************************
+ * Updates the MAC's list of multicast addresses.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * mc_addr_list - the list of new multicast addresses
+ * mc_addr_count - number of addresses
+ * pad - number of bytes between addresses in the list
+ *
+ * The given list replaces any existing list. Clears the last 15 receive
+ * address registers and the multicast table. Uses receive address registers
+ * for the first 15 multicast addresses, and hashes the rest into the
+ * multicast table.
+ *****************************************************************************/
+void
+ixgb_mc_addr_list_update(struct ixgb_hw *hw,
+			  uint8_t *mc_addr_list,
+			  uint32_t mc_addr_count,
+			  uint32_t pad)
+{
+	uint32_t hash_value;
+	uint32_t i;
+	uint32_t rar_used_count = 1;		/* RAR[0] is used for our MAC address */
+
+	DEBUGFUNC("ixgb_mc_addr_list_update");
+
+	/* Set the new number of MC addresses that we are being requested to use. */
+	hw->num_mc_addrs = mc_addr_count;
+
+	/* Clear RAR[1-15] */
+	DEBUGOUT(" Clearing RAR[1-15]\n");
+	for(i = rar_used_count; i < IXGB_RAR_ENTRIES; i++) {
+		IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
+		IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
+	}
+
+	/* Clear the MTA */
+	DEBUGOUT(" Clearing MTA\n");
+	for(i = 0; i < IXGB_MC_TBL_SIZE; i++) {
+		IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0);
+	}
+
+	/* Add the new addresses */
+	for(i = 0; i < mc_addr_count; i++) {
+		DEBUGOUT(" Adding the multicast addresses:\n");
+		DEBUGOUT7(" MC Addr #%d =%.2X %.2X %.2X %.2X %.2X %.2X\n", i,
+			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)],
+			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
+				       1],
+			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
+				       2],
+			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
+				       3],
+			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
+				       4],
+			  mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) +
+				       5]);
+
+		/* Place this multicast address in the RAR if there is room, *
+		 * else put it in the MTA
+		 */
+		if(rar_used_count < IXGB_RAR_ENTRIES) {
+			ixgb_rar_set(hw,
+				     mc_addr_list +
+				     (i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)),
+				     rar_used_count);
+			DEBUGOUT1("Added a multicast address to RAR[%d]\n", i);
+			rar_used_count++;
+		} else {
+			hash_value = ixgb_hash_mc_addr(hw,
+						       mc_addr_list +
+						       (i *
+							(IXGB_ETH_LENGTH_OF_ADDRESS
+							 + pad)));
+
+			DEBUGOUT1(" Hash value = 0x%03X\n", hash_value);
+
+			ixgb_mta_set(hw, hash_value);
+		}
+	}
+
+	DEBUGOUT("MC Update Complete\n");
+	return;
+}
+
+/******************************************************************************
+ * Hashes an address to determine its location in the multicast table
+ *
+ * hw - Struct containing variables accessed by shared code
+ * mc_addr - the multicast address to hash
+ *
+ * Returns:
+ *      The hash value
+ *****************************************************************************/
+static uint32_t
+ixgb_hash_mc_addr(struct ixgb_hw *hw,
+		   uint8_t *mc_addr)
+{
+	uint32_t hash_value = 0;
+
+	DEBUGFUNC("ixgb_hash_mc_addr");
+
+	/* The portion of the address that is used for the hash table is
+	 * determined by the mc_filter_type setting.
+	 */
+	switch (hw->mc_filter_type) {
+		/* [0] [1] [2] [3] [4] [5]
+		 * 01  AA  00  12  34  56
+		 * LSB                 MSB - According to H/W docs */
+	case 0:
+		/* [47:36] i.e. 0x563 for above example address */
+		hash_value =
+		    ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
+		break;
+	case 1:		/* [46:35] i.e. 0xAC6 for above example address */
+		hash_value =
+		    ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));
+		break;
+	case 2:		/* [45:34] i.e. 0x5D8 for above example address */
+		hash_value =
+		    ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
+		break;
+	case 3:		/* [43:32] i.e. 0x634 for above example address */
+		hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));
+		break;
+	default:
+		/* Invalid mc_filter_type, what should we do? */
+		DEBUGOUT("MC filter type param set incorrectly\n");
+		ASSERT(0);
+		break;
+	}
+
+	hash_value &= 0xFFF;
+	return (hash_value);
+}
+
+/******************************************************************************
+ * Sets the bit in the multicast table corresponding to the hash value.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ *****************************************************************************/
+static void
+ixgb_mta_set(struct ixgb_hw *hw,
+		  uint32_t hash_value)
+{
+	uint32_t hash_bit, hash_reg;
+	uint32_t mta_reg;
+
+	/* The MTA is a register array of 128 32-bit registers.
+	 * It is treated like an array of 4096 bits.  We want to set
+	 * bit BitArray[hash_value]. So we figure out what register
+	 * the bit is in, read it, OR in the new bit, then write
+	 * back the new value.  The register is determined by the
+	 * upper 7 bits of the hash value and the bit within that
+	 * register are determined by the lower 5 bits of the value.
+	 */
+	hash_reg = (hash_value >> 5) & 0x7F;
+	hash_bit = hash_value & 0x1F;
+
+	mta_reg = IXGB_READ_REG_ARRAY(hw, MTA, hash_reg);
+
+	mta_reg |= (1 << hash_bit);
+
+	IXGB_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta_reg);
+
+	return;
+}
+
+/******************************************************************************
+ * Puts an ethernet address into a receive address register.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * addr - Address to put into receive address register
+ * index - Receive address register to write
+ *****************************************************************************/
+void
+ixgb_rar_set(struct ixgb_hw *hw,
+		  uint8_t *addr,
+		  uint32_t index)
+{
+	uint32_t rar_low, rar_high;
+
+	DEBUGFUNC("ixgb_rar_set");
+
+	/* HW expects these in little endian so we reverse the byte order
+	 * from network order (big endian) to little endian
+	 */
+	rar_low = ((uint32_t) addr[0] |
+		   ((uint32_t)addr[1] << 8) |
+		   ((uint32_t)addr[2] << 16) |
+		   ((uint32_t)addr[3] << 24));
+
+	rar_high = ((uint32_t) addr[4] |
+			((uint32_t)addr[5] << 8) |
+			IXGB_RAH_AV);
+
+	IXGB_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
+	IXGB_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
+	return;
+}
+
+/******************************************************************************
+ * Writes a value to the specified offset in the VLAN filter table.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - Offset in VLAN filer table to write
+ * value - Value to write into VLAN filter table
+ *****************************************************************************/
+void
+ixgb_write_vfta(struct ixgb_hw *hw,
+		 uint32_t offset,
+		 uint32_t value)
+{
+	IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, value);
+	return;
+}
+
+/******************************************************************************
+ * Clears the VLAN filer table
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+ixgb_clear_vfta(struct ixgb_hw *hw)
+{
+	uint32_t offset;
+
+	for(offset = 0; offset < IXGB_VLAN_FILTER_TBL_SIZE; offset++)
+		IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
+	return;
+}
+
+/******************************************************************************
+ * Configures the flow control settings based on SW configuration.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+
+boolean_t
+ixgb_setup_fc(struct ixgb_hw *hw)
+{
+	uint32_t ctrl_reg;
+	uint32_t pap_reg = 0;   /* by default, assume no pause time */
+	boolean_t status = TRUE;
+
+	DEBUGFUNC("ixgb_setup_fc");
+
+	/* Get the current control reg 0 settings */
+	ctrl_reg = IXGB_READ_REG(hw, CTRL0);
+
+	/* Clear the Receive Pause Enable and Transmit Pause Enable bits */
+	ctrl_reg &= ~(IXGB_CTRL0_RPE | IXGB_CTRL0_TPE);
+
+	/* The possible values of the "flow_control" parameter are:
+	 *      0:  Flow control is completely disabled
+	 *      1:  Rx flow control is enabled (we can receive pause frames
+	 *          but not send pause frames).
+	 *      2:  Tx flow control is enabled (we can send pause frames
+	 *          but we do not support receiving pause frames).
+	 *      3:  Both Rx and TX flow control (symmetric) are enabled.
+	 *  other:  Invalid.
+	 */
+	switch (hw->fc.type) {
+	case ixgb_fc_none:	/* 0 */
+		/* Set CMDC bit to disable Rx Flow control */
+		ctrl_reg |= (IXGB_CTRL0_CMDC);
+		break;
+	case ixgb_fc_rx_pause:	/* 1 */
+		/* RX Flow control is enabled, and TX Flow control is
+		 * disabled.
+		 */
+		ctrl_reg |= (IXGB_CTRL0_RPE);
+		break;
+	case ixgb_fc_tx_pause:	/* 2 */
+		/* TX Flow control is enabled, and RX Flow control is
+		 * disabled, by a software over-ride.
+		 */
+		ctrl_reg |= (IXGB_CTRL0_TPE);
+		pap_reg = hw->fc.pause_time;
+		break;
+	case ixgb_fc_full:	/* 3 */
+		/* Flow control (both RX and TX) is enabled by a software
+		 * over-ride.
+		 */
+		ctrl_reg |= (IXGB_CTRL0_RPE | IXGB_CTRL0_TPE);
+		pap_reg = hw->fc.pause_time;
+		break;
+	default:
+		/* We should never get here.  The value should be 0-3. */
+		DEBUGOUT("Flow control param set incorrectly\n");
+		ASSERT(0);
+		break;
+	}
+
+	/* Write the new settings */
+	IXGB_WRITE_REG(hw, CTRL0, ctrl_reg);
+
+	if (pap_reg != 0) {
+		IXGB_WRITE_REG(hw, PAP, pap_reg);
+	}
+
+	/* Set the flow control receive threshold registers.  Normally,
+	 * these registers will be set to a default threshold that may be
+	 * adjusted later by the driver's runtime code.  However, if the
+	 * ability to transmit pause frames in not enabled, then these
+	 * registers will be set to 0.
+	 */
+	if(!(hw->fc.type & ixgb_fc_tx_pause)) {
+		IXGB_WRITE_REG(hw, FCRTL, 0);
+		IXGB_WRITE_REG(hw, FCRTH, 0);
+	} else {
+	   /* We need to set up the Receive Threshold high and low water
+	    * marks as well as (optionally) enabling the transmission of XON
+	    * frames. */
+		if(hw->fc.send_xon) {
+			IXGB_WRITE_REG(hw, FCRTL,
+				(hw->fc.low_water | IXGB_FCRTL_XONE));
+		} else {
+			IXGB_WRITE_REG(hw, FCRTL, hw->fc.low_water);
+		}
+		IXGB_WRITE_REG(hw, FCRTH, hw->fc.high_water);
+	}
+	return (status);
+}
+
+/******************************************************************************
+ * Reads a word from a device over the Management Data Interface (MDI) bus.
+ * This interface is used to manage Physical layer devices.
+ *
+ * hw          - Struct containing variables accessed by hw code
+ * reg_address - Offset of device register being read.
+ * phy_address - Address of device on MDI.
+ *
+ * Returns:  Data word (16 bits) from MDI device.
+ *
+ * The 82597EX has support for several MDI access methods.  This routine
+ * uses the new protocol MDI Single Command and Address Operation.
+ * This requires that first an address cycle command is sent, followed by a
+ * read command.
+ *****************************************************************************/
+uint16_t
+ixgb_read_phy_reg(struct ixgb_hw *hw,
+		uint32_t reg_address,
+		uint32_t phy_address,
+		uint32_t device_type)
+{
+	uint32_t i;
+	uint32_t data;
+	uint32_t command = 0;
+
+	ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);
+	ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);
+	ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE);
+
+	/* Setup and write the address cycle command */
+	command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
+		   (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
+		   (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
+		   (IXGB_MSCA_ADDR_CYCLE | IXGB_MSCA_MDI_COMMAND));
+
+	IXGB_WRITE_REG(hw, MSCA, command);
+
+    /**************************************************************
+    ** Check every 10 usec to see if the address cycle completed
+    ** The COMMAND bit will clear when the operation is complete.
+    ** This may take as long as 64 usecs (we'll wait 100 usecs max)
+    ** from the CPU Write to the Ready bit assertion.
+    **************************************************************/
+
+	for(i = 0; i < 10; i++)
+	{
+		udelay(10);
+
+		command = IXGB_READ_REG(hw, MSCA);
+
+		if ((command & IXGB_MSCA_MDI_COMMAND) == 0)
+			break;
+	}
+
+	ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
+
+	/* Address cycle complete, setup and write the read command */
+	command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
+		   (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
+		   (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
+		   (IXGB_MSCA_READ | IXGB_MSCA_MDI_COMMAND));
+
+	IXGB_WRITE_REG(hw, MSCA, command);
+
+    /**************************************************************
+    ** Check every 10 usec to see if the read command completed
+    ** The COMMAND bit will clear when the operation is complete.
+    ** The read may take as long as 64 usecs (we'll wait 100 usecs max)
+    ** from the CPU Write to the Ready bit assertion.
+    **************************************************************/
+
+	for(i = 0; i < 10; i++)
+	{
+		udelay(10);
+
+		command = IXGB_READ_REG(hw, MSCA);
+
+		if ((command & IXGB_MSCA_MDI_COMMAND) == 0)
+			break;
+	}
+
+	ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
+
+	/* Operation is complete, get the data from the MDIO Read/Write Data
+	 * register and return.
+	 */
+	data = IXGB_READ_REG(hw, MSRWD);
+	data >>= IXGB_MSRWD_READ_DATA_SHIFT;
+	return((uint16_t) data);
+}
+
+/******************************************************************************
+ * Writes a word to a device over the Management Data Interface (MDI) bus.
+ * This interface is used to manage Physical layer devices.
+ *
+ * hw          - Struct containing variables accessed by hw code
+ * reg_address - Offset of device register being read.
+ * phy_address - Address of device on MDI.
+ * device_type - Also known as the Device ID or DID.
+ * data        - 16-bit value to be written
+ *
+ * Returns:  void.
+ *
+ * The 82597EX has support for several MDI access methods.  This routine
+ * uses the new protocol MDI Single Command and Address Operation.
+ * This requires that first an address cycle command is sent, followed by a
+ * write command.
+ *****************************************************************************/
+void
+ixgb_write_phy_reg(struct ixgb_hw *hw,
+			uint32_t reg_address,
+			uint32_t phy_address,
+			uint32_t device_type,
+			uint16_t data)
+{
+	uint32_t i;
+	uint32_t command = 0;
+
+	ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);
+	ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);
+	ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE);
+
+	/* Put the data in the MDIO Read/Write Data register */
+	IXGB_WRITE_REG(hw, MSRWD, (uint32_t)data);
+
+	/* Setup and write the address cycle command */
+	command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT)  |
+			   (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
+			   (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
+			   (IXGB_MSCA_ADDR_CYCLE | IXGB_MSCA_MDI_COMMAND));
+
+	IXGB_WRITE_REG(hw, MSCA, command);
+
+	/**************************************************************
+	** Check every 10 usec to see if the address cycle completed
+	** The COMMAND bit will clear when the operation is complete.
+	** This may take as long as 64 usecs (we'll wait 100 usecs max)
+	** from the CPU Write to the Ready bit assertion.
+	**************************************************************/
+
+	for(i = 0; i < 10; i++)
+	{
+		udelay(10);
+
+		command = IXGB_READ_REG(hw, MSCA);
+
+		if ((command & IXGB_MSCA_MDI_COMMAND) == 0)
+			break;
+	}
+
+	ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
+
+	/* Address cycle complete, setup and write the write command */
+	command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT)  |
+			   (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
+			   (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
+			   (IXGB_MSCA_WRITE | IXGB_MSCA_MDI_COMMAND));
+
+	IXGB_WRITE_REG(hw, MSCA, command);
+
+	/**************************************************************
+	** Check every 10 usec to see if the read command completed
+	** The COMMAND bit will clear when the operation is complete.
+	** The write may take as long as 64 usecs (we'll wait 100 usecs max)
+	** from the CPU Write to the Ready bit assertion.
+	**************************************************************/
+
+	for(i = 0; i < 10; i++)
+	{
+		udelay(10);
+
+		command = IXGB_READ_REG(hw, MSCA);
+
+		if ((command & IXGB_MSCA_MDI_COMMAND) == 0)
+			break;
+	}
+
+	ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
+
+	/* Operation is complete, return. */
+}
+
+/******************************************************************************
+ * Checks to see if the link status of the hardware has changed.
+ *
+ * hw - Struct containing variables accessed by hw code
+ *
+ * Called by any function that needs to check the link status of the adapter.
+ *****************************************************************************/
+void
+ixgb_check_for_link(struct ixgb_hw *hw)
+{
+	uint32_t status_reg;
+	uint32_t xpcss_reg;
+
+	DEBUGFUNC("ixgb_check_for_link");
+
+	xpcss_reg = IXGB_READ_REG(hw, XPCSS);
+	status_reg = IXGB_READ_REG(hw, STATUS);
+
+	if ((xpcss_reg & IXGB_XPCSS_ALIGN_STATUS) &&
+	    (status_reg & IXGB_STATUS_LU)) {
+		hw->link_up = TRUE;
+	} else if (!(xpcss_reg & IXGB_XPCSS_ALIGN_STATUS) &&
+		   (status_reg & IXGB_STATUS_LU)) {
+		DEBUGOUT("XPCSS Not Aligned while Status:LU is set.\n");
+		hw->link_up = ixgb_link_reset(hw);
+	} else {
+		/*
+		 * 82597EX errata.  Since the lane deskew problem may prevent
+		 * link, reset the link before reporting link down.
+		 */
+		hw->link_up = ixgb_link_reset(hw);
+	}
+	/*  Anything else for 10 Gig?? */
+}
+
+/******************************************************************************
+ * Check for a bad link condition that may have occured.
+ * The indication is that the RFC / LFC registers may be incrementing
+ * continually.  A full adapter reset is required to recover.
+ *
+ * hw - Struct containing variables accessed by hw code
+ *
+ * Called by any function that needs to check the link status of the adapter.
+ *****************************************************************************/
+boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw)
+{
+	uint32_t newLFC, newRFC;
+	boolean_t bad_link_returncode = FALSE;
+
+	if (hw->phy_type == ixgb_phy_type_txn17401) {
+		newLFC = IXGB_READ_REG(hw, LFC);
+		newRFC = IXGB_READ_REG(hw, RFC);
+		if ((hw->lastLFC + 250 < newLFC)
+		    || (hw->lastRFC + 250 < newRFC)) {
+			DEBUGOUT
+			    ("BAD LINK! too many LFC/RFC since last check\n");
+			bad_link_returncode = TRUE;
+		}
+		hw->lastLFC = newLFC;
+		hw->lastRFC = newRFC;
+	}
+
+	return bad_link_returncode;
+}
+
+/******************************************************************************
+ * Clears all hardware statistics counters.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
+{
+	volatile uint32_t temp_reg;
+
+	DEBUGFUNC("ixgb_clear_hw_cntrs");
+
+	/* if we are stopped or resetting exit gracefully */
+	if(hw->adapter_stopped) {
+		DEBUGOUT("Exiting because the adapter is stopped!!!\n");
+		return;
+	}
+
+	temp_reg = IXGB_READ_REG(hw, TPRL);
+	temp_reg = IXGB_READ_REG(hw, TPRH);
+	temp_reg = IXGB_READ_REG(hw, GPRCL);
+	temp_reg = IXGB_READ_REG(hw, GPRCH);
+	temp_reg = IXGB_READ_REG(hw, BPRCL);
+	temp_reg = IXGB_READ_REG(hw, BPRCH);
+	temp_reg = IXGB_READ_REG(hw, MPRCL);
+	temp_reg = IXGB_READ_REG(hw, MPRCH);
+	temp_reg = IXGB_READ_REG(hw, UPRCL);
+	temp_reg = IXGB_READ_REG(hw, UPRCH);
+	temp_reg = IXGB_READ_REG(hw, VPRCL);
+	temp_reg = IXGB_READ_REG(hw, VPRCH);
+	temp_reg = IXGB_READ_REG(hw, JPRCL);
+	temp_reg = IXGB_READ_REG(hw, JPRCH);
+	temp_reg = IXGB_READ_REG(hw, GORCL);
+	temp_reg = IXGB_READ_REG(hw, GORCH);
+	temp_reg = IXGB_READ_REG(hw, TORL);
+	temp_reg = IXGB_READ_REG(hw, TORH);
+	temp_reg = IXGB_READ_REG(hw, RNBC);
+	temp_reg = IXGB_READ_REG(hw, RUC);
+	temp_reg = IXGB_READ_REG(hw, ROC);
+	temp_reg = IXGB_READ_REG(hw, RLEC);
+	temp_reg = IXGB_READ_REG(hw, CRCERRS);
+	temp_reg = IXGB_READ_REG(hw, ICBC);
+	temp_reg = IXGB_READ_REG(hw, ECBC);
+	temp_reg = IXGB_READ_REG(hw, MPC);
+	temp_reg = IXGB_READ_REG(hw, TPTL);
+	temp_reg = IXGB_READ_REG(hw, TPTH);
+	temp_reg = IXGB_READ_REG(hw, GPTCL);
+	temp_reg = IXGB_READ_REG(hw, GPTCH);
+	temp_reg = IXGB_READ_REG(hw, BPTCL);
+	temp_reg = IXGB_READ_REG(hw, BPTCH);
+	temp_reg = IXGB_READ_REG(hw, MPTCL);
+	temp_reg = IXGB_READ_REG(hw, MPTCH);
+	temp_reg = IXGB_READ_REG(hw, UPTCL);
+	temp_reg = IXGB_READ_REG(hw, UPTCH);
+	temp_reg = IXGB_READ_REG(hw, VPTCL);
+	temp_reg = IXGB_READ_REG(hw, VPTCH);
+	temp_reg = IXGB_READ_REG(hw, JPTCL);
+	temp_reg = IXGB_READ_REG(hw, JPTCH);
+	temp_reg = IXGB_READ_REG(hw, GOTCL);
+	temp_reg = IXGB_READ_REG(hw, GOTCH);
+	temp_reg = IXGB_READ_REG(hw, TOTL);
+	temp_reg = IXGB_READ_REG(hw, TOTH);
+	temp_reg = IXGB_READ_REG(hw, DC);
+	temp_reg = IXGB_READ_REG(hw, PLT64C);
+	temp_reg = IXGB_READ_REG(hw, TSCTC);
+	temp_reg = IXGB_READ_REG(hw, TSCTFC);
+	temp_reg = IXGB_READ_REG(hw, IBIC);
+	temp_reg = IXGB_READ_REG(hw, RFC);
+	temp_reg = IXGB_READ_REG(hw, LFC);
+	temp_reg = IXGB_READ_REG(hw, PFRC);
+	temp_reg = IXGB_READ_REG(hw, PFTC);
+	temp_reg = IXGB_READ_REG(hw, MCFRC);
+	temp_reg = IXGB_READ_REG(hw, MCFTC);
+	temp_reg = IXGB_READ_REG(hw, XONRXC);
+	temp_reg = IXGB_READ_REG(hw, XONTXC);
+	temp_reg = IXGB_READ_REG(hw, XOFFRXC);
+	temp_reg = IXGB_READ_REG(hw, XOFFTXC);
+	temp_reg = IXGB_READ_REG(hw, RJC);
+	return;
+}
+
+/******************************************************************************
+ * Turns on the software controllable LED
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+ixgb_led_on(struct ixgb_hw *hw)
+{
+	uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
+
+	/* To turn on the LED, clear software-definable pin 0 (SDP0). */
+	ctrl0_reg &= ~IXGB_CTRL0_SDP0;
+	IXGB_WRITE_REG(hw, CTRL0, ctrl0_reg);
+	return;
+}
+
+/******************************************************************************
+ * Turns off the software controllable LED
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+ixgb_led_off(struct ixgb_hw *hw)
+{
+	uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
+
+	/* To turn off the LED, set software-definable pin 0 (SDP0). */
+	ctrl0_reg |= IXGB_CTRL0_SDP0;
+	IXGB_WRITE_REG(hw, CTRL0, ctrl0_reg);
+	return;
+}
+
+/******************************************************************************
+ * Gets the current PCI bus type, speed, and width of the hardware
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static void
+ixgb_get_bus_info(struct ixgb_hw *hw)
+{
+	uint32_t status_reg;
+
+	status_reg = IXGB_READ_REG(hw, STATUS);
+
+	hw->bus.type = (status_reg & IXGB_STATUS_PCIX_MODE) ?
+		ixgb_bus_type_pcix : ixgb_bus_type_pci;
+
+	if (hw->bus.type == ixgb_bus_type_pci) {
+		hw->bus.speed = (status_reg & IXGB_STATUS_PCI_SPD) ?
+			ixgb_bus_speed_66 : ixgb_bus_speed_33;
+	} else {
+		switch (status_reg & IXGB_STATUS_PCIX_SPD_MASK) {
+		case IXGB_STATUS_PCIX_SPD_66:
+			hw->bus.speed = ixgb_bus_speed_66;
+			break;
+		case IXGB_STATUS_PCIX_SPD_100:
+			hw->bus.speed = ixgb_bus_speed_100;
+			break;
+		case IXGB_STATUS_PCIX_SPD_133:
+			hw->bus.speed = ixgb_bus_speed_133;
+			break;
+		default:
+			hw->bus.speed = ixgb_bus_speed_reserved;
+			break;
+		}
+	}
+
+	hw->bus.width = (status_reg & IXGB_STATUS_BUS64) ?
+		ixgb_bus_width_64 : ixgb_bus_width_32;
+
+	return;
+}
+
+/******************************************************************************
+ * Tests a MAC address to ensure it is a valid Individual Address
+ *
+ * mac_addr - pointer to MAC address.
+ *
+ *****************************************************************************/
+boolean_t
+mac_addr_valid(uint8_t *mac_addr)
+{
+	boolean_t is_valid = TRUE;
+	DEBUGFUNC("mac_addr_valid");
+
+	/* Make sure it is not a multicast address */
+	if (IS_MULTICAST(mac_addr)) {
+		DEBUGOUT("MAC address is multicast\n");
+		is_valid = FALSE;
+	}
+	/* Not a broadcast address */
+	else if (IS_BROADCAST(mac_addr)) {
+		DEBUGOUT("MAC address is broadcast\n");
+		is_valid = FALSE;
+	}
+	/* Reject the zero address */
+	else if (mac_addr[0] == 0 &&
+			 mac_addr[1] == 0 &&
+			 mac_addr[2] == 0 &&
+			 mac_addr[3] == 0 &&
+			 mac_addr[4] == 0 &&
+			 mac_addr[5] == 0) {
+		DEBUGOUT("MAC address is all zeros\n");
+		is_valid = FALSE;
+	}
+	return (is_valid);
+}
+
+/******************************************************************************
+ * Resets the 10GbE link.  Waits the settle time and returns the state of
+ * the link.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+boolean_t
+ixgb_link_reset(struct ixgb_hw *hw)
+{
+	boolean_t link_status = FALSE;
+	uint8_t wait_retries = MAX_RESET_ITERATIONS;
+	uint8_t lrst_retries = MAX_RESET_ITERATIONS;
+
+	do {
+		/* Reset the link */
+		IXGB_WRITE_REG(hw, CTRL0,
+			       IXGB_READ_REG(hw, CTRL0) | IXGB_CTRL0_LRST);
+
+		/* Wait for link-up and lane re-alignment */
+		do {
+			udelay(IXGB_DELAY_USECS_AFTER_LINK_RESET);
+			link_status =
+			    ((IXGB_READ_REG(hw, STATUS) & IXGB_STATUS_LU)
+			     && (IXGB_READ_REG(hw, XPCSS) &
+				 IXGB_XPCSS_ALIGN_STATUS)) ? TRUE : FALSE;
+		} while (!link_status && --wait_retries);
+
+	} while (!link_status && --lrst_retries);
+
+	return link_status;
+}
+
+/******************************************************************************
+ * Resets the 10GbE optics module.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+ixgb_optics_reset(struct ixgb_hw *hw)
+{
+	if (hw->phy_type == ixgb_phy_type_txn17401) {
+		uint16_t mdio_reg;
+
+		ixgb_write_phy_reg(hw,
+					MDIO_PMA_PMD_CR1,
+					IXGB_PHY_ADDRESS,
+					MDIO_PMA_PMD_DID,
+					MDIO_PMA_PMD_CR1_RESET);
+
+		mdio_reg = ixgb_read_phy_reg( hw,
+						MDIO_PMA_PMD_CR1,
+						IXGB_PHY_ADDRESS,
+						MDIO_PMA_PMD_DID);
+	}
+
+	return;
+}
diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h
new file mode 100644
index 0000000..97898ef
--- /dev/null
+++ b/drivers/net/ixgb/ixgb_hw.h
@@ -0,0 +1,847 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of the GNU General Public License as published by the Free 
+  Software Foundation; either version 2 of the License, or (at your option) 
+  any later version.
+  
+  This program is distributed in the hope that it will be useful, but WITHOUT 
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+  more details.
+  
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#ifndef _IXGB_HW_H_
+#define _IXGB_HW_H_
+
+#include "ixgb_osdep.h"
+
+/* Enums */
+typedef enum {
+	ixgb_mac_unknown = 0,
+	ixgb_82597,
+	ixgb_num_macs
+} ixgb_mac_type;
+
+/* Types of physical layer modules */
+typedef enum {
+	ixgb_phy_type_unknown = 0,
+	ixgb_phy_type_g6005,	/* 850nm, MM fiber, XPAK transceiver */
+	ixgb_phy_type_g6104,	/* 1310nm, SM fiber, XPAK transceiver */
+	ixgb_phy_type_txn17201,	/* 850nm, MM fiber, XPAK transceiver */
+	ixgb_phy_type_txn17401	/* 1310nm, SM fiber, XENPAK transceiver */
+} ixgb_phy_type;
+
+/* XPAK transceiver vendors, for the SR adapters */
+typedef enum {
+	ixgb_xpak_vendor_intel,
+	ixgb_xpak_vendor_infineon
+} ixgb_xpak_vendor;
+
+/* Media Types */
+typedef enum {
+	ixgb_media_type_unknown = 0,
+	ixgb_media_type_fiber = 1,
+	ixgb_num_media_types
+} ixgb_media_type;
+
+/* Flow Control Settings */
+typedef enum {
+	ixgb_fc_none = 0,
+	ixgb_fc_rx_pause = 1,
+	ixgb_fc_tx_pause = 2,
+	ixgb_fc_full = 3,
+	ixgb_fc_default = 0xFF
+} ixgb_fc_type;
+
+/* PCI bus types */
+typedef enum {
+	ixgb_bus_type_unknown = 0,
+	ixgb_bus_type_pci,
+	ixgb_bus_type_pcix
+} ixgb_bus_type;
+
+/* PCI bus speeds */
+typedef enum {
+	ixgb_bus_speed_unknown = 0,
+	ixgb_bus_speed_33,
+	ixgb_bus_speed_66,
+	ixgb_bus_speed_100,
+	ixgb_bus_speed_133,
+	ixgb_bus_speed_reserved
+} ixgb_bus_speed;
+
+/* PCI bus widths */
+typedef enum {
+	ixgb_bus_width_unknown = 0,
+	ixgb_bus_width_32,
+	ixgb_bus_width_64
+} ixgb_bus_width;
+
+#define IXGB_ETH_LENGTH_OF_ADDRESS   6
+
+#define IXGB_EEPROM_SIZE    64	/* Size in words */
+
+#define SPEED_10000  10000
+#define FULL_DUPLEX  2
+
+#define MIN_NUMBER_OF_DESCRIPTORS       8
+#define MAX_NUMBER_OF_DESCRIPTORS  0xFFF8	/* 13 bits in RDLEN/TDLEN, 128B aligned     */
+
+#define IXGB_DELAY_BEFORE_RESET        10	/* allow 10ms after idling rx/tx units      */
+#define IXGB_DELAY_AFTER_RESET          1	/* allow 1ms after the reset                */
+#define IXGB_DELAY_AFTER_EE_RESET      10	/* allow 10ms after the EEPROM reset        */
+
+#define IXGB_DELAY_USECS_AFTER_LINK_RESET    13	/* allow 13 microseconds after the reset    */
+					   /* NOTE: this is MICROSECONDS               */
+#define MAX_RESET_ITERATIONS            8	/* number of iterations to get things right */
+
+/* General Registers */
+#define IXGB_CTRL0   0x00000	/* Device Control Register 0 - RW */
+#define IXGB_CTRL1   0x00008	/* Device Control Register 1 - RW */
+#define IXGB_STATUS  0x00010	/* Device Status Register - RO */
+#define IXGB_EECD    0x00018	/* EEPROM/Flash Control/Data Register - RW */
+#define IXGB_MFS     0x00020	/* Maximum Frame Size - RW */
+
+/* Interrupt */
+#define IXGB_ICR     0x00080	/* Interrupt Cause Read - R/clr */
+#define IXGB_ICS     0x00088	/* Interrupt Cause Set - RW */
+#define IXGB_IMS     0x00090	/* Interrupt Mask Set/Read - RW */
+#define IXGB_IMC     0x00098	/* Interrupt Mask Clear - WO */
+
+/* Receive */
+#define IXGB_RCTL    0x00100	/* RX Control - RW */
+#define IXGB_FCRTL   0x00108	/* Flow Control Receive Threshold Low - RW */
+#define IXGB_FCRTH   0x00110	/* Flow Control Receive Threshold High - RW */
+#define IXGB_RDBAL   0x00118	/* RX Descriptor Base Low - RW */
+#define IXGB_RDBAH   0x0011C	/* RX Descriptor Base High - RW */
+#define IXGB_RDLEN   0x00120	/* RX Descriptor Length - RW */
+#define IXGB_RDH     0x00128	/* RX Descriptor Head - RW */
+#define IXGB_RDT     0x00130	/* RX Descriptor Tail - RW */
+#define IXGB_RDTR    0x00138	/* RX Delay Timer Ring - RW */
+#define IXGB_RXDCTL  0x00140	/* Receive Descriptor Control - RW */
+#define IXGB_RAIDC   0x00148	/* Receive Adaptive Interrupt Delay Control - RW */
+#define IXGB_RXCSUM  0x00158	/* Receive Checksum Control - RW */
+#define IXGB_RA      0x00180	/* Receive Address Array Base - RW */
+#define IXGB_RAL     0x00180	/* Receive Address Low [0:15] - RW */
+#define IXGB_RAH     0x00184	/* Receive Address High [0:15] - RW */
+#define IXGB_MTA     0x00200	/* Multicast Table Array [0:127] - RW */
+#define IXGB_VFTA    0x00400	/* VLAN Filter Table Array [0:127] - RW */
+#define IXGB_REQ_RX_DESCRIPTOR_MULTIPLE 8
+
+/* Transmit */
+#define IXGB_TCTL    0x00600	/* TX Control - RW */
+#define IXGB_TDBAL   0x00608	/* TX Descriptor Base Low - RW */
+#define IXGB_TDBAH   0x0060C	/* TX Descriptor Base High - RW */
+#define IXGB_TDLEN   0x00610	/* TX Descriptor Length - RW */
+#define IXGB_TDH     0x00618	/* TX Descriptor Head - RW */
+#define IXGB_TDT     0x00620	/* TX Descriptor Tail - RW */
+#define IXGB_TIDV    0x00628	/* TX Interrupt Delay Value - RW */
+#define IXGB_TXDCTL  0x00630	/* Transmit Descriptor Control - RW */
+#define IXGB_TSPMT   0x00638	/* TCP Segmentation PAD & Min Threshold - RW */
+#define IXGB_PAP     0x00640	/* Pause and Pace - RW */
+#define IXGB_REQ_TX_DESCRIPTOR_MULTIPLE 8
+
+/* Physical */
+#define IXGB_PCSC1   0x00700	/* PCS Control 1 - RW */
+#define IXGB_PCSC2   0x00708	/* PCS Control 2 - RW */
+#define IXGB_PCSS1   0x00710	/* PCS Status 1 - RO */
+#define IXGB_PCSS2   0x00718	/* PCS Status 2 - RO */
+#define IXGB_XPCSS   0x00720	/* 10GBASE-X PCS Status (or XGXS Lane Status) - RO */
+#define IXGB_UCCR    0x00728	/* Unilink Circuit Control Register */
+#define IXGB_XPCSTC  0x00730	/* 10GBASE-X PCS Test Control */
+#define IXGB_MACA    0x00738	/* MDI Autoscan Command and Address - RW */
+#define IXGB_APAE    0x00740	/* Autoscan PHY Address Enable - RW */
+#define IXGB_ARD     0x00748	/* Autoscan Read Data - RO */
+#define IXGB_AIS     0x00750	/* Autoscan Interrupt Status - RO */
+#define IXGB_MSCA    0x00758	/* MDI Single Command and Address - RW */
+#define IXGB_MSRWD   0x00760	/* MDI Single Read and Write Data - RW, RO */
+
+/* Wake-up */
+#define IXGB_WUFC    0x00808	/* Wake Up Filter Control - RW */
+#define IXGB_WUS     0x00810	/* Wake Up Status - RO */
+#define IXGB_FFLT    0x01000	/* Flexible Filter Length Table - RW */
+#define IXGB_FFMT    0x01020	/* Flexible Filter Mask Table - RW */
+#define IXGB_FTVT    0x01420	/* Flexible Filter Value Table - RW */
+
+/* Statistics */
+#define IXGB_TPRL    0x02000	/* Total Packets Received (Low) */
+#define IXGB_TPRH    0x02004	/* Total Packets Received (High) */
+#define IXGB_GPRCL   0x02008	/* Good Packets Received Count (Low) */
+#define IXGB_GPRCH   0x0200C	/* Good Packets Received Count (High) */
+#define IXGB_BPRCL   0x02010	/* Broadcast Packets Received Count (Low) */
+#define IXGB_BPRCH   0x02014	/* Broadcast Packets Received Count (High) */
+#define IXGB_MPRCL   0x02018	/* Multicast Packets Received Count (Low) */
+#define IXGB_MPRCH   0x0201C	/* Multicast Packets Received Count (High) */
+#define IXGB_UPRCL   0x02020	/* Unicast Packets Received Count (Low) */
+#define IXGB_UPRCH   0x02024	/* Unicast Packets Received Count (High) */
+#define IXGB_VPRCL   0x02028	/* VLAN Packets Received Count (Low) */
+#define IXGB_VPRCH   0x0202C	/* VLAN Packets Received Count (High) */
+#define IXGB_JPRCL   0x02030	/* Jumbo Packets Received Count (Low) */
+#define IXGB_JPRCH   0x02034	/* Jumbo Packets Received Count (High) */
+#define IXGB_GORCL   0x02038	/* Good Octets Received Count (Low) */
+#define IXGB_GORCH   0x0203C	/* Good Octets Received Count (High) */
+#define IXGB_TORL    0x02040	/* Total Octets Received (Low) */
+#define IXGB_TORH    0x02044	/* Total Octets Received (High) */
+#define IXGB_RNBC    0x02048	/* Receive No Buffers Count */
+#define IXGB_RUC     0x02050	/* Receive Undersize Count */
+#define IXGB_ROC     0x02058	/* Receive Oversize Count */
+#define IXGB_RLEC    0x02060	/* Receive Length Error Count */
+#define IXGB_CRCERRS 0x02068	/* CRC Error Count */
+#define IXGB_ICBC    0x02070	/* Illegal control byte in mid-packet Count */
+#define IXGB_ECBC    0x02078	/* Error Control byte in mid-packet Count */
+#define IXGB_MPC     0x02080	/* Missed Packets Count */
+#define IXGB_TPTL    0x02100	/* Total Packets Transmitted (Low) */
+#define IXGB_TPTH    0x02104	/* Total Packets Transmitted (High) */
+#define IXGB_GPTCL   0x02108	/* Good Packets Transmitted Count (Low) */
+#define IXGB_GPTCH   0x0210C	/* Good Packets Transmitted Count (High) */
+#define IXGB_BPTCL   0x02110	/* Broadcast Packets Transmitted Count (Low) */
+#define IXGB_BPTCH   0x02114	/* Broadcast Packets Transmitted Count (High) */
+#define IXGB_MPTCL   0x02118	/* Multicast Packets Transmitted Count (Low) */
+#define IXGB_MPTCH   0x0211C	/* Multicast Packets Transmitted Count (High) */
+#define IXGB_UPTCL   0x02120	/* Unicast Packets Transmitted Count (Low) */
+#define IXGB_UPTCH   0x02124	/* Unicast Packets Transmitted Count (High) */
+#define IXGB_VPTCL   0x02128	/* VLAN Packets Transmitted Count (Low) */
+#define IXGB_VPTCH   0x0212C	/* VLAN Packets Transmitted Count (High) */
+#define IXGB_JPTCL   0x02130	/* Jumbo Packets Transmitted Count (Low) */
+#define IXGB_JPTCH   0x02134	/* Jumbo Packets Transmitted Count (High) */
+#define IXGB_GOTCL   0x02138	/* Good Octets Transmitted Count (Low) */
+#define IXGB_GOTCH   0x0213C	/* Good Octets Transmitted Count (High) */
+#define IXGB_TOTL    0x02140	/* Total Octets Transmitted Count (Low) */
+#define IXGB_TOTH    0x02144	/* Total Octets Transmitted Count (High) */
+#define IXGB_DC      0x02148	/* Defer Count */
+#define IXGB_PLT64C  0x02150	/* Packet Transmitted was less than 64 bytes Count */
+#define IXGB_TSCTC   0x02170	/* TCP Segmentation Context Transmitted Count */
+#define IXGB_TSCTFC  0x02178	/* TCP Segmentation Context Tx Fail Count */
+#define IXGB_IBIC    0x02180	/* Illegal byte during Idle stream count */
+#define IXGB_RFC     0x02188	/* Remote Fault Count */
+#define IXGB_LFC     0x02190	/* Local Fault Count */
+#define IXGB_PFRC    0x02198	/* Pause Frame Receive Count */
+#define IXGB_PFTC    0x021A0	/* Pause Frame Transmit Count */
+#define IXGB_MCFRC   0x021A8	/* MAC Control Frames (non-Pause) Received Count */
+#define IXGB_MCFTC   0x021B0	/* MAC Control Frames (non-Pause) Transmitted Count */
+#define IXGB_XONRXC  0x021B8	/* XON Received Count */
+#define IXGB_XONTXC  0x021C0	/* XON Transmitted Count */
+#define IXGB_XOFFRXC 0x021C8	/* XOFF Received Count */
+#define IXGB_XOFFTXC 0x021D0	/* XOFF Transmitted Count */
+#define IXGB_RJC     0x021D8	/* Receive Jabber Count */
+
+/* CTRL0 Bit Masks */
+#define IXGB_CTRL0_LRST     0x00000008
+#define IXGB_CTRL0_JFE      0x00000010
+#define IXGB_CTRL0_XLE      0x00000020
+#define IXGB_CTRL0_MDCS     0x00000040
+#define IXGB_CTRL0_CMDC     0x00000080
+#define IXGB_CTRL0_SDP0     0x00040000
+#define IXGB_CTRL0_SDP1     0x00080000
+#define IXGB_CTRL0_SDP2     0x00100000
+#define IXGB_CTRL0_SDP3     0x00200000
+#define IXGB_CTRL0_SDP0_DIR 0x00400000
+#define IXGB_CTRL0_SDP1_DIR 0x00800000
+#define IXGB_CTRL0_SDP2_DIR 0x01000000
+#define IXGB_CTRL0_SDP3_DIR 0x02000000
+#define IXGB_CTRL0_RST      0x04000000
+#define IXGB_CTRL0_RPE      0x08000000
+#define IXGB_CTRL0_TPE      0x10000000
+#define IXGB_CTRL0_VME      0x40000000
+
+/* CTRL1 Bit Masks */
+#define IXGB_CTRL1_GPI0_EN     0x00000001
+#define IXGB_CTRL1_GPI1_EN     0x00000002
+#define IXGB_CTRL1_GPI2_EN     0x00000004
+#define IXGB_CTRL1_GPI3_EN     0x00000008
+#define IXGB_CTRL1_SDP4        0x00000010
+#define IXGB_CTRL1_SDP5        0x00000020
+#define IXGB_CTRL1_SDP6        0x00000040
+#define IXGB_CTRL1_SDP7        0x00000080
+#define IXGB_CTRL1_SDP4_DIR    0x00000100
+#define IXGB_CTRL1_SDP5_DIR    0x00000200
+#define IXGB_CTRL1_SDP6_DIR    0x00000400
+#define IXGB_CTRL1_SDP7_DIR    0x00000800
+#define IXGB_CTRL1_EE_RST      0x00002000
+#define IXGB_CTRL1_RO_DIS      0x00020000
+#define IXGB_CTRL1_PCIXHM_MASK 0x00C00000
+#define IXGB_CTRL1_PCIXHM_1_2  0x00000000
+#define IXGB_CTRL1_PCIXHM_5_8  0x00400000
+#define IXGB_CTRL1_PCIXHM_3_4  0x00800000
+#define IXGB_CTRL1_PCIXHM_7_8  0x00C00000
+
+/* STATUS Bit Masks */
+#define IXGB_STATUS_LU            0x00000002
+#define IXGB_STATUS_AIP           0x00000004
+#define IXGB_STATUS_TXOFF         0x00000010
+#define IXGB_STATUS_XAUIME        0x00000020
+#define IXGB_STATUS_RES           0x00000040
+#define IXGB_STATUS_RIS           0x00000080
+#define IXGB_STATUS_RIE           0x00000100
+#define IXGB_STATUS_RLF           0x00000200
+#define IXGB_STATUS_RRF           0x00000400
+#define IXGB_STATUS_PCI_SPD       0x00000800
+#define IXGB_STATUS_BUS64         0x00001000
+#define IXGB_STATUS_PCIX_MODE     0x00002000
+#define IXGB_STATUS_PCIX_SPD_MASK 0x0000C000
+#define IXGB_STATUS_PCIX_SPD_66   0x00000000
+#define IXGB_STATUS_PCIX_SPD_100  0x00004000
+#define IXGB_STATUS_PCIX_SPD_133  0x00008000
+#define IXGB_STATUS_REV_ID_MASK   0x000F0000
+#define IXGB_STATUS_REV_ID_SHIFT  16
+
+/* EECD Bit Masks */
+#define IXGB_EECD_SK       0x00000001
+#define IXGB_EECD_CS       0x00000002
+#define IXGB_EECD_DI       0x00000004
+#define IXGB_EECD_DO       0x00000008
+#define IXGB_EECD_FWE_MASK 0x00000030
+#define IXGB_EECD_FWE_DIS  0x00000010
+#define IXGB_EECD_FWE_EN   0x00000020
+
+/* MFS */
+#define IXGB_MFS_SHIFT 16
+
+/* Interrupt Register Bit Masks (used for ICR, ICS, IMS, and IMC) */
+#define IXGB_INT_TXDW     0x00000001
+#define IXGB_INT_TXQE     0x00000002
+#define IXGB_INT_LSC      0x00000004
+#define IXGB_INT_RXSEQ    0x00000008
+#define IXGB_INT_RXDMT0   0x00000010
+#define IXGB_INT_RXO      0x00000040
+#define IXGB_INT_RXT0     0x00000080
+#define IXGB_INT_AUTOSCAN 0x00000200
+#define IXGB_INT_GPI0     0x00000800
+#define IXGB_INT_GPI1     0x00001000
+#define IXGB_INT_GPI2     0x00002000
+#define IXGB_INT_GPI3     0x00004000
+
+/* RCTL Bit Masks */
+#define IXGB_RCTL_RXEN        0x00000002
+#define IXGB_RCTL_SBP         0x00000004
+#define IXGB_RCTL_UPE         0x00000008
+#define IXGB_RCTL_MPE         0x00000010
+#define IXGB_RCTL_RDMTS_MASK  0x00000300
+#define IXGB_RCTL_RDMTS_1_2   0x00000000
+#define IXGB_RCTL_RDMTS_1_4   0x00000100
+#define IXGB_RCTL_RDMTS_1_8   0x00000200
+#define IXGB_RCTL_MO_MASK     0x00003000
+#define IXGB_RCTL_MO_47_36    0x00000000
+#define IXGB_RCTL_MO_46_35    0x00001000
+#define IXGB_RCTL_MO_45_34    0x00002000
+#define IXGB_RCTL_MO_43_32    0x00003000
+#define IXGB_RCTL_MO_SHIFT    12
+#define IXGB_RCTL_BAM         0x00008000
+#define IXGB_RCTL_BSIZE_MASK  0x00030000
+#define IXGB_RCTL_BSIZE_2048  0x00000000
+#define IXGB_RCTL_BSIZE_4096  0x00010000
+#define IXGB_RCTL_BSIZE_8192  0x00020000
+#define IXGB_RCTL_BSIZE_16384 0x00030000
+#define IXGB_RCTL_VFE         0x00040000
+#define IXGB_RCTL_CFIEN       0x00080000
+#define IXGB_RCTL_CFI         0x00100000
+#define IXGB_RCTL_RPDA_MASK   0x00600000
+#define IXGB_RCTL_RPDA_MC_MAC 0x00000000
+#define IXGB_RCTL_MC_ONLY     0x00400000
+#define IXGB_RCTL_CFF         0x00800000
+#define IXGB_RCTL_SECRC       0x04000000
+#define IXGB_RDT_FPDB         0x80000000
+
+#define IXGB_RCTL_IDLE_RX_UNIT 0
+
+/* FCRTL Bit Masks */
+#define IXGB_FCRTL_XONE       0x80000000
+
+/* RXDCTL Bit Masks */
+#define IXGB_RXDCTL_PTHRESH_MASK  0x000001FF
+#define IXGB_RXDCTL_PTHRESH_SHIFT 0
+#define IXGB_RXDCTL_HTHRESH_MASK  0x0003FE00
+#define IXGB_RXDCTL_HTHRESH_SHIFT 9
+#define IXGB_RXDCTL_WTHRESH_MASK  0x07FC0000
+#define IXGB_RXDCTL_WTHRESH_SHIFT 18
+
+/* RAIDC Bit Masks */
+#define IXGB_RAIDC_HIGHTHRS_MASK 0x0000003F
+#define IXGB_RAIDC_DELAY_MASK    0x000FF800
+#define IXGB_RAIDC_DELAY_SHIFT   11
+#define IXGB_RAIDC_POLL_MASK     0x1FF00000
+#define IXGB_RAIDC_POLL_SHIFT    20
+#define IXGB_RAIDC_RXT_GATE      0x40000000
+#define IXGB_RAIDC_EN            0x80000000
+
+#define IXGB_RAIDC_POLL_1000_INTERRUPTS_PER_SECOND      1220
+#define IXGB_RAIDC_POLL_5000_INTERRUPTS_PER_SECOND      244
+#define IXGB_RAIDC_POLL_10000_INTERRUPTS_PER_SECOND     122
+#define IXGB_RAIDC_POLL_20000_INTERRUPTS_PER_SECOND     61
+
+/* RXCSUM Bit Masks */
+#define IXGB_RXCSUM_IPOFL 0x00000100
+#define IXGB_RXCSUM_TUOFL 0x00000200
+
+/* RAH Bit Masks */
+#define IXGB_RAH_ASEL_MASK 0x00030000
+#define IXGB_RAH_ASEL_DEST 0x00000000
+#define IXGB_RAH_ASEL_SRC  0x00010000
+#define IXGB_RAH_AV        0x80000000
+
+/* TCTL Bit Masks */
+#define IXGB_TCTL_TCE  0x00000001
+#define IXGB_TCTL_TXEN 0x00000002
+#define IXGB_TCTL_TPDE 0x00000004
+
+#define IXGB_TCTL_IDLE_TX_UNIT  0
+
+/* TXDCTL Bit Masks */
+#define IXGB_TXDCTL_PTHRESH_MASK  0x0000007F
+#define IXGB_TXDCTL_HTHRESH_MASK  0x00007F00
+#define IXGB_TXDCTL_HTHRESH_SHIFT 8
+#define IXGB_TXDCTL_WTHRESH_MASK  0x007F0000
+#define IXGB_TXDCTL_WTHRESH_SHIFT 16
+
+/* TSPMT Bit Masks */
+#define IXGB_TSPMT_TSMT_MASK   0x0000FFFF
+#define IXGB_TSPMT_TSPBP_MASK  0xFFFF0000
+#define IXGB_TSPMT_TSPBP_SHIFT 16
+
+/* PAP Bit Masks */
+#define IXGB_PAP_TXPC_MASK 0x0000FFFF
+#define IXGB_PAP_TXPV_MASK 0x000F0000
+#define IXGB_PAP_TXPV_10G  0x00000000
+#define IXGB_PAP_TXPV_1G   0x00010000
+#define IXGB_PAP_TXPV_2G   0x00020000
+#define IXGB_PAP_TXPV_3G   0x00030000
+#define IXGB_PAP_TXPV_4G   0x00040000
+#define IXGB_PAP_TXPV_5G   0x00050000
+#define IXGB_PAP_TXPV_6G   0x00060000
+#define IXGB_PAP_TXPV_7G   0x00070000
+#define IXGB_PAP_TXPV_8G   0x00080000
+#define IXGB_PAP_TXPV_9G   0x00090000
+#define IXGB_PAP_TXPV_WAN  0x000F0000
+
+/* PCSC1 Bit Masks */
+#define IXGB_PCSC1_LOOPBACK 0x00004000
+
+/* PCSC2 Bit Masks */
+#define IXGB_PCSC2_PCS_TYPE_MASK  0x00000003
+#define IXGB_PCSC2_PCS_TYPE_10GBX 0x00000001
+
+/* PCSS1 Bit Masks */
+#define IXGB_PCSS1_LOCAL_FAULT    0x00000080
+#define IXGB_PCSS1_RX_LINK_STATUS 0x00000004
+
+/* PCSS2 Bit Masks */
+#define IXGB_PCSS2_DEV_PRES_MASK 0x0000C000
+#define IXGB_PCSS2_DEV_PRES      0x00004000
+#define IXGB_PCSS2_TX_LF         0x00000800
+#define IXGB_PCSS2_RX_LF         0x00000400
+#define IXGB_PCSS2_10GBW         0x00000004
+#define IXGB_PCSS2_10GBX         0x00000002
+#define IXGB_PCSS2_10GBR         0x00000001
+
+/* XPCSS Bit Masks */
+#define IXGB_XPCSS_ALIGN_STATUS 0x00001000
+#define IXGB_XPCSS_PATTERN_TEST 0x00000800
+#define IXGB_XPCSS_LANE_3_SYNC  0x00000008
+#define IXGB_XPCSS_LANE_2_SYNC  0x00000004
+#define IXGB_XPCSS_LANE_1_SYNC  0x00000002
+#define IXGB_XPCSS_LANE_0_SYNC  0x00000001
+
+/* XPCSTC Bit Masks */
+#define IXGB_XPCSTC_BERT_TRIG       0x00200000
+#define IXGB_XPCSTC_BERT_SST        0x00100000
+#define IXGB_XPCSTC_BERT_PSZ_MASK   0x000C0000
+#define IXGB_XPCSTC_BERT_PSZ_SHIFT  17
+#define IXGB_XPCSTC_BERT_PSZ_INF    0x00000003
+#define IXGB_XPCSTC_BERT_PSZ_68     0x00000001
+#define IXGB_XPCSTC_BERT_PSZ_1028   0x00000000
+
+/* MSCA bit Masks */
+/* New Protocol Address */
+#define IXGB_MSCA_NP_ADDR_MASK      0x0000FFFF
+#define IXGB_MSCA_NP_ADDR_SHIFT     0
+/* Either Device Type or Register Address,depending on ST_CODE */
+#define IXGB_MSCA_DEV_TYPE_MASK     0x001F0000
+#define IXGB_MSCA_DEV_TYPE_SHIFT    16
+#define IXGB_MSCA_PHY_ADDR_MASK     0x03E00000
+#define IXGB_MSCA_PHY_ADDR_SHIFT    21
+#define IXGB_MSCA_OP_CODE_MASK      0x0C000000
+/* OP_CODE == 00, Address cycle, New Protocol           */
+/* OP_CODE == 01, Write operation                       */
+/* OP_CODE == 10, Read operation                        */
+/* OP_CODE == 11, Read, auto increment, New Protocol    */
+#define IXGB_MSCA_ADDR_CYCLE        0x00000000
+#define IXGB_MSCA_WRITE             0x04000000
+#define IXGB_MSCA_READ              0x08000000
+#define IXGB_MSCA_READ_AUTOINC      0x0C000000
+#define IXGB_MSCA_OP_CODE_SHIFT     26
+#define IXGB_MSCA_ST_CODE_MASK      0x30000000
+/* ST_CODE == 00, New Protocol  */
+/* ST_CODE == 01, Old Protocol  */
+#define IXGB_MSCA_NEW_PROTOCOL      0x00000000
+#define IXGB_MSCA_OLD_PROTOCOL      0x10000000
+#define IXGB_MSCA_ST_CODE_SHIFT     28
+/* Initiate command, self-clearing when command completes */
+#define IXGB_MSCA_MDI_COMMAND       0x40000000
+/*MDI In Progress Enable. */
+#define IXGB_MSCA_MDI_IN_PROG_EN    0x80000000
+
+/* MSRWD bit masks */
+#define IXGB_MSRWD_WRITE_DATA_MASK  0x0000FFFF
+#define IXGB_MSRWD_WRITE_DATA_SHIFT 0
+#define IXGB_MSRWD_READ_DATA_MASK   0xFFFF0000
+#define IXGB_MSRWD_READ_DATA_SHIFT  16
+
+/* Definitions for the optics devices on the MDIO bus. */
+#define IXGB_PHY_ADDRESS             0x0	/* Single PHY, multiple "Devices" */
+
+/* Standard five-bit Device IDs.  See IEEE 802.3ae, clause 45 */
+#define MDIO_PMA_PMD_DID        0x01
+#define MDIO_WIS_DID            0x02
+#define MDIO_PCS_DID            0x03
+#define MDIO_XGXS_DID           0x04
+
+/* Standard PMA/PMD registers and bit definitions. */
+/* Note: This is a very limited set of definitions,      */
+/* only implemented features are defined.                */
+#define MDIO_PMA_PMD_CR1        0x0000
+#define MDIO_PMA_PMD_CR1_RESET  0x8000
+
+#define MDIO_PMA_PMD_XPAK_VENDOR_NAME       0x803A	/* XPAK/XENPAK devices only */
+
+/* Vendor-specific MDIO registers */
+#define G6XXX_PMA_PMD_VS1                   0xC001	/* Vendor-specific register */
+#define G6XXX_XGXS_XAUI_VS2                 0x18	/* Vendor-specific register */
+
+#define G6XXX_PMA_PMD_VS1_PLL_RESET         0x80
+#define G6XXX_PMA_PMD_VS1_REMOVE_PLL_RESET  0x00
+#define G6XXX_XGXS_XAUI_VS2_INPUT_MASK      0x0F	/* XAUI lanes synchronized */
+
+/* Layout of a single receive descriptor.  The controller assumes that this
+ * structure is packed into 16 bytes, which is a safe assumption with most
+ * compilers.  However, some compilers may insert padding between the fields,
+ * in which case the structure must be packed in some compiler-specific
+ * manner. */
+struct ixgb_rx_desc {
+	uint64_t buff_addr;
+	uint16_t length;
+	uint16_t reserved;
+	uint8_t status;
+	uint8_t errors;
+	uint16_t special;
+};
+
+#define IXGB_RX_DESC_STATUS_DD    0x01
+#define IXGB_RX_DESC_STATUS_EOP   0x02
+#define IXGB_RX_DESC_STATUS_IXSM  0x04
+#define IXGB_RX_DESC_STATUS_VP    0x08
+#define IXGB_RX_DESC_STATUS_TCPCS 0x20
+#define IXGB_RX_DESC_STATUS_IPCS  0x40
+#define IXGB_RX_DESC_STATUS_PIF   0x80
+
+#define IXGB_RX_DESC_ERRORS_CE   0x01
+#define IXGB_RX_DESC_ERRORS_SE   0x02
+#define IXGB_RX_DESC_ERRORS_P    0x08
+#define IXGB_RX_DESC_ERRORS_TCPE 0x20
+#define IXGB_RX_DESC_ERRORS_IPE  0x40
+#define IXGB_RX_DESC_ERRORS_RXE  0x80
+
+#define IXGB_RX_DESC_SPECIAL_VLAN_MASK  0x0FFF	/* VLAN ID is in lower 12 bits */
+#define IXGB_RX_DESC_SPECIAL_PRI_MASK   0xE000	/* Priority is in upper 3 bits */
+#define IXGB_RX_DESC_SPECIAL_PRI_SHIFT  0x000D	/* Priority is in upper 3 of 16 */
+
+/* Layout of a single transmit descriptor.  The controller assumes that this
+ * structure is packed into 16 bytes, which is a safe assumption with most
+ * compilers.  However, some compilers may insert padding between the fields,
+ * in which case the structure must be packed in some compiler-specific
+ * manner. */
+struct ixgb_tx_desc {
+	uint64_t buff_addr;
+	uint32_t cmd_type_len;
+	uint8_t status;
+	uint8_t popts;
+	uint16_t vlan;
+};
+
+#define IXGB_TX_DESC_LENGTH_MASK    0x000FFFFF
+#define IXGB_TX_DESC_TYPE_MASK      0x00F00000
+#define IXGB_TX_DESC_TYPE_SHIFT     20
+#define IXGB_TX_DESC_CMD_MASK       0xFF000000
+#define IXGB_TX_DESC_CMD_SHIFT      24
+#define IXGB_TX_DESC_CMD_EOP        0x01000000
+#define IXGB_TX_DESC_CMD_TSE        0x04000000
+#define IXGB_TX_DESC_CMD_RS         0x08000000
+#define IXGB_TX_DESC_CMD_VLE        0x40000000
+#define IXGB_TX_DESC_CMD_IDE        0x80000000
+
+#define IXGB_TX_DESC_TYPE           0x00100000
+
+#define IXGB_TX_DESC_STATUS_DD  0x01
+
+#define IXGB_TX_DESC_POPTS_IXSM 0x01
+#define IXGB_TX_DESC_POPTS_TXSM 0x02
+#define IXGB_TX_DESC_SPECIAL_PRI_SHIFT  IXGB_RX_DESC_SPECIAL_PRI_SHIFT	/* Priority is in upper 3 of 16 */
+
+struct ixgb_context_desc {
+	uint8_t ipcss;
+	uint8_t ipcso;
+	uint16_t ipcse;
+	uint8_t tucss;
+	uint8_t tucso;
+	uint16_t tucse;
+	uint32_t cmd_type_len;
+	uint8_t status;
+	uint8_t hdr_len;
+	uint16_t mss;
+};
+
+#define IXGB_CONTEXT_DESC_CMD_TCP 0x01000000
+#define IXGB_CONTEXT_DESC_CMD_IP  0x02000000
+#define IXGB_CONTEXT_DESC_CMD_TSE 0x04000000
+#define IXGB_CONTEXT_DESC_CMD_RS  0x08000000
+#define IXGB_CONTEXT_DESC_CMD_IDE 0x80000000
+
+#define IXGB_CONTEXT_DESC_TYPE 0x00000000
+
+#define IXGB_CONTEXT_DESC_STATUS_DD 0x01
+
+/* Filters */
+#define IXGB_MC_TBL_SIZE          128	/* Multicast Filter Table (4096 bits) */
+#define IXGB_VLAN_FILTER_TBL_SIZE 128	/* VLAN Filter Table (4096 bits) */
+#define IXGB_RAR_ENTRIES		  3	/* Number of entries in Rx Address array */
+
+#define IXGB_MEMORY_REGISTER_BASE_ADDRESS   0
+#define ENET_HEADER_SIZE			14
+#define ENET_FCS_LENGTH			 4
+#define IXGB_MAX_NUM_MULTICAST_ADDRESSES	128
+#define IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS	60
+#define IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS	1514
+#define IXGB_MAX_JUMBO_FRAME_SIZE		0x3F00
+
+/* Phy Addresses */
+#define IXGB_OPTICAL_PHY_ADDR 0x0	/* Optical Module phy address */
+#define IXGB_XAUII_PHY_ADDR   0x1	/* Xauii transceiver phy address */
+#define IXGB_DIAG_PHY_ADDR    0x1F	/* Diagnostic Device phy address */
+
+/* This structure takes a 64k flash and maps it for identification commands */
+struct ixgb_flash_buffer {
+	uint8_t manufacturer_id;
+	uint8_t device_id;
+	uint8_t filler1[0x2AA8];
+	uint8_t cmd2;
+	uint8_t filler2[0x2AAA];
+	uint8_t cmd1;
+	uint8_t filler3[0xAAAA];
+};
+
+/*
+ * This is a little-endian specific check.
+ */
+#define IS_MULTICAST(Address) \
+    (boolean_t)(((uint8_t *)(Address))[0] & ((uint8_t)0x01))
+
+/*
+ * Check whether an address is broadcast.
+ */
+#define IS_BROADCAST(Address)               \
+    ((((uint8_t *)(Address))[0] == ((uint8_t)0xff)) && (((uint8_t *)(Address))[1] == ((uint8_t)0xff)))
+
+/* Flow control parameters */
+struct ixgb_fc {
+	uint32_t high_water;	/* Flow Control High-water          */
+	uint32_t low_water;	/* Flow Control Low-water           */
+	uint16_t pause_time;	/* Flow Control Pause timer         */
+	boolean_t send_xon;	/* Flow control send XON            */
+	ixgb_fc_type type;	/* Type of flow control             */
+};
+
+/* The historical defaults for the flow control values are given below. */
+#define FC_DEFAULT_HI_THRESH        (0x8000)	/* 32KB */
+#define FC_DEFAULT_LO_THRESH        (0x4000)	/* 16KB */
+#define FC_DEFAULT_TX_TIMER         (0x100)	/* ~130 us */
+
+/* Phy definitions */
+#define IXGB_MAX_PHY_REG_ADDRESS    0xFFFF
+#define IXGB_MAX_PHY_ADDRESS        31
+#define IXGB_MAX_PHY_DEV_TYPE       31
+
+/* Bus parameters */
+struct ixgb_bus {
+	ixgb_bus_speed speed;
+	ixgb_bus_width width;
+	ixgb_bus_type type;
+};
+
+struct ixgb_hw {
+	uint8_t __iomem *hw_addr;/* Base Address of the hardware     */
+	void *back;		/* Pointer to OS-dependent struct   */
+	struct ixgb_fc fc;	/* Flow control parameters          */
+	struct ixgb_bus bus;	/* Bus parameters                   */
+	uint32_t phy_id;	/* Phy Identifier                   */
+	uint32_t phy_addr;	/* XGMII address of Phy             */
+	ixgb_mac_type mac_type;	/* Identifier for MAC controller    */
+	ixgb_phy_type phy_type;	/* Transceiver/phy identifier       */
+	uint32_t max_frame_size;	/* Maximum frame size supported     */
+	uint32_t mc_filter_type;	/* Multicast filter hash type       */
+	uint32_t num_mc_addrs;	/* Number of current Multicast addrs */
+	uint8_t curr_mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS];	/* Individual address currently programmed in MAC */
+	uint32_t num_tx_desc;	/* Number of Transmit descriptors   */
+	uint32_t num_rx_desc;	/* Number of Receive descriptors    */
+	uint32_t rx_buffer_size;	/* Size of Receive buffer           */
+	boolean_t link_up;	/* TRUE if link is valid            */
+	boolean_t adapter_stopped;	/* State of adapter                 */
+	uint16_t device_id;	/* device id from PCI configuration space */
+	uint16_t vendor_id;	/* vendor id from PCI configuration space */
+	uint8_t revision_id;	/* revision id from PCI configuration space */
+	uint16_t subsystem_vendor_id;	/* subsystem vendor id from PCI configuration space */
+	uint16_t subsystem_id;	/* subsystem id from PCI configuration space */
+	uint32_t bar0;		/* Base Address registers           */
+	uint32_t bar1;
+	uint32_t bar2;
+	uint32_t bar3;
+	uint16_t pci_cmd_word;	/* PCI command register id from PCI configuration space */
+	uint16_t eeprom[IXGB_EEPROM_SIZE];	/* EEPROM contents read at init time  */
+	unsigned long io_base;	/* Our I/O mapped location */
+	uint32_t lastLFC;
+	uint32_t lastRFC;
+};
+
+/* Statistics reported by the hardware */
+struct ixgb_hw_stats {
+	uint64_t tprl;
+	uint64_t tprh;
+	uint64_t gprcl;
+	uint64_t gprch;
+	uint64_t bprcl;
+	uint64_t bprch;
+	uint64_t mprcl;
+	uint64_t mprch;
+	uint64_t uprcl;
+	uint64_t uprch;
+	uint64_t vprcl;
+	uint64_t vprch;
+	uint64_t jprcl;
+	uint64_t jprch;
+	uint64_t gorcl;
+	uint64_t gorch;
+	uint64_t torl;
+	uint64_t torh;
+	uint64_t rnbc;
+	uint64_t ruc;
+	uint64_t roc;
+	uint64_t rlec;
+	uint64_t crcerrs;
+	uint64_t icbc;
+	uint64_t ecbc;
+	uint64_t mpc;
+	uint64_t tptl;
+	uint64_t tpth;
+	uint64_t gptcl;
+	uint64_t gptch;
+	uint64_t bptcl;
+	uint64_t bptch;
+	uint64_t mptcl;
+	uint64_t mptch;
+	uint64_t uptcl;
+	uint64_t uptch;
+	uint64_t vptcl;
+	uint64_t vptch;
+	uint64_t jptcl;
+	uint64_t jptch;
+	uint64_t gotcl;
+	uint64_t gotch;
+	uint64_t totl;
+	uint64_t toth;
+	uint64_t dc;
+	uint64_t plt64c;
+	uint64_t tsctc;
+	uint64_t tsctfc;
+	uint64_t ibic;
+	uint64_t rfc;
+	uint64_t lfc;
+	uint64_t pfrc;
+	uint64_t pftc;
+	uint64_t mcfrc;
+	uint64_t mcftc;
+	uint64_t xonrxc;
+	uint64_t xontxc;
+	uint64_t xoffrxc;
+	uint64_t xofftxc;
+	uint64_t rjc;
+};
+
+/* Function Prototypes */
+extern boolean_t ixgb_adapter_stop(struct ixgb_hw *hw);
+extern boolean_t ixgb_init_hw(struct ixgb_hw *hw);
+extern boolean_t ixgb_adapter_start(struct ixgb_hw *hw);
+extern void ixgb_init_rx_addrs(struct ixgb_hw *hw);
+extern void ixgb_check_for_link(struct ixgb_hw *hw);
+extern boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw);
+extern boolean_t ixgb_setup_fc(struct ixgb_hw *hw);
+extern void ixgb_clear_hw_cntrs(struct ixgb_hw *hw);
+extern boolean_t mac_addr_valid(uint8_t *mac_addr);
+
+extern uint16_t ixgb_read_phy_reg(struct ixgb_hw *hw,
+				uint32_t reg_addr,
+				uint32_t phy_addr,
+				uint32_t device_type);
+
+extern void ixgb_write_phy_reg(struct ixgb_hw *hw,
+				uint32_t reg_addr,
+				uint32_t phy_addr,
+				uint32_t device_type,
+				uint16_t data);
+
+extern void ixgb_rar_set(struct ixgb_hw *hw,
+				uint8_t *addr,
+				uint32_t index);
+
+
+/* Filters (multicast, vlan, receive) */
+extern void ixgb_mc_addr_list_update(struct ixgb_hw *hw,
+				   uint8_t *mc_addr_list,
+				   uint32_t mc_addr_count,
+				   uint32_t pad);
+
+/* Vfta functions */
+extern void ixgb_write_vfta(struct ixgb_hw *hw,
+				 uint32_t offset,
+				 uint32_t value);
+
+extern void ixgb_clear_vfta(struct ixgb_hw *hw);
+
+/* Access functions to eeprom data */
+void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t *mac_addr);
+uint16_t ixgb_get_ee_compatibility(struct ixgb_hw *hw);
+uint32_t ixgb_get_ee_pba_number(struct ixgb_hw *hw);
+uint16_t ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw);
+uint16_t ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw);
+uint16_t ixgb_get_ee_subsystem_id(struct ixgb_hw *hw);
+uint16_t ixgb_get_ee_subvendor_id(struct ixgb_hw *hw);
+uint16_t ixgb_get_ee_device_id(struct ixgb_hw *hw);
+uint16_t ixgb_get_ee_vendor_id(struct ixgb_hw *hw);
+uint16_t ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw);
+uint8_t ixgb_get_ee_d3_power(struct ixgb_hw *hw);
+uint8_t ixgb_get_ee_d0_power(struct ixgb_hw *hw);
+boolean_t ixgb_get_eeprom_data(struct ixgb_hw *hw);
+uint16_t ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index);
+
+/* Everything else */
+void ixgb_led_on(struct ixgb_hw *hw);
+void ixgb_led_off(struct ixgb_hw *hw);
+void ixgb_write_pci_cfg(struct ixgb_hw *hw,
+			 uint32_t reg,
+			 uint16_t * value);
+
+
+#endif /* _IXGB_HW_H_ */
diff --git a/drivers/net/ixgb/ixgb_ids.h b/drivers/net/ixgb/ixgb_ids.h
new file mode 100644
index 0000000..aee207e
--- /dev/null
+++ b/drivers/net/ixgb/ixgb_ids.h
@@ -0,0 +1,48 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of the GNU General Public License as published by the Free 
+  Software Foundation; either version 2 of the License, or (at your option) 
+  any later version.
+  
+  This program is distributed in the hope that it will be useful, but WITHOUT 
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+  more details.
+  
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#ifndef _IXGB_IDS_H_
+#define _IXGB_IDS_H_
+
+/**********************************************************************
+** The Device and Vendor IDs for 10 Gigabit MACs
+**********************************************************************/
+
+#define INTEL_VENDOR_ID             0x8086
+#define INTEL_SUBVENDOR_ID          0x8086
+
+
+#define IXGB_DEVICE_ID_82597EX      0x1048   
+#define IXGB_DEVICE_ID_82597EX_SR   0x1A48   
+#define IXGB_DEVICE_ID_82597EX_LR   0x1B48
+#define IXGB_SUBDEVICE_ID_A11F      0xA11F   
+#define IXGB_SUBDEVICE_ID_A01F      0xA01F   
+
+#endif /* #ifndef _IXGB_IDS_H_ */
+
+/* End of File */
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
new file mode 100644
index 0000000..7d26623
--- /dev/null
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -0,0 +1,2166 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of the GNU General Public License as published by the Free 
+  Software Foundation; either version 2 of the License, or (at your option) 
+  any later version.
+  
+  This program is distributed in the hope that it will be useful, but WITHOUT 
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+  more details.
+  
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include "ixgb.h"
+
+/* Change Log
+ * 1.0.88 01/05/05
+ * - include fix to the condition that determines when to quit NAPI - Robert Olsson
+ * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down
+ * 1.0.84 10/26/04
+ * - reset buffer_info->dma in Tx resource cleanup logic
+ * 1.0.83 10/12/04
+ * - sparse cleanup - shemminger@osdl.org
+ * - fix tx resource cleanup logic
+ */
+
+char ixgb_driver_name[] = "ixgb";
+char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
+
+#ifndef CONFIG_IXGB_NAPI
+#define DRIVERNAPI
+#else
+#define DRIVERNAPI "-NAPI"
+#endif
+char ixgb_driver_version[] = "1.0.90-k2"DRIVERNAPI;
+char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
+
+/* ixgb_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 ixgb_pci_tbl[] = {
+	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_SR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_LR,  
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+
+	/* required last entry */
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);
+
+/* Local Function Prototypes */
+
+int ixgb_up(struct ixgb_adapter *adapter);
+void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
+void ixgb_reset(struct ixgb_adapter *adapter);
+int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
+int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
+void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
+void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
+void ixgb_update_stats(struct ixgb_adapter *adapter);
+
+static int ixgb_init_module(void);
+static void ixgb_exit_module(void);
+static int ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void __devexit ixgb_remove(struct pci_dev *pdev);
+static int ixgb_sw_init(struct ixgb_adapter *adapter);
+static int ixgb_open(struct net_device *netdev);
+static int ixgb_close(struct net_device *netdev);
+static void ixgb_configure_tx(struct ixgb_adapter *adapter);
+static void ixgb_configure_rx(struct ixgb_adapter *adapter);
+static void ixgb_setup_rctl(struct ixgb_adapter *adapter);
+static void ixgb_clean_tx_ring(struct ixgb_adapter *adapter);
+static void ixgb_clean_rx_ring(struct ixgb_adapter *adapter);
+static void ixgb_set_multi(struct net_device *netdev);
+static void ixgb_watchdog(unsigned long data);
+static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
+static struct net_device_stats *ixgb_get_stats(struct net_device *netdev);
+static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);
+static int ixgb_set_mac(struct net_device *netdev, void *p);
+static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs);
+static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
+#ifdef CONFIG_IXGB_NAPI
+static int ixgb_clean(struct net_device *netdev, int *budget);
+static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
+				   int *work_done, int work_to_do);
+#else
+static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
+#endif
+static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
+void ixgb_set_ethtool_ops(struct net_device *netdev);
+static void ixgb_tx_timeout(struct net_device *dev);
+static void ixgb_tx_timeout_task(struct net_device *dev);
+static void ixgb_vlan_rx_register(struct net_device *netdev,
+				  struct vlan_group *grp);
+static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
+static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
+static void ixgb_restore_vlan(struct ixgb_adapter *adapter);
+
+static int ixgb_notify_reboot(struct notifier_block *, unsigned long event,
+			      void *ptr);
+static int ixgb_suspend(struct pci_dev *pdev, uint32_t state);
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/* for netdump / net console */
+static void ixgb_netpoll(struct net_device *dev);
+#endif
+
+struct notifier_block ixgb_notifier_reboot = {
+	.notifier_call = ixgb_notify_reboot,
+	.next = NULL,
+	.priority = 0
+};
+
+/* Exported from other modules */
+
+extern void ixgb_check_options(struct ixgb_adapter *adapter);
+
+static struct pci_driver ixgb_driver = {
+	.name = ixgb_driver_name,
+	.id_table = ixgb_pci_tbl,
+	.probe = ixgb_probe,
+	.remove = __devexit_p(ixgb_remove),
+	/* Power Managment Hooks */
+	.suspend = NULL,
+	.resume = NULL
+};
+
+MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
+MODULE_DESCRIPTION("Intel(R) PRO/10GbE Network Driver");
+MODULE_LICENSE("GPL");
+
+/* some defines for controlling descriptor fetches in h/w */
+#define RXDCTL_PTHRESH_DEFAULT 128	/* chip considers prefech below this */
+#define RXDCTL_HTHRESH_DEFAULT 16	/* chip will only prefetch if tail is 
+					   pushed this many descriptors from head */
+#define RXDCTL_WTHRESH_DEFAULT 16	/* chip writes back at this many or RXT0 */
+
+/**
+ * ixgb_init_module - Driver Registration Routine
+ *
+ * ixgb_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ **/
+
+static int __init
+ixgb_init_module(void)
+{
+	int ret;
+	printk(KERN_INFO "%s - version %s\n",
+	       ixgb_driver_string, ixgb_driver_version);
+
+	printk(KERN_INFO "%s\n", ixgb_copyright);
+
+	ret = pci_module_init(&ixgb_driver);
+	if(ret >= 0) {
+		register_reboot_notifier(&ixgb_notifier_reboot);
+	}
+	return ret;
+}
+
+module_init(ixgb_init_module);
+
+/**
+ * ixgb_exit_module - Driver Exit Cleanup Routine
+ *
+ * ixgb_exit_module is called just before the driver is removed
+ * from memory.
+ **/
+
+static void __exit
+ixgb_exit_module(void)
+{
+	unregister_reboot_notifier(&ixgb_notifier_reboot);
+	pci_unregister_driver(&ixgb_driver);
+}
+
+module_exit(ixgb_exit_module);
+
+/**
+ * ixgb_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+
+static inline void
+ixgb_irq_disable(struct ixgb_adapter *adapter)
+{
+	atomic_inc(&adapter->irq_sem);
+	IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
+	IXGB_WRITE_FLUSH(&adapter->hw);
+	synchronize_irq(adapter->pdev->irq);
+}
+
+/**
+ * ixgb_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ **/
+
+static inline void
+ixgb_irq_enable(struct ixgb_adapter *adapter)
+{
+	if(atomic_dec_and_test(&adapter->irq_sem)) {
+		IXGB_WRITE_REG(&adapter->hw, IMS,
+			   IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
+			   IXGB_INT_RXO | IXGB_INT_LSC);
+		IXGB_WRITE_FLUSH(&adapter->hw);
+	}
+}
+
+int
+ixgb_up(struct ixgb_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	int err;
+	int max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+	struct ixgb_hw *hw = &adapter->hw;
+
+	/* hardware has been reset, we need to reload some things */
+
+	ixgb_set_multi(netdev);
+
+	ixgb_restore_vlan(adapter);
+
+	ixgb_configure_tx(adapter);
+	ixgb_setup_rctl(adapter);
+	ixgb_configure_rx(adapter);
+	ixgb_alloc_rx_buffers(adapter);
+
+#ifdef CONFIG_PCI_MSI
+	{
+	boolean_t pcix = (IXGB_READ_REG(&adapter->hw, STATUS) & 
+						  IXGB_STATUS_PCIX_MODE) ? TRUE : FALSE;
+	adapter->have_msi = TRUE;
+
+	if (!pcix)
+	   adapter->have_msi = FALSE;
+	else if((err = pci_enable_msi(adapter->pdev))) {
+		printk (KERN_ERR
+		 "Unable to allocate MSI interrupt Error: %d\n", err);
+		adapter->have_msi = FALSE;
+		/* proceed to try to request regular interrupt */
+	}
+	}
+
+#endif
+	if((err = request_irq(adapter->pdev->irq, &ixgb_intr,
+				  SA_SHIRQ | SA_SAMPLE_RANDOM,
+				  netdev->name, netdev)))
+		return err;
+
+	/* disable interrupts and get the hardware into a known state */
+	IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
+
+	if((hw->max_frame_size != max_frame) ||
+		(hw->max_frame_size !=
+		(IXGB_READ_REG(hw, MFS) >> IXGB_MFS_SHIFT))) {
+
+		hw->max_frame_size = max_frame;
+
+		IXGB_WRITE_REG(hw, MFS, hw->max_frame_size << IXGB_MFS_SHIFT);
+
+		if(hw->max_frame_size >
+		   IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) {
+			uint32_t ctrl0 = IXGB_READ_REG(hw, CTRL0);
+
+			if(!(ctrl0 & IXGB_CTRL0_JFE)) {
+				ctrl0 |= IXGB_CTRL0_JFE;
+				IXGB_WRITE_REG(hw, CTRL0, ctrl0);
+			}
+		}
+	}
+
+	mod_timer(&adapter->watchdog_timer, jiffies);
+	ixgb_irq_enable(adapter);
+
+#ifdef CONFIG_IXGB_NAPI
+	netif_poll_enable(netdev);
+#endif
+	return 0;
+}
+
+void
+ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	ixgb_irq_disable(adapter);
+	free_irq(adapter->pdev->irq, netdev);
+#ifdef CONFIG_PCI_MSI
+	if(adapter->have_msi == TRUE)
+		pci_disable_msi(adapter->pdev);
+
+#endif
+	if(kill_watchdog)
+		del_timer_sync(&adapter->watchdog_timer);
+#ifdef CONFIG_IXGB_NAPI
+	netif_poll_disable(netdev);
+#endif
+	adapter->link_speed = 0;
+	adapter->link_duplex = 0;
+	netif_carrier_off(netdev);
+	netif_stop_queue(netdev);
+
+	ixgb_reset(adapter);
+	ixgb_clean_tx_ring(adapter);
+	ixgb_clean_rx_ring(adapter);
+}
+
+void
+ixgb_reset(struct ixgb_adapter *adapter)
+{
+
+	ixgb_adapter_stop(&adapter->hw);
+	if(!ixgb_init_hw(&adapter->hw))
+		IXGB_DBG("ixgb_init_hw failed.\n");
+}
+
+/**
+ * ixgb_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in ixgb_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * ixgb_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ **/
+
+static int __devinit
+ixgb_probe(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
+{
+	struct net_device *netdev = NULL;
+	struct ixgb_adapter *adapter;
+	static int cards_found = 0;
+	unsigned long mmio_start;
+	int mmio_len;
+	int pci_using_dac;
+	int i;
+	int err;
+
+	if((err = pci_enable_device(pdev)))
+		return err;
+
+	if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+		pci_using_dac = 1;
+	} else {
+		if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+			IXGB_ERR("No usable DMA configuration, aborting\n");
+			return err;
+		}
+		pci_using_dac = 0;
+	}
+
+	if((err = pci_request_regions(pdev, ixgb_driver_name)))
+		return err;
+
+	pci_set_master(pdev);
+
+	netdev = alloc_etherdev(sizeof(struct ixgb_adapter));
+	if(!netdev) {
+		err = -ENOMEM;
+		goto err_alloc_etherdev;
+	}
+
+	SET_MODULE_OWNER(netdev);
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+
+	pci_set_drvdata(pdev, netdev);
+	adapter = netdev->priv;
+	adapter->netdev = netdev;
+	adapter->pdev = pdev;
+	adapter->hw.back = adapter;
+
+	mmio_start = pci_resource_start(pdev, BAR_0);
+	mmio_len = pci_resource_len(pdev, BAR_0);
+
+	adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
+	if(!adapter->hw.hw_addr) {
+		err = -EIO;
+		goto err_ioremap;
+	}
+
+	for(i = BAR_1; i <= BAR_5; i++) {
+		if(pci_resource_len(pdev, i) == 0)
+			continue;
+		if(pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+			adapter->hw.io_base = pci_resource_start(pdev, i);
+			break;
+		}
+	}
+
+	netdev->open = &ixgb_open;
+	netdev->stop = &ixgb_close;
+	netdev->hard_start_xmit = &ixgb_xmit_frame;
+	netdev->get_stats = &ixgb_get_stats;
+	netdev->set_multicast_list = &ixgb_set_multi;
+	netdev->set_mac_address = &ixgb_set_mac;
+	netdev->change_mtu = &ixgb_change_mtu;
+	ixgb_set_ethtool_ops(netdev);
+	netdev->tx_timeout = &ixgb_tx_timeout;
+	netdev->watchdog_timeo = HZ;
+#ifdef CONFIG_IXGB_NAPI
+	netdev->poll = &ixgb_clean;
+	netdev->weight = 64;
+#endif
+	netdev->vlan_rx_register = ixgb_vlan_rx_register;
+	netdev->vlan_rx_add_vid = ixgb_vlan_rx_add_vid;
+	netdev->vlan_rx_kill_vid = ixgb_vlan_rx_kill_vid;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	netdev->poll_controller = ixgb_netpoll;
+#endif
+
+	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->link_speed = 0;
+	adapter->link_duplex = 0;
+
+	/* setup the private structure */
+
+	if((err = ixgb_sw_init(adapter)))
+		goto err_sw_init;
+
+	netdev->features = NETIF_F_SG |
+			   NETIF_F_HW_CSUM |
+			   NETIF_F_HW_VLAN_TX |
+			   NETIF_F_HW_VLAN_RX |
+			   NETIF_F_HW_VLAN_FILTER;
+#ifdef NETIF_F_TSO
+	netdev->features |= NETIF_F_TSO;
+#endif
+
+	if(pci_using_dac)
+		netdev->features |= NETIF_F_HIGHDMA;
+
+	/* make sure the EEPROM is good */
+
+	if(!ixgb_validate_eeprom_checksum(&adapter->hw)) {
+		printk(KERN_ERR "The EEPROM Checksum Is Not Valid\n");
+		err = -EIO;
+		goto err_eeprom;
+	}
+
+	ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
+
+	if(!is_valid_ether_addr(netdev->dev_addr)) {
+		err = -EIO;
+		goto err_eeprom;
+	}
+
+	adapter->part_num = ixgb_get_ee_pba_number(&adapter->hw);
+
+	init_timer(&adapter->watchdog_timer);
+	adapter->watchdog_timer.function = &ixgb_watchdog;
+	adapter->watchdog_timer.data = (unsigned long)adapter;
+
+	INIT_WORK(&adapter->tx_timeout_task,
+		  (void (*)(void *))ixgb_tx_timeout_task, netdev);
+
+	if((err = register_netdev(netdev)))
+		goto err_register;
+
+	/* 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/10GbE Network Connection\n",
+		   netdev->name);
+	ixgb_check_options(adapter);
+	/* reset the hardware with the new settings */
+
+	ixgb_reset(adapter);
+
+	cards_found++;
+	return 0;
+
+err_register:
+err_sw_init:
+err_eeprom:
+	iounmap(adapter->hw.hw_addr);
+err_ioremap:
+	free_netdev(netdev);
+err_alloc_etherdev:
+	pci_release_regions(pdev);
+	return err;
+}
+
+/**
+ * ixgb_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * ixgb_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.  The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ **/
+
+static void __devexit
+ixgb_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	unregister_netdev(netdev);
+
+	iounmap(adapter->hw.hw_addr);
+	pci_release_regions(pdev);
+
+	free_netdev(netdev);
+}
+
+/**
+ * ixgb_sw_init - Initialize general software structures (struct ixgb_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * ixgb_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ **/
+
+static int __devinit
+ixgb_sw_init(struct ixgb_adapter *adapter)
+{
+	struct ixgb_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+
+	/* PCI config space info */
+
+	hw->vendor_id = pdev->vendor;
+	hw->device_id = pdev->device;
+	hw->subsystem_vendor_id = pdev->subsystem_vendor;
+	hw->subsystem_id = pdev->subsystem_device;
+
+	adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
+
+	hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+
+	if((hw->device_id == IXGB_DEVICE_ID_82597EX)
+	   ||(hw->device_id == IXGB_DEVICE_ID_82597EX_LR)
+	   ||(hw->device_id == IXGB_DEVICE_ID_82597EX_SR))
+			hw->mac_type = ixgb_82597;
+	else {
+		/* should never have loaded on this device */
+		printk(KERN_ERR "ixgb: unsupported device id\n");
+	}
+
+	/* enable flow control to be programmed */
+	hw->fc.send_xon = 1;
+
+	atomic_set(&adapter->irq_sem, 1);
+	spin_lock_init(&adapter->tx_lock);
+
+	return 0;
+}
+
+/**
+ * ixgb_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP).  At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ **/
+
+static int
+ixgb_open(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	int err;
+
+	/* allocate transmit descriptors */
+
+	if((err = ixgb_setup_tx_resources(adapter)))
+		goto err_setup_tx;
+
+	/* allocate receive descriptors */
+
+	if((err = ixgb_setup_rx_resources(adapter)))
+		goto err_setup_rx;
+
+	if((err = ixgb_up(adapter)))
+		goto err_up;
+
+	return 0;
+
+err_up:
+	ixgb_free_rx_resources(adapter);
+err_setup_rx:
+	ixgb_free_tx_resources(adapter);
+err_setup_tx:
+	ixgb_reset(adapter);
+
+	return err;
+}
+
+/**
+ * ixgb_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS.  The hardware is still under the drivers control, but
+ * needs to be disabled.  A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ **/
+
+static int
+ixgb_close(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	ixgb_down(adapter, TRUE);
+
+	ixgb_free_tx_resources(adapter);
+	ixgb_free_rx_resources(adapter);
+
+	return 0;
+}
+
+/**
+ * ixgb_setup_tx_resources - allocate Tx resources (Descriptors)
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ **/
+
+int
+ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
+{
+	struct ixgb_desc_ring *txdr = &adapter->tx_ring;
+	struct pci_dev *pdev = adapter->pdev;
+	int size;
+
+	size = sizeof(struct ixgb_buffer) * txdr->count;
+	txdr->buffer_info = vmalloc(size);
+	if(!txdr->buffer_info) {
+		return -ENOMEM;
+	}
+	memset(txdr->buffer_info, 0, size);
+
+	/* round up to nearest 4K */
+
+	txdr->size = txdr->count * sizeof(struct ixgb_tx_desc);
+	IXGB_ROUNDUP(txdr->size, 4096);
+
+	txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
+	if(!txdr->desc) {
+		vfree(txdr->buffer_info);
+		return -ENOMEM;
+	}
+	memset(txdr->desc, 0, txdr->size);
+
+	txdr->next_to_use = 0;
+	txdr->next_to_clean = 0;
+
+	return 0;
+}
+
+/**
+ * ixgb_configure_tx - Configure 82597 Transmit Unit after Reset.
+ * @adapter: board private structure
+ *
+ * Configure the Tx unit of the MAC after a reset.
+ **/
+
+static void
+ixgb_configure_tx(struct ixgb_adapter *adapter)
+{
+	uint64_t tdba = adapter->tx_ring.dma;
+	uint32_t tdlen = adapter->tx_ring.count * sizeof(struct ixgb_tx_desc);
+	uint32_t tctl;
+	struct ixgb_hw *hw = &adapter->hw;
+
+	/* Setup the Base and Length of the Tx Descriptor Ring 
+	 * tx_ring.dma can be either a 32 or 64 bit value 
+	 */
+
+	IXGB_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
+	IXGB_WRITE_REG(hw, TDBAH, (tdba >> 32));
+
+	IXGB_WRITE_REG(hw, TDLEN, tdlen);
+
+	/* Setup the HW Tx Head and Tail descriptor pointers */
+
+	IXGB_WRITE_REG(hw, TDH, 0);
+	IXGB_WRITE_REG(hw, TDT, 0);
+
+	/* don't set up txdctl, it induces performance problems if configured
+	 * incorrectly */
+	/* Set the Tx Interrupt Delay register */
+
+	IXGB_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
+
+	/* Program the Transmit Control Register */
+
+	tctl = IXGB_TCTL_TCE | IXGB_TCTL_TXEN | IXGB_TCTL_TPDE;
+	IXGB_WRITE_REG(hw, TCTL, tctl);
+
+	/* Setup Transmit Descriptor Settings for this adapter */
+	adapter->tx_cmd_type =
+		IXGB_TX_DESC_TYPE 
+		| (adapter->tx_int_delay_enable ? IXGB_TX_DESC_CMD_IDE : 0);
+}
+
+/**
+ * ixgb_setup_rx_resources - allocate Rx resources (Descriptors)
+ * @adapter: board private structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+
+int
+ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
+{
+	struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
+	struct pci_dev *pdev = adapter->pdev;
+	int size;
+
+	size = sizeof(struct ixgb_buffer) * rxdr->count;
+	rxdr->buffer_info = vmalloc(size);
+	if(!rxdr->buffer_info) {
+		return -ENOMEM;
+	}
+	memset(rxdr->buffer_info, 0, size);
+
+	/* Round up to nearest 4K */
+
+	rxdr->size = rxdr->count * sizeof(struct ixgb_rx_desc);
+	IXGB_ROUNDUP(rxdr->size, 4096);
+
+	rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+
+	if(!rxdr->desc) {
+		vfree(rxdr->buffer_info);
+		return -ENOMEM;
+	}
+	memset(rxdr->desc, 0, rxdr->size);
+
+	rxdr->next_to_clean = 0;
+	rxdr->next_to_use = 0;
+
+	return 0;
+}
+
+/**
+ * ixgb_setup_rctl - configure the receive control register
+ * @adapter: Board private structure
+ **/
+
+static void
+ixgb_setup_rctl(struct ixgb_adapter *adapter)
+{
+	uint32_t rctl;
+
+	rctl = IXGB_READ_REG(&adapter->hw, RCTL);
+
+	rctl &= ~(3 << IXGB_RCTL_MO_SHIFT);
+
+	rctl |=
+		IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 | 
+		IXGB_RCTL_RXEN | IXGB_RCTL_CFF | 
+		(adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT);
+
+	rctl |= IXGB_RCTL_SECRC;
+
+	switch (adapter->rx_buffer_len) {
+	case IXGB_RXBUFFER_2048:
+	default:
+		rctl |= IXGB_RCTL_BSIZE_2048;
+		break;
+	case IXGB_RXBUFFER_4096:
+		rctl |= IXGB_RCTL_BSIZE_4096;
+		break;
+	case IXGB_RXBUFFER_8192:
+		rctl |= IXGB_RCTL_BSIZE_8192;
+		break;
+	case IXGB_RXBUFFER_16384:
+		rctl |= IXGB_RCTL_BSIZE_16384;
+		break;
+	}
+
+	IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
+}
+
+/**
+ * ixgb_configure_rx - Configure 82597 Receive Unit after Reset.
+ * @adapter: board private structure
+ *
+ * Configure the Rx unit of the MAC after a reset.
+ **/
+
+static void
+ixgb_configure_rx(struct ixgb_adapter *adapter)
+{
+	uint64_t rdba = adapter->rx_ring.dma;
+	uint32_t rdlen = adapter->rx_ring.count * sizeof(struct ixgb_rx_desc);
+	struct ixgb_hw *hw = &adapter->hw;
+	uint32_t rctl;
+	uint32_t rxcsum;
+	uint32_t rxdctl;
+
+	/* make sure receives are disabled while setting up the descriptors */
+
+	rctl = IXGB_READ_REG(hw, RCTL);
+	IXGB_WRITE_REG(hw, RCTL, rctl & ~IXGB_RCTL_RXEN);
+
+	/* set the Receive Delay Timer Register */
+
+	IXGB_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
+
+	/* Setup the Base and Length of the Rx Descriptor Ring */
+
+	IXGB_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
+	IXGB_WRITE_REG(hw, RDBAH, (rdba >> 32));
+
+	IXGB_WRITE_REG(hw, RDLEN, rdlen);
+
+	/* Setup the HW Rx Head and Tail Descriptor Pointers */
+	IXGB_WRITE_REG(hw, RDH, 0);
+	IXGB_WRITE_REG(hw, RDT, 0);
+
+	/* set up pre-fetching of receive buffers so we get some before we
+	 * run out (default hardware behavior is to run out before fetching
+	 * more).  This sets up to fetch if HTHRESH rx descriptors are avail
+	 * and the descriptors in hw cache are below PTHRESH.  This avoids
+	 * the hardware behavior of fetching <=512 descriptors in a single
+	 * burst that pre-empts all other activity, usually causing fifo
+	 * overflows. */
+	/* use WTHRESH to burst write 16 descriptors or burst when RXT0 */
+	rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT |
+	         RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT |
+	         RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
+	IXGB_WRITE_REG(hw, RXDCTL, rxdctl);
+
+	/* Enable Receive Checksum Offload for TCP and UDP */
+	if(adapter->rx_csum == TRUE) {
+		rxcsum = IXGB_READ_REG(hw, RXCSUM);
+		rxcsum |= IXGB_RXCSUM_TUOFL;
+		IXGB_WRITE_REG(hw, RXCSUM, rxcsum);
+	}
+
+	/* Enable Receives */
+
+	IXGB_WRITE_REG(hw, RCTL, rctl);
+}
+
+/**
+ * ixgb_free_tx_resources - Free Tx Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ **/
+
+void
+ixgb_free_tx_resources(struct ixgb_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	ixgb_clean_tx_ring(adapter);
+
+	vfree(adapter->tx_ring.buffer_info);
+	adapter->tx_ring.buffer_info = NULL;
+
+	pci_free_consistent(pdev, adapter->tx_ring.size,
+			    adapter->tx_ring.desc, adapter->tx_ring.dma);
+
+	adapter->tx_ring.desc = NULL;
+}
+
+static inline void
+ixgb_unmap_and_free_tx_resource(struct ixgb_adapter *adapter,
+					struct ixgb_buffer *buffer_info)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	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;
+	}
+}
+
+/**
+ * ixgb_clean_tx_ring - Free Tx Buffers
+ * @adapter: board private structure
+ **/
+
+static void
+ixgb_clean_tx_ring(struct ixgb_adapter *adapter)
+{
+	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+	struct ixgb_buffer *buffer_info;
+	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];
+		ixgb_unmap_and_free_tx_resource(adapter, buffer_info);
+	}
+
+	size = sizeof(struct ixgb_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;
+
+	IXGB_WRITE_REG(&adapter->hw, TDH, 0);
+	IXGB_WRITE_REG(&adapter->hw, TDT, 0);
+}
+
+/**
+ * ixgb_free_rx_resources - Free Rx Resources
+ * @adapter: board private structure
+ *
+ * Free all receive software resources
+ **/
+
+void
+ixgb_free_rx_resources(struct ixgb_adapter *adapter)
+{
+	struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
+	struct pci_dev *pdev = adapter->pdev;
+
+	ixgb_clean_rx_ring(adapter);
+
+	vfree(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;
+}
+
+/**
+ * ixgb_clean_rx_ring - Free Rx Buffers
+ * @adapter: board private structure
+ **/
+
+static void
+ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
+{
+	struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
+	struct ixgb_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 ixgb_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;
+
+	IXGB_WRITE_REG(&adapter->hw, RDH, 0);
+	IXGB_WRITE_REG(&adapter->hw, RDT, 0);
+}
+
+/**
+ * ixgb_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+
+static int
+ixgb_set_mac(struct net_device *netdev, void *p)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	struct sockaddr *addr = p;
+
+	if(!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+
+	ixgb_rar_set(&adapter->hw, addr->sa_data, 0);
+
+	return 0;
+}
+
+/**
+ * ixgb_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated.  This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ **/
+
+static void
+ixgb_set_multi(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	struct ixgb_hw *hw = &adapter->hw;
+	struct dev_mc_list *mc_ptr;
+	uint32_t rctl;
+	int i;
+
+	/* Check for Promiscuous and All Multicast modes */
+
+	rctl = IXGB_READ_REG(hw, RCTL);
+
+	if(netdev->flags & IFF_PROMISC) {
+		rctl |= (IXGB_RCTL_UPE | IXGB_RCTL_MPE);
+	} else if(netdev->flags & IFF_ALLMULTI) {
+		rctl |= IXGB_RCTL_MPE;
+		rctl &= ~IXGB_RCTL_UPE;
+	} else {
+		rctl &= ~(IXGB_RCTL_UPE | IXGB_RCTL_MPE);
+	}
+
+	if(netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES) {
+		rctl |= IXGB_RCTL_MPE;
+		IXGB_WRITE_REG(hw, RCTL, rctl);
+	} else {
+		uint8_t mta[netdev->mc_count * IXGB_ETH_LENGTH_OF_ADDRESS];
+
+		IXGB_WRITE_REG(hw, RCTL, rctl);
+
+		for(i = 0, mc_ptr = netdev->mc_list; mc_ptr;
+			i++, mc_ptr = mc_ptr->next)
+			memcpy(&mta[i * IXGB_ETH_LENGTH_OF_ADDRESS],
+				   mc_ptr->dmi_addr, IXGB_ETH_LENGTH_OF_ADDRESS);
+
+		ixgb_mc_addr_list_update(hw, mta, netdev->mc_count, 0);
+	}
+}
+
+/**
+ * ixgb_watchdog - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ **/
+
+static void
+ixgb_watchdog(unsigned long data)
+{
+	struct ixgb_adapter *adapter = (struct ixgb_adapter *)data;
+	struct net_device *netdev = adapter->netdev;
+	struct ixgb_desc_ring *txdr = &adapter->tx_ring;
+
+	ixgb_check_for_link(&adapter->hw);
+
+	if (ixgb_check_for_bad_link(&adapter->hw)) {
+		/* force the reset path */
+		netif_stop_queue(netdev);
+	}
+
+	if(adapter->hw.link_up) {
+		if(!netif_carrier_ok(netdev)) {
+			printk(KERN_INFO "ixgb: %s NIC Link is Up %d Mbps %s\n",
+				   netdev->name, 10000, "Full Duplex");
+			adapter->link_speed = 10000;
+			adapter->link_duplex = FULL_DUPLEX;
+			netif_carrier_on(netdev);
+			netif_wake_queue(netdev);
+		}
+	} else {
+		if(netif_carrier_ok(netdev)) {
+			adapter->link_speed = 0;
+			adapter->link_duplex = 0;
+			printk(KERN_INFO
+				   "ixgb: %s NIC Link is Down\n",
+				   netdev->name);
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+
+		}
+	}
+
+	ixgb_update_stats(adapter);
+
+	if(!netif_carrier_ok(netdev)) {
+		if(IXGB_DESC_UNUSED(txdr) + 1 < txdr->count) {
+			/* We've lost link, so the controller stops DMA,
+			 * but we've got queued Tx work that's never going
+			 * to get done, so reset controller to flush Tx.
+			 * (Do the reset outside of interrupt context). */
+			schedule_work(&adapter->tx_timeout_task);
+		}
+	}
+
+	/* Force detection of hung controller every watchdog period */
+	adapter->detect_tx_hung = TRUE;
+
+	/* generate an interrupt to force clean up of any stragglers */
+	IXGB_WRITE_REG(&adapter->hw, ICS, IXGB_INT_TXDW);
+
+	/* Reset the timer */
+	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
+
+#define IXGB_TX_FLAGS_CSUM		0x00000001
+#define IXGB_TX_FLAGS_VLAN		0x00000002
+#define IXGB_TX_FLAGS_TSO		0x00000004
+
+static inline int
+ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
+{
+#ifdef NETIF_F_TSO
+	struct ixgb_context_desc *context_desc;
+	unsigned int i;
+	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
+	uint16_t ipcse, tucse, mss;
+	int err;
+
+	if(likely(skb_shinfo(skb)->tso_size)) {
+		if (skb_header_cloned(skb)) {
+			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+			if (err)
+				return err;
+		}
+
+		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 = IXGB_CONTEXT_DESC(adapter->tx_ring, i);
+
+		context_desc->ipcss = ipcss;
+		context_desc->ipcso = ipcso;
+		context_desc->ipcse = cpu_to_le16(ipcse);
+		context_desc->tucss = tucss;
+		context_desc->tucso = tucso;
+		context_desc->tucse = cpu_to_le16(tucse);
+		context_desc->mss = cpu_to_le16(mss);
+		context_desc->hdr_len = hdr_len;
+		context_desc->status = 0;
+		context_desc->cmd_type_len = cpu_to_le32(
+						  IXGB_CONTEXT_DESC_TYPE 
+						| IXGB_CONTEXT_DESC_CMD_TSE
+						| IXGB_CONTEXT_DESC_CMD_IP
+						| IXGB_CONTEXT_DESC_CMD_TCP
+						| IXGB_CONTEXT_DESC_CMD_RS
+						| IXGB_CONTEXT_DESC_CMD_IDE
+						| (skb->len - (hdr_len)));
+
+		if(++i == adapter->tx_ring.count) i = 0;
+		adapter->tx_ring.next_to_use = i;
+
+		return 1;
+	}
+#endif
+
+	return 0;
+}
+
+static inline boolean_t
+ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
+{
+	struct ixgb_context_desc *context_desc;
+	unsigned int i;
+	uint8_t css, cso;
+
+	if(likely(skb->ip_summed == CHECKSUM_HW)) {
+		css = skb->h.raw - skb->data;
+		cso = (skb->h.raw + skb->csum) - skb->data;
+
+		i = adapter->tx_ring.next_to_use;
+		context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i);
+
+		context_desc->tucss = css;
+		context_desc->tucso = cso;
+		context_desc->tucse = 0;
+		/* zero out any previously existing data in one instruction */
+		*(uint32_t *)&(context_desc->ipcss) = 0;
+		context_desc->status = 0;
+		context_desc->hdr_len = 0;
+		context_desc->mss = 0;
+		context_desc->cmd_type_len =
+			cpu_to_le32(IXGB_CONTEXT_DESC_TYPE
+					| IXGB_TX_DESC_CMD_RS 
+					| IXGB_TX_DESC_CMD_IDE);
+
+		if(++i == adapter->tx_ring.count) i = 0;
+		adapter->tx_ring.next_to_use = i;
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+#define IXGB_MAX_TXD_PWR	14
+#define IXGB_MAX_DATA_PER_TXD	(1<<IXGB_MAX_TXD_PWR)
+
+static inline int
+ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
+	    unsigned int first)
+{
+	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+	struct ixgb_buffer *buffer_info;
+	int len = skb->len;
+	unsigned int offset = 0, size, count = 0, i;
+
+	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, IXGB_MAX_JUMBO_FRAME_SIZE);
+		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;
+		count++;
+		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];
+		len = frag->size;
+		offset = 0;
+
+		while(len) {
+			buffer_info = &tx_ring->buffer_info[i];
+			size = min(len, IXGB_MAX_JUMBO_FRAME_SIZE);
+			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;
+			count++;
+			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;
+}
+
+static inline void
+ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
+{
+	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+	struct ixgb_tx_desc *tx_desc = NULL;
+	struct ixgb_buffer *buffer_info;
+	uint32_t cmd_type_len = adapter->tx_cmd_type;
+	uint8_t status = 0;
+	uint8_t popts = 0;
+	unsigned int i;
+
+	if(tx_flags & IXGB_TX_FLAGS_TSO) {
+		cmd_type_len |= IXGB_TX_DESC_CMD_TSE;
+		popts |= (IXGB_TX_DESC_POPTS_IXSM | IXGB_TX_DESC_POPTS_TXSM);
+	}
+
+	if(tx_flags & IXGB_TX_FLAGS_CSUM)
+		popts |= IXGB_TX_DESC_POPTS_TXSM;
+
+	if(tx_flags & IXGB_TX_FLAGS_VLAN) {
+		cmd_type_len |= IXGB_TX_DESC_CMD_VLE;
+	}
+
+	i = tx_ring->next_to_use;
+
+	while(count--) {
+		buffer_info = &tx_ring->buffer_info[i];
+		tx_desc = IXGB_TX_DESC(*tx_ring, i);
+		tx_desc->buff_addr = cpu_to_le64(buffer_info->dma);
+		tx_desc->cmd_type_len =
+			cpu_to_le32(cmd_type_len | buffer_info->length);
+		tx_desc->status = status;
+		tx_desc->popts = popts;
+		tx_desc->vlan = cpu_to_le16(vlan_id);
+
+		if(++i == tx_ring->count) i = 0;
+	}
+
+	tx_desc->cmd_type_len |= cpu_to_le32(IXGB_TX_DESC_CMD_EOP 
+				| IXGB_TX_DESC_CMD_RS );
+
+	/* Force memory writes to complete before letting h/w
+	 * know there are new descriptors to fetch.  (Only
+	 * applicable for weak-ordered memory model archs,
+	 * such as IA-64). */
+	wmb();
+
+	tx_ring->next_to_use = i;
+	IXGB_WRITE_REG(&adapter->hw, TDT, i);
+}
+
+/* Tx Descriptors needed, worst case */
+#define TXD_USE_COUNT(S) (((S) >> IXGB_MAX_TXD_PWR) + \
+			 (((S) & (IXGB_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
+#define DESC_NEEDED TXD_USE_COUNT(IXGB_MAX_DATA_PER_TXD) + \
+	MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1
+
+static int
+ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	unsigned int first;
+	unsigned int tx_flags = 0;
+	unsigned long flags;
+	int vlan_id = 0;
+	int tso;
+
+	if(skb->len <= 0) {
+		dev_kfree_skb_any(skb);
+		return 0;
+	}
+
+	spin_lock_irqsave(&adapter->tx_lock, flags);
+	if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) {
+		netif_stop_queue(netdev);
+		spin_unlock_irqrestore(&adapter->tx_lock, flags);
+		return 1;
+	}
+	spin_unlock_irqrestore(&adapter->tx_lock, flags);
+
+	if(adapter->vlgrp && vlan_tx_tag_present(skb)) {
+		tx_flags |= IXGB_TX_FLAGS_VLAN;
+		vlan_id = vlan_tx_tag_get(skb);
+	}
+
+	first = adapter->tx_ring.next_to_use;
+	
+	tso = ixgb_tso(adapter, skb);
+	if (tso < 0) {
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	if (tso)
+		tx_flags |= IXGB_TX_FLAGS_TSO;
+	else if(ixgb_tx_csum(adapter, skb))
+		tx_flags |= IXGB_TX_FLAGS_CSUM;
+
+	ixgb_tx_queue(adapter, ixgb_tx_map(adapter, skb, first), vlan_id,
+			tx_flags);
+
+	netdev->trans_start = jiffies;
+
+	return 0;
+}
+
+/**
+ * ixgb_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ **/
+
+static void
+ixgb_tx_timeout(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	/* Do the reset outside of interrupt context */
+	schedule_work(&adapter->tx_timeout_task);
+}
+
+static void
+ixgb_tx_timeout_task(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	ixgb_down(adapter, TRUE);
+	ixgb_up(adapter);
+}
+
+/**
+ * ixgb_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ **/
+
+static struct net_device_stats *
+ixgb_get_stats(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	return &adapter->net_stats;
+}
+
+/**
+ * ixgb_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ **/
+
+static int
+ixgb_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+	int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+
+
+	if((max_frame < IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
+	   || (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {
+		IXGB_ERR("Invalid MTU setting\n");
+		return -EINVAL;
+	}
+
+	if((max_frame <= IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
+	   || (max_frame <= IXGB_RXBUFFER_2048)) {
+		adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
+
+	} else if(max_frame <= IXGB_RXBUFFER_4096) {
+		adapter->rx_buffer_len = IXGB_RXBUFFER_4096;
+
+	} else if(max_frame <= IXGB_RXBUFFER_8192) {
+		adapter->rx_buffer_len = IXGB_RXBUFFER_8192;
+
+	} else {
+		adapter->rx_buffer_len = IXGB_RXBUFFER_16384;
+	}
+
+	netdev->mtu = new_mtu;
+
+	if(old_max_frame != max_frame && netif_running(netdev)) {
+
+		ixgb_down(adapter, TRUE);
+		ixgb_up(adapter);
+	}
+
+	return 0;
+}
+
+/**
+ * ixgb_update_stats - Update the board statistics counters.
+ * @adapter: board private structure
+ **/
+
+void
+ixgb_update_stats(struct ixgb_adapter *adapter)
+{
+	adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL);
+	adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH);
+	adapter->stats.gprcl += IXGB_READ_REG(&adapter->hw, GPRCL);
+	adapter->stats.gprch += IXGB_READ_REG(&adapter->hw, GPRCH);
+	adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL);
+	adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH);
+	adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL);
+	adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH);
+	adapter->stats.uprcl += IXGB_READ_REG(&adapter->hw, UPRCL);
+	adapter->stats.uprch += IXGB_READ_REG(&adapter->hw, UPRCH);
+	adapter->stats.vprcl += IXGB_READ_REG(&adapter->hw, VPRCL);
+	adapter->stats.vprch += IXGB_READ_REG(&adapter->hw, VPRCH);
+	adapter->stats.jprcl += IXGB_READ_REG(&adapter->hw, JPRCL);
+	adapter->stats.jprch += IXGB_READ_REG(&adapter->hw, JPRCH);
+	adapter->stats.gorcl += IXGB_READ_REG(&adapter->hw, GORCL);
+	adapter->stats.gorch += IXGB_READ_REG(&adapter->hw, GORCH);
+	adapter->stats.torl += IXGB_READ_REG(&adapter->hw, TORL);
+	adapter->stats.torh += IXGB_READ_REG(&adapter->hw, TORH);
+	adapter->stats.rnbc += IXGB_READ_REG(&adapter->hw, RNBC);
+	adapter->stats.ruc += IXGB_READ_REG(&adapter->hw, RUC);
+	adapter->stats.roc += IXGB_READ_REG(&adapter->hw, ROC);
+	adapter->stats.rlec += IXGB_READ_REG(&adapter->hw, RLEC);
+	adapter->stats.crcerrs += IXGB_READ_REG(&adapter->hw, CRCERRS);
+	adapter->stats.icbc += IXGB_READ_REG(&adapter->hw, ICBC);
+	adapter->stats.ecbc += IXGB_READ_REG(&adapter->hw, ECBC);
+	adapter->stats.mpc += IXGB_READ_REG(&adapter->hw, MPC);
+	adapter->stats.tptl += IXGB_READ_REG(&adapter->hw, TPTL);
+	adapter->stats.tpth += IXGB_READ_REG(&adapter->hw, TPTH);
+	adapter->stats.gptcl += IXGB_READ_REG(&adapter->hw, GPTCL);
+	adapter->stats.gptch += IXGB_READ_REG(&adapter->hw, GPTCH);
+	adapter->stats.bptcl += IXGB_READ_REG(&adapter->hw, BPTCL);
+	adapter->stats.bptch += IXGB_READ_REG(&adapter->hw, BPTCH);
+	adapter->stats.mptcl += IXGB_READ_REG(&adapter->hw, MPTCL);
+	adapter->stats.mptch += IXGB_READ_REG(&adapter->hw, MPTCH);
+	adapter->stats.uptcl += IXGB_READ_REG(&adapter->hw, UPTCL);
+	adapter->stats.uptch += IXGB_READ_REG(&adapter->hw, UPTCH);
+	adapter->stats.vptcl += IXGB_READ_REG(&adapter->hw, VPTCL);
+	adapter->stats.vptch += IXGB_READ_REG(&adapter->hw, VPTCH);
+	adapter->stats.jptcl += IXGB_READ_REG(&adapter->hw, JPTCL);
+	adapter->stats.jptch += IXGB_READ_REG(&adapter->hw, JPTCH);
+	adapter->stats.gotcl += IXGB_READ_REG(&adapter->hw, GOTCL);
+	adapter->stats.gotch += IXGB_READ_REG(&adapter->hw, GOTCH);
+	adapter->stats.totl += IXGB_READ_REG(&adapter->hw, TOTL);
+	adapter->stats.toth += IXGB_READ_REG(&adapter->hw, TOTH);
+	adapter->stats.dc += IXGB_READ_REG(&adapter->hw, DC);
+	adapter->stats.plt64c += IXGB_READ_REG(&adapter->hw, PLT64C);
+	adapter->stats.tsctc += IXGB_READ_REG(&adapter->hw, TSCTC);
+	adapter->stats.tsctfc += IXGB_READ_REG(&adapter->hw, TSCTFC);
+	adapter->stats.ibic += IXGB_READ_REG(&adapter->hw, IBIC);
+	adapter->stats.rfc += IXGB_READ_REG(&adapter->hw, RFC);
+	adapter->stats.lfc += IXGB_READ_REG(&adapter->hw, LFC);
+	adapter->stats.pfrc += IXGB_READ_REG(&adapter->hw, PFRC);
+	adapter->stats.pftc += IXGB_READ_REG(&adapter->hw, PFTC);
+	adapter->stats.mcfrc += IXGB_READ_REG(&adapter->hw, MCFRC);
+	adapter->stats.mcftc += IXGB_READ_REG(&adapter->hw, MCFTC);
+	adapter->stats.xonrxc += IXGB_READ_REG(&adapter->hw, XONRXC);
+	adapter->stats.xontxc += IXGB_READ_REG(&adapter->hw, XONTXC);
+	adapter->stats.xoffrxc += IXGB_READ_REG(&adapter->hw, XOFFRXC);
+	adapter->stats.xofftxc += IXGB_READ_REG(&adapter->hw, XOFFTXC);
+	adapter->stats.rjc += IXGB_READ_REG(&adapter->hw, RJC);
+
+	/* Fill out the OS statistics structure */
+
+	adapter->net_stats.rx_packets = adapter->stats.gprcl;
+	adapter->net_stats.tx_packets = adapter->stats.gptcl;
+	adapter->net_stats.rx_bytes = adapter->stats.gorcl;
+	adapter->net_stats.tx_bytes = adapter->stats.gotcl;
+	adapter->net_stats.multicast = adapter->stats.mprcl;
+	adapter->net_stats.collisions = 0;
+
+	/* ignore RLEC as it reports errors for padded (<64bytes) frames
+	 * with a length in the type/len field */
+	adapter->net_stats.rx_errors =
+	    /* adapter->stats.rnbc + */ adapter->stats.crcerrs +
+	    adapter->stats.ruc +
+	    adapter->stats.roc /*+ adapter->stats.rlec */  +
+	    adapter->stats.icbc +
+	    adapter->stats.ecbc + adapter->stats.mpc;
+
+	adapter->net_stats.rx_dropped = adapter->stats.mpc;
+
+	/* see above
+	 * adapter->net_stats.rx_length_errors = adapter->stats.rlec;
+	 */
+
+	adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
+	adapter->net_stats.rx_fifo_errors = adapter->stats.mpc;
+	adapter->net_stats.rx_missed_errors = adapter->stats.mpc;
+	adapter->net_stats.rx_over_errors = adapter->stats.mpc;
+
+	adapter->net_stats.tx_errors = 0;
+	adapter->net_stats.rx_frame_errors = 0;
+	adapter->net_stats.tx_aborted_errors = 0;
+	adapter->net_stats.tx_carrier_errors = 0;
+	adapter->net_stats.tx_fifo_errors = 0;
+	adapter->net_stats.tx_heartbeat_errors = 0;
+	adapter->net_stats.tx_window_errors = 0;
+}
+
+#define IXGB_MAX_INTR 10
+/**
+ * ixgb_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+ **/
+
+static irqreturn_t
+ixgb_intr(int irq, void *data, struct pt_regs *regs)
+{
+	struct net_device *netdev = data;
+	struct ixgb_adapter *adapter = netdev->priv;
+	struct ixgb_hw *hw = &adapter->hw;
+	uint32_t icr = IXGB_READ_REG(hw, ICR);
+#ifndef CONFIG_IXGB_NAPI
+	unsigned int i;
+#endif
+
+	if(unlikely(!icr))
+		return IRQ_NONE;  /* Not our interrupt */
+
+	if(unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) {
+		mod_timer(&adapter->watchdog_timer, jiffies);
+	}
+
+#ifdef CONFIG_IXGB_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);
+		IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
+		__netif_rx_schedule(netdev);
+	}
+#else
+	/* yes, that is actually a & and it is meant to make sure that
+	 * every pass through this for loop checks both receive and
+	 * transmit queues for completed descriptors, intended to
+	 * avoid starvation issues and assist tx/rx fairness. */
+	for(i = 0; i < IXGB_MAX_INTR; i++)
+		if(!ixgb_clean_rx_irq(adapter) &
+		   !ixgb_clean_tx_irq(adapter))
+			break;
+#endif 
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_IXGB_NAPI
+/**
+ * ixgb_clean - NAPI Rx polling callback
+ * @adapter: board private structure
+ **/
+
+static int
+ixgb_clean(struct net_device *netdev, int *budget)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	int work_to_do = min(*budget, netdev->quota);
+	int tx_cleaned;
+	int work_done = 0;
+
+	tx_cleaned = ixgb_clean_tx_irq(adapter);
+	ixgb_clean_rx_irq(adapter, &work_done, work_to_do);
+
+	*budget -= work_done;
+	netdev->quota -= work_done;
+
+	/* if no Tx and not enough Rx work done, exit the polling mode */
+	if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
+		netif_rx_complete(netdev);
+		ixgb_irq_enable(adapter);
+		return 0;
+	}
+
+	return 1;
+}
+#endif
+
+/**
+ * ixgb_clean_tx_irq - Reclaim resources after transmit completes
+ * @adapter: board private structure
+ **/
+
+static boolean_t
+ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+{
+	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+	struct net_device *netdev = adapter->netdev;
+	struct ixgb_tx_desc *tx_desc, *eop_desc;
+	struct ixgb_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 = IXGB_TX_DESC(*tx_ring, eop);
+
+	while(eop_desc->status & IXGB_TX_DESC_STATUS_DD) {
+
+		for(cleaned = FALSE; !cleaned; ) {
+			tx_desc = IXGB_TX_DESC(*tx_ring, i);
+			buffer_info = &tx_ring->buffer_info[i];
+
+			if (tx_desc->popts
+			    & (IXGB_TX_DESC_POPTS_TXSM |
+			       IXGB_TX_DESC_POPTS_IXSM))
+				adapter->hw_csum_tx_good++;
+
+			ixgb_unmap_and_free_tx_resource(adapter, buffer_info);
+
+			*(uint32_t *)&(tx_desc->status) = 0;
+
+			cleaned = (i == eop);
+			if(++i == tx_ring->count) i = 0;
+		}
+
+		eop = tx_ring->buffer_info[i].next_to_watch;
+		eop_desc = IXGB_TX_DESC(*tx_ring, eop);
+	}
+
+	tx_ring->next_to_clean = i;
+
+	spin_lock(&adapter->tx_lock);
+	if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
+	   (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE)) {
+
+		netif_wake_queue(netdev);
+	}
+	spin_unlock(&adapter->tx_lock);
+
+	if(adapter->detect_tx_hung) {
+		/* detect a transmit hang in hardware, this serializes the
+		 * check with the clearing of time_stamp and movement of i */
+		adapter->detect_tx_hung = FALSE;
+		if(tx_ring->buffer_info[i].dma &&
+		   time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ)
+		   && !(IXGB_READ_REG(&adapter->hw, STATUS) &
+			IXGB_STATUS_TXOFF))
+			netif_stop_queue(netdev);
+	}
+
+	return cleaned;
+}
+
+/**
+ * ixgb_rx_checksum - Receive Checksum Offload for 82597.
+ * @adapter: board private structure
+ * @rx_desc: receive descriptor
+ * @sk_buff: socket buffer with received data
+ **/
+
+static inline void
+ixgb_rx_checksum(struct ixgb_adapter *adapter,
+		 struct ixgb_rx_desc *rx_desc,
+		 struct sk_buff *skb)
+{
+	/* Ignore Checksum bit is set OR
+	 * TCP Checksum has not been calculated
+	 */
+	if((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) ||
+	   (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) {
+		skb->ip_summed = CHECKSUM_NONE;
+		return;
+	}
+
+	/* At this point we know the hardware did the TCP checksum */
+	/* now look at the TCP checksum error bit */
+	if(rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) {
+		/* let the stack verify checksum errors */
+		skb->ip_summed = CHECKSUM_NONE;
+		adapter->hw_csum_rx_error++;
+	} else {
+		/* TCP checksum is good */
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		adapter->hw_csum_rx_good++;
+	}
+}
+
+/**
+ * ixgb_clean_rx_irq - Send received data up the network stack,
+ * @adapter: board private structure
+ **/
+
+static boolean_t
+#ifdef CONFIG_IXGB_NAPI
+ixgb_clean_rx_irq(struct ixgb_adapter *adapter, int *work_done, int work_to_do)
+#else
+ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
+#endif
+{
+	struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	struct ixgb_rx_desc *rx_desc, *next_rxd;
+	struct ixgb_buffer *buffer_info, *next_buffer, *next2_buffer;
+	struct sk_buff *skb, *next_skb;
+	uint32_t length;
+	unsigned int i, j;
+	boolean_t cleaned = FALSE;
+
+	i = rx_ring->next_to_clean;
+	rx_desc = IXGB_RX_DESC(*rx_ring, i);
+	buffer_info = &rx_ring->buffer_info[i];
+
+	while(rx_desc->status & IXGB_RX_DESC_STATUS_DD) {
+
+#ifdef CONFIG_IXGB_NAPI
+		if(*work_done >= work_to_do)
+			break;
+
+		(*work_done)++;
+#endif
+		skb = buffer_info->skb;
+		prefetch(skb->data);
+
+		if(++i == rx_ring->count) i = 0;
+		next_rxd = IXGB_RX_DESC(*rx_ring, i);
+		prefetch(next_rxd);
+
+		if((j = i + 1) == rx_ring->count) j = 0;
+		next2_buffer = &rx_ring->buffer_info[j];
+		prefetch(next2_buffer);
+
+		next_buffer = &rx_ring->buffer_info[i];
+		next_skb = next_buffer->skb;
+		prefetch(next_skb);
+
+
+		cleaned = TRUE;
+
+		pci_unmap_single(pdev,
+				 buffer_info->dma,
+				 buffer_info->length,
+				 PCI_DMA_FROMDEVICE);
+
+		length = le16_to_cpu(rx_desc->length);
+
+		if(unlikely(!(rx_desc->status & IXGB_RX_DESC_STATUS_EOP))) {
+
+			/* All receives must fit into a single buffer */
+
+			IXGB_DBG("Receive packet consumed multiple buffers "
+					 "length<%x>\n", length);
+
+			dev_kfree_skb_irq(skb);
+			rx_desc->status = 0;
+			buffer_info->skb = NULL;
+
+			rx_desc = next_rxd;
+			buffer_info = next_buffer;
+			continue;
+		}
+
+		if (unlikely(rx_desc->errors
+			     & (IXGB_RX_DESC_ERRORS_CE | IXGB_RX_DESC_ERRORS_SE
+				| IXGB_RX_DESC_ERRORS_P |
+				IXGB_RX_DESC_ERRORS_RXE))) {
+
+			dev_kfree_skb_irq(skb);
+			rx_desc->status = 0;
+			buffer_info->skb = NULL;
+
+			rx_desc = next_rxd;
+			buffer_info = next_buffer;
+			continue;
+		}
+
+		/* Good Receive */
+		skb_put(skb, length);
+
+		/* Receive Checksum Offload */
+		ixgb_rx_checksum(adapter, rx_desc, skb);
+
+		skb->protocol = eth_type_trans(skb, netdev);
+#ifdef CONFIG_IXGB_NAPI
+		if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
+			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
+				le16_to_cpu(rx_desc->special) &
+					IXGB_RX_DESC_SPECIAL_VLAN_MASK);
+		} else {
+			netif_receive_skb(skb);
+		}
+#else /* CONFIG_IXGB_NAPI */
+		if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
+			vlan_hwaccel_rx(skb, adapter->vlgrp,
+				le16_to_cpu(rx_desc->special) &
+					IXGB_RX_DESC_SPECIAL_VLAN_MASK);
+		} else {
+			netif_rx(skb);
+		}
+#endif /* CONFIG_IXGB_NAPI */
+		netdev->last_rx = jiffies;
+
+		rx_desc->status = 0;
+		buffer_info->skb = NULL;
+
+		rx_desc = next_rxd;
+		buffer_info = next_buffer;
+	}
+
+	rx_ring->next_to_clean = i;
+
+	ixgb_alloc_rx_buffers(adapter);
+
+	return cleaned;
+}
+
+/**
+ * ixgb_alloc_rx_buffers - Replace used receive buffers
+ * @adapter: address of board private structure
+ **/
+
+static void
+ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
+{
+	struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	struct ixgb_rx_desc *rx_desc;
+	struct ixgb_buffer *buffer_info;
+	struct sk_buff *skb;
+	unsigned int i;
+	int num_group_tail_writes;
+	long cleancount;
+
+	i = rx_ring->next_to_use;
+	buffer_info = &rx_ring->buffer_info[i];
+	cleancount = IXGB_DESC_UNUSED(rx_ring);
+
+	num_group_tail_writes = IXGB_RX_BUFFER_WRITE;
+
+	/* leave one descriptor unused */
+	while(--cleancount > 0) {
+		rx_desc = IXGB_RX_DESC(*rx_ring, i);
+
+		skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
+
+		if(unlikely(!skb)) {
+			/* Better luck next round */
+			break;
+		}
+
+		/* Make buffer alignment 2 beyond a 16 byte boundary
+		 * this will result in a 16 byte aligned IP header after
+		 * the 14 byte MAC header is removed
+		 */
+		skb_reserve(skb, NET_IP_ALIGN);
+
+		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->buff_addr = cpu_to_le64(buffer_info->dma);
+
+		if((i & ~(num_group_tail_writes- 1)) == i) {
+			/* Force memory writes to complete before letting h/w
+			 * know there are new descriptors to fetch.  (Only
+			 * applicable for weak-ordered memory model archs,
+			 * such as IA-64). */
+			wmb();
+
+			IXGB_WRITE_REG(&adapter->hw, RDT, i);
+		}
+
+		if(++i == rx_ring->count) i = 0;
+		buffer_info = &rx_ring->buffer_info[i];
+	}
+
+	rx_ring->next_to_use = i;
+}
+
+/**
+ * ixgb_vlan_rx_register - enables or disables vlan tagging/stripping.
+ * 
+ * @param netdev network interface device structure
+ * @param grp indicates to enable or disable tagging/stripping
+ **/
+static void
+ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	uint32_t ctrl, rctl;
+
+	ixgb_irq_disable(adapter);
+	adapter->vlgrp = grp;
+
+	if(grp) {
+		/* enable VLAN tag insert/strip */
+		ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
+		ctrl |= IXGB_CTRL0_VME;
+		IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
+
+		/* enable VLAN receive filtering */
+
+		rctl = IXGB_READ_REG(&adapter->hw, RCTL);
+		rctl |= IXGB_RCTL_VFE;
+		rctl &= ~IXGB_RCTL_CFIEN;
+		IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
+	} else {
+		/* disable VLAN tag insert/strip */
+
+		ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
+		ctrl &= ~IXGB_CTRL0_VME;
+		IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
+
+		/* disable VLAN filtering */
+
+		rctl = IXGB_READ_REG(&adapter->hw, RCTL);
+		rctl &= ~IXGB_RCTL_VFE;
+		IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
+	}
+
+	ixgb_irq_enable(adapter);
+}
+
+static void
+ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	uint32_t vfta, index;
+
+	/* add VID to filter table */
+
+	index = (vid >> 5) & 0x7F;
+	vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+	vfta |= (1 << (vid & 0x1F));
+	ixgb_write_vfta(&adapter->hw, index, vfta);
+}
+
+static void
+ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
+{
+	struct ixgb_adapter *adapter = netdev->priv;
+	uint32_t vfta, index;
+
+	ixgb_irq_disable(adapter);
+
+	if(adapter->vlgrp)
+		adapter->vlgrp->vlan_devices[vid] = NULL;
+
+	ixgb_irq_enable(adapter);
+
+	/* remove VID from filter table*/
+
+	index = (vid >> 5) & 0x7F;
+	vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+	vfta &= ~(1 << (vid & 0x1F));
+	ixgb_write_vfta(&adapter->hw, index, vfta);
+}
+
+static void
+ixgb_restore_vlan(struct ixgb_adapter *adapter)
+{
+	ixgb_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+
+	if(adapter->vlgrp) {
+		uint16_t vid;
+		for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+			if(!adapter->vlgrp->vlan_devices[vid])
+				continue;
+			ixgb_vlan_rx_add_vid(adapter->netdev, vid);
+		}
+	}
+}
+
+/**
+ * ixgb_notify_reboot - handles OS notification of reboot event.
+ * @param nb notifier block, unused
+ * @param event Event being passed to driver to act upon
+ * @param p A pointer to our net device
+ **/
+static int
+ixgb_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
+{
+	struct pci_dev *pdev = NULL;
+
+	switch(event) {
+	case SYS_DOWN:
+	case SYS_HALT:
+	case SYS_POWER_OFF:
+		while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) {
+			if (pci_dev_driver(pdev) == &ixgb_driver)
+				ixgb_suspend(pdev, 3);
+		}
+	}
+	return NOTIFY_DONE;
+}
+
+/**
+ * ixgb_suspend - driver suspend function called from notify.
+ * @param pdev pci driver structure used for passing to
+ * @param state power state to enter 
+ **/
+static int
+ixgb_suspend(struct pci_dev *pdev, uint32_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	netif_device_detach(netdev);
+
+	if(netif_running(netdev))
+		ixgb_down(adapter, TRUE);
+
+	pci_save_state(pdev);
+
+	state = (state > 0) ? 3 : 0;
+	pci_set_power_state(pdev, state);
+	msec_delay(200);
+
+	return 0;
+}
+
+#ifdef CONFIG_NET_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 ixgb_netpoll(struct net_device *dev)
+{
+	struct ixgb_adapter *adapter = dev->priv;
+	disable_irq(adapter->pdev->irq);
+	ixgb_intr(adapter->pdev->irq, dev, NULL);
+	enable_irq(adapter->pdev->irq);
+}
+#endif
+
+/* ixgb_main.c */
diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h
new file mode 100644
index 0000000..9eba928
--- /dev/null
+++ b/drivers/net/ixgb/ixgb_osdep.h
@@ -0,0 +1,96 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of the GNU General Public License as published by the Free 
+  Software Foundation; either version 2 of the License, or (at your option) 
+  any later version.
+  
+  This program is distributed in the hope that it will be useful, but WITHOUT 
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+  more details.
+  
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+/* glue for the OS independent part of ixgb
+ * includes register access macros
+ */
+
+#ifndef _IXGB_OSDEP_H_
+#define _IXGB_OSDEP_H_
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
+#ifndef msec_delay
+#define msec_delay(x)	do { if(in_interrupt()) { \
+				/* Don't mdelay in interrupt context! */ \
+	                	BUG(); \
+			} else { \
+				set_current_state(TASK_UNINTERRUPTIBLE); \
+				schedule_timeout((x * HZ)/1000 + 2); \
+			} } while(0)
+#endif
+
+#define PCI_COMMAND_REGISTER   PCI_COMMAND
+#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE
+
+typedef enum {
+#undef FALSE
+	FALSE = 0,
+#undef TRUE
+	TRUE = 1
+} boolean_t;
+
+#undef ASSERT
+#define ASSERT(x)	if(!(x)) BUG()
+#define MSGOUT(S, A, B)	printk(KERN_DEBUG S "\n", A, B)
+
+#ifdef DBG
+#define DEBUGOUT(S)		printk(KERN_DEBUG S "\n")
+#define DEBUGOUT1(S, A...)	printk(KERN_DEBUG S "\n", A)
+#else
+#define DEBUGOUT(S)
+#define DEBUGOUT1(S, A...)
+#endif
+
+#define DEBUGFUNC(F) DEBUGOUT(F)
+#define DEBUGOUT2 DEBUGOUT1
+#define DEBUGOUT3 DEBUGOUT2
+#define DEBUGOUT7 DEBUGOUT3
+
+#define IXGB_WRITE_REG(a, reg, value) ( \
+	writel((value), ((a)->hw_addr + IXGB_##reg)))
+
+#define IXGB_READ_REG(a, reg) ( \
+	readl((a)->hw_addr + IXGB_##reg))
+
+#define IXGB_WRITE_REG_ARRAY(a, reg, offset, value) ( \
+	writel((value), ((a)->hw_addr + IXGB_##reg + ((offset) << 2))))
+
+#define IXGB_READ_REG_ARRAY(a, reg, offset) ( \
+	readl((a)->hw_addr + IXGB_##reg + ((offset) << 2)))
+
+#define IXGB_WRITE_FLUSH(a) IXGB_READ_REG(a, STATUS)
+
+#define IXGB_MEMCPY memcpy
+
+#endif /* _IXGB_OSDEP_H_ */
diff --git a/drivers/net/ixgb/ixgb_param.c b/drivers/net/ixgb/ixgb_param.c
new file mode 100644
index 0000000..8a83dfd
--- /dev/null
+++ b/drivers/net/ixgb/ixgb_param.c
@@ -0,0 +1,476 @@
+/*******************************************************************************
+
+  
+  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of the GNU General Public License as published by the Free 
+  Software Foundation; either version 2 of the License, or (at your option) 
+  any later version.
+  
+  This program is distributed in the hope that it will be useful, but WITHOUT 
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+  more details.
+  
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc., 59 
+  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  Linux NICS <linux.nics@intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include "ixgb.h"
+
+/* This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+
+#define IXGB_MAX_NIC 8
+
+#define OPTION_UNSET	-1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED  1
+
+/* All parameters are treated the same, as an integer array of values.
+ * This macro just reduces the need to repeat the same declaration code
+ * over and over (plus this helps to avoid typo bugs).
+ */
+
+#define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET }
+#define IXGB_PARAM(X, desc) \
+	static int __devinitdata X[IXGB_MAX_NIC+1] = IXGB_PARAM_INIT; \
+	static int num_##X = 0; \
+	module_param_array_named(X, X, int, &num_##X, 0); \
+	MODULE_PARM_DESC(X, desc);
+
+/* Transmit Descriptor Count
+ *
+ * Valid Range: 64-4096
+ *
+ * Default Value: 256
+ */
+
+IXGB_PARAM(TxDescriptors, "Number of transmit descriptors");
+
+/* Receive Descriptor Count
+ *
+ * Valid Range: 64-4096
+ *
+ * Default Value: 1024
+ */
+
+IXGB_PARAM(RxDescriptors, "Number of receive descriptors");
+
+/* User Specified Flow Control Override
+ *
+ * Valid Range: 0-3
+ *  - 0 - No Flow Control
+ *  - 1 - Rx only, respond to PAUSE frames but do not generate them
+ *  - 2 - Tx only, generate PAUSE frames but ignore them on receive
+ *  - 3 - Full Flow Control Support
+ *
+ * Default Value: Read flow control settings from the EEPROM
+ */
+
+IXGB_PARAM(FlowControl, "Flow Control setting");
+
+/* XsumRX - Receive Checksum Offload Enable/Disable
+ *
+ * Valid Range: 0, 1
+ *  - 0 - disables all checksum offload
+ *  - 1 - enables receive IP/TCP/UDP checksum offload
+ *        on 82597 based NICs
+ *
+ * Default Value: 1
+ */
+
+IXGB_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
+
+/* Transmit Interrupt Delay in units of 0.8192 microseconds
+ *
+ * Valid Range: 0-65535
+ *
+ * Default Value: 32
+ */
+
+IXGB_PARAM(TxIntDelay, "Transmit Interrupt Delay");
+
+/* Receive Interrupt Delay in units of 0.8192 microseconds
+ *
+ * Valid Range: 0-65535
+ *
+ * Default Value: 72
+ */
+
+IXGB_PARAM(RxIntDelay, "Receive Interrupt Delay");
+
+/* Receive Flow control high threshold (when we send a pause frame)
+ * (FCRTH)
+ *
+ * Valid Range: 1,536 - 262,136 (0x600 - 0x3FFF8, 8 byte granularity)
+ *
+ * Default Value: 196,608 (0x30000)
+ */
+
+IXGB_PARAM(RxFCHighThresh, "Receive Flow Control High Threshold");
+
+/* Receive Flow control low threshold (when we send a resume frame)
+ * (FCRTL)
+ *
+ * Valid Range: 64 - 262,136 (0x40 - 0x3FFF8, 8 byte granularity)
+ *              must be less than high threshold by at least 8 bytes
+ *
+ * Default Value:  163,840 (0x28000)
+ */
+
+IXGB_PARAM(RxFCLowThresh, "Receive Flow Control Low Threshold");
+
+/* Flow control request timeout (how long to pause the link partner's tx)
+ * (PAP 15:0)
+ *
+ * Valid Range: 1 - 65535 
+ *
+ * Default Value:  256 (0x100)
+ */
+
+IXGB_PARAM(FCReqTimeout, "Flow Control Request Timeout");
+
+/* Interrupt Delay Enable
+ *
+ * Valid Range: 0, 1
+ *
+ *  - 0 - disables transmit interrupt delay
+ *  - 1 - enables transmmit interrupt delay
+ *
+ * Default Value: 1
+ */
+
+IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable");
+
+
+#define DEFAULT_TIDV	   		     32
+#define MAX_TIDV			 0xFFFF
+#define MIN_TIDV			      0
+
+#define DEFAULT_RDTR		   	     72
+#define MAX_RDTR			 0xFFFF
+#define MIN_RDTR			      0
+
+#define XSUMRX_DEFAULT		 OPTION_ENABLED
+
+#define FLOW_CONTROL_FULL	   ixgb_fc_full
+#define FLOW_CONTROL_DEFAULT  FLOW_CONTROL_FULL
+#define DEFAULT_FCRTL	  		0x28000
+#define DEFAULT_FCRTH			0x30000
+#define MIN_FCRTL			      0
+#define MAX_FCRTL			0x3FFE8
+#define MIN_FCRTH			      8
+#define MAX_FCRTH			0x3FFF0
+
+#define DEFAULT_FCPAUSE		  	0x100	/* this may be too long */
+#define MIN_FCPAUSE			      1
+#define MAX_FCPAUSE			 0xffff
+
+struct ixgb_option {
+	enum { enable_option, range_option, list_option } type;
+	char *name;
+	char *err;
+	int def;
+	union {
+		struct {	/* range_option info */
+			int min;
+			int max;
+		} r;
+		struct {	/* list_option info */
+			int nr;
+			struct ixgb_opt_list {
+				int i;
+				char *str;
+			} *p;
+		} l;
+	} arg;
+};
+
+static int __devinit
+ixgb_validate_option(int *value, struct ixgb_option *opt)
+{
+	if(*value == OPTION_UNSET) {
+		*value = opt->def;
+		return 0;
+	}
+
+	switch (opt->type) {
+	case enable_option:
+		switch (*value) {
+		case OPTION_ENABLED:
+			printk(KERN_INFO "%s Enabled\n", opt->name);
+			return 0;
+		case OPTION_DISABLED:
+			printk(KERN_INFO "%s Disabled\n", opt->name);
+			return 0;
+		}
+		break;
+	case range_option:
+		if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+			printk(KERN_INFO "%s set to %i\n", opt->name, *value);
+			return 0;
+		}
+		break;
+	case list_option: {
+		int i;
+		struct ixgb_opt_list *ent;
+
+		for(i = 0; i < opt->arg.l.nr; i++) {
+			ent = &opt->arg.l.p[i];
+			if(*value == ent->i) {
+				if(ent->str[0] != '\0')
+					printk(KERN_INFO "%s\n", ent->str);
+				return 0;
+			}
+		}
+	}
+		break;
+	default:
+		BUG();
+	}
+
+	printk(KERN_INFO "Invalid %s specified (%i) %s\n",
+		   opt->name, *value, opt->err);
+	*value = opt->def;
+	return -1;
+}
+
+#define LIST_LEN(l) (sizeof(l) / sizeof(l[0]))
+
+/**
+ * ixgb_check_options - Range Checking for Command Line Parameters
+ * @adapter: board private structure
+ *
+ * This routine checks all command line parameters for valid user
+ * input.  If an invalid value is given, or if no user specified
+ * value exists, a default value is used.  The final value is stored
+ * in a variable in the adapter structure.
+ **/
+
+void __devinit
+ixgb_check_options(struct ixgb_adapter *adapter)
+{
+	int bd = adapter->bd_number;
+	if(bd >= IXGB_MAX_NIC) {
+		printk(KERN_NOTICE
+			   "Warning: no configuration for board #%i\n", bd);
+		printk(KERN_NOTICE "Using defaults for all values\n");
+	}
+
+	{ /* Transmit Descriptor Count */
+		struct ixgb_option opt = {
+			.type = range_option,
+			.name = "Transmit Descriptors",
+			.err  = "using default of " __MODULE_STRING(DEFAULT_TXD),
+			.def  = DEFAULT_TXD,
+			.arg  = { .r = { .min = MIN_TXD,
+					 .max = MAX_TXD}}
+		};
+		struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+
+		if(num_TxDescriptors > bd) {
+			tx_ring->count = TxDescriptors[bd];
+			ixgb_validate_option(&tx_ring->count, &opt);
+		} else {
+			tx_ring->count = opt.def;
+		}
+		IXGB_ROUNDUP(tx_ring->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
+	}
+	{ /* Receive Descriptor Count */
+		struct ixgb_option opt = {
+			.type = range_option,
+			.name = "Receive Descriptors",
+			.err  = "using default of " __MODULE_STRING(DEFAULT_RXD),
+			.def  = DEFAULT_RXD,
+			.arg  = { .r = { .min = MIN_RXD,
+					 .max = MAX_RXD}}
+		};
+		struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
+
+		if(num_RxDescriptors > bd) {
+			rx_ring->count = RxDescriptors[bd];
+			ixgb_validate_option(&rx_ring->count, &opt);
+		} else {
+			rx_ring->count = opt.def;
+		}
+		IXGB_ROUNDUP(rx_ring->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
+	}
+	{ /* Receive Checksum Offload Enable */
+		struct ixgb_option opt = {
+			.type = enable_option,
+			.name = "Receive Checksum Offload",
+			.err  = "defaulting to Enabled",
+			.def  = OPTION_ENABLED
+		};
+
+		if(num_XsumRX > bd) {
+			int rx_csum = XsumRX[bd];
+			ixgb_validate_option(&rx_csum, &opt);
+			adapter->rx_csum = rx_csum;
+		} else {
+			adapter->rx_csum = opt.def;
+		}
+	}
+	{ /* Flow Control */
+
+		struct ixgb_opt_list fc_list[] =
+			{{ ixgb_fc_none,	"Flow Control Disabled" },
+			 { ixgb_fc_rx_pause,"Flow Control Receive Only" },
+			 { ixgb_fc_tx_pause,"Flow Control Transmit Only" },
+			 { ixgb_fc_full,	"Flow Control Enabled" },
+			 { ixgb_fc_default, "Flow Control Hardware Default" }};
+
+		struct ixgb_option opt = {
+			.type = list_option,
+			.name = "Flow Control",
+			.err  = "reading default settings from EEPROM",
+			.def  = ixgb_fc_full,
+			.arg  = { .l = { .nr = LIST_LEN(fc_list),
+					 .p = fc_list }}
+		};
+
+		if(num_FlowControl > bd) {
+			int fc = FlowControl[bd];
+			ixgb_validate_option(&fc, &opt);
+			adapter->hw.fc.type = fc;
+		} else {
+			adapter->hw.fc.type = opt.def;
+		}
+	}
+	{ /* Receive Flow Control High Threshold */
+		struct ixgb_option opt = {
+			.type = range_option,
+			.name = "Rx Flow Control High Threshold",
+			.err  = "using default of " __MODULE_STRING(DEFAULT_FCRTH),
+			.def  = DEFAULT_FCRTH,
+			.arg  = { .r = { .min = MIN_FCRTH,
+					 .max = MAX_FCRTH}}
+		};
+
+		if(num_RxFCHighThresh > bd) {
+			adapter->hw.fc.high_water = RxFCHighThresh[bd];
+			ixgb_validate_option(&adapter->hw.fc.high_water, &opt);
+		} else {
+			adapter->hw.fc.high_water = opt.def;
+		}
+		if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
+			printk (KERN_INFO 
+				"Ignoring RxFCHighThresh when no RxFC\n");
+	}
+	{ /* Receive Flow Control Low Threshold */
+		struct ixgb_option opt = {
+			.type = range_option,
+			.name = "Rx Flow Control Low Threshold",
+			.err  = "using default of " __MODULE_STRING(DEFAULT_FCRTL),
+			.def  = DEFAULT_FCRTL,
+			.arg  = { .r = { .min = MIN_FCRTL,
+					 .max = MAX_FCRTL}}
+		};
+
+		if(num_RxFCLowThresh > bd) {
+			adapter->hw.fc.low_water = RxFCLowThresh[bd];
+			ixgb_validate_option(&adapter->hw.fc.low_water, &opt);
+		} else {
+			adapter->hw.fc.low_water = opt.def;
+		}
+		if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
+			printk (KERN_INFO 
+				"Ignoring RxFCLowThresh when no RxFC\n");
+	}
+	{ /* Flow Control Pause Time Request*/
+		struct ixgb_option opt = {
+			.type = range_option,
+			.name = "Flow Control Pause Time Request",
+			.err  = "using default of "__MODULE_STRING(DEFAULT_FCPAUSE),
+			.def  = DEFAULT_FCPAUSE,
+			.arg = { .r = { .min = MIN_FCPAUSE,
+					.max = MAX_FCPAUSE}}
+		};
+
+		if(num_FCReqTimeout > bd) {
+			int pause_time = FCReqTimeout[bd];
+			ixgb_validate_option(&pause_time, &opt);
+			adapter->hw.fc.pause_time = pause_time;
+		} else {
+			adapter->hw.fc.pause_time = opt.def;
+		}
+		if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
+			printk (KERN_INFO 
+				"Ignoring FCReqTimeout when no RxFC\n");
+	}
+	/* high low and spacing check for rx flow control thresholds */
+	if (adapter->hw.fc.type & ixgb_fc_rx_pause) {
+		/* high must be greater than low */
+		if (adapter->hw.fc.high_water < (adapter->hw.fc.low_water + 8)) {
+			/* set defaults */
+			printk (KERN_INFO 
+				"RxFCHighThresh must be >= (RxFCLowThresh + 8), "
+				"Using Defaults\n");
+			adapter->hw.fc.high_water = DEFAULT_FCRTH;
+			adapter->hw.fc.low_water  = DEFAULT_FCRTL;
+		}
+	}
+	{ /* Receive Interrupt Delay */
+		struct ixgb_option opt = {
+			.type = range_option,
+			.name = "Receive Interrupt Delay",
+			.err  = "using default of " __MODULE_STRING(DEFAULT_RDTR),
+			.def  = DEFAULT_RDTR,
+			.arg  = { .r = { .min = MIN_RDTR,
+					 .max = MAX_RDTR}}
+		};
+
+		if(num_RxIntDelay > bd) {
+			adapter->rx_int_delay = RxIntDelay[bd];
+			ixgb_validate_option(&adapter->rx_int_delay, &opt);
+		} else {
+			adapter->rx_int_delay = opt.def;
+		}
+	}
+	{ /* Transmit Interrupt Delay */
+		struct ixgb_option opt = {
+			.type = range_option,
+			.name = "Transmit Interrupt Delay",
+			.err  = "using default of " __MODULE_STRING(DEFAULT_TIDV),
+			.def  = DEFAULT_TIDV,
+			.arg  = { .r = { .min = MIN_TIDV,
+					 .max = MAX_TIDV}}
+		};
+
+		if(num_TxIntDelay > bd) {
+			adapter->tx_int_delay = TxIntDelay[bd];
+			ixgb_validate_option(&adapter->tx_int_delay, &opt);
+		} else {
+			adapter->tx_int_delay = opt.def;
+		}
+	}
+
+	{ /* Transmit Interrupt Delay Enable */
+		struct ixgb_option opt = {
+			.type = enable_option,
+			.name = "Tx Interrupt Delay Enable",
+			.err  = "defaulting to Enabled",
+			.def  = OPTION_ENABLED
+		};
+
+		if(num_IntDelayEnable > bd) {
+			int ide = IntDelayEnable[bd];
+			ixgb_validate_option(&ide, &opt);
+			adapter->tx_int_delay_enable = ide;
+		} else {
+			adapter->tx_int_delay_enable = opt.def;
+		}
+	}
+}